json-json.hpp (921069B)
1 // © 2024 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 // 4 // From the nlohmann/json library. Original license: 5 // 6 // MIT License 7 // 8 // Copyright (c) 2013-2022 Niels Lohmann 9 // 10 // Permission is hereby granted, free of charge, to any person obtaining a copy 11 // of this software and associated documentation files (the "Software"), to deal 12 // in the Software without restriction, including without limitation the rights 13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 // copies of the Software, and to permit persons to whom the Software is 15 // furnished to do so, subject to the following conditions: 16 // 17 // The above copyright notice and this permission notice shall be included in all 18 // copies or substantial portions of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 // SOFTWARE. 27 28 29 // __ _____ _____ _____ 30 // __| | __| | | | JSON for Modern C++ 31 // | | |__ | | | | | | version 3.11.3 32 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 33 // 34 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 35 // SPDX-License-Identifier: MIT 36 37 /****************************************************************************\ 38 * Note on documentation: The source files contain links to the online * 39 * documentation of the public API at https://json.nlohmann.me. This URL * 40 * contains the most recent documentation and should also be applicable to * 41 * previous versions; documentation for deprecated functions is not * 42 * removed, but marked deprecated. See "Generate documentation" section in * 43 * file docs/README.md. * 44 \****************************************************************************/ 45 46 #ifndef INCLUDE_NLOHMANN_JSON_HPP_ 47 #define INCLUDE_NLOHMANN_JSON_HPP_ 48 49 #include <algorithm> // all_of, find, for_each 50 #include <cstddef> // nullptr_t, ptrdiff_t, size_t 51 #include <functional> // hash, less 52 #include <initializer_list> // initializer_list 53 #ifndef JSON_NO_IO 54 #include <iosfwd> // istream, ostream 55 #endif // JSON_NO_IO 56 #include <iterator> // random_access_iterator_tag 57 #include <memory> // unique_ptr 58 #include <string> // string, stoi, to_string 59 #include <utility> // declval, forward, move, pair, swap 60 #include <vector> // vector 61 62 // #include <nlohmann/adl_serializer.hpp> 63 // __ _____ _____ _____ 64 // __| | __| | | | JSON for Modern C++ 65 // | | |__ | | | | | | version 3.11.3 66 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 67 // 68 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 69 // SPDX-License-Identifier: MIT 70 71 72 73 #include <utility> 74 75 // #include <nlohmann/detail/abi_macros.hpp> 76 // __ _____ _____ _____ 77 // __| | __| | | | JSON for Modern C++ 78 // | | |__ | | | | | | version 3.11.3 79 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 80 // 81 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 82 // SPDX-License-Identifier: MIT 83 84 85 86 // This file contains all macro definitions affecting or depending on the ABI 87 88 #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK 89 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) 90 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 91 #warning "Already included a different version of the library!" 92 #endif 93 #endif 94 #endif 95 96 #define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) 97 #define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) 98 #define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) 99 100 #ifndef JSON_DIAGNOSTICS 101 #define JSON_DIAGNOSTICS 0 102 #endif 103 104 #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 105 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 106 #endif 107 108 #if JSON_DIAGNOSTICS 109 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag 110 #else 111 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS 112 #endif 113 114 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 115 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp 116 #else 117 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON 118 #endif 119 120 #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION 121 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 122 #endif 123 124 // Construct the namespace ABI tags component 125 #define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b 126 #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ 127 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) 128 129 #define NLOHMANN_JSON_ABI_TAGS \ 130 NLOHMANN_JSON_ABI_TAGS_CONCAT( \ 131 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ 132 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) 133 134 // Construct the namespace version component 135 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ 136 _v ## major ## _ ## minor ## _ ## patch 137 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ 138 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) 139 140 #if NLOHMANN_JSON_NAMESPACE_NO_VERSION 141 #define NLOHMANN_JSON_NAMESPACE_VERSION 142 #else 143 #define NLOHMANN_JSON_NAMESPACE_VERSION \ 144 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ 145 NLOHMANN_JSON_VERSION_MINOR, \ 146 NLOHMANN_JSON_VERSION_PATCH) 147 #endif 148 149 // Combine namespace components 150 #define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b 151 #define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ 152 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) 153 154 #ifndef NLOHMANN_JSON_NAMESPACE 155 #define NLOHMANN_JSON_NAMESPACE \ 156 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ 157 NLOHMANN_JSON_ABI_TAGS, \ 158 NLOHMANN_JSON_NAMESPACE_VERSION) 159 #endif 160 161 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN 162 #define NLOHMANN_JSON_NAMESPACE_BEGIN \ 163 namespace nlohmann \ 164 { \ 165 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ 166 NLOHMANN_JSON_ABI_TAGS, \ 167 NLOHMANN_JSON_NAMESPACE_VERSION) \ 168 { 169 #endif 170 171 #ifndef NLOHMANN_JSON_NAMESPACE_END 172 #define NLOHMANN_JSON_NAMESPACE_END \ 173 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ 174 } // namespace nlohmann 175 #endif 176 177 // #include <nlohmann/detail/conversions/from_json.hpp> 178 // __ _____ _____ _____ 179 // __| | __| | | | JSON for Modern C++ 180 // | | |__ | | | | | | version 3.11.3 181 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 182 // 183 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 184 // SPDX-License-Identifier: MIT 185 186 187 188 #include <algorithm> // transform 189 #include <array> // array 190 #include <forward_list> // forward_list 191 #include <iterator> // inserter, front_inserter, end 192 #include <map> // map 193 #include <string> // string 194 #include <tuple> // tuple, make_tuple 195 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible 196 #include <unordered_map> // unordered_map 197 #include <utility> // pair, declval 198 #include <valarray> // valarray 199 200 // #include <nlohmann/detail/exceptions.hpp> 201 // __ _____ _____ _____ 202 // __| | __| | | | JSON for Modern C++ 203 // | | |__ | | | | | | version 3.11.3 204 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 205 // 206 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 207 // SPDX-License-Identifier: MIT 208 209 210 211 #include <cstddef> // nullptr_t 212 #include <exception> // exception 213 #if JSON_DIAGNOSTICS 214 #include <numeric> // accumulate 215 #endif 216 #include <stdexcept> // runtime_error 217 #include <string> // to_string 218 #include <vector> // vector 219 220 // #include <nlohmann/detail/value_t.hpp> 221 // __ _____ _____ _____ 222 // __| | __| | | | JSON for Modern C++ 223 // | | |__ | | | | | | version 3.11.3 224 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 225 // 226 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 227 // SPDX-License-Identifier: MIT 228 229 230 231 #include <array> // array 232 #include <cstddef> // size_t 233 #include <cstdint> // uint8_t 234 #include <string> // string 235 236 // #include <nlohmann/detail/macro_scope.hpp> 237 // __ _____ _____ _____ 238 // __| | __| | | | JSON for Modern C++ 239 // | | |__ | | | | | | version 3.11.3 240 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 241 // 242 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 243 // SPDX-License-Identifier: MIT 244 245 246 247 #include <utility> // declval, pair 248 // #include <nlohmann/detail/meta/detected.hpp> 249 // __ _____ _____ _____ 250 // __| | __| | | | JSON for Modern C++ 251 // | | |__ | | | | | | version 3.11.3 252 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 253 // 254 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 255 // SPDX-License-Identifier: MIT 256 257 258 259 #include <type_traits> 260 261 // #include <nlohmann/detail/meta/void_t.hpp> 262 // __ _____ _____ _____ 263 // __| | __| | | | JSON for Modern C++ 264 // | | |__ | | | | | | version 3.11.3 265 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 266 // 267 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 268 // SPDX-License-Identifier: MIT 269 270 271 272 // #include <nlohmann/detail/abi_macros.hpp> 273 274 275 NLOHMANN_JSON_NAMESPACE_BEGIN 276 namespace detail 277 { 278 279 template<typename ...Ts> struct make_void 280 { 281 using type = void; 282 }; 283 template<typename ...Ts> using void_t = typename make_void<Ts...>::type; 284 285 } // namespace detail 286 NLOHMANN_JSON_NAMESPACE_END 287 288 289 NLOHMANN_JSON_NAMESPACE_BEGIN 290 namespace detail 291 { 292 293 // https://en.cppreference.com/w/cpp/experimental/is_detected 294 struct nonesuch 295 { 296 nonesuch() = delete; 297 ~nonesuch() = delete; 298 nonesuch(nonesuch const&) = delete; 299 nonesuch(nonesuch const&&) = delete; 300 void operator=(nonesuch const&) = delete; 301 void operator=(nonesuch&&) = delete; 302 }; 303 304 template<class Default, 305 class AlwaysVoid, 306 template<class...> class Op, 307 class... Args> 308 struct detector 309 { 310 using value_t = std::false_type; 311 using type = Default; 312 }; 313 314 template<class Default, template<class...> class Op, class... Args> 315 struct detector<Default, void_t<Op<Args...>>, Op, Args...> 316 { 317 using value_t = std::true_type; 318 using type = Op<Args...>; 319 }; 320 321 template<template<class...> class Op, class... Args> 322 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t; 323 324 template<template<class...> class Op, class... Args> 325 struct is_detected_lazy : is_detected<Op, Args...> { }; 326 327 template<template<class...> class Op, class... Args> 328 using detected_t = typename detector<nonesuch, void, Op, Args...>::type; 329 330 template<class Default, template<class...> class Op, class... Args> 331 using detected_or = detector<Default, void, Op, Args...>; 332 333 template<class Default, template<class...> class Op, class... Args> 334 using detected_or_t = typename detected_or<Default, Op, Args...>::type; 335 336 template<class Expected, template<class...> class Op, class... Args> 337 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>; 338 339 template<class To, template<class...> class Op, class... Args> 340 using is_detected_convertible = 341 std::is_convertible<detected_t<Op, Args...>, To>; 342 343 } // namespace detail 344 NLOHMANN_JSON_NAMESPACE_END 345 346 // #include <nlohmann/thirdparty/hedley/hedley.hpp> 347 348 349 // __ _____ _____ _____ 350 // __| | __| | | | JSON for Modern C++ 351 // | | |__ | | | | | | version 3.11.3 352 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 353 // 354 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 355 // SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com> 356 // SPDX-License-Identifier: MIT 357 358 /* Hedley - https://nemequ.github.io/hedley 359 * Created by Evan Nemerson <evan@nemerson.com> 360 */ 361 362 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) 363 #if defined(JSON_HEDLEY_VERSION) 364 #undef JSON_HEDLEY_VERSION 365 #endif 366 #define JSON_HEDLEY_VERSION 15 367 368 #if defined(JSON_HEDLEY_STRINGIFY_EX) 369 #undef JSON_HEDLEY_STRINGIFY_EX 370 #endif 371 #define JSON_HEDLEY_STRINGIFY_EX(x) #x 372 373 #if defined(JSON_HEDLEY_STRINGIFY) 374 #undef JSON_HEDLEY_STRINGIFY 375 #endif 376 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) 377 378 #if defined(JSON_HEDLEY_CONCAT_EX) 379 #undef JSON_HEDLEY_CONCAT_EX 380 #endif 381 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b 382 383 #if defined(JSON_HEDLEY_CONCAT) 384 #undef JSON_HEDLEY_CONCAT 385 #endif 386 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) 387 388 #if defined(JSON_HEDLEY_CONCAT3_EX) 389 #undef JSON_HEDLEY_CONCAT3_EX 390 #endif 391 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c 392 393 #if defined(JSON_HEDLEY_CONCAT3) 394 #undef JSON_HEDLEY_CONCAT3 395 #endif 396 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) 397 398 #if defined(JSON_HEDLEY_VERSION_ENCODE) 399 #undef JSON_HEDLEY_VERSION_ENCODE 400 #endif 401 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) 402 403 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) 404 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR 405 #endif 406 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) 407 408 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) 409 #undef JSON_HEDLEY_VERSION_DECODE_MINOR 410 #endif 411 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) 412 413 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) 414 #undef JSON_HEDLEY_VERSION_DECODE_REVISION 415 #endif 416 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) 417 418 #if defined(JSON_HEDLEY_GNUC_VERSION) 419 #undef JSON_HEDLEY_GNUC_VERSION 420 #endif 421 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) 422 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) 423 #elif defined(__GNUC__) 424 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) 425 #endif 426 427 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) 428 #undef JSON_HEDLEY_GNUC_VERSION_CHECK 429 #endif 430 #if defined(JSON_HEDLEY_GNUC_VERSION) 431 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 432 #else 433 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) 434 #endif 435 436 #if defined(JSON_HEDLEY_MSVC_VERSION) 437 #undef JSON_HEDLEY_MSVC_VERSION 438 #endif 439 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) 440 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) 441 #elif defined(_MSC_FULL_VER) && !defined(__ICL) 442 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) 443 #elif defined(_MSC_VER) && !defined(__ICL) 444 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) 445 #endif 446 447 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) 448 #undef JSON_HEDLEY_MSVC_VERSION_CHECK 449 #endif 450 #if !defined(JSON_HEDLEY_MSVC_VERSION) 451 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) 452 #elif defined(_MSC_VER) && (_MSC_VER >= 1400) 453 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) 454 #elif defined(_MSC_VER) && (_MSC_VER >= 1200) 455 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) 456 #else 457 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) 458 #endif 459 460 #if defined(JSON_HEDLEY_INTEL_VERSION) 461 #undef JSON_HEDLEY_INTEL_VERSION 462 #endif 463 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) 464 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) 465 #elif defined(__INTEL_COMPILER) && !defined(__ICL) 466 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) 467 #endif 468 469 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) 470 #undef JSON_HEDLEY_INTEL_VERSION_CHECK 471 #endif 472 #if defined(JSON_HEDLEY_INTEL_VERSION) 473 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 474 #else 475 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) 476 #endif 477 478 #if defined(JSON_HEDLEY_INTEL_CL_VERSION) 479 #undef JSON_HEDLEY_INTEL_CL_VERSION 480 #endif 481 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) 482 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) 483 #endif 484 485 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) 486 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK 487 #endif 488 #if defined(JSON_HEDLEY_INTEL_CL_VERSION) 489 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 490 #else 491 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) 492 #endif 493 494 #if defined(JSON_HEDLEY_PGI_VERSION) 495 #undef JSON_HEDLEY_PGI_VERSION 496 #endif 497 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) 498 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) 499 #endif 500 501 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK) 502 #undef JSON_HEDLEY_PGI_VERSION_CHECK 503 #endif 504 #if defined(JSON_HEDLEY_PGI_VERSION) 505 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 506 #else 507 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) 508 #endif 509 510 #if defined(JSON_HEDLEY_SUNPRO_VERSION) 511 #undef JSON_HEDLEY_SUNPRO_VERSION 512 #endif 513 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) 514 #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) 515 #elif defined(__SUNPRO_C) 516 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) 517 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) 518 #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) 519 #elif defined(__SUNPRO_CC) 520 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) 521 #endif 522 523 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) 524 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK 525 #endif 526 #if defined(JSON_HEDLEY_SUNPRO_VERSION) 527 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 528 #else 529 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) 530 #endif 531 532 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) 533 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION 534 #endif 535 #if defined(__EMSCRIPTEN__) 536 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) 537 #endif 538 539 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) 540 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK 541 #endif 542 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) 543 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 544 #else 545 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) 546 #endif 547 548 #if defined(JSON_HEDLEY_ARM_VERSION) 549 #undef JSON_HEDLEY_ARM_VERSION 550 #endif 551 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) 552 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) 553 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION) 554 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) 555 #endif 556 557 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK) 558 #undef JSON_HEDLEY_ARM_VERSION_CHECK 559 #endif 560 #if defined(JSON_HEDLEY_ARM_VERSION) 561 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 562 #else 563 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) 564 #endif 565 566 #if defined(JSON_HEDLEY_IBM_VERSION) 567 #undef JSON_HEDLEY_IBM_VERSION 568 #endif 569 #if defined(__ibmxl__) 570 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) 571 #elif defined(__xlC__) && defined(__xlC_ver__) 572 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) 573 #elif defined(__xlC__) 574 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) 575 #endif 576 577 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK) 578 #undef JSON_HEDLEY_IBM_VERSION_CHECK 579 #endif 580 #if defined(JSON_HEDLEY_IBM_VERSION) 581 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 582 #else 583 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) 584 #endif 585 586 #if defined(JSON_HEDLEY_TI_VERSION) 587 #undef JSON_HEDLEY_TI_VERSION 588 #endif 589 #if \ 590 defined(__TI_COMPILER_VERSION__) && \ 591 ( \ 592 defined(__TMS470__) || defined(__TI_ARM__) || \ 593 defined(__MSP430__) || \ 594 defined(__TMS320C2000__) \ 595 ) 596 #if (__TI_COMPILER_VERSION__ >= 16000000) 597 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 598 #endif 599 #endif 600 601 #if defined(JSON_HEDLEY_TI_VERSION_CHECK) 602 #undef JSON_HEDLEY_TI_VERSION_CHECK 603 #endif 604 #if defined(JSON_HEDLEY_TI_VERSION) 605 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 606 #else 607 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) 608 #endif 609 610 #if defined(JSON_HEDLEY_TI_CL2000_VERSION) 611 #undef JSON_HEDLEY_TI_CL2000_VERSION 612 #endif 613 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) 614 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 615 #endif 616 617 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) 618 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK 619 #endif 620 #if defined(JSON_HEDLEY_TI_CL2000_VERSION) 621 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 622 #else 623 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) 624 #endif 625 626 #if defined(JSON_HEDLEY_TI_CL430_VERSION) 627 #undef JSON_HEDLEY_TI_CL430_VERSION 628 #endif 629 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) 630 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 631 #endif 632 633 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) 634 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK 635 #endif 636 #if defined(JSON_HEDLEY_TI_CL430_VERSION) 637 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 638 #else 639 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) 640 #endif 641 642 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) 643 #undef JSON_HEDLEY_TI_ARMCL_VERSION 644 #endif 645 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) 646 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 647 #endif 648 649 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) 650 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK 651 #endif 652 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION) 653 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 654 #else 655 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) 656 #endif 657 658 #if defined(JSON_HEDLEY_TI_CL6X_VERSION) 659 #undef JSON_HEDLEY_TI_CL6X_VERSION 660 #endif 661 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) 662 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 663 #endif 664 665 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) 666 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK 667 #endif 668 #if defined(JSON_HEDLEY_TI_CL6X_VERSION) 669 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 670 #else 671 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) 672 #endif 673 674 #if defined(JSON_HEDLEY_TI_CL7X_VERSION) 675 #undef JSON_HEDLEY_TI_CL7X_VERSION 676 #endif 677 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) 678 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 679 #endif 680 681 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) 682 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK 683 #endif 684 #if defined(JSON_HEDLEY_TI_CL7X_VERSION) 685 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 686 #else 687 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) 688 #endif 689 690 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) 691 #undef JSON_HEDLEY_TI_CLPRU_VERSION 692 #endif 693 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) 694 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) 695 #endif 696 697 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) 698 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK 699 #endif 700 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION) 701 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 702 #else 703 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) 704 #endif 705 706 #if defined(JSON_HEDLEY_CRAY_VERSION) 707 #undef JSON_HEDLEY_CRAY_VERSION 708 #endif 709 #if defined(_CRAYC) 710 #if defined(_RELEASE_PATCHLEVEL) 711 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) 712 #else 713 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) 714 #endif 715 #endif 716 717 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) 718 #undef JSON_HEDLEY_CRAY_VERSION_CHECK 719 #endif 720 #if defined(JSON_HEDLEY_CRAY_VERSION) 721 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 722 #else 723 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) 724 #endif 725 726 #if defined(JSON_HEDLEY_IAR_VERSION) 727 #undef JSON_HEDLEY_IAR_VERSION 728 #endif 729 #if defined(__IAR_SYSTEMS_ICC__) 730 #if __VER__ > 1000 731 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) 732 #else 733 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) 734 #endif 735 #endif 736 737 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK) 738 #undef JSON_HEDLEY_IAR_VERSION_CHECK 739 #endif 740 #if defined(JSON_HEDLEY_IAR_VERSION) 741 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 742 #else 743 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) 744 #endif 745 746 #if defined(JSON_HEDLEY_TINYC_VERSION) 747 #undef JSON_HEDLEY_TINYC_VERSION 748 #endif 749 #if defined(__TINYC__) 750 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) 751 #endif 752 753 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) 754 #undef JSON_HEDLEY_TINYC_VERSION_CHECK 755 #endif 756 #if defined(JSON_HEDLEY_TINYC_VERSION) 757 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 758 #else 759 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) 760 #endif 761 762 #if defined(JSON_HEDLEY_DMC_VERSION) 763 #undef JSON_HEDLEY_DMC_VERSION 764 #endif 765 #if defined(__DMC__) 766 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) 767 #endif 768 769 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK) 770 #undef JSON_HEDLEY_DMC_VERSION_CHECK 771 #endif 772 #if defined(JSON_HEDLEY_DMC_VERSION) 773 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 774 #else 775 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) 776 #endif 777 778 #if defined(JSON_HEDLEY_COMPCERT_VERSION) 779 #undef JSON_HEDLEY_COMPCERT_VERSION 780 #endif 781 #if defined(__COMPCERT_VERSION__) 782 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) 783 #endif 784 785 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) 786 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK 787 #endif 788 #if defined(JSON_HEDLEY_COMPCERT_VERSION) 789 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 790 #else 791 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) 792 #endif 793 794 #if defined(JSON_HEDLEY_PELLES_VERSION) 795 #undef JSON_HEDLEY_PELLES_VERSION 796 #endif 797 #if defined(__POCC__) 798 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) 799 #endif 800 801 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) 802 #undef JSON_HEDLEY_PELLES_VERSION_CHECK 803 #endif 804 #if defined(JSON_HEDLEY_PELLES_VERSION) 805 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 806 #else 807 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) 808 #endif 809 810 #if defined(JSON_HEDLEY_MCST_LCC_VERSION) 811 #undef JSON_HEDLEY_MCST_LCC_VERSION 812 #endif 813 #if defined(__LCC__) && defined(__LCC_MINOR__) 814 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) 815 #endif 816 817 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) 818 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK 819 #endif 820 #if defined(JSON_HEDLEY_MCST_LCC_VERSION) 821 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 822 #else 823 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) 824 #endif 825 826 #if defined(JSON_HEDLEY_GCC_VERSION) 827 #undef JSON_HEDLEY_GCC_VERSION 828 #endif 829 #if \ 830 defined(JSON_HEDLEY_GNUC_VERSION) && \ 831 !defined(__clang__) && \ 832 !defined(JSON_HEDLEY_INTEL_VERSION) && \ 833 !defined(JSON_HEDLEY_PGI_VERSION) && \ 834 !defined(JSON_HEDLEY_ARM_VERSION) && \ 835 !defined(JSON_HEDLEY_CRAY_VERSION) && \ 836 !defined(JSON_HEDLEY_TI_VERSION) && \ 837 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ 838 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ 839 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ 840 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ 841 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ 842 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ 843 !defined(__COMPCERT__) && \ 844 !defined(JSON_HEDLEY_MCST_LCC_VERSION) 845 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION 846 #endif 847 848 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK) 849 #undef JSON_HEDLEY_GCC_VERSION_CHECK 850 #endif 851 #if defined(JSON_HEDLEY_GCC_VERSION) 852 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) 853 #else 854 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) 855 #endif 856 857 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE) 858 #undef JSON_HEDLEY_HAS_ATTRIBUTE 859 #endif 860 #if \ 861 defined(__has_attribute) && \ 862 ( \ 863 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ 864 ) 865 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) 866 #else 867 # define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) 868 #endif 869 870 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) 871 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE 872 #endif 873 #if defined(__has_attribute) 874 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 875 #else 876 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 877 #endif 878 879 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) 880 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE 881 #endif 882 #if defined(__has_attribute) 883 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 884 #else 885 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 886 #endif 887 888 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) 889 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE 890 #endif 891 #if \ 892 defined(__has_cpp_attribute) && \ 893 defined(__cplusplus) && \ 894 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) 895 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) 896 #else 897 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) 898 #endif 899 900 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) 901 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS 902 #endif 903 #if !defined(__cplusplus) || !defined(__has_cpp_attribute) 904 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) 905 #elif \ 906 !defined(JSON_HEDLEY_PGI_VERSION) && \ 907 !defined(JSON_HEDLEY_IAR_VERSION) && \ 908 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ 909 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) 910 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) 911 #else 912 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) 913 #endif 914 915 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) 916 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE 917 #endif 918 #if defined(__has_cpp_attribute) && defined(__cplusplus) 919 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) 920 #else 921 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 922 #endif 923 924 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) 925 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE 926 #endif 927 #if defined(__has_cpp_attribute) && defined(__cplusplus) 928 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) 929 #else 930 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 931 #endif 932 933 #if defined(JSON_HEDLEY_HAS_BUILTIN) 934 #undef JSON_HEDLEY_HAS_BUILTIN 935 #endif 936 #if defined(__has_builtin) 937 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) 938 #else 939 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) 940 #endif 941 942 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) 943 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN 944 #endif 945 #if defined(__has_builtin) 946 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) 947 #else 948 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 949 #endif 950 951 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) 952 #undef JSON_HEDLEY_GCC_HAS_BUILTIN 953 #endif 954 #if defined(__has_builtin) 955 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) 956 #else 957 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 958 #endif 959 960 #if defined(JSON_HEDLEY_HAS_FEATURE) 961 #undef JSON_HEDLEY_HAS_FEATURE 962 #endif 963 #if defined(__has_feature) 964 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) 965 #else 966 #define JSON_HEDLEY_HAS_FEATURE(feature) (0) 967 #endif 968 969 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) 970 #undef JSON_HEDLEY_GNUC_HAS_FEATURE 971 #endif 972 #if defined(__has_feature) 973 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) 974 #else 975 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 976 #endif 977 978 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE) 979 #undef JSON_HEDLEY_GCC_HAS_FEATURE 980 #endif 981 #if defined(__has_feature) 982 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) 983 #else 984 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 985 #endif 986 987 #if defined(JSON_HEDLEY_HAS_EXTENSION) 988 #undef JSON_HEDLEY_HAS_EXTENSION 989 #endif 990 #if defined(__has_extension) 991 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) 992 #else 993 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) 994 #endif 995 996 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) 997 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION 998 #endif 999 #if defined(__has_extension) 1000 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) 1001 #else 1002 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 1003 #endif 1004 1005 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) 1006 #undef JSON_HEDLEY_GCC_HAS_EXTENSION 1007 #endif 1008 #if defined(__has_extension) 1009 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) 1010 #else 1011 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 1012 #endif 1013 1014 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) 1015 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE 1016 #endif 1017 #if defined(__has_declspec_attribute) 1018 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) 1019 #else 1020 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) 1021 #endif 1022 1023 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) 1024 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE 1025 #endif 1026 #if defined(__has_declspec_attribute) 1027 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) 1028 #else 1029 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 1030 #endif 1031 1032 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) 1033 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE 1034 #endif 1035 #if defined(__has_declspec_attribute) 1036 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) 1037 #else 1038 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 1039 #endif 1040 1041 #if defined(JSON_HEDLEY_HAS_WARNING) 1042 #undef JSON_HEDLEY_HAS_WARNING 1043 #endif 1044 #if defined(__has_warning) 1045 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) 1046 #else 1047 #define JSON_HEDLEY_HAS_WARNING(warning) (0) 1048 #endif 1049 1050 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING) 1051 #undef JSON_HEDLEY_GNUC_HAS_WARNING 1052 #endif 1053 #if defined(__has_warning) 1054 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) 1055 #else 1056 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) 1057 #endif 1058 1059 #if defined(JSON_HEDLEY_GCC_HAS_WARNING) 1060 #undef JSON_HEDLEY_GCC_HAS_WARNING 1061 #endif 1062 #if defined(__has_warning) 1063 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) 1064 #else 1065 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 1066 #endif 1067 1068 #if \ 1069 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ 1070 defined(__clang__) || \ 1071 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ 1072 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1073 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ 1074 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ 1075 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1076 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1077 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ 1078 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ 1079 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ 1080 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ 1081 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1082 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1083 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ 1084 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ 1085 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ 1086 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) 1087 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) 1088 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) 1089 #define JSON_HEDLEY_PRAGMA(value) __pragma(value) 1090 #else 1091 #define JSON_HEDLEY_PRAGMA(value) 1092 #endif 1093 1094 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) 1095 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH 1096 #endif 1097 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP) 1098 #undef JSON_HEDLEY_DIAGNOSTIC_POP 1099 #endif 1100 #if defined(__clang__) 1101 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") 1102 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") 1103 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1104 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") 1105 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") 1106 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) 1107 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") 1108 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") 1109 #elif \ 1110 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ 1111 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1112 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) 1113 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) 1114 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) 1115 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") 1116 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") 1117 #elif \ 1118 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1119 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1120 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ 1121 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ 1122 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1123 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) 1124 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") 1125 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") 1126 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) 1127 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") 1128 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") 1129 #else 1130 #define JSON_HEDLEY_DIAGNOSTIC_PUSH 1131 #define JSON_HEDLEY_DIAGNOSTIC_POP 1132 #endif 1133 1134 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for 1135 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ 1136 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) 1137 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ 1138 #endif 1139 #if defined(__cplusplus) 1140 # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") 1141 # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") 1142 # if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") 1143 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 1144 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1145 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1146 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 1147 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ 1148 xpr \ 1149 JSON_HEDLEY_DIAGNOSTIC_POP 1150 # else 1151 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 1152 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1153 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1154 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ 1155 xpr \ 1156 JSON_HEDLEY_DIAGNOSTIC_POP 1157 # endif 1158 # else 1159 # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ 1160 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1161 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ 1162 xpr \ 1163 JSON_HEDLEY_DIAGNOSTIC_POP 1164 # endif 1165 # endif 1166 #endif 1167 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) 1168 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x 1169 #endif 1170 1171 #if defined(JSON_HEDLEY_CONST_CAST) 1172 #undef JSON_HEDLEY_CONST_CAST 1173 #endif 1174 #if defined(__cplusplus) 1175 # define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr)) 1176 #elif \ 1177 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ 1178 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ 1179 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1180 # define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ 1181 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1182 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ 1183 ((T) (expr)); \ 1184 JSON_HEDLEY_DIAGNOSTIC_POP \ 1185 })) 1186 #else 1187 # define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) 1188 #endif 1189 1190 #if defined(JSON_HEDLEY_REINTERPRET_CAST) 1191 #undef JSON_HEDLEY_REINTERPRET_CAST 1192 #endif 1193 #if defined(__cplusplus) 1194 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr)) 1195 #else 1196 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) 1197 #endif 1198 1199 #if defined(JSON_HEDLEY_STATIC_CAST) 1200 #undef JSON_HEDLEY_STATIC_CAST 1201 #endif 1202 #if defined(__cplusplus) 1203 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr)) 1204 #else 1205 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) 1206 #endif 1207 1208 #if defined(JSON_HEDLEY_CPP_CAST) 1209 #undef JSON_HEDLEY_CPP_CAST 1210 #endif 1211 #if defined(__cplusplus) 1212 # if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") 1213 # define JSON_HEDLEY_CPP_CAST(T, expr) \ 1214 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1215 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ 1216 ((T) (expr)) \ 1217 JSON_HEDLEY_DIAGNOSTIC_POP 1218 # elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) 1219 # define JSON_HEDLEY_CPP_CAST(T, expr) \ 1220 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 1221 _Pragma("diag_suppress=Pe137") \ 1222 JSON_HEDLEY_DIAGNOSTIC_POP 1223 # else 1224 # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) 1225 # endif 1226 #else 1227 # define JSON_HEDLEY_CPP_CAST(T, expr) (expr) 1228 #endif 1229 1230 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) 1231 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 1232 #endif 1233 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") 1234 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") 1235 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1236 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") 1237 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1238 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) 1239 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) 1240 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") 1241 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) 1242 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") 1243 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) 1244 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") 1245 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) 1246 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) 1247 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1248 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") 1249 #elif \ 1250 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1251 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1252 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1253 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1254 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1255 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1256 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1257 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1258 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1259 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1260 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) 1261 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") 1262 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) 1263 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") 1264 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) 1265 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") 1266 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1267 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") 1268 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) 1269 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") 1270 #else 1271 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 1272 #endif 1273 1274 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) 1275 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 1276 #endif 1277 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") 1278 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") 1279 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1280 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") 1281 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1282 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) 1283 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) 1284 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") 1285 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) 1286 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") 1287 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) 1288 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) 1289 #elif \ 1290 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ 1291 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ 1292 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1293 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) 1294 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") 1295 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) 1296 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") 1297 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1298 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") 1299 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") 1301 #else 1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 1303 #endif 1304 1305 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) 1306 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 1307 #endif 1308 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") 1309 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") 1310 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) 1311 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") 1312 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) 1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") 1314 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) 1316 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) 1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) 1318 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) 1319 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") 1320 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) 1321 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") 1322 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) 1323 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") 1324 #elif \ 1325 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ 1326 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ 1327 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) 1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") 1329 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") 1331 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1332 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") 1333 #else 1334 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 1335 #endif 1336 1337 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) 1338 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 1339 #endif 1340 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") 1341 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") 1342 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 1343 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") 1344 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) 1345 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") 1346 #else 1347 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 1348 #endif 1349 1350 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) 1351 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 1352 #endif 1353 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function") 1354 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") 1355 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) 1356 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") 1357 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) 1358 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) 1359 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1360 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") 1361 #else 1362 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 1363 #endif 1364 1365 #if defined(JSON_HEDLEY_DEPRECATED) 1366 #undef JSON_HEDLEY_DEPRECATED 1367 #endif 1368 #if defined(JSON_HEDLEY_DEPRECATED_FOR) 1369 #undef JSON_HEDLEY_DEPRECATED_FOR 1370 #endif 1371 #if \ 1372 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 1373 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1374 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) 1375 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) 1376 #elif \ 1377 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ 1378 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ 1379 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1380 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ 1381 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ 1382 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1383 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ 1384 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ 1385 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ 1386 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1387 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ 1388 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1389 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) 1390 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) 1391 #elif defined(__cplusplus) && (__cplusplus >= 201402L) 1392 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) 1393 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) 1394 #elif \ 1395 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ 1396 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1397 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1398 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1399 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1400 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1401 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1402 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1403 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1404 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1405 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1406 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1407 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1408 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1409 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 1410 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1411 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) 1412 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) 1413 #elif \ 1414 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1415 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ 1416 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1417 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) 1418 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) 1419 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1420 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") 1421 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") 1422 #else 1423 #define JSON_HEDLEY_DEPRECATED(since) 1424 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) 1425 #endif 1426 1427 #if defined(JSON_HEDLEY_UNAVAILABLE) 1428 #undef JSON_HEDLEY_UNAVAILABLE 1429 #endif 1430 #if \ 1431 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ 1432 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ 1433 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1434 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1435 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) 1436 #else 1437 #define JSON_HEDLEY_UNAVAILABLE(available_since) 1438 #endif 1439 1440 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) 1441 #undef JSON_HEDLEY_WARN_UNUSED_RESULT 1442 #endif 1443 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) 1444 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG 1445 #endif 1446 #if \ 1447 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ 1448 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 1449 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1450 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1451 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1452 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1453 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1454 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1455 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1456 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1457 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1458 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1459 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1460 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1461 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ 1462 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1463 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1464 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) 1465 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) 1466 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) 1467 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1468 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) 1469 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) 1470 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1471 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) 1472 #elif defined(_Check_return_) /* SAL */ 1473 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ 1474 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ 1475 #else 1476 #define JSON_HEDLEY_WARN_UNUSED_RESULT 1477 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) 1478 #endif 1479 1480 #if defined(JSON_HEDLEY_SENTINEL) 1481 #undef JSON_HEDLEY_SENTINEL 1482 #endif 1483 #if \ 1484 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ 1485 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 1486 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1487 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ 1488 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1489 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) 1490 #else 1491 #define JSON_HEDLEY_SENTINEL(position) 1492 #endif 1493 1494 #if defined(JSON_HEDLEY_NO_RETURN) 1495 #undef JSON_HEDLEY_NO_RETURN 1496 #endif 1497 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1498 #define JSON_HEDLEY_NO_RETURN __noreturn 1499 #elif \ 1500 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1501 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1502 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) 1503 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L 1504 #define JSON_HEDLEY_NO_RETURN _Noreturn 1505 #elif defined(__cplusplus) && (__cplusplus >= 201103L) 1506 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) 1507 #elif \ 1508 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ 1509 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ 1510 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1511 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1512 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1513 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1514 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1515 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1516 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1517 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1518 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1519 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1520 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1521 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1522 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1523 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1524 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1525 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) 1526 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1527 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") 1528 #elif \ 1529 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1530 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1531 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) 1532 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) 1533 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") 1534 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) 1535 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) 1536 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) 1537 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) 1538 #else 1539 #define JSON_HEDLEY_NO_RETURN 1540 #endif 1541 1542 #if defined(JSON_HEDLEY_NO_ESCAPE) 1543 #undef JSON_HEDLEY_NO_ESCAPE 1544 #endif 1545 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) 1546 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) 1547 #else 1548 #define JSON_HEDLEY_NO_ESCAPE 1549 #endif 1550 1551 #if defined(JSON_HEDLEY_UNREACHABLE) 1552 #undef JSON_HEDLEY_UNREACHABLE 1553 #endif 1554 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN) 1555 #undef JSON_HEDLEY_UNREACHABLE_RETURN 1556 #endif 1557 #if defined(JSON_HEDLEY_ASSUME) 1558 #undef JSON_HEDLEY_ASSUME 1559 #endif 1560 #if \ 1561 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1562 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1563 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1564 #define JSON_HEDLEY_ASSUME(expr) __assume(expr) 1565 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) 1566 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) 1567 #elif \ 1568 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 1569 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) 1570 #if defined(__cplusplus) 1571 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) 1572 #else 1573 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) 1574 #endif 1575 #endif 1576 #if \ 1577 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ 1578 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ 1579 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ 1580 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1581 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ 1582 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ 1583 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1584 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() 1585 #elif defined(JSON_HEDLEY_ASSUME) 1586 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) 1587 #endif 1588 #if !defined(JSON_HEDLEY_ASSUME) 1589 #if defined(JSON_HEDLEY_UNREACHABLE) 1590 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) 1591 #else 1592 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) 1593 #endif 1594 #endif 1595 #if defined(JSON_HEDLEY_UNREACHABLE) 1596 #if \ 1597 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 1598 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) 1599 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) 1600 #else 1601 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() 1602 #endif 1603 #else 1604 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) 1605 #endif 1606 #if !defined(JSON_HEDLEY_UNREACHABLE) 1607 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) 1608 #endif 1609 1610 JSON_HEDLEY_DIAGNOSTIC_PUSH 1611 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic") 1612 #pragma clang diagnostic ignored "-Wpedantic" 1613 #endif 1614 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) 1615 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 1616 #endif 1617 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) 1618 #if defined(__clang__) 1619 #pragma clang diagnostic ignored "-Wvariadic-macros" 1620 #elif defined(JSON_HEDLEY_GCC_VERSION) 1621 #pragma GCC diagnostic ignored "-Wvariadic-macros" 1622 #endif 1623 #endif 1624 #if defined(JSON_HEDLEY_NON_NULL) 1625 #undef JSON_HEDLEY_NON_NULL 1626 #endif 1627 #if \ 1628 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ 1629 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 1630 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1631 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) 1632 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) 1633 #else 1634 #define JSON_HEDLEY_NON_NULL(...) 1635 #endif 1636 JSON_HEDLEY_DIAGNOSTIC_POP 1637 1638 #if defined(JSON_HEDLEY_PRINTF_FORMAT) 1639 #undef JSON_HEDLEY_PRINTF_FORMAT 1640 #endif 1641 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) 1642 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) 1643 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) 1644 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) 1645 #elif \ 1646 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ 1647 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1648 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1649 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ 1650 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1651 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1652 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1653 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1654 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1655 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1656 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1657 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1658 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1659 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1660 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1661 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1662 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1663 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) 1664 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) 1665 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) 1666 #else 1667 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) 1668 #endif 1669 1670 #if defined(JSON_HEDLEY_CONSTEXPR) 1671 #undef JSON_HEDLEY_CONSTEXPR 1672 #endif 1673 #if defined(__cplusplus) 1674 #if __cplusplus >= 201103L 1675 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) 1676 #endif 1677 #endif 1678 #if !defined(JSON_HEDLEY_CONSTEXPR) 1679 #define JSON_HEDLEY_CONSTEXPR 1680 #endif 1681 1682 #if defined(JSON_HEDLEY_PREDICT) 1683 #undef JSON_HEDLEY_PREDICT 1684 #endif 1685 #if defined(JSON_HEDLEY_LIKELY) 1686 #undef JSON_HEDLEY_LIKELY 1687 #endif 1688 #if defined(JSON_HEDLEY_UNLIKELY) 1689 #undef JSON_HEDLEY_UNLIKELY 1690 #endif 1691 #if defined(JSON_HEDLEY_UNPREDICTABLE) 1692 #undef JSON_HEDLEY_UNPREDICTABLE 1693 #endif 1694 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) 1695 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) 1696 #endif 1697 #if \ 1698 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ 1699 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ 1700 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1701 # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) 1702 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) 1703 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) 1704 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) 1705 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) 1706 #elif \ 1707 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ 1708 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ 1709 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1710 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ 1711 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1712 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1713 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1714 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ 1715 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ 1716 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ 1717 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 1718 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1719 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1720 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ 1721 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 1722 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1723 # define JSON_HEDLEY_PREDICT(expr, expected, probability) \ 1724 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) 1725 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ 1726 (__extension__ ({ \ 1727 double hedley_probability_ = (probability); \ 1728 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ 1729 })) 1730 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ 1731 (__extension__ ({ \ 1732 double hedley_probability_ = (probability); \ 1733 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ 1734 })) 1735 # define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) 1736 # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) 1737 #else 1738 # define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) 1739 # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) 1740 # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) 1741 # define JSON_HEDLEY_LIKELY(expr) (!!(expr)) 1742 # define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) 1743 #endif 1744 #if !defined(JSON_HEDLEY_UNPREDICTABLE) 1745 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) 1746 #endif 1747 1748 #if defined(JSON_HEDLEY_MALLOC) 1749 #undef JSON_HEDLEY_MALLOC 1750 #endif 1751 #if \ 1752 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ 1753 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1754 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1755 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1756 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1757 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ 1758 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1759 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1760 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1761 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1762 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1763 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1764 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1765 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1766 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1767 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1768 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1769 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1770 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) 1771 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1772 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") 1773 #elif \ 1774 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 1775 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1776 #define JSON_HEDLEY_MALLOC __declspec(restrict) 1777 #else 1778 #define JSON_HEDLEY_MALLOC 1779 #endif 1780 1781 #if defined(JSON_HEDLEY_PURE) 1782 #undef JSON_HEDLEY_PURE 1783 #endif 1784 #if \ 1785 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ 1786 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ 1787 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1788 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1789 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1790 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1791 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1792 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1793 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1794 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1795 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1796 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1797 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1798 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1799 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1800 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1801 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1802 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1803 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1804 # define JSON_HEDLEY_PURE __attribute__((__pure__)) 1805 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1806 # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") 1807 #elif defined(__cplusplus) && \ 1808 ( \ 1809 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ 1810 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ 1811 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ 1812 ) 1813 # define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") 1814 #else 1815 # define JSON_HEDLEY_PURE 1816 #endif 1817 1818 #if defined(JSON_HEDLEY_CONST) 1819 #undef JSON_HEDLEY_CONST 1820 #endif 1821 #if \ 1822 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ 1823 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ 1824 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1825 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1826 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1827 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1828 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1829 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1830 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1831 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1832 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1833 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1834 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1835 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1836 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1837 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1838 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1839 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1840 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1841 #define JSON_HEDLEY_CONST __attribute__((__const__)) 1842 #elif \ 1843 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) 1844 #define JSON_HEDLEY_CONST _Pragma("no_side_effect") 1845 #else 1846 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE 1847 #endif 1848 1849 #if defined(JSON_HEDLEY_RESTRICT) 1850 #undef JSON_HEDLEY_RESTRICT 1851 #endif 1852 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) 1853 #define JSON_HEDLEY_RESTRICT restrict 1854 #elif \ 1855 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ 1856 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ 1857 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1858 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 1859 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1860 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1861 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ 1862 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1863 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ 1864 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ 1865 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1866 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ 1867 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ 1868 defined(__clang__) || \ 1869 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1870 #define JSON_HEDLEY_RESTRICT __restrict 1871 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) 1872 #define JSON_HEDLEY_RESTRICT _Restrict 1873 #else 1874 #define JSON_HEDLEY_RESTRICT 1875 #endif 1876 1877 #if defined(JSON_HEDLEY_INLINE) 1878 #undef JSON_HEDLEY_INLINE 1879 #endif 1880 #if \ 1881 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ 1882 (defined(__cplusplus) && (__cplusplus >= 199711L)) 1883 #define JSON_HEDLEY_INLINE inline 1884 #elif \ 1885 defined(JSON_HEDLEY_GCC_VERSION) || \ 1886 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) 1887 #define JSON_HEDLEY_INLINE __inline__ 1888 #elif \ 1889 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ 1890 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 1891 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1892 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ 1893 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ 1894 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ 1895 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ 1896 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1897 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1898 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 1899 #define JSON_HEDLEY_INLINE __inline 1900 #else 1901 #define JSON_HEDLEY_INLINE 1902 #endif 1903 1904 #if defined(JSON_HEDLEY_ALWAYS_INLINE) 1905 #undef JSON_HEDLEY_ALWAYS_INLINE 1906 #endif 1907 #if \ 1908 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ 1909 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 1910 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1911 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1912 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1913 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1914 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1915 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1916 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1917 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1918 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1919 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1920 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1921 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1922 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1923 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1924 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1925 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 1926 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1927 # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE 1928 #elif \ 1929 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ 1930 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1931 # define JSON_HEDLEY_ALWAYS_INLINE __forceinline 1932 #elif defined(__cplusplus) && \ 1933 ( \ 1934 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1935 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1936 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1937 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 1938 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1939 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ 1940 ) 1941 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") 1942 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1943 # define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") 1944 #else 1945 # define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE 1946 #endif 1947 1948 #if defined(JSON_HEDLEY_NEVER_INLINE) 1949 #undef JSON_HEDLEY_NEVER_INLINE 1950 #endif 1951 #if \ 1952 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ 1953 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ 1954 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 1955 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 1956 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 1957 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ 1958 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ 1959 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1960 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ 1961 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1962 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ 1963 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1964 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ 1965 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 1966 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ 1967 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ 1968 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ 1969 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ 1970 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) 1971 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) 1972 #elif \ 1973 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ 1974 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 1975 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) 1976 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) 1977 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") 1978 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) 1979 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") 1980 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 1981 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") 1982 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) 1983 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) 1984 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) 1985 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) 1986 #else 1987 #define JSON_HEDLEY_NEVER_INLINE 1988 #endif 1989 1990 #if defined(JSON_HEDLEY_PRIVATE) 1991 #undef JSON_HEDLEY_PRIVATE 1992 #endif 1993 #if defined(JSON_HEDLEY_PUBLIC) 1994 #undef JSON_HEDLEY_PUBLIC 1995 #endif 1996 #if defined(JSON_HEDLEY_IMPORT) 1997 #undef JSON_HEDLEY_IMPORT 1998 #endif 1999 #if defined(_WIN32) || defined(__CYGWIN__) 2000 # define JSON_HEDLEY_PRIVATE 2001 # define JSON_HEDLEY_PUBLIC __declspec(dllexport) 2002 # define JSON_HEDLEY_IMPORT __declspec(dllimport) 2003 #else 2004 # if \ 2005 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ 2006 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 2007 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ 2008 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2009 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 2010 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 2011 ( \ 2012 defined(__TI_EABI__) && \ 2013 ( \ 2014 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ 2015 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ 2016 ) \ 2017 ) || \ 2018 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2019 # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) 2020 # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) 2021 # else 2022 # define JSON_HEDLEY_PRIVATE 2023 # define JSON_HEDLEY_PUBLIC 2024 # endif 2025 # define JSON_HEDLEY_IMPORT extern 2026 #endif 2027 2028 #if defined(JSON_HEDLEY_NO_THROW) 2029 #undef JSON_HEDLEY_NO_THROW 2030 #endif 2031 #if \ 2032 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ 2033 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ 2034 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2035 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2036 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) 2037 #elif \ 2038 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ 2039 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ 2040 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) 2041 #define JSON_HEDLEY_NO_THROW __declspec(nothrow) 2042 #else 2043 #define JSON_HEDLEY_NO_THROW 2044 #endif 2045 2046 #if defined(JSON_HEDLEY_FALL_THROUGH) 2047 #undef JSON_HEDLEY_FALL_THROUGH 2048 #endif 2049 #if \ 2050 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ 2051 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ 2052 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2053 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) 2054 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) 2055 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) 2056 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) 2057 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) 2058 #elif defined(__fallthrough) /* SAL */ 2059 #define JSON_HEDLEY_FALL_THROUGH __fallthrough 2060 #else 2061 #define JSON_HEDLEY_FALL_THROUGH 2062 #endif 2063 2064 #if defined(JSON_HEDLEY_RETURNS_NON_NULL) 2065 #undef JSON_HEDLEY_RETURNS_NON_NULL 2066 #endif 2067 #if \ 2068 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ 2069 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ 2070 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2071 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) 2072 #elif defined(_Ret_notnull_) /* SAL */ 2073 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ 2074 #else 2075 #define JSON_HEDLEY_RETURNS_NON_NULL 2076 #endif 2077 2078 #if defined(JSON_HEDLEY_ARRAY_PARAM) 2079 #undef JSON_HEDLEY_ARRAY_PARAM 2080 #endif 2081 #if \ 2082 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ 2083 !defined(__STDC_NO_VLA__) && \ 2084 !defined(__cplusplus) && \ 2085 !defined(JSON_HEDLEY_PGI_VERSION) && \ 2086 !defined(JSON_HEDLEY_TINYC_VERSION) 2087 #define JSON_HEDLEY_ARRAY_PARAM(name) (name) 2088 #else 2089 #define JSON_HEDLEY_ARRAY_PARAM(name) 2090 #endif 2091 2092 #if defined(JSON_HEDLEY_IS_CONSTANT) 2093 #undef JSON_HEDLEY_IS_CONSTANT 2094 #endif 2095 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) 2096 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR 2097 #endif 2098 /* JSON_HEDLEY_IS_CONSTEXPR_ is for 2099 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ 2100 #if defined(JSON_HEDLEY_IS_CONSTEXPR_) 2101 #undef JSON_HEDLEY_IS_CONSTEXPR_ 2102 #endif 2103 #if \ 2104 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ 2105 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 2106 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2107 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ 2108 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ 2109 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 2110 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ 2111 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ 2112 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 2113 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) 2114 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) 2115 #endif 2116 #if !defined(__cplusplus) 2117 # if \ 2118 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ 2119 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ 2120 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2121 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ 2122 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ 2123 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ 2124 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) 2125 #if defined(__INTPTR_TYPE__) 2126 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) 2127 #else 2128 #include <stdint.h> 2129 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) 2130 #endif 2131 # elif \ 2132 ( \ 2133 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ 2134 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ 2135 !defined(JSON_HEDLEY_PGI_VERSION) && \ 2136 !defined(JSON_HEDLEY_IAR_VERSION)) || \ 2137 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ 2138 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ 2139 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ 2140 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ 2141 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) 2142 #if defined(__INTPTR_TYPE__) 2143 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) 2144 #else 2145 #include <stdint.h> 2146 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) 2147 #endif 2148 # elif \ 2149 defined(JSON_HEDLEY_GCC_VERSION) || \ 2150 defined(JSON_HEDLEY_INTEL_VERSION) || \ 2151 defined(JSON_HEDLEY_TINYC_VERSION) || \ 2152 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ 2153 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ 2154 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ 2155 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ 2156 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ 2157 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ 2158 defined(__clang__) 2159 # define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ 2160 sizeof(void) != \ 2161 sizeof(*( \ 2162 1 ? \ 2163 ((void*) ((expr) * 0L) ) : \ 2164 ((struct { char v[sizeof(void) * 2]; } *) 1) \ 2165 ) \ 2166 ) \ 2167 ) 2168 # endif 2169 #endif 2170 #if defined(JSON_HEDLEY_IS_CONSTEXPR_) 2171 #if !defined(JSON_HEDLEY_IS_CONSTANT) 2172 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) 2173 #endif 2174 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) 2175 #else 2176 #if !defined(JSON_HEDLEY_IS_CONSTANT) 2177 #define JSON_HEDLEY_IS_CONSTANT(expr) (0) 2178 #endif 2179 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) 2180 #endif 2181 2182 #if defined(JSON_HEDLEY_BEGIN_C_DECLS) 2183 #undef JSON_HEDLEY_BEGIN_C_DECLS 2184 #endif 2185 #if defined(JSON_HEDLEY_END_C_DECLS) 2186 #undef JSON_HEDLEY_END_C_DECLS 2187 #endif 2188 #if defined(JSON_HEDLEY_C_DECL) 2189 #undef JSON_HEDLEY_C_DECL 2190 #endif 2191 #if defined(__cplusplus) 2192 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { 2193 #define JSON_HEDLEY_END_C_DECLS } 2194 #define JSON_HEDLEY_C_DECL extern "C" 2195 #else 2196 #define JSON_HEDLEY_BEGIN_C_DECLS 2197 #define JSON_HEDLEY_END_C_DECLS 2198 #define JSON_HEDLEY_C_DECL 2199 #endif 2200 2201 #if defined(JSON_HEDLEY_STATIC_ASSERT) 2202 #undef JSON_HEDLEY_STATIC_ASSERT 2203 #endif 2204 #if \ 2205 !defined(__cplusplus) && ( \ 2206 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ 2207 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ 2208 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ 2209 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ 2210 defined(_Static_assert) \ 2211 ) 2212 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) 2213 #elif \ 2214 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ 2215 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ 2216 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 2217 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) 2218 #else 2219 # define JSON_HEDLEY_STATIC_ASSERT(expr, message) 2220 #endif 2221 2222 #if defined(JSON_HEDLEY_NULL) 2223 #undef JSON_HEDLEY_NULL 2224 #endif 2225 #if defined(__cplusplus) 2226 #if __cplusplus >= 201103L 2227 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) 2228 #elif defined(NULL) 2229 #define JSON_HEDLEY_NULL NULL 2230 #else 2231 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) 2232 #endif 2233 #elif defined(NULL) 2234 #define JSON_HEDLEY_NULL NULL 2235 #else 2236 #define JSON_HEDLEY_NULL ((void*) 0) 2237 #endif 2238 2239 #if defined(JSON_HEDLEY_MESSAGE) 2240 #undef JSON_HEDLEY_MESSAGE 2241 #endif 2242 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") 2243 # define JSON_HEDLEY_MESSAGE(msg) \ 2244 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2245 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 2246 JSON_HEDLEY_PRAGMA(message msg) \ 2247 JSON_HEDLEY_DIAGNOSTIC_POP 2248 #elif \ 2249 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ 2250 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 2251 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) 2252 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) 2253 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) 2254 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) 2255 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) 2256 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) 2257 # define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) 2258 #else 2259 # define JSON_HEDLEY_MESSAGE(msg) 2260 #endif 2261 2262 #if defined(JSON_HEDLEY_WARNING) 2263 #undef JSON_HEDLEY_WARNING 2264 #endif 2265 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") 2266 # define JSON_HEDLEY_WARNING(msg) \ 2267 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2268 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ 2269 JSON_HEDLEY_PRAGMA(clang warning msg) \ 2270 JSON_HEDLEY_DIAGNOSTIC_POP 2271 #elif \ 2272 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ 2273 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ 2274 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) 2275 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) 2276 #elif \ 2277 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ 2278 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 2279 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) 2280 #else 2281 # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) 2282 #endif 2283 2284 #if defined(JSON_HEDLEY_REQUIRE) 2285 #undef JSON_HEDLEY_REQUIRE 2286 #endif 2287 #if defined(JSON_HEDLEY_REQUIRE_MSG) 2288 #undef JSON_HEDLEY_REQUIRE_MSG 2289 #endif 2290 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) 2291 # if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") 2292 # define JSON_HEDLEY_REQUIRE(expr) \ 2293 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2294 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 2295 __attribute__((diagnose_if(!(expr), #expr, "error"))) \ 2296 JSON_HEDLEY_DIAGNOSTIC_POP 2297 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ 2298 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2299 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ 2300 __attribute__((diagnose_if(!(expr), msg, "error"))) \ 2301 JSON_HEDLEY_DIAGNOSTIC_POP 2302 # else 2303 # define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) 2304 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) 2305 # endif 2306 #else 2307 # define JSON_HEDLEY_REQUIRE(expr) 2308 # define JSON_HEDLEY_REQUIRE_MSG(expr,msg) 2309 #endif 2310 2311 #if defined(JSON_HEDLEY_FLAGS) 2312 #undef JSON_HEDLEY_FLAGS 2313 #endif 2314 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) 2315 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) 2316 #else 2317 #define JSON_HEDLEY_FLAGS 2318 #endif 2319 2320 #if defined(JSON_HEDLEY_FLAGS_CAST) 2321 #undef JSON_HEDLEY_FLAGS_CAST 2322 #endif 2323 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) 2324 # define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ 2325 JSON_HEDLEY_DIAGNOSTIC_PUSH \ 2326 _Pragma("warning(disable:188)") \ 2327 ((T) (expr)); \ 2328 JSON_HEDLEY_DIAGNOSTIC_POP \ 2329 })) 2330 #else 2331 # define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) 2332 #endif 2333 2334 #if defined(JSON_HEDLEY_EMPTY_BASES) 2335 #undef JSON_HEDLEY_EMPTY_BASES 2336 #endif 2337 #if \ 2338 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ 2339 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) 2340 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) 2341 #else 2342 #define JSON_HEDLEY_EMPTY_BASES 2343 #endif 2344 2345 /* Remaining macros are deprecated. */ 2346 2347 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) 2348 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK 2349 #endif 2350 #if defined(__clang__) 2351 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) 2352 #else 2353 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) 2354 #endif 2355 2356 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) 2357 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE 2358 #endif 2359 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) 2360 2361 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) 2362 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE 2363 #endif 2364 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) 2365 2366 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) 2367 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN 2368 #endif 2369 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) 2370 2371 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) 2372 #undef JSON_HEDLEY_CLANG_HAS_FEATURE 2373 #endif 2374 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) 2375 2376 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) 2377 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION 2378 #endif 2379 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) 2380 2381 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) 2382 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE 2383 #endif 2384 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) 2385 2386 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING) 2387 #undef JSON_HEDLEY_CLANG_HAS_WARNING 2388 #endif 2389 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) 2390 2391 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ 2392 2393 2394 // This file contains all internal macro definitions (except those affecting ABI) 2395 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them 2396 2397 // #include <nlohmann/detail/abi_macros.hpp> 2398 2399 2400 // exclude unsupported compilers 2401 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) 2402 #if defined(__clang__) 2403 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 2404 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" 2405 #endif 2406 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) 2407 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 2408 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" 2409 #endif 2410 #endif 2411 #endif 2412 2413 // C++ language standard detection 2414 // if the user manually specified the used c++ version this is skipped 2415 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) 2416 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) 2417 #define JSON_HAS_CPP_20 2418 #define JSON_HAS_CPP_17 2419 #define JSON_HAS_CPP_14 2420 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 2421 #define JSON_HAS_CPP_17 2422 #define JSON_HAS_CPP_14 2423 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) 2424 #define JSON_HAS_CPP_14 2425 #endif 2426 // the cpp 11 flag is always specified because it is the minimal required version 2427 #define JSON_HAS_CPP_11 2428 #endif 2429 2430 #ifdef __has_include 2431 #if __has_include(<version>) 2432 #include <version> 2433 #endif 2434 #endif 2435 2436 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) 2437 #ifdef JSON_HAS_CPP_17 2438 #if defined(__cpp_lib_filesystem) 2439 #define JSON_HAS_FILESYSTEM 1 2440 #elif defined(__cpp_lib_experimental_filesystem) 2441 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2442 #elif !defined(__has_include) 2443 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2444 #elif __has_include(<filesystem>) 2445 #define JSON_HAS_FILESYSTEM 1 2446 #elif __has_include(<experimental/filesystem>) 2447 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 2448 #endif 2449 2450 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ 2451 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 2452 #undef JSON_HAS_FILESYSTEM 2453 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2454 #endif 2455 2456 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support 2457 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 2458 #undef JSON_HAS_FILESYSTEM 2459 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2460 #endif 2461 2462 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support 2463 #if defined(__clang_major__) && __clang_major__ < 7 2464 #undef JSON_HAS_FILESYSTEM 2465 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2466 #endif 2467 2468 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support 2469 #if defined(_MSC_VER) && _MSC_VER < 1914 2470 #undef JSON_HAS_FILESYSTEM 2471 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2472 #endif 2473 2474 // no filesystem support before iOS 13 2475 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 2476 #undef JSON_HAS_FILESYSTEM 2477 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2478 #endif 2479 2480 // no filesystem support before macOS Catalina 2481 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 2482 #undef JSON_HAS_FILESYSTEM 2483 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2484 #endif 2485 #endif 2486 #endif 2487 2488 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM 2489 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 2490 #endif 2491 2492 #ifndef JSON_HAS_FILESYSTEM 2493 #define JSON_HAS_FILESYSTEM 0 2494 #endif 2495 2496 #ifndef JSON_HAS_THREE_WAY_COMPARISON 2497 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ 2498 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L 2499 #define JSON_HAS_THREE_WAY_COMPARISON 1 2500 #else 2501 #define JSON_HAS_THREE_WAY_COMPARISON 0 2502 #endif 2503 #endif 2504 2505 #ifndef JSON_HAS_RANGES 2506 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error 2507 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 2508 #define JSON_HAS_RANGES 0 2509 #elif defined(__cpp_lib_ranges) 2510 #define JSON_HAS_RANGES 1 2511 #else 2512 #define JSON_HAS_RANGES 0 2513 #endif 2514 #endif 2515 2516 #ifndef JSON_HAS_STATIC_RTTI 2517 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 2518 #define JSON_HAS_STATIC_RTTI 1 2519 #else 2520 #define JSON_HAS_STATIC_RTTI 0 2521 #endif 2522 #endif 2523 2524 #ifdef JSON_HAS_CPP_17 2525 #define JSON_INLINE_VARIABLE inline 2526 #else 2527 #define JSON_INLINE_VARIABLE 2528 #endif 2529 2530 #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) 2531 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] 2532 #else 2533 #define JSON_NO_UNIQUE_ADDRESS 2534 #endif 2535 2536 // disable documentation warnings on clang 2537 #if defined(__clang__) 2538 #pragma clang diagnostic push 2539 #pragma clang diagnostic ignored "-Wdocumentation" 2540 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" 2541 #endif 2542 2543 // allow disabling exceptions 2544 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) 2545 #define JSON_THROW(exception) throw exception 2546 #define JSON_TRY try 2547 #define JSON_CATCH(exception) catch(exception) 2548 #define JSON_INTERNAL_CATCH(exception) catch(exception) 2549 #else 2550 #include <cstdlib> 2551 #define JSON_THROW(exception) std::abort() 2552 #define JSON_TRY if(true) 2553 #define JSON_CATCH(exception) if(false) 2554 #define JSON_INTERNAL_CATCH(exception) if(false) 2555 #endif 2556 2557 // override exception macros 2558 #if defined(JSON_THROW_USER) 2559 #undef JSON_THROW 2560 #define JSON_THROW JSON_THROW_USER 2561 #endif 2562 #if defined(JSON_TRY_USER) 2563 #undef JSON_TRY 2564 #define JSON_TRY JSON_TRY_USER 2565 #endif 2566 #if defined(JSON_CATCH_USER) 2567 #undef JSON_CATCH 2568 #define JSON_CATCH JSON_CATCH_USER 2569 #undef JSON_INTERNAL_CATCH 2570 #define JSON_INTERNAL_CATCH JSON_CATCH_USER 2571 #endif 2572 #if defined(JSON_INTERNAL_CATCH_USER) 2573 #undef JSON_INTERNAL_CATCH 2574 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER 2575 #endif 2576 2577 // allow overriding assert 2578 #if !defined(JSON_ASSERT) 2579 #include <cassert> // assert 2580 #define JSON_ASSERT(x) assert(x) 2581 #endif 2582 2583 // allow to access some private functions (needed by the test suite) 2584 #if defined(JSON_TESTS_PRIVATE) 2585 #define JSON_PRIVATE_UNLESS_TESTED public 2586 #else 2587 #define JSON_PRIVATE_UNLESS_TESTED private 2588 #endif 2589 2590 /*! 2591 @brief macro to briefly define a mapping between an enum and JSON 2592 @def NLOHMANN_JSON_SERIALIZE_ENUM 2593 @since version 3.4.0 2594 */ 2595 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ 2596 template<typename BasicJsonType> \ 2597 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ 2598 { \ 2599 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ 2600 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ 2601 auto it = std::find_if(std::begin(m), std::end(m), \ 2602 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ 2603 { \ 2604 return ej_pair.first == e; \ 2605 }); \ 2606 j = ((it != std::end(m)) ? it : std::begin(m))->second; \ 2607 } \ 2608 template<typename BasicJsonType> \ 2609 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ 2610 { \ 2611 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \ 2612 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \ 2613 auto it = std::find_if(std::begin(m), std::end(m), \ 2614 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \ 2615 { \ 2616 return ej_pair.second == j; \ 2617 }); \ 2618 e = ((it != std::end(m)) ? it : std::begin(m))->first; \ 2619 } 2620 2621 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They 2622 // may be removed in the future once the class is split. 2623 2624 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ 2625 template<template<typename, typename, typename...> class ObjectType, \ 2626 template<typename, typename...> class ArrayType, \ 2627 class StringType, class BooleanType, class NumberIntegerType, \ 2628 class NumberUnsignedType, class NumberFloatType, \ 2629 template<typename> class AllocatorType, \ 2630 template<typename, typename = void> class JSONSerializer, \ 2631 class BinaryType, \ 2632 class CustomBaseClass> 2633 2634 #define NLOHMANN_BASIC_JSON_TPL \ 2635 basic_json<ObjectType, ArrayType, StringType, BooleanType, \ 2636 NumberIntegerType, NumberUnsignedType, NumberFloatType, \ 2637 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass> 2638 2639 // Macros to simplify conversion from/to types 2640 2641 #define NLOHMANN_JSON_EXPAND( x ) x 2642 #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 2643 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ 2644 NLOHMANN_JSON_PASTE64, \ 2645 NLOHMANN_JSON_PASTE63, \ 2646 NLOHMANN_JSON_PASTE62, \ 2647 NLOHMANN_JSON_PASTE61, \ 2648 NLOHMANN_JSON_PASTE60, \ 2649 NLOHMANN_JSON_PASTE59, \ 2650 NLOHMANN_JSON_PASTE58, \ 2651 NLOHMANN_JSON_PASTE57, \ 2652 NLOHMANN_JSON_PASTE56, \ 2653 NLOHMANN_JSON_PASTE55, \ 2654 NLOHMANN_JSON_PASTE54, \ 2655 NLOHMANN_JSON_PASTE53, \ 2656 NLOHMANN_JSON_PASTE52, \ 2657 NLOHMANN_JSON_PASTE51, \ 2658 NLOHMANN_JSON_PASTE50, \ 2659 NLOHMANN_JSON_PASTE49, \ 2660 NLOHMANN_JSON_PASTE48, \ 2661 NLOHMANN_JSON_PASTE47, \ 2662 NLOHMANN_JSON_PASTE46, \ 2663 NLOHMANN_JSON_PASTE45, \ 2664 NLOHMANN_JSON_PASTE44, \ 2665 NLOHMANN_JSON_PASTE43, \ 2666 NLOHMANN_JSON_PASTE42, \ 2667 NLOHMANN_JSON_PASTE41, \ 2668 NLOHMANN_JSON_PASTE40, \ 2669 NLOHMANN_JSON_PASTE39, \ 2670 NLOHMANN_JSON_PASTE38, \ 2671 NLOHMANN_JSON_PASTE37, \ 2672 NLOHMANN_JSON_PASTE36, \ 2673 NLOHMANN_JSON_PASTE35, \ 2674 NLOHMANN_JSON_PASTE34, \ 2675 NLOHMANN_JSON_PASTE33, \ 2676 NLOHMANN_JSON_PASTE32, \ 2677 NLOHMANN_JSON_PASTE31, \ 2678 NLOHMANN_JSON_PASTE30, \ 2679 NLOHMANN_JSON_PASTE29, \ 2680 NLOHMANN_JSON_PASTE28, \ 2681 NLOHMANN_JSON_PASTE27, \ 2682 NLOHMANN_JSON_PASTE26, \ 2683 NLOHMANN_JSON_PASTE25, \ 2684 NLOHMANN_JSON_PASTE24, \ 2685 NLOHMANN_JSON_PASTE23, \ 2686 NLOHMANN_JSON_PASTE22, \ 2687 NLOHMANN_JSON_PASTE21, \ 2688 NLOHMANN_JSON_PASTE20, \ 2689 NLOHMANN_JSON_PASTE19, \ 2690 NLOHMANN_JSON_PASTE18, \ 2691 NLOHMANN_JSON_PASTE17, \ 2692 NLOHMANN_JSON_PASTE16, \ 2693 NLOHMANN_JSON_PASTE15, \ 2694 NLOHMANN_JSON_PASTE14, \ 2695 NLOHMANN_JSON_PASTE13, \ 2696 NLOHMANN_JSON_PASTE12, \ 2697 NLOHMANN_JSON_PASTE11, \ 2698 NLOHMANN_JSON_PASTE10, \ 2699 NLOHMANN_JSON_PASTE9, \ 2700 NLOHMANN_JSON_PASTE8, \ 2701 NLOHMANN_JSON_PASTE7, \ 2702 NLOHMANN_JSON_PASTE6, \ 2703 NLOHMANN_JSON_PASTE5, \ 2704 NLOHMANN_JSON_PASTE4, \ 2705 NLOHMANN_JSON_PASTE3, \ 2706 NLOHMANN_JSON_PASTE2, \ 2707 NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) 2708 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1) 2709 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) 2710 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) 2711 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) 2712 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) 2713 #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) 2714 #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) 2715 #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) 2716 #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) 2717 #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) 2718 #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) 2719 #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) 2720 #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) 2721 #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) 2722 #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) 2723 #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) 2724 #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) 2725 #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) 2726 #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) 2727 #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) 2728 #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) 2729 #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) 2730 #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) 2731 #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) 2732 #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) 2733 #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) 2734 #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) 2735 #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) 2736 #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) 2737 #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) 2738 #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) 2739 #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) 2740 #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) 2741 #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) 2742 #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) 2743 #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) 2744 #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) 2745 #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) 2746 #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) 2747 #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) 2748 #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) 2749 #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) 2750 #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) 2751 #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) 2752 #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) 2753 #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) 2754 #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) 2755 #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) 2756 #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) 2757 #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) 2758 #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) 2759 #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) 2760 #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) 2761 #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) 2762 #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) 2763 #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) 2764 #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) 2765 #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) 2766 #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) 2767 #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) 2768 #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) 2769 #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) 2770 #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) 2771 2772 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; 2773 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); 2774 #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); 2775 2776 /*! 2777 @brief macro 2778 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE 2779 @since version 3.9.0 2780 */ 2781 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ 2782 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__)) } \ 2783 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__)) } 2784 2785 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ 2786 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__)) } \ 2787 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__)) } 2788 2789 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ 2790 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__)) } 2791 2792 /*! 2793 @brief macro 2794 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE 2795 @since version 3.9.0 2796 */ 2797 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ 2798 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__)) } \ 2799 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__)) } 2800 2801 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ 2802 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__)) } 2803 2804 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ 2805 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__)) } \ 2806 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__)) } 2807 2808 // inspired from https://stackoverflow.com/a/26745591 2809 // allows to call any std function as if (e.g. with begin): 2810 // using std::begin; begin(x); 2811 // 2812 // it allows using the detected idiom to retrieve the return type 2813 // of such an expression 2814 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ 2815 namespace detail { \ 2816 using std::std_name; \ 2817 \ 2818 template<typename... T> \ 2819 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ 2820 } \ 2821 \ 2822 namespace detail2 { \ 2823 struct std_name##_tag \ 2824 { \ 2825 }; \ 2826 \ 2827 template<typename... T> \ 2828 std_name##_tag std_name(T&&...); \ 2829 \ 2830 template<typename... T> \ 2831 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \ 2832 \ 2833 template<typename... T> \ 2834 struct would_call_std_##std_name \ 2835 { \ 2836 static constexpr auto const value = ::nlohmann::detail:: \ 2837 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \ 2838 }; \ 2839 } /* namespace detail2 */ \ 2840 \ 2841 template<typename... T> \ 2842 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \ 2843 { \ 2844 } 2845 2846 #ifndef JSON_USE_IMPLICIT_CONVERSIONS 2847 #define JSON_USE_IMPLICIT_CONVERSIONS 1 2848 #endif 2849 2850 #if JSON_USE_IMPLICIT_CONVERSIONS 2851 #define JSON_EXPLICIT 2852 #else 2853 #define JSON_EXPLICIT explicit 2854 #endif 2855 2856 #ifndef JSON_DISABLE_ENUM_SERIALIZATION 2857 #define JSON_DISABLE_ENUM_SERIALIZATION 0 2858 #endif 2859 2860 #ifndef JSON_USE_GLOBAL_UDLS 2861 #define JSON_USE_GLOBAL_UDLS 1 2862 #endif 2863 2864 #if JSON_HAS_THREE_WAY_COMPARISON 2865 #include <compare> // partial_ordering 2866 #endif 2867 2868 NLOHMANN_JSON_NAMESPACE_BEGIN 2869 namespace detail 2870 { 2871 2872 /////////////////////////// 2873 // JSON type enumeration // 2874 /////////////////////////// 2875 2876 /*! 2877 @brief the JSON type enumeration 2878 2879 This enumeration collects the different JSON types. It is internally used to 2880 distinguish the stored values, and the functions @ref basic_json::is_null(), 2881 @ref basic_json::is_object(), @ref basic_json::is_array(), 2882 @ref basic_json::is_string(), @ref basic_json::is_boolean(), 2883 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(), 2884 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), 2885 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and 2886 @ref basic_json::is_structured() rely on it. 2887 2888 @note There are three enumeration entries (number_integer, number_unsigned, and 2889 number_float), because the library distinguishes these three types for numbers: 2890 @ref basic_json::number_unsigned_t is used for unsigned integers, 2891 @ref basic_json::number_integer_t is used for signed integers, and 2892 @ref basic_json::number_float_t is used for floating-point numbers or to 2893 approximate integers which do not fit in the limits of their respective type. 2894 2895 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON 2896 value with the default value for a given type 2897 2898 @since version 1.0.0 2899 */ 2900 enum class value_t : std::uint8_t 2901 { 2902 null, ///< null value 2903 object, ///< object (unordered set of name/value pairs) 2904 array, ///< array (ordered collection of values) 2905 string, ///< string value 2906 boolean, ///< boolean value 2907 number_integer, ///< number value (signed integer) 2908 number_unsigned, ///< number value (unsigned integer) 2909 number_float, ///< number value (floating-point) 2910 binary, ///< binary array (ordered collection of bytes) 2911 discarded ///< discarded by the parser callback function 2912 }; 2913 2914 /*! 2915 @brief comparison operator for JSON types 2916 2917 Returns an ordering that is similar to Python: 2918 - order: null < boolean < number < object < array < string < binary 2919 - furthermore, each type is not smaller than itself 2920 - discarded values are not comparable 2921 - binary is represented as a b"" string in python and directly comparable to a 2922 string; however, making a binary array directly comparable with a string would 2923 be surprising behavior in a JSON file. 2924 2925 @since version 1.0.0 2926 */ 2927 #if JSON_HAS_THREE_WAY_COMPARISON 2928 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* 2929 #else 2930 inline bool operator<(const value_t lhs, const value_t rhs) noexcept 2931 #endif 2932 { 2933 static constexpr std::array<std::uint8_t, 9> order = {{ 2934 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, 2935 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, 2936 6 /* binary */ 2937 } 2938 }; 2939 2940 const auto l_index = static_cast<std::size_t>(lhs); 2941 const auto r_index = static_cast<std::size_t>(rhs); 2942 #if JSON_HAS_THREE_WAY_COMPARISON 2943 if (l_index < order.size() && r_index < order.size()) 2944 { 2945 return order[l_index] <=> order[r_index]; // *NOPAD* 2946 } 2947 return std::partial_ordering::unordered; 2948 #else 2949 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; 2950 #endif 2951 } 2952 2953 // GCC selects the built-in operator< over an operator rewritten from 2954 // a user-defined spaceship operator 2955 // Clang, MSVC, and ICC select the rewritten candidate 2956 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) 2957 #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) 2958 inline bool operator<(const value_t lhs, const value_t rhs) noexcept 2959 { 2960 return std::is_lt(lhs <=> rhs); // *NOPAD* 2961 } 2962 #endif 2963 2964 } // namespace detail 2965 NLOHMANN_JSON_NAMESPACE_END 2966 2967 // #include <nlohmann/detail/string_escape.hpp> 2968 // __ _____ _____ _____ 2969 // __| | __| | | | JSON for Modern C++ 2970 // | | |__ | | | | | | version 3.11.3 2971 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 2972 // 2973 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 2974 // SPDX-License-Identifier: MIT 2975 2976 2977 2978 // #include <nlohmann/detail/abi_macros.hpp> 2979 2980 2981 NLOHMANN_JSON_NAMESPACE_BEGIN 2982 namespace detail 2983 { 2984 2985 /*! 2986 @brief replace all occurrences of a substring by another string 2987 2988 @param[in,out] s the string to manipulate; changed so that all 2989 occurrences of @a f are replaced with @a t 2990 @param[in] f the substring to replace with @a t 2991 @param[in] t the string to replace @a f 2992 2993 @pre The search string @a f must not be empty. **This precondition is 2994 enforced with an assertion.** 2995 2996 @since version 2.0.0 2997 */ 2998 template<typename StringType> 2999 inline void replace_substring(StringType& s, const StringType& f, 3000 const StringType& t) 3001 { 3002 JSON_ASSERT(!f.empty()); 3003 for (auto pos = s.find(f); // find first occurrence of f 3004 pos != StringType::npos; // make sure f was found 3005 s.replace(pos, f.size(), t), // replace with t, and 3006 pos = s.find(f, pos + t.size())) // find next occurrence of f 3007 {} 3008 } 3009 3010 /*! 3011 * @brief string escaping as described in RFC 6901 (Sect. 4) 3012 * @param[in] s string to escape 3013 * @return escaped string 3014 * 3015 * Note the order of escaping "~" to "~0" and "/" to "~1" is important. 3016 */ 3017 template<typename StringType> 3018 inline StringType escape(StringType s) 3019 { 3020 replace_substring(s, StringType{"~"}, StringType{"~0"}); 3021 replace_substring(s, StringType{"/"}, StringType{"~1"}); 3022 return s; 3023 } 3024 3025 /*! 3026 * @brief string unescaping as described in RFC 6901 (Sect. 4) 3027 * @param[in] s string to unescape 3028 * @return unescaped string 3029 * 3030 * Note the order of escaping "~1" to "/" and "~0" to "~" is important. 3031 */ 3032 template<typename StringType> 3033 static void unescape(StringType& s) 3034 { 3035 replace_substring(s, StringType{"~1"}, StringType{"/"}); 3036 replace_substring(s, StringType{"~0"}, StringType{"~"}); 3037 } 3038 3039 } // namespace detail 3040 NLOHMANN_JSON_NAMESPACE_END 3041 3042 // #include <nlohmann/detail/input/position_t.hpp> 3043 // __ _____ _____ _____ 3044 // __| | __| | | | JSON for Modern C++ 3045 // | | |__ | | | | | | version 3.11.3 3046 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3047 // 3048 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 3049 // SPDX-License-Identifier: MIT 3050 3051 3052 3053 #include <cstddef> // size_t 3054 3055 // #include <nlohmann/detail/abi_macros.hpp> 3056 3057 3058 NLOHMANN_JSON_NAMESPACE_BEGIN 3059 namespace detail 3060 { 3061 3062 /// struct to capture the start position of the current token 3063 struct position_t 3064 { 3065 /// the total number of characters read 3066 std::size_t chars_read_total = 0; 3067 /// the number of characters read in the current line 3068 std::size_t chars_read_current_line = 0; 3069 /// the number of lines read 3070 std::size_t lines_read = 0; 3071 3072 /// conversion to size_t to preserve SAX interface 3073 constexpr operator size_t() const 3074 { 3075 return chars_read_total; 3076 } 3077 }; 3078 3079 } // namespace detail 3080 NLOHMANN_JSON_NAMESPACE_END 3081 3082 // #include <nlohmann/detail/macro_scope.hpp> 3083 3084 // #include <nlohmann/detail/meta/cpp_future.hpp> 3085 // __ _____ _____ _____ 3086 // __| | __| | | | JSON for Modern C++ 3087 // | | |__ | | | | | | version 3.11.3 3088 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3089 // 3090 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 3091 // SPDX-FileCopyrightText: 2018 The Abseil Authors 3092 // SPDX-License-Identifier: MIT 3093 3094 3095 3096 #include <array> // array 3097 #include <cstddef> // size_t 3098 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type 3099 #include <utility> // index_sequence, make_index_sequence, index_sequence_for 3100 3101 // #include <nlohmann/detail/macro_scope.hpp> 3102 3103 3104 NLOHMANN_JSON_NAMESPACE_BEGIN 3105 namespace detail 3106 { 3107 3108 template<typename T> 3109 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type; 3110 3111 #ifdef JSON_HAS_CPP_14 3112 3113 // the following utilities are natively available in C++14 3114 using std::enable_if_t; 3115 using std::index_sequence; 3116 using std::make_index_sequence; 3117 using std::index_sequence_for; 3118 3119 #else 3120 3121 // alias templates to reduce boilerplate 3122 template<bool B, typename T = void> 3123 using enable_if_t = typename std::enable_if<B, T>::type; 3124 3125 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h 3126 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. 3127 3128 //// START OF CODE FROM GOOGLE ABSEIL 3129 3130 // integer_sequence 3131 // 3132 // Class template representing a compile-time integer sequence. An instantiation 3133 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its 3134 // type through its template arguments (which is a common need when 3135 // working with C++11 variadic templates). `absl::integer_sequence` is designed 3136 // to be a drop-in replacement for C++14's `std::integer_sequence`. 3137 // 3138 // Example: 3139 // 3140 // template< class T, T... Ints > 3141 // void user_function(integer_sequence<T, Ints...>); 3142 // 3143 // int main() 3144 // { 3145 // // user_function's `T` will be deduced to `int` and `Ints...` 3146 // // will be deduced to `0, 1, 2, 3, 4`. 3147 // user_function(make_integer_sequence<int, 5>()); 3148 // } 3149 template <typename T, T... Ints> 3150 struct integer_sequence 3151 { 3152 using value_type = T; 3153 static constexpr std::size_t size() noexcept 3154 { 3155 return sizeof...(Ints); 3156 } 3157 }; 3158 3159 // index_sequence 3160 // 3161 // A helper template for an `integer_sequence` of `size_t`, 3162 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's 3163 // `std::index_sequence`. 3164 template <size_t... Ints> 3165 using index_sequence = integer_sequence<size_t, Ints...>; 3166 3167 namespace utility_internal 3168 { 3169 3170 template <typename Seq, size_t SeqSize, size_t Rem> 3171 struct Extend; 3172 3173 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. 3174 template <typename T, T... Ints, size_t SeqSize> 3175 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0> 3176 { 3177 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; 3178 }; 3179 3180 template <typename T, T... Ints, size_t SeqSize> 3181 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1> 3182 { 3183 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; 3184 }; 3185 3186 // Recursion helper for 'make_integer_sequence<T, N>'. 3187 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'. 3188 template <typename T, size_t N> 3189 struct Gen 3190 { 3191 using type = 3192 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; 3193 }; 3194 3195 template <typename T> 3196 struct Gen<T, 0> 3197 { 3198 using type = integer_sequence<T>; 3199 }; 3200 3201 } // namespace utility_internal 3202 3203 // Compile-time sequences of integers 3204 3205 // make_integer_sequence 3206 // 3207 // This template alias is equivalent to 3208 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in 3209 // replacement for C++14's `std::make_integer_sequence`. 3210 template <typename T, T N> 3211 using make_integer_sequence = typename utility_internal::Gen<T, N>::type; 3212 3213 // make_index_sequence 3214 // 3215 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, 3216 // and is designed to be a drop-in replacement for C++14's 3217 // `std::make_index_sequence`. 3218 template <size_t N> 3219 using make_index_sequence = make_integer_sequence<size_t, N>; 3220 3221 // index_sequence_for 3222 // 3223 // Converts a typename pack into an index sequence of the same length, and 3224 // is designed to be a drop-in replacement for C++14's 3225 // `std::index_sequence_for()` 3226 template <typename... Ts> 3227 using index_sequence_for = make_index_sequence<sizeof...(Ts)>; 3228 3229 //// END OF CODE FROM GOOGLE ABSEIL 3230 3231 #endif 3232 3233 // dispatch utility (taken from ranges-v3) 3234 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {}; 3235 template<> struct priority_tag<0> {}; 3236 3237 // taken from ranges-v3 3238 template<typename T> 3239 struct static_const 3240 { 3241 static JSON_INLINE_VARIABLE constexpr T value{}; 3242 }; 3243 3244 #ifndef JSON_HAS_CPP_17 3245 template<typename T> 3246 constexpr T static_const<T>::value; 3247 #endif 3248 3249 template<typename T, typename... Args> 3250 inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args) 3251 { 3252 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}}; 3253 } 3254 3255 } // namespace detail 3256 NLOHMANN_JSON_NAMESPACE_END 3257 3258 // #include <nlohmann/detail/meta/type_traits.hpp> 3259 // __ _____ _____ _____ 3260 // __| | __| | | | JSON for Modern C++ 3261 // | | |__ | | | | | | version 3.11.3 3262 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3263 // 3264 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 3265 // SPDX-License-Identifier: MIT 3266 3267 3268 3269 #include <limits> // numeric_limits 3270 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type 3271 #include <utility> // declval 3272 #include <tuple> // tuple 3273 #include <string> // char_traits 3274 3275 // #include <nlohmann/detail/iterators/iterator_traits.hpp> 3276 // __ _____ _____ _____ 3277 // __| | __| | | | JSON for Modern C++ 3278 // | | |__ | | | | | | version 3.11.3 3279 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3280 // 3281 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 3282 // SPDX-License-Identifier: MIT 3283 3284 3285 3286 #include <iterator> // random_access_iterator_tag 3287 3288 // #include <nlohmann/detail/abi_macros.hpp> 3289 3290 // #include <nlohmann/detail/meta/void_t.hpp> 3291 3292 // #include <nlohmann/detail/meta/cpp_future.hpp> 3293 3294 3295 NLOHMANN_JSON_NAMESPACE_BEGIN 3296 namespace detail 3297 { 3298 3299 template<typename It, typename = void> 3300 struct iterator_types {}; 3301 3302 template<typename It> 3303 struct iterator_types < 3304 It, 3305 void_t<typename It::difference_type, typename It::value_type, typename It::pointer, 3306 typename It::reference, typename It::iterator_category >> 3307 { 3308 using difference_type = typename It::difference_type; 3309 using value_type = typename It::value_type; 3310 using pointer = typename It::pointer; 3311 using reference = typename It::reference; 3312 using iterator_category = typename It::iterator_category; 3313 }; 3314 3315 // This is required as some compilers implement std::iterator_traits in a way that 3316 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. 3317 template<typename T, typename = void> 3318 struct iterator_traits 3319 { 3320 }; 3321 3322 template<typename T> 3323 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >> 3324 : iterator_types<T> 3325 { 3326 }; 3327 3328 template<typename T> 3329 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> 3330 { 3331 using iterator_category = std::random_access_iterator_tag; 3332 using value_type = T; 3333 using difference_type = ptrdiff_t; 3334 using pointer = T*; 3335 using reference = T&; 3336 }; 3337 3338 } // namespace detail 3339 NLOHMANN_JSON_NAMESPACE_END 3340 3341 // #include <nlohmann/detail/macro_scope.hpp> 3342 3343 // #include <nlohmann/detail/meta/call_std/begin.hpp> 3344 // __ _____ _____ _____ 3345 // __| | __| | | | JSON for Modern C++ 3346 // | | |__ | | | | | | version 3.11.3 3347 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3348 // 3349 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 3350 // SPDX-License-Identifier: MIT 3351 3352 3353 3354 // #include <nlohmann/detail/macro_scope.hpp> 3355 3356 3357 NLOHMANN_JSON_NAMESPACE_BEGIN 3358 3359 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); 3360 3361 NLOHMANN_JSON_NAMESPACE_END 3362 3363 // #include <nlohmann/detail/meta/call_std/end.hpp> 3364 // __ _____ _____ _____ 3365 // __| | __| | | | JSON for Modern C++ 3366 // | | |__ | | | | | | version 3.11.3 3367 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3368 // 3369 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 3370 // SPDX-License-Identifier: MIT 3371 3372 3373 3374 // #include <nlohmann/detail/macro_scope.hpp> 3375 3376 3377 NLOHMANN_JSON_NAMESPACE_BEGIN 3378 3379 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); 3380 3381 NLOHMANN_JSON_NAMESPACE_END 3382 3383 // #include <nlohmann/detail/meta/cpp_future.hpp> 3384 3385 // #include <nlohmann/detail/meta/detected.hpp> 3386 3387 // #include <nlohmann/json_fwd.hpp> 3388 // __ _____ _____ _____ 3389 // __| | __| | | | JSON for Modern C++ 3390 // | | |__ | | | | | | version 3.11.3 3391 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 3392 // 3393 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 3394 // SPDX-License-Identifier: MIT 3395 3396 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3397 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3398 3399 #include <cstdint> // int64_t, uint64_t 3400 #include <map> // map 3401 #include <memory> // allocator 3402 #include <string> // string 3403 #include <vector> // vector 3404 3405 // #include <nlohmann/detail/abi_macros.hpp> 3406 3407 3408 /*! 3409 @brief namespace for Niels Lohmann 3410 @see https://github.com/nlohmann 3411 @since version 1.0.0 3412 */ 3413 NLOHMANN_JSON_NAMESPACE_BEGIN 3414 3415 /*! 3416 @brief default JSONSerializer template argument 3417 3418 This serializer ignores the template arguments and uses ADL 3419 ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) 3420 for serialization. 3421 */ 3422 template<typename T = void, typename SFINAE = void> 3423 struct adl_serializer; 3424 3425 /// a class to store JSON values 3426 /// @sa https://json.nlohmann.me/api/basic_json/ 3427 template<template<typename U, typename V, typename... Args> class ObjectType = 3428 std::map, 3429 template<typename U, typename... Args> class ArrayType = std::vector, 3430 class StringType = std::string, class BooleanType = bool, 3431 class NumberIntegerType = std::int64_t, 3432 class NumberUnsignedType = std::uint64_t, 3433 class NumberFloatType = double, 3434 template<typename U> class AllocatorType = std::allocator, 3435 template<typename T, typename SFINAE = void> class JSONSerializer = 3436 adl_serializer, 3437 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError 3438 class CustomBaseClass = void> 3439 class basic_json; 3440 3441 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document 3442 /// @sa https://json.nlohmann.me/api/json_pointer/ 3443 template<typename RefStringType> 3444 class json_pointer; 3445 3446 /*! 3447 @brief default specialization 3448 @sa https://json.nlohmann.me/api/json/ 3449 */ 3450 using json = basic_json<>; 3451 3452 /// @brief a minimal map-like container that preserves insertion order 3453 /// @sa https://json.nlohmann.me/api/ordered_map/ 3454 template<class Key, class T, class IgnoredLess, class Allocator> 3455 struct ordered_map; 3456 3457 /// @brief specialization that maintains the insertion order of object keys 3458 /// @sa https://json.nlohmann.me/api/ordered_json/ 3459 using ordered_json = basic_json<nlohmann::ordered_map>; 3460 3461 NLOHMANN_JSON_NAMESPACE_END 3462 3463 #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ 3464 3465 3466 NLOHMANN_JSON_NAMESPACE_BEGIN 3467 /*! 3468 @brief detail namespace with internal helper functions 3469 3470 This namespace collects functions that should not be exposed, 3471 implementations of some @ref basic_json methods, and meta-programming helpers. 3472 3473 @since version 2.1.0 3474 */ 3475 namespace detail 3476 { 3477 3478 ///////////// 3479 // helpers // 3480 ///////////// 3481 3482 // Note to maintainers: 3483 // 3484 // Every trait in this file expects a non CV-qualified type. 3485 // The only exceptions are in the 'aliases for detected' section 3486 // (i.e. those of the form: decltype(T::member_function(std::declval<T>()))) 3487 // 3488 // In this case, T has to be properly CV-qualified to constraint the function arguments 3489 // (e.g. to_json(BasicJsonType&, const T&)) 3490 3491 template<typename> struct is_basic_json : std::false_type {}; 3492 3493 NLOHMANN_BASIC_JSON_TPL_DECLARATION 3494 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {}; 3495 3496 // used by exceptions create() member functions 3497 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t 3498 // false_type otherwise 3499 template<typename BasicJsonContext> 3500 struct is_basic_json_context : 3501 std::integral_constant < bool, 3502 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value 3503 || std::is_same<BasicJsonContext, std::nullptr_t>::value > 3504 {}; 3505 3506 ////////////////////// 3507 // json_ref helpers // 3508 ////////////////////// 3509 3510 template<typename> 3511 class json_ref; 3512 3513 template<typename> 3514 struct is_json_ref : std::false_type {}; 3515 3516 template<typename T> 3517 struct is_json_ref<json_ref<T>> : std::true_type {}; 3518 3519 ////////////////////////// 3520 // aliases for detected // 3521 ////////////////////////// 3522 3523 template<typename T> 3524 using mapped_type_t = typename T::mapped_type; 3525 3526 template<typename T> 3527 using key_type_t = typename T::key_type; 3528 3529 template<typename T> 3530 using value_type_t = typename T::value_type; 3531 3532 template<typename T> 3533 using difference_type_t = typename T::difference_type; 3534 3535 template<typename T> 3536 using pointer_t = typename T::pointer; 3537 3538 template<typename T> 3539 using reference_t = typename T::reference; 3540 3541 template<typename T> 3542 using iterator_category_t = typename T::iterator_category; 3543 3544 template<typename T, typename... Args> 3545 using to_json_function = decltype(T::to_json(std::declval<Args>()...)); 3546 3547 template<typename T, typename... Args> 3548 using from_json_function = decltype(T::from_json(std::declval<Args>()...)); 3549 3550 template<typename T, typename U> 3551 using get_template_function = decltype(std::declval<T>().template get<U>()); 3552 3553 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists 3554 template<typename BasicJsonType, typename T, typename = void> 3555 struct has_from_json : std::false_type {}; 3556 3557 // trait checking if j.get<T> is valid 3558 // use this trait instead of std::is_constructible or std::is_convertible, 3559 // both rely on, or make use of implicit conversions, and thus fail when T 3560 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) 3561 template <typename BasicJsonType, typename T> 3562 struct is_getable 3563 { 3564 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value; 3565 }; 3566 3567 template<typename BasicJsonType, typename T> 3568 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> 3569 { 3570 using serializer = typename BasicJsonType::template json_serializer<T, void>; 3571 3572 static constexpr bool value = 3573 is_detected_exact<void, from_json_function, serializer, 3574 const BasicJsonType&, T&>::value; 3575 }; 3576 3577 // This trait checks if JSONSerializer<T>::from_json(json const&) exists 3578 // this overload is used for non-default-constructible user-defined-types 3579 template<typename BasicJsonType, typename T, typename = void> 3580 struct has_non_default_from_json : std::false_type {}; 3581 3582 template<typename BasicJsonType, typename T> 3583 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> 3584 { 3585 using serializer = typename BasicJsonType::template json_serializer<T, void>; 3586 3587 static constexpr bool value = 3588 is_detected_exact<T, from_json_function, serializer, 3589 const BasicJsonType&>::value; 3590 }; 3591 3592 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists 3593 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. 3594 template<typename BasicJsonType, typename T, typename = void> 3595 struct has_to_json : std::false_type {}; 3596 3597 template<typename BasicJsonType, typename T> 3598 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >> 3599 { 3600 using serializer = typename BasicJsonType::template json_serializer<T, void>; 3601 3602 static constexpr bool value = 3603 is_detected_exact<void, to_json_function, serializer, BasicJsonType&, 3604 T>::value; 3605 }; 3606 3607 template<typename T> 3608 using detect_key_compare = typename T::key_compare; 3609 3610 template<typename T> 3611 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {}; 3612 3613 // obtains the actual object key comparator 3614 template<typename BasicJsonType> 3615 struct actual_object_comparator 3616 { 3617 using object_t = typename BasicJsonType::object_t; 3618 using object_comparator_t = typename BasicJsonType::default_object_comparator_t; 3619 using type = typename std::conditional < has_key_compare<object_t>::value, 3620 typename object_t::key_compare, object_comparator_t>::type; 3621 }; 3622 3623 template<typename BasicJsonType> 3624 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type; 3625 3626 ///////////////// 3627 // char_traits // 3628 ///////////////// 3629 3630 // Primary template of char_traits calls std char_traits 3631 template<typename T> 3632 struct char_traits : std::char_traits<T> 3633 {}; 3634 3635 // Explicitly define char traits for unsigned char since it is not standard 3636 template<> 3637 struct char_traits<unsigned char> : std::char_traits<char> 3638 { 3639 using char_type = unsigned char; 3640 using int_type = uint64_t; 3641 3642 // Redefine to_int_type function 3643 static int_type to_int_type(char_type c) noexcept 3644 { 3645 return static_cast<int_type>(c); 3646 } 3647 3648 static char_type to_char_type(int_type i) noexcept 3649 { 3650 return static_cast<char_type>(i); 3651 } 3652 3653 static constexpr int_type eof() noexcept 3654 { 3655 return static_cast<int_type>(EOF); 3656 } 3657 }; 3658 3659 // Explicitly define char traits for signed char since it is not standard 3660 template<> 3661 struct char_traits<signed char> : std::char_traits<char> 3662 { 3663 using char_type = signed char; 3664 using int_type = uint64_t; 3665 3666 // Redefine to_int_type function 3667 static int_type to_int_type(char_type c) noexcept 3668 { 3669 return static_cast<int_type>(c); 3670 } 3671 3672 static char_type to_char_type(int_type i) noexcept 3673 { 3674 return static_cast<char_type>(i); 3675 } 3676 3677 static constexpr int_type eof() noexcept 3678 { 3679 return static_cast<int_type>(EOF); 3680 } 3681 }; 3682 3683 /////////////////// 3684 // is_ functions // 3685 /////////////////// 3686 3687 // https://en.cppreference.com/w/cpp/types/conjunction 3688 template<class...> struct conjunction : std::true_type { }; 3689 template<class B> struct conjunction<B> : B { }; 3690 template<class B, class... Bn> 3691 struct conjunction<B, Bn...> 3692 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {}; 3693 3694 // https://en.cppreference.com/w/cpp/types/negation 3695 template<class B> struct negation : std::integral_constant < bool, !B::value > { }; 3696 3697 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for 3698 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). 3699 // This causes compile errors in e.g. clang 3.5 or gcc 4.9. 3700 template <typename T> 3701 struct is_default_constructible : std::is_default_constructible<T> {}; 3702 3703 template <typename T1, typename T2> 3704 struct is_default_constructible<std::pair<T1, T2>> 3705 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; 3706 3707 template <typename T1, typename T2> 3708 struct is_default_constructible<const std::pair<T1, T2>> 3709 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {}; 3710 3711 template <typename... Ts> 3712 struct is_default_constructible<std::tuple<Ts...>> 3713 : conjunction<is_default_constructible<Ts>...> {}; 3714 3715 template <typename... Ts> 3716 struct is_default_constructible<const std::tuple<Ts...>> 3717 : conjunction<is_default_constructible<Ts>...> {}; 3718 3719 template <typename T, typename... Args> 3720 struct is_constructible : std::is_constructible<T, Args...> {}; 3721 3722 template <typename T1, typename T2> 3723 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {}; 3724 3725 template <typename T1, typename T2> 3726 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {}; 3727 3728 template <typename... Ts> 3729 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {}; 3730 3731 template <typename... Ts> 3732 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {}; 3733 3734 template<typename T, typename = void> 3735 struct is_iterator_traits : std::false_type {}; 3736 3737 template<typename T> 3738 struct is_iterator_traits<iterator_traits<T>> 3739 { 3740 private: 3741 using traits = iterator_traits<T>; 3742 3743 public: 3744 static constexpr auto value = 3745 is_detected<value_type_t, traits>::value && 3746 is_detected<difference_type_t, traits>::value && 3747 is_detected<pointer_t, traits>::value && 3748 is_detected<iterator_category_t, traits>::value && 3749 is_detected<reference_t, traits>::value; 3750 }; 3751 3752 template<typename T> 3753 struct is_range 3754 { 3755 private: 3756 using t_ref = typename std::add_lvalue_reference<T>::type; 3757 3758 using iterator = detected_t<result_of_begin, t_ref>; 3759 using sentinel = detected_t<result_of_end, t_ref>; 3760 3761 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator 3762 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for 3763 // but reimplementing these would be too much work, as a lot of other concepts are used underneath 3764 static constexpr auto is_iterator_begin = 3765 is_iterator_traits<iterator_traits<iterator>>::value; 3766 3767 public: 3768 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin; 3769 }; 3770 3771 template<typename R> 3772 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>; 3773 3774 template<typename T> 3775 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>; 3776 3777 // The following implementation of is_complete_type is taken from 3778 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ 3779 // and is written by Xiang Fan who agreed to using it in this library. 3780 3781 template<typename T, typename = void> 3782 struct is_complete_type : std::false_type {}; 3783 3784 template<typename T> 3785 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {}; 3786 3787 template<typename BasicJsonType, typename CompatibleObjectType, 3788 typename = void> 3789 struct is_compatible_object_type_impl : std::false_type {}; 3790 3791 template<typename BasicJsonType, typename CompatibleObjectType> 3792 struct is_compatible_object_type_impl < 3793 BasicJsonType, CompatibleObjectType, 3794 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&& 3795 is_detected<key_type_t, CompatibleObjectType>::value >> 3796 { 3797 using object_t = typename BasicJsonType::object_t; 3798 3799 // macOS's is_constructible does not play well with nonesuch... 3800 static constexpr bool value = 3801 is_constructible<typename object_t::key_type, 3802 typename CompatibleObjectType::key_type>::value && 3803 is_constructible<typename object_t::mapped_type, 3804 typename CompatibleObjectType::mapped_type>::value; 3805 }; 3806 3807 template<typename BasicJsonType, typename CompatibleObjectType> 3808 struct is_compatible_object_type 3809 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {}; 3810 3811 template<typename BasicJsonType, typename ConstructibleObjectType, 3812 typename = void> 3813 struct is_constructible_object_type_impl : std::false_type {}; 3814 3815 template<typename BasicJsonType, typename ConstructibleObjectType> 3816 struct is_constructible_object_type_impl < 3817 BasicJsonType, ConstructibleObjectType, 3818 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&& 3819 is_detected<key_type_t, ConstructibleObjectType>::value >> 3820 { 3821 using object_t = typename BasicJsonType::object_t; 3822 3823 static constexpr bool value = 3824 (is_default_constructible<ConstructibleObjectType>::value && 3825 (std::is_move_assignable<ConstructibleObjectType>::value || 3826 std::is_copy_assignable<ConstructibleObjectType>::value) && 3827 (is_constructible<typename ConstructibleObjectType::key_type, 3828 typename object_t::key_type>::value && 3829 std::is_same < 3830 typename object_t::mapped_type, 3831 typename ConstructibleObjectType::mapped_type >::value)) || 3832 (has_from_json<BasicJsonType, 3833 typename ConstructibleObjectType::mapped_type>::value || 3834 has_non_default_from_json < 3835 BasicJsonType, 3836 typename ConstructibleObjectType::mapped_type >::value); 3837 }; 3838 3839 template<typename BasicJsonType, typename ConstructibleObjectType> 3840 struct is_constructible_object_type 3841 : is_constructible_object_type_impl<BasicJsonType, 3842 ConstructibleObjectType> {}; 3843 3844 template<typename BasicJsonType, typename CompatibleStringType> 3845 struct is_compatible_string_type 3846 { 3847 static constexpr auto value = 3848 is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value; 3849 }; 3850 3851 template<typename BasicJsonType, typename ConstructibleStringType> 3852 struct is_constructible_string_type 3853 { 3854 // launder type through decltype() to fix compilation failure on ICPC 3855 #ifdef __INTEL_COMPILER 3856 using laundered_type = decltype(std::declval<ConstructibleStringType>()); 3857 #else 3858 using laundered_type = ConstructibleStringType; 3859 #endif 3860 3861 static constexpr auto value = 3862 conjunction < 3863 is_constructible<laundered_type, typename BasicJsonType::string_t>, 3864 is_detected_exact<typename BasicJsonType::string_t::value_type, 3865 value_type_t, laundered_type >>::value; 3866 }; 3867 3868 template<typename BasicJsonType, typename CompatibleArrayType, typename = void> 3869 struct is_compatible_array_type_impl : std::false_type {}; 3870 3871 template<typename BasicJsonType, typename CompatibleArrayType> 3872 struct is_compatible_array_type_impl < 3873 BasicJsonType, CompatibleArrayType, 3874 enable_if_t < 3875 is_detected<iterator_t, CompatibleArrayType>::value&& 3876 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&& 3877 // special case for types like std::filesystem::path whose iterator's value_type are themselves 3878 // c.f. https://github.com/nlohmann/json/pull/3073 3879 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >> 3880 { 3881 static constexpr bool value = 3882 is_constructible<BasicJsonType, 3883 range_value_t<CompatibleArrayType>>::value; 3884 }; 3885 3886 template<typename BasicJsonType, typename CompatibleArrayType> 3887 struct is_compatible_array_type 3888 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {}; 3889 3890 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void> 3891 struct is_constructible_array_type_impl : std::false_type {}; 3892 3893 template<typename BasicJsonType, typename ConstructibleArrayType> 3894 struct is_constructible_array_type_impl < 3895 BasicJsonType, ConstructibleArrayType, 3896 enable_if_t<std::is_same<ConstructibleArrayType, 3897 typename BasicJsonType::value_type>::value >> 3898 : std::true_type {}; 3899 3900 template<typename BasicJsonType, typename ConstructibleArrayType> 3901 struct is_constructible_array_type_impl < 3902 BasicJsonType, ConstructibleArrayType, 3903 enable_if_t < !std::is_same<ConstructibleArrayType, 3904 typename BasicJsonType::value_type>::value&& 3905 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&& 3906 is_default_constructible<ConstructibleArrayType>::value&& 3907 (std::is_move_assignable<ConstructibleArrayType>::value || 3908 std::is_copy_assignable<ConstructibleArrayType>::value)&& 3909 is_detected<iterator_t, ConstructibleArrayType>::value&& 3910 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&& 3911 is_detected<range_value_t, ConstructibleArrayType>::value&& 3912 // special case for types like std::filesystem::path whose iterator's value_type are themselves 3913 // c.f. https://github.com/nlohmann/json/pull/3073 3914 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&& 3915 is_complete_type < 3916 detected_t<range_value_t, ConstructibleArrayType >>::value >> 3917 { 3918 using value_type = range_value_t<ConstructibleArrayType>; 3919 3920 static constexpr bool value = 3921 std::is_same<value_type, 3922 typename BasicJsonType::array_t::value_type>::value || 3923 has_from_json<BasicJsonType, 3924 value_type>::value || 3925 has_non_default_from_json < 3926 BasicJsonType, 3927 value_type >::value; 3928 }; 3929 3930 template<typename BasicJsonType, typename ConstructibleArrayType> 3931 struct is_constructible_array_type 3932 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {}; 3933 3934 template<typename RealIntegerType, typename CompatibleNumberIntegerType, 3935 typename = void> 3936 struct is_compatible_integer_type_impl : std::false_type {}; 3937 3938 template<typename RealIntegerType, typename CompatibleNumberIntegerType> 3939 struct is_compatible_integer_type_impl < 3940 RealIntegerType, CompatibleNumberIntegerType, 3941 enable_if_t < std::is_integral<RealIntegerType>::value&& 3942 std::is_integral<CompatibleNumberIntegerType>::value&& 3943 !std::is_same<bool, CompatibleNumberIntegerType>::value >> 3944 { 3945 // is there an assert somewhere on overflows? 3946 using RealLimits = std::numeric_limits<RealIntegerType>; 3947 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>; 3948 3949 static constexpr auto value = 3950 is_constructible<RealIntegerType, 3951 CompatibleNumberIntegerType>::value && 3952 CompatibleLimits::is_integer && 3953 RealLimits::is_signed == CompatibleLimits::is_signed; 3954 }; 3955 3956 template<typename RealIntegerType, typename CompatibleNumberIntegerType> 3957 struct is_compatible_integer_type 3958 : is_compatible_integer_type_impl<RealIntegerType, 3959 CompatibleNumberIntegerType> {}; 3960 3961 template<typename BasicJsonType, typename CompatibleType, typename = void> 3962 struct is_compatible_type_impl: std::false_type {}; 3963 3964 template<typename BasicJsonType, typename CompatibleType> 3965 struct is_compatible_type_impl < 3966 BasicJsonType, CompatibleType, 3967 enable_if_t<is_complete_type<CompatibleType>::value >> 3968 { 3969 static constexpr bool value = 3970 has_to_json<BasicJsonType, CompatibleType>::value; 3971 }; 3972 3973 template<typename BasicJsonType, typename CompatibleType> 3974 struct is_compatible_type 3975 : is_compatible_type_impl<BasicJsonType, CompatibleType> {}; 3976 3977 template<typename T1, typename T2> 3978 struct is_constructible_tuple : std::false_type {}; 3979 3980 template<typename T1, typename... Args> 3981 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {}; 3982 3983 template<typename BasicJsonType, typename T> 3984 struct is_json_iterator_of : std::false_type {}; 3985 3986 template<typename BasicJsonType> 3987 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {}; 3988 3989 template<typename BasicJsonType> 3990 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type 3991 {}; 3992 3993 // checks if a given type T is a template specialization of Primary 3994 template<template <typename...> class Primary, typename T> 3995 struct is_specialization_of : std::false_type {}; 3996 3997 template<template <typename...> class Primary, typename... Args> 3998 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {}; 3999 4000 template<typename T> 4001 using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>; 4002 4003 // checks if A and B are comparable using Compare functor 4004 template<typename Compare, typename A, typename B, typename = void> 4005 struct is_comparable : std::false_type {}; 4006 4007 template<typename Compare, typename A, typename B> 4008 struct is_comparable<Compare, A, B, void_t< 4009 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())), 4010 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>())) 4011 >> : std::true_type {}; 4012 4013 template<typename T> 4014 using detect_is_transparent = typename T::is_transparent; 4015 4016 // type trait to check if KeyType can be used as object key (without a BasicJsonType) 4017 // see is_usable_as_basic_json_key_type below 4018 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, 4019 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> 4020 using is_usable_as_key_type = typename std::conditional < 4021 is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value 4022 && !(ExcludeObjectKeyType && std::is_same<KeyType, 4023 ObjectKeyType>::value) 4024 && (!RequireTransparentComparator 4025 || is_detected <detect_is_transparent, Comparator>::value) 4026 && !is_json_pointer<KeyType>::value, 4027 std::true_type, 4028 std::false_type >::type; 4029 4030 // type trait to check if KeyType can be used as object key 4031 // true if: 4032 // - KeyType is comparable with BasicJsonType::object_t::key_type 4033 // - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type 4034 // - the comparator is transparent or RequireTransparentComparator is false 4035 // - KeyType is not a JSON iterator or json_pointer 4036 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true, 4037 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>> 4038 using is_usable_as_basic_json_key_type = typename std::conditional < 4039 is_usable_as_key_type<typename BasicJsonType::object_comparator_t, 4040 typename BasicJsonType::object_t::key_type, KeyTypeCVRef, 4041 RequireTransparentComparator, ExcludeObjectKeyType>::value 4042 && !is_json_iterator_of<BasicJsonType, KeyType>::value, 4043 std::true_type, 4044 std::false_type >::type; 4045 4046 template<typename ObjectType, typename KeyType> 4047 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>())); 4048 4049 // type trait to check if object_t has an erase() member functions accepting KeyType 4050 template<typename BasicJsonType, typename KeyType> 4051 using has_erase_with_key_type = typename std::conditional < 4052 is_detected < 4053 detect_erase_with_key_type, 4054 typename BasicJsonType::object_t, KeyType >::value, 4055 std::true_type, 4056 std::false_type >::type; 4057 4058 // a naive helper to check if a type is an ordered_map (exploits the fact that 4059 // ordered_map inherits capacity() from std::vector) 4060 template <typename T> 4061 struct is_ordered_map 4062 { 4063 using one = char; 4064 4065 struct two 4066 { 4067 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 4068 }; 4069 4070 template <typename C> static one test( decltype(&C::capacity) ) ; 4071 template <typename C> static two test(...); 4072 4073 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 4074 }; 4075 4076 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324) 4077 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 > 4078 T conditional_static_cast(U value) 4079 { 4080 return static_cast<T>(value); 4081 } 4082 4083 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0> 4084 T conditional_static_cast(U value) 4085 { 4086 return value; 4087 } 4088 4089 template<typename... Types> 4090 using all_integral = conjunction<std::is_integral<Types>...>; 4091 4092 template<typename... Types> 4093 using all_signed = conjunction<std::is_signed<Types>...>; 4094 4095 template<typename... Types> 4096 using all_unsigned = conjunction<std::is_unsigned<Types>...>; 4097 4098 // there's a disjunction trait in another PR; replace when merged 4099 template<typename... Types> 4100 using same_sign = std::integral_constant < bool, 4101 all_signed<Types...>::value || all_unsigned<Types...>::value >; 4102 4103 template<typename OfType, typename T> 4104 using never_out_of_range = std::integral_constant < bool, 4105 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType))) 4106 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >; 4107 4108 template<typename OfType, typename T, 4109 bool OfTypeSigned = std::is_signed<OfType>::value, 4110 bool TSigned = std::is_signed<T>::value> 4111 struct value_in_range_of_impl2; 4112 4113 template<typename OfType, typename T> 4114 struct value_in_range_of_impl2<OfType, T, false, false> 4115 { 4116 static constexpr bool test(T val) 4117 { 4118 using CommonType = typename std::common_type<OfType, T>::type; 4119 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4120 } 4121 }; 4122 4123 template<typename OfType, typename T> 4124 struct value_in_range_of_impl2<OfType, T, true, false> 4125 { 4126 static constexpr bool test(T val) 4127 { 4128 using CommonType = typename std::common_type<OfType, T>::type; 4129 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4130 } 4131 }; 4132 4133 template<typename OfType, typename T> 4134 struct value_in_range_of_impl2<OfType, T, false, true> 4135 { 4136 static constexpr bool test(T val) 4137 { 4138 using CommonType = typename std::common_type<OfType, T>::type; 4139 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4140 } 4141 }; 4142 4143 template<typename OfType, typename T> 4144 struct value_in_range_of_impl2<OfType, T, true, true> 4145 { 4146 static constexpr bool test(T val) 4147 { 4148 using CommonType = typename std::common_type<OfType, T>::type; 4149 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)()) 4150 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)()); 4151 } 4152 }; 4153 4154 template<typename OfType, typename T, 4155 bool NeverOutOfRange = never_out_of_range<OfType, T>::value, 4156 typename = detail::enable_if_t<all_integral<OfType, T>::value>> 4157 struct value_in_range_of_impl1; 4158 4159 template<typename OfType, typename T> 4160 struct value_in_range_of_impl1<OfType, T, false> 4161 { 4162 static constexpr bool test(T val) 4163 { 4164 return value_in_range_of_impl2<OfType, T>::test(val); 4165 } 4166 }; 4167 4168 template<typename OfType, typename T> 4169 struct value_in_range_of_impl1<OfType, T, true> 4170 { 4171 static constexpr bool test(T /*val*/) 4172 { 4173 return true; 4174 } 4175 }; 4176 4177 template<typename OfType, typename T> 4178 inline constexpr bool value_in_range_of(T val) 4179 { 4180 return value_in_range_of_impl1<OfType, T>::test(val); 4181 } 4182 4183 template<bool Value> 4184 using bool_constant = std::integral_constant<bool, Value>; 4185 4186 /////////////////////////////////////////////////////////////////////////////// 4187 // is_c_string 4188 /////////////////////////////////////////////////////////////////////////////// 4189 4190 namespace impl 4191 { 4192 4193 template<typename T> 4194 inline constexpr bool is_c_string() 4195 { 4196 using TUnExt = typename std::remove_extent<T>::type; 4197 using TUnCVExt = typename std::remove_cv<TUnExt>::type; 4198 using TUnPtr = typename std::remove_pointer<T>::type; 4199 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type; 4200 return 4201 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value) 4202 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value); 4203 } 4204 4205 } // namespace impl 4206 4207 // checks whether T is a [cv] char */[cv] char[] C string 4208 template<typename T> 4209 struct is_c_string : bool_constant<impl::is_c_string<T>()> {}; 4210 4211 template<typename T> 4212 using is_c_string_uncvref = is_c_string<uncvref_t<T>>; 4213 4214 /////////////////////////////////////////////////////////////////////////////// 4215 // is_transparent 4216 /////////////////////////////////////////////////////////////////////////////// 4217 4218 namespace impl 4219 { 4220 4221 template<typename T> 4222 inline constexpr bool is_transparent() 4223 { 4224 return is_detected<detect_is_transparent, T>::value; 4225 } 4226 4227 } // namespace impl 4228 4229 // checks whether T has a member named is_transparent 4230 template<typename T> 4231 struct is_transparent : bool_constant<impl::is_transparent<T>()> {}; 4232 4233 /////////////////////////////////////////////////////////////////////////////// 4234 4235 } // namespace detail 4236 NLOHMANN_JSON_NAMESPACE_END 4237 4238 // #include <nlohmann/detail/string_concat.hpp> 4239 // __ _____ _____ _____ 4240 // __| | __| | | | JSON for Modern C++ 4241 // | | |__ | | | | | | version 3.11.3 4242 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 4243 // 4244 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 4245 // SPDX-License-Identifier: MIT 4246 4247 4248 4249 #include <cstring> // strlen 4250 #include <string> // string 4251 #include <utility> // forward 4252 4253 // #include <nlohmann/detail/meta/cpp_future.hpp> 4254 4255 // #include <nlohmann/detail/meta/detected.hpp> 4256 4257 4258 NLOHMANN_JSON_NAMESPACE_BEGIN 4259 namespace detail 4260 { 4261 4262 inline std::size_t concat_length() 4263 { 4264 return 0; 4265 } 4266 4267 template<typename... Args> 4268 inline std::size_t concat_length(const char* cstr, const Args& ... rest); 4269 4270 template<typename StringType, typename... Args> 4271 inline std::size_t concat_length(const StringType& str, const Args& ... rest); 4272 4273 template<typename... Args> 4274 inline std::size_t concat_length(const char /*c*/, const Args& ... rest) 4275 { 4276 return 1 + concat_length(rest...); 4277 } 4278 4279 template<typename... Args> 4280 inline std::size_t concat_length(const char* cstr, const Args& ... rest) 4281 { 4282 // cppcheck-suppress ignoredReturnValue 4283 return ::strlen(cstr) + concat_length(rest...); 4284 } 4285 4286 template<typename StringType, typename... Args> 4287 inline std::size_t concat_length(const StringType& str, const Args& ... rest) 4288 { 4289 return str.size() + concat_length(rest...); 4290 } 4291 4292 template<typename OutStringType> 4293 inline void concat_into(OutStringType& /*out*/) 4294 {} 4295 4296 template<typename StringType, typename Arg> 4297 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ())); 4298 4299 template<typename StringType, typename Arg> 4300 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>; 4301 4302 template<typename StringType, typename Arg> 4303 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ()); 4304 4305 template<typename StringType, typename Arg> 4306 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>; 4307 4308 template<typename StringType, typename Arg> 4309 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end())); 4310 4311 template<typename StringType, typename Arg> 4312 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>; 4313 4314 template<typename StringType, typename Arg> 4315 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size())); 4316 4317 template<typename StringType, typename Arg> 4318 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>; 4319 4320 template < typename OutStringType, typename Arg, typename... Args, 4321 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4322 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 > 4323 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest); 4324 4325 template < typename OutStringType, typename Arg, typename... Args, 4326 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4327 && !detect_string_can_append_op<OutStringType, Arg>::value 4328 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 > 4329 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); 4330 4331 template < typename OutStringType, typename Arg, typename... Args, 4332 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4333 && !detect_string_can_append_op<OutStringType, Arg>::value 4334 && !detect_string_can_append_iter<OutStringType, Arg>::value 4335 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 > 4336 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest); 4337 4338 template<typename OutStringType, typename Arg, typename... Args, 4339 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0> 4340 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest) 4341 { 4342 out.append(std::forward<Arg>(arg)); 4343 concat_into(out, std::forward<Args>(rest)...); 4344 } 4345 4346 template < typename OutStringType, typename Arg, typename... Args, 4347 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4348 && detect_string_can_append_op<OutStringType, Arg>::value, int > > 4349 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest) 4350 { 4351 out += std::forward<Arg>(arg); 4352 concat_into(out, std::forward<Args>(rest)...); 4353 } 4354 4355 template < typename OutStringType, typename Arg, typename... Args, 4356 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4357 && !detect_string_can_append_op<OutStringType, Arg>::value 4358 && detect_string_can_append_iter<OutStringType, Arg>::value, int > > 4359 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) 4360 { 4361 out.append(arg.begin(), arg.end()); 4362 concat_into(out, std::forward<Args>(rest)...); 4363 } 4364 4365 template < typename OutStringType, typename Arg, typename... Args, 4366 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value 4367 && !detect_string_can_append_op<OutStringType, Arg>::value 4368 && !detect_string_can_append_iter<OutStringType, Arg>::value 4369 && detect_string_can_append_data<OutStringType, Arg>::value, int > > 4370 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest) 4371 { 4372 out.append(arg.data(), arg.size()); 4373 concat_into(out, std::forward<Args>(rest)...); 4374 } 4375 4376 template<typename OutStringType = std::string, typename... Args> 4377 inline OutStringType concat(Args && ... args) 4378 { 4379 OutStringType str; 4380 str.reserve(concat_length(args...)); 4381 concat_into(str, std::forward<Args>(args)...); 4382 return str; 4383 } 4384 4385 } // namespace detail 4386 NLOHMANN_JSON_NAMESPACE_END 4387 4388 4389 NLOHMANN_JSON_NAMESPACE_BEGIN 4390 namespace detail 4391 { 4392 4393 //////////////// 4394 // exceptions // 4395 //////////////// 4396 4397 /// @brief general exception of the @ref basic_json class 4398 /// @sa https://json.nlohmann.me/api/basic_json/exception/ 4399 class exception : public std::exception 4400 { 4401 public: 4402 /// returns the explanatory string 4403 const char* what() const noexcept override 4404 { 4405 return m.what(); 4406 } 4407 4408 /// the id of the exception 4409 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) 4410 4411 protected: 4412 JSON_HEDLEY_NON_NULL(3) 4413 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing) 4414 4415 static std::string name(const std::string& ename, int id_) 4416 { 4417 return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); 4418 } 4419 4420 static std::string diagnostics(std::nullptr_t /*leaf_element*/) 4421 { 4422 return ""; 4423 } 4424 4425 template<typename BasicJsonType> 4426 static std::string diagnostics(const BasicJsonType* leaf_element) 4427 { 4428 #if JSON_DIAGNOSTICS 4429 std::vector<std::string> tokens; 4430 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) 4431 { 4432 switch (current->m_parent->type()) 4433 { 4434 case value_t::array: 4435 { 4436 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) 4437 { 4438 if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) 4439 { 4440 tokens.emplace_back(std::to_string(i)); 4441 break; 4442 } 4443 } 4444 break; 4445 } 4446 4447 case value_t::object: 4448 { 4449 for (const auto& element : *current->m_parent->m_data.m_value.object) 4450 { 4451 if (&element.second == current) 4452 { 4453 tokens.emplace_back(element.first.c_str()); 4454 break; 4455 } 4456 } 4457 break; 4458 } 4459 4460 case value_t::null: // LCOV_EXCL_LINE 4461 case value_t::string: // LCOV_EXCL_LINE 4462 case value_t::boolean: // LCOV_EXCL_LINE 4463 case value_t::number_integer: // LCOV_EXCL_LINE 4464 case value_t::number_unsigned: // LCOV_EXCL_LINE 4465 case value_t::number_float: // LCOV_EXCL_LINE 4466 case value_t::binary: // LCOV_EXCL_LINE 4467 case value_t::discarded: // LCOV_EXCL_LINE 4468 default: // LCOV_EXCL_LINE 4469 break; // LCOV_EXCL_LINE 4470 } 4471 } 4472 4473 if (tokens.empty()) 4474 { 4475 return ""; 4476 } 4477 4478 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, 4479 [](const std::string & a, const std::string & b) 4480 { 4481 return concat(a, '/', detail::escape(b)); 4482 }); 4483 return concat('(', str, ") "); 4484 #else 4485 static_cast<void>(leaf_element); 4486 return ""; 4487 #endif 4488 } 4489 4490 private: 4491 /// an exception object as storage for error messages 4492 std::runtime_error m; 4493 }; 4494 4495 /// @brief exception indicating a parse error 4496 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/ 4497 class parse_error : public exception 4498 { 4499 public: 4500 /*! 4501 @brief create a parse error exception 4502 @param[in] id_ the id of the exception 4503 @param[in] pos the position where the error occurred (or with 4504 chars_read_total=0 if the position cannot be 4505 determined) 4506 @param[in] what_arg the explanatory string 4507 @return parse_error object 4508 */ 4509 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4510 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) 4511 { 4512 const std::string w = concat(exception::name("parse_error", id_), "parse error", 4513 position_string(pos), ": ", exception::diagnostics(context), what_arg); 4514 return {id_, pos.chars_read_total, w.c_str()}; 4515 } 4516 4517 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4518 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) 4519 { 4520 const std::string w = concat(exception::name("parse_error", id_), "parse error", 4521 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), 4522 ": ", exception::diagnostics(context), what_arg); 4523 return {id_, byte_, w.c_str()}; 4524 } 4525 4526 /*! 4527 @brief byte index of the parse error 4528 4529 The byte index of the last read character in the input file. 4530 4531 @note For an input with n bytes, 1 is the index of the first character and 4532 n+1 is the index of the terminating null byte or the end of file. 4533 This also holds true when reading a byte vector (CBOR or MessagePack). 4534 */ 4535 const std::size_t byte; 4536 4537 private: 4538 parse_error(int id_, std::size_t byte_, const char* what_arg) 4539 : exception(id_, what_arg), byte(byte_) {} 4540 4541 static std::string position_string(const position_t& pos) 4542 { 4543 return concat(" at line ", std::to_string(pos.lines_read + 1), 4544 ", column ", std::to_string(pos.chars_read_current_line)); 4545 } 4546 }; 4547 4548 /// @brief exception indicating errors with iterators 4549 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/ 4550 class invalid_iterator : public exception 4551 { 4552 public: 4553 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4554 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) 4555 { 4556 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); 4557 return {id_, w.c_str()}; 4558 } 4559 4560 private: 4561 JSON_HEDLEY_NON_NULL(3) 4562 invalid_iterator(int id_, const char* what_arg) 4563 : exception(id_, what_arg) {} 4564 }; 4565 4566 /// @brief exception indicating executing a member function with a wrong type 4567 /// @sa https://json.nlohmann.me/api/basic_json/type_error/ 4568 class type_error : public exception 4569 { 4570 public: 4571 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4572 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) 4573 { 4574 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); 4575 return {id_, w.c_str()}; 4576 } 4577 4578 private: 4579 JSON_HEDLEY_NON_NULL(3) 4580 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} 4581 }; 4582 4583 /// @brief exception indicating access out of the defined range 4584 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/ 4585 class out_of_range : public exception 4586 { 4587 public: 4588 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4589 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) 4590 { 4591 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); 4592 return {id_, w.c_str()}; 4593 } 4594 4595 private: 4596 JSON_HEDLEY_NON_NULL(3) 4597 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} 4598 }; 4599 4600 /// @brief exception indicating other library errors 4601 /// @sa https://json.nlohmann.me/api/basic_json/other_error/ 4602 class other_error : public exception 4603 { 4604 public: 4605 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0> 4606 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) 4607 { 4608 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); 4609 return {id_, w.c_str()}; 4610 } 4611 4612 private: 4613 JSON_HEDLEY_NON_NULL(3) 4614 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} 4615 }; 4616 4617 } // namespace detail 4618 NLOHMANN_JSON_NAMESPACE_END 4619 4620 // #include <nlohmann/detail/macro_scope.hpp> 4621 4622 // #include <nlohmann/detail/meta/cpp_future.hpp> 4623 4624 // #include <nlohmann/detail/meta/identity_tag.hpp> 4625 // __ _____ _____ _____ 4626 // __| | __| | | | JSON for Modern C++ 4627 // | | |__ | | | | | | version 3.11.3 4628 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 4629 // 4630 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 4631 // SPDX-License-Identifier: MIT 4632 4633 4634 4635 // #include <nlohmann/detail/abi_macros.hpp> 4636 4637 4638 NLOHMANN_JSON_NAMESPACE_BEGIN 4639 namespace detail 4640 { 4641 4642 // dispatching helper struct 4643 template <class T> struct identity_tag {}; 4644 4645 } // namespace detail 4646 NLOHMANN_JSON_NAMESPACE_END 4647 4648 // #include <nlohmann/detail/meta/std_fs.hpp> 4649 // __ _____ _____ _____ 4650 // __| | __| | | | JSON for Modern C++ 4651 // | | |__ | | | | | | version 3.11.3 4652 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 4653 // 4654 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 4655 // SPDX-License-Identifier: MIT 4656 4657 4658 4659 // #include <nlohmann/detail/macro_scope.hpp> 4660 4661 4662 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM 4663 #include <experimental/filesystem> 4664 NLOHMANN_JSON_NAMESPACE_BEGIN 4665 namespace detail 4666 { 4667 namespace std_fs = std::experimental::filesystem; 4668 } // namespace detail 4669 NLOHMANN_JSON_NAMESPACE_END 4670 #elif JSON_HAS_FILESYSTEM 4671 #include <filesystem> 4672 NLOHMANN_JSON_NAMESPACE_BEGIN 4673 namespace detail 4674 { 4675 namespace std_fs = std::filesystem; 4676 } // namespace detail 4677 NLOHMANN_JSON_NAMESPACE_END 4678 #endif 4679 4680 // #include <nlohmann/detail/meta/type_traits.hpp> 4681 4682 // #include <nlohmann/detail/string_concat.hpp> 4683 4684 // #include <nlohmann/detail/value_t.hpp> 4685 4686 4687 NLOHMANN_JSON_NAMESPACE_BEGIN 4688 namespace detail 4689 { 4690 4691 template<typename BasicJsonType> 4692 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) 4693 { 4694 if (JSON_HEDLEY_UNLIKELY(!j.is_null())) 4695 { 4696 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); 4697 } 4698 n = nullptr; 4699 } 4700 4701 // overloads for basic_json template parameters 4702 template < typename BasicJsonType, typename ArithmeticType, 4703 enable_if_t < std::is_arithmetic<ArithmeticType>::value&& 4704 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, 4705 int > = 0 > 4706 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) 4707 { 4708 switch (static_cast<value_t>(j)) 4709 { 4710 case value_t::number_unsigned: 4711 { 4712 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); 4713 break; 4714 } 4715 case value_t::number_integer: 4716 { 4717 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); 4718 break; 4719 } 4720 case value_t::number_float: 4721 { 4722 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); 4723 break; 4724 } 4725 4726 case value_t::null: 4727 case value_t::object: 4728 case value_t::array: 4729 case value_t::string: 4730 case value_t::boolean: 4731 case value_t::binary: 4732 case value_t::discarded: 4733 default: 4734 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); 4735 } 4736 } 4737 4738 template<typename BasicJsonType> 4739 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) 4740 { 4741 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) 4742 { 4743 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); 4744 } 4745 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); 4746 } 4747 4748 template<typename BasicJsonType> 4749 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) 4750 { 4751 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) 4752 { 4753 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); 4754 } 4755 s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); 4756 } 4757 4758 template < 4759 typename BasicJsonType, typename StringType, 4760 enable_if_t < 4761 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value 4762 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value 4763 && !std::is_same<typename BasicJsonType::string_t, StringType>::value 4764 && !is_json_ref<StringType>::value, int > = 0 > 4765 inline void from_json(const BasicJsonType& j, StringType& s) 4766 { 4767 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) 4768 { 4769 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); 4770 } 4771 4772 s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); 4773 } 4774 4775 template<typename BasicJsonType> 4776 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) 4777 { 4778 get_arithmetic_value(j, val); 4779 } 4780 4781 template<typename BasicJsonType> 4782 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) 4783 { 4784 get_arithmetic_value(j, val); 4785 } 4786 4787 template<typename BasicJsonType> 4788 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) 4789 { 4790 get_arithmetic_value(j, val); 4791 } 4792 4793 #if !JSON_DISABLE_ENUM_SERIALIZATION 4794 template<typename BasicJsonType, typename EnumType, 4795 enable_if_t<std::is_enum<EnumType>::value, int> = 0> 4796 inline void from_json(const BasicJsonType& j, EnumType& e) 4797 { 4798 typename std::underlying_type<EnumType>::type val; 4799 get_arithmetic_value(j, val); 4800 e = static_cast<EnumType>(val); 4801 } 4802 #endif // JSON_DISABLE_ENUM_SERIALIZATION 4803 4804 // forward_list doesn't have an insert method 4805 template<typename BasicJsonType, typename T, typename Allocator, 4806 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> 4807 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) 4808 { 4809 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4810 { 4811 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4812 } 4813 l.clear(); 4814 std::transform(j.rbegin(), j.rend(), 4815 std::front_inserter(l), [](const BasicJsonType & i) 4816 { 4817 return i.template get<T>(); 4818 }); 4819 } 4820 4821 // valarray doesn't have an insert method 4822 template<typename BasicJsonType, typename T, 4823 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> 4824 inline void from_json(const BasicJsonType& j, std::valarray<T>& l) 4825 { 4826 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4827 { 4828 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4829 } 4830 l.resize(j.size()); 4831 std::transform(j.begin(), j.end(), std::begin(l), 4832 [](const BasicJsonType & elem) 4833 { 4834 return elem.template get<T>(); 4835 }); 4836 } 4837 4838 template<typename BasicJsonType, typename T, std::size_t N> 4839 auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 4840 -> decltype(j.template get<T>(), void()) 4841 { 4842 for (std::size_t i = 0; i < N; ++i) 4843 { 4844 arr[i] = j.at(i).template get<T>(); 4845 } 4846 } 4847 4848 template<typename BasicJsonType> 4849 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) 4850 { 4851 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>(); 4852 } 4853 4854 template<typename BasicJsonType, typename T, std::size_t N> 4855 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, 4856 priority_tag<2> /*unused*/) 4857 -> decltype(j.template get<T>(), void()) 4858 { 4859 for (std::size_t i = 0; i < N; ++i) 4860 { 4861 arr[i] = j.at(i).template get<T>(); 4862 } 4863 } 4864 4865 template<typename BasicJsonType, typename ConstructibleArrayType, 4866 enable_if_t< 4867 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, 4868 int> = 0> 4869 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) 4870 -> decltype( 4871 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()), 4872 j.template get<typename ConstructibleArrayType::value_type>(), 4873 void()) 4874 { 4875 using std::end; 4876 4877 ConstructibleArrayType ret; 4878 ret.reserve(j.size()); 4879 std::transform(j.begin(), j.end(), 4880 std::inserter(ret, end(ret)), [](const BasicJsonType & i) 4881 { 4882 // get<BasicJsonType>() returns *this, this won't call a from_json 4883 // method when value_type is BasicJsonType 4884 return i.template get<typename ConstructibleArrayType::value_type>(); 4885 }); 4886 arr = std::move(ret); 4887 } 4888 4889 template<typename BasicJsonType, typename ConstructibleArrayType, 4890 enable_if_t< 4891 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, 4892 int> = 0> 4893 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, 4894 priority_tag<0> /*unused*/) 4895 { 4896 using std::end; 4897 4898 ConstructibleArrayType ret; 4899 std::transform( 4900 j.begin(), j.end(), std::inserter(ret, end(ret)), 4901 [](const BasicJsonType & i) 4902 { 4903 // get<BasicJsonType>() returns *this, this won't call a from_json 4904 // method when value_type is BasicJsonType 4905 return i.template get<typename ConstructibleArrayType::value_type>(); 4906 }); 4907 arr = std::move(ret); 4908 } 4909 4910 template < typename BasicJsonType, typename ConstructibleArrayType, 4911 enable_if_t < 4912 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&& 4913 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&& 4914 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&& 4915 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&& 4916 !is_basic_json<ConstructibleArrayType>::value, 4917 int > = 0 > 4918 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) 4919 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), 4920 j.template get<typename ConstructibleArrayType::value_type>(), 4921 void()) 4922 { 4923 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4924 { 4925 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4926 } 4927 4928 from_json_array_impl(j, arr, priority_tag<3> {}); 4929 } 4930 4931 template < typename BasicJsonType, typename T, std::size_t... Idx > 4932 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j, 4933 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/) 4934 { 4935 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } }; 4936 } 4937 4938 template < typename BasicJsonType, typename T, std::size_t N > 4939 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag) 4940 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {})) 4941 { 4942 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 4943 { 4944 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 4945 } 4946 4947 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}); 4948 } 4949 4950 template<typename BasicJsonType> 4951 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) 4952 { 4953 if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) 4954 { 4955 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); 4956 } 4957 4958 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>(); 4959 } 4960 4961 template<typename BasicJsonType, typename ConstructibleObjectType, 4962 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0> 4963 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) 4964 { 4965 if (JSON_HEDLEY_UNLIKELY(!j.is_object())) 4966 { 4967 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); 4968 } 4969 4970 ConstructibleObjectType ret; 4971 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); 4972 using value_type = typename ConstructibleObjectType::value_type; 4973 std::transform( 4974 inner_object->begin(), inner_object->end(), 4975 std::inserter(ret, ret.begin()), 4976 [](typename BasicJsonType::object_t::value_type const & p) 4977 { 4978 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>()); 4979 }); 4980 obj = std::move(ret); 4981 } 4982 4983 // overload for arithmetic types, not chosen for basic_json template arguments 4984 // (BooleanType, etc..); note: Is it really necessary to provide explicit 4985 // overloads for boolean_t etc. in case of a custom BooleanType which is not 4986 // an arithmetic type? 4987 template < typename BasicJsonType, typename ArithmeticType, 4988 enable_if_t < 4989 std::is_arithmetic<ArithmeticType>::value&& 4990 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&& 4991 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&& 4992 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&& 4993 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, 4994 int > = 0 > 4995 inline void from_json(const BasicJsonType& j, ArithmeticType& val) 4996 { 4997 switch (static_cast<value_t>(j)) 4998 { 4999 case value_t::number_unsigned: 5000 { 5001 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); 5002 break; 5003 } 5004 case value_t::number_integer: 5005 { 5006 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); 5007 break; 5008 } 5009 case value_t::number_float: 5010 { 5011 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); 5012 break; 5013 } 5014 case value_t::boolean: 5015 { 5016 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); 5017 break; 5018 } 5019 5020 case value_t::null: 5021 case value_t::object: 5022 case value_t::array: 5023 case value_t::string: 5024 case value_t::binary: 5025 case value_t::discarded: 5026 default: 5027 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); 5028 } 5029 } 5030 5031 template<typename BasicJsonType, typename... Args, std::size_t... Idx> 5032 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/) 5033 { 5034 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...); 5035 } 5036 5037 template < typename BasicJsonType, class A1, class A2 > 5038 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/) 5039 { 5040 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(), 5041 std::forward<BasicJsonType>(j).at(1).template get<A2>()}; 5042 } 5043 5044 template<typename BasicJsonType, typename A1, typename A2> 5045 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/) 5046 { 5047 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {}); 5048 } 5049 5050 template<typename BasicJsonType, typename... Args> 5051 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/) 5052 { 5053 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); 5054 } 5055 5056 template<typename BasicJsonType, typename... Args> 5057 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/) 5058 { 5059 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); 5060 } 5061 5062 template<typename BasicJsonType, typename TupleRelated> 5063 auto from_json(BasicJsonType&& j, TupleRelated&& t) 5064 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {})) 5065 { 5066 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 5067 { 5068 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 5069 } 5070 5071 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}); 5072 } 5073 5074 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, 5075 typename = enable_if_t < !std::is_constructible < 5076 typename BasicJsonType::string_t, Key >::value >> 5077 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m) 5078 { 5079 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 5080 { 5081 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 5082 } 5083 m.clear(); 5084 for (const auto& p : j) 5085 { 5086 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) 5087 { 5088 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); 5089 } 5090 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); 5091 } 5092 } 5093 5094 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, 5095 typename = enable_if_t < !std::is_constructible < 5096 typename BasicJsonType::string_t, Key >::value >> 5097 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m) 5098 { 5099 if (JSON_HEDLEY_UNLIKELY(!j.is_array())) 5100 { 5101 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); 5102 } 5103 m.clear(); 5104 for (const auto& p : j) 5105 { 5106 if (JSON_HEDLEY_UNLIKELY(!p.is_array())) 5107 { 5108 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); 5109 } 5110 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); 5111 } 5112 } 5113 5114 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM 5115 template<typename BasicJsonType> 5116 inline void from_json(const BasicJsonType& j, std_fs::path& p) 5117 { 5118 if (JSON_HEDLEY_UNLIKELY(!j.is_string())) 5119 { 5120 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); 5121 } 5122 p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); 5123 } 5124 #endif 5125 5126 struct from_json_fn 5127 { 5128 template<typename BasicJsonType, typename T> 5129 auto operator()(const BasicJsonType& j, T&& val) const 5130 noexcept(noexcept(from_json(j, std::forward<T>(val)))) 5131 -> decltype(from_json(j, std::forward<T>(val))) 5132 { 5133 return from_json(j, std::forward<T>(val)); 5134 } 5135 }; 5136 5137 } // namespace detail 5138 5139 #ifndef JSON_HAS_CPP_17 5140 /// namespace to hold default `from_json` function 5141 /// to see why this is required: 5142 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html 5143 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) 5144 { 5145 #endif 5146 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) 5147 detail::static_const<detail::from_json_fn>::value; 5148 #ifndef JSON_HAS_CPP_17 5149 } // namespace 5150 #endif 5151 5152 NLOHMANN_JSON_NAMESPACE_END 5153 5154 // #include <nlohmann/detail/conversions/to_json.hpp> 5155 // __ _____ _____ _____ 5156 // __| | __| | | | JSON for Modern C++ 5157 // | | |__ | | | | | | version 3.11.3 5158 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5159 // 5160 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 5161 // SPDX-License-Identifier: MIT 5162 5163 5164 5165 #include <algorithm> // copy 5166 #include <iterator> // begin, end 5167 #include <string> // string 5168 #include <tuple> // tuple, get 5169 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type 5170 #include <utility> // move, forward, declval, pair 5171 #include <valarray> // valarray 5172 #include <vector> // vector 5173 5174 // #include <nlohmann/detail/iterators/iteration_proxy.hpp> 5175 // __ _____ _____ _____ 5176 // __| | __| | | | JSON for Modern C++ 5177 // | | |__ | | | | | | version 3.11.3 5178 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5179 // 5180 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 5181 // SPDX-License-Identifier: MIT 5182 5183 5184 5185 #include <cstddef> // size_t 5186 #include <iterator> // input_iterator_tag 5187 #include <string> // string, to_string 5188 #include <tuple> // tuple_size, get, tuple_element 5189 #include <utility> // move 5190 5191 #if JSON_HAS_RANGES 5192 #include <ranges> // enable_borrowed_range 5193 #endif 5194 5195 // #include <nlohmann/detail/abi_macros.hpp> 5196 5197 // #include <nlohmann/detail/meta/type_traits.hpp> 5198 5199 // #include <nlohmann/detail/value_t.hpp> 5200 5201 5202 NLOHMANN_JSON_NAMESPACE_BEGIN 5203 namespace detail 5204 { 5205 5206 template<typename string_type> 5207 void int_to_string( string_type& target, std::size_t value ) 5208 { 5209 // For ADL 5210 using std::to_string; 5211 target = to_string(value); 5212 } 5213 template<typename IteratorType> class iteration_proxy_value 5214 { 5215 public: 5216 using difference_type = std::ptrdiff_t; 5217 using value_type = iteration_proxy_value; 5218 using pointer = value_type *; 5219 using reference = value_type &; 5220 using iterator_category = std::input_iterator_tag; 5221 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type; 5222 5223 private: 5224 /// the iterator 5225 IteratorType anchor{}; 5226 /// an index for arrays (used to create key names) 5227 std::size_t array_index = 0; 5228 /// last stringified array index 5229 mutable std::size_t array_index_last = 0; 5230 /// a string representation of the array index 5231 mutable string_type array_index_str = "0"; 5232 /// an empty string (to return a reference for primitive values) 5233 string_type empty_str{}; 5234 5235 public: 5236 explicit iteration_proxy_value() = default; 5237 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) 5238 noexcept(std::is_nothrow_move_constructible<IteratorType>::value 5239 && std::is_nothrow_default_constructible<string_type>::value) 5240 : anchor(std::move(it)) 5241 , array_index(array_index_) 5242 {} 5243 5244 iteration_proxy_value(iteration_proxy_value const&) = default; 5245 iteration_proxy_value& operator=(iteration_proxy_value const&) = default; 5246 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions 5247 iteration_proxy_value(iteration_proxy_value&&) 5248 noexcept(std::is_nothrow_move_constructible<IteratorType>::value 5249 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) 5250 iteration_proxy_value& operator=(iteration_proxy_value&&) 5251 noexcept(std::is_nothrow_move_assignable<IteratorType>::value 5252 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) 5253 ~iteration_proxy_value() = default; 5254 5255 /// dereference operator (needed for range-based for) 5256 const iteration_proxy_value& operator*() const 5257 { 5258 return *this; 5259 } 5260 5261 /// increment operator (needed for range-based for) 5262 iteration_proxy_value& operator++() 5263 { 5264 ++anchor; 5265 ++array_index; 5266 5267 return *this; 5268 } 5269 5270 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp) 5271 { 5272 auto tmp = iteration_proxy_value(anchor, array_index); 5273 ++anchor; 5274 ++array_index; 5275 return tmp; 5276 } 5277 5278 /// equality operator (needed for InputIterator) 5279 bool operator==(const iteration_proxy_value& o) const 5280 { 5281 return anchor == o.anchor; 5282 } 5283 5284 /// inequality operator (needed for range-based for) 5285 bool operator!=(const iteration_proxy_value& o) const 5286 { 5287 return anchor != o.anchor; 5288 } 5289 5290 /// return key of the iterator 5291 const string_type& key() const 5292 { 5293 JSON_ASSERT(anchor.m_object != nullptr); 5294 5295 switch (anchor.m_object->type()) 5296 { 5297 // use integer array index as key 5298 case value_t::array: 5299 { 5300 if (array_index != array_index_last) 5301 { 5302 int_to_string( array_index_str, array_index ); 5303 array_index_last = array_index; 5304 } 5305 return array_index_str; 5306 } 5307 5308 // use key from the object 5309 case value_t::object: 5310 return anchor.key(); 5311 5312 // use an empty key for all primitive types 5313 case value_t::null: 5314 case value_t::string: 5315 case value_t::boolean: 5316 case value_t::number_integer: 5317 case value_t::number_unsigned: 5318 case value_t::number_float: 5319 case value_t::binary: 5320 case value_t::discarded: 5321 default: 5322 return empty_str; 5323 } 5324 } 5325 5326 /// return value of the iterator 5327 typename IteratorType::reference value() const 5328 { 5329 return anchor.value(); 5330 } 5331 }; 5332 5333 /// proxy class for the items() function 5334 template<typename IteratorType> class iteration_proxy 5335 { 5336 private: 5337 /// the container to iterate 5338 typename IteratorType::pointer container = nullptr; 5339 5340 public: 5341 explicit iteration_proxy() = default; 5342 5343 /// construct iteration proxy from a container 5344 explicit iteration_proxy(typename IteratorType::reference cont) noexcept 5345 : container(&cont) {} 5346 5347 iteration_proxy(iteration_proxy const&) = default; 5348 iteration_proxy& operator=(iteration_proxy const&) = default; 5349 iteration_proxy(iteration_proxy&&) noexcept = default; 5350 iteration_proxy& operator=(iteration_proxy&&) noexcept = default; 5351 ~iteration_proxy() = default; 5352 5353 /// return iterator begin (needed for range-based for) 5354 iteration_proxy_value<IteratorType> begin() const noexcept 5355 { 5356 return iteration_proxy_value<IteratorType>(container->begin()); 5357 } 5358 5359 /// return iterator end (needed for range-based for) 5360 iteration_proxy_value<IteratorType> end() const noexcept 5361 { 5362 return iteration_proxy_value<IteratorType>(container->end()); 5363 } 5364 }; 5365 5366 // Structured Bindings Support 5367 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5368 // And see https://github.com/nlohmann/json/pull/1391 5369 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0> 5370 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key()) 5371 { 5372 return i.key(); 5373 } 5374 // Structured Bindings Support 5375 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5376 // And see https://github.com/nlohmann/json/pull/1391 5377 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0> 5378 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value()) 5379 { 5380 return i.value(); 5381 } 5382 5383 } // namespace detail 5384 NLOHMANN_JSON_NAMESPACE_END 5385 5386 // The Addition to the STD Namespace is required to add 5387 // Structured Bindings Support to the iteration_proxy_value class 5388 // For further reference see https://blog.tartanllama.xyz/structured-bindings/ 5389 // And see https://github.com/nlohmann/json/pull/1391 5390 namespace std 5391 { 5392 5393 #if defined(__clang__) 5394 // Fix: https://github.com/nlohmann/json/issues/1401 5395 #pragma clang diagnostic push 5396 #pragma clang diagnostic ignored "-Wmismatched-tags" 5397 #endif 5398 template<typename IteratorType> 5399 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp) 5400 : public std::integral_constant<std::size_t, 2> {}; 5401 5402 template<std::size_t N, typename IteratorType> 5403 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp) 5404 { 5405 public: 5406 using type = decltype( 5407 get<N>(std::declval < 5408 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ())); 5409 }; 5410 #if defined(__clang__) 5411 #pragma clang diagnostic pop 5412 #endif 5413 5414 } // namespace std 5415 5416 #if JSON_HAS_RANGES 5417 template <typename IteratorType> 5418 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true; 5419 #endif 5420 5421 // #include <nlohmann/detail/macro_scope.hpp> 5422 5423 // #include <nlohmann/detail/meta/cpp_future.hpp> 5424 5425 // #include <nlohmann/detail/meta/std_fs.hpp> 5426 5427 // #include <nlohmann/detail/meta/type_traits.hpp> 5428 5429 // #include <nlohmann/detail/value_t.hpp> 5430 5431 5432 NLOHMANN_JSON_NAMESPACE_BEGIN 5433 namespace detail 5434 { 5435 5436 ////////////////// 5437 // constructors // 5438 ////////////////// 5439 5440 /* 5441 * Note all external_constructor<>::construct functions need to call 5442 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an 5443 * allocated value (e.g., a string). See bug issue 5444 * https://github.com/nlohmann/json/issues/2865 for more information. 5445 */ 5446 5447 template<value_t> struct external_constructor; 5448 5449 template<> 5450 struct external_constructor<value_t::boolean> 5451 { 5452 template<typename BasicJsonType> 5453 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept 5454 { 5455 j.m_data.m_value.destroy(j.m_data.m_type); 5456 j.m_data.m_type = value_t::boolean; 5457 j.m_data.m_value = b; 5458 j.assert_invariant(); 5459 } 5460 }; 5461 5462 template<> 5463 struct external_constructor<value_t::string> 5464 { 5465 template<typename BasicJsonType> 5466 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) 5467 { 5468 j.m_data.m_value.destroy(j.m_data.m_type); 5469 j.m_data.m_type = value_t::string; 5470 j.m_data.m_value = s; 5471 j.assert_invariant(); 5472 } 5473 5474 template<typename BasicJsonType> 5475 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) 5476 { 5477 j.m_data.m_value.destroy(j.m_data.m_type); 5478 j.m_data.m_type = value_t::string; 5479 j.m_data.m_value = std::move(s); 5480 j.assert_invariant(); 5481 } 5482 5483 template < typename BasicJsonType, typename CompatibleStringType, 5484 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value, 5485 int > = 0 > 5486 static void construct(BasicJsonType& j, const CompatibleStringType& str) 5487 { 5488 j.m_data.m_value.destroy(j.m_data.m_type); 5489 j.m_data.m_type = value_t::string; 5490 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str); 5491 j.assert_invariant(); 5492 } 5493 }; 5494 5495 template<> 5496 struct external_constructor<value_t::binary> 5497 { 5498 template<typename BasicJsonType> 5499 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) 5500 { 5501 j.m_data.m_value.destroy(j.m_data.m_type); 5502 j.m_data.m_type = value_t::binary; 5503 j.m_data.m_value = typename BasicJsonType::binary_t(b); 5504 j.assert_invariant(); 5505 } 5506 5507 template<typename BasicJsonType> 5508 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) 5509 { 5510 j.m_data.m_value.destroy(j.m_data.m_type); 5511 j.m_data.m_type = value_t::binary; 5512 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); 5513 j.assert_invariant(); 5514 } 5515 }; 5516 5517 template<> 5518 struct external_constructor<value_t::number_float> 5519 { 5520 template<typename BasicJsonType> 5521 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept 5522 { 5523 j.m_data.m_value.destroy(j.m_data.m_type); 5524 j.m_data.m_type = value_t::number_float; 5525 j.m_data.m_value = val; 5526 j.assert_invariant(); 5527 } 5528 }; 5529 5530 template<> 5531 struct external_constructor<value_t::number_unsigned> 5532 { 5533 template<typename BasicJsonType> 5534 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept 5535 { 5536 j.m_data.m_value.destroy(j.m_data.m_type); 5537 j.m_data.m_type = value_t::number_unsigned; 5538 j.m_data.m_value = val; 5539 j.assert_invariant(); 5540 } 5541 }; 5542 5543 template<> 5544 struct external_constructor<value_t::number_integer> 5545 { 5546 template<typename BasicJsonType> 5547 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept 5548 { 5549 j.m_data.m_value.destroy(j.m_data.m_type); 5550 j.m_data.m_type = value_t::number_integer; 5551 j.m_data.m_value = val; 5552 j.assert_invariant(); 5553 } 5554 }; 5555 5556 template<> 5557 struct external_constructor<value_t::array> 5558 { 5559 template<typename BasicJsonType> 5560 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) 5561 { 5562 j.m_data.m_value.destroy(j.m_data.m_type); 5563 j.m_data.m_type = value_t::array; 5564 j.m_data.m_value = arr; 5565 j.set_parents(); 5566 j.assert_invariant(); 5567 } 5568 5569 template<typename BasicJsonType> 5570 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) 5571 { 5572 j.m_data.m_value.destroy(j.m_data.m_type); 5573 j.m_data.m_type = value_t::array; 5574 j.m_data.m_value = std::move(arr); 5575 j.set_parents(); 5576 j.assert_invariant(); 5577 } 5578 5579 template < typename BasicJsonType, typename CompatibleArrayType, 5580 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, 5581 int > = 0 > 5582 static void construct(BasicJsonType& j, const CompatibleArrayType& arr) 5583 { 5584 using std::begin; 5585 using std::end; 5586 5587 j.m_data.m_value.destroy(j.m_data.m_type); 5588 j.m_data.m_type = value_t::array; 5589 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr)); 5590 j.set_parents(); 5591 j.assert_invariant(); 5592 } 5593 5594 template<typename BasicJsonType> 5595 static void construct(BasicJsonType& j, const std::vector<bool>& arr) 5596 { 5597 j.m_data.m_value.destroy(j.m_data.m_type); 5598 j.m_data.m_type = value_t::array; 5599 j.m_data.m_value = value_t::array; 5600 j.m_data.m_value.array->reserve(arr.size()); 5601 for (const bool x : arr) 5602 { 5603 j.m_data.m_value.array->push_back(x); 5604 j.set_parent(j.m_data.m_value.array->back()); 5605 } 5606 j.assert_invariant(); 5607 } 5608 5609 template<typename BasicJsonType, typename T, 5610 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> 5611 static void construct(BasicJsonType& j, const std::valarray<T>& arr) 5612 { 5613 j.m_data.m_value.destroy(j.m_data.m_type); 5614 j.m_data.m_type = value_t::array; 5615 j.m_data.m_value = value_t::array; 5616 j.m_data.m_value.array->resize(arr.size()); 5617 if (arr.size() > 0) 5618 { 5619 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); 5620 } 5621 j.set_parents(); 5622 j.assert_invariant(); 5623 } 5624 }; 5625 5626 template<> 5627 struct external_constructor<value_t::object> 5628 { 5629 template<typename BasicJsonType> 5630 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) 5631 { 5632 j.m_data.m_value.destroy(j.m_data.m_type); 5633 j.m_data.m_type = value_t::object; 5634 j.m_data.m_value = obj; 5635 j.set_parents(); 5636 j.assert_invariant(); 5637 } 5638 5639 template<typename BasicJsonType> 5640 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) 5641 { 5642 j.m_data.m_value.destroy(j.m_data.m_type); 5643 j.m_data.m_type = value_t::object; 5644 j.m_data.m_value = std::move(obj); 5645 j.set_parents(); 5646 j.assert_invariant(); 5647 } 5648 5649 template < typename BasicJsonType, typename CompatibleObjectType, 5650 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 > 5651 static void construct(BasicJsonType& j, const CompatibleObjectType& obj) 5652 { 5653 using std::begin; 5654 using std::end; 5655 5656 j.m_data.m_value.destroy(j.m_data.m_type); 5657 j.m_data.m_type = value_t::object; 5658 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj)); 5659 j.set_parents(); 5660 j.assert_invariant(); 5661 } 5662 }; 5663 5664 ///////////// 5665 // to_json // 5666 ///////////// 5667 5668 template<typename BasicJsonType, typename T, 5669 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0> 5670 inline void to_json(BasicJsonType& j, T b) noexcept 5671 { 5672 external_constructor<value_t::boolean>::construct(j, b); 5673 } 5674 5675 template < typename BasicJsonType, typename BoolRef, 5676 enable_if_t < 5677 ((std::is_same<std::vector<bool>::reference, BoolRef>::value 5678 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) 5679 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value 5680 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>, 5681 typename BasicJsonType::boolean_t >::value)) 5682 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 > 5683 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept 5684 { 5685 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b)); 5686 } 5687 5688 template<typename BasicJsonType, typename CompatibleString, 5689 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0> 5690 inline void to_json(BasicJsonType& j, const CompatibleString& s) 5691 { 5692 external_constructor<value_t::string>::construct(j, s); 5693 } 5694 5695 template<typename BasicJsonType> 5696 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) 5697 { 5698 external_constructor<value_t::string>::construct(j, std::move(s)); 5699 } 5700 5701 template<typename BasicJsonType, typename FloatType, 5702 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0> 5703 inline void to_json(BasicJsonType& j, FloatType val) noexcept 5704 { 5705 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val)); 5706 } 5707 5708 template<typename BasicJsonType, typename CompatibleNumberUnsignedType, 5709 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0> 5710 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept 5711 { 5712 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val)); 5713 } 5714 5715 template<typename BasicJsonType, typename CompatibleNumberIntegerType, 5716 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0> 5717 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept 5718 { 5719 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val)); 5720 } 5721 5722 #if !JSON_DISABLE_ENUM_SERIALIZATION 5723 template<typename BasicJsonType, typename EnumType, 5724 enable_if_t<std::is_enum<EnumType>::value, int> = 0> 5725 inline void to_json(BasicJsonType& j, EnumType e) noexcept 5726 { 5727 using underlying_type = typename std::underlying_type<EnumType>::type; 5728 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e)); 5729 } 5730 #endif // JSON_DISABLE_ENUM_SERIALIZATION 5731 5732 template<typename BasicJsonType> 5733 inline void to_json(BasicJsonType& j, const std::vector<bool>& e) 5734 { 5735 external_constructor<value_t::array>::construct(j, e); 5736 } 5737 5738 template < typename BasicJsonType, typename CompatibleArrayType, 5739 enable_if_t < is_compatible_array_type<BasicJsonType, 5740 CompatibleArrayType>::value&& 5741 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&& 5742 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&& 5743 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&& 5744 !is_basic_json<CompatibleArrayType>::value, 5745 int > = 0 > 5746 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) 5747 { 5748 external_constructor<value_t::array>::construct(j, arr); 5749 } 5750 5751 template<typename BasicJsonType> 5752 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) 5753 { 5754 external_constructor<value_t::binary>::construct(j, bin); 5755 } 5756 5757 template<typename BasicJsonType, typename T, 5758 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> 5759 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr) 5760 { 5761 external_constructor<value_t::array>::construct(j, std::move(arr)); 5762 } 5763 5764 template<typename BasicJsonType> 5765 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) 5766 { 5767 external_constructor<value_t::array>::construct(j, std::move(arr)); 5768 } 5769 5770 template < typename BasicJsonType, typename CompatibleObjectType, 5771 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 > 5772 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) 5773 { 5774 external_constructor<value_t::object>::construct(j, obj); 5775 } 5776 5777 template<typename BasicJsonType> 5778 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) 5779 { 5780 external_constructor<value_t::object>::construct(j, std::move(obj)); 5781 } 5782 5783 template < 5784 typename BasicJsonType, typename T, std::size_t N, 5785 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t, 5786 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 5787 int > = 0 > 5788 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 5789 { 5790 external_constructor<value_t::array>::construct(j, arr); 5791 } 5792 5793 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 > 5794 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p) 5795 { 5796 j = { p.first, p.second }; 5797 } 5798 5799 // for https://github.com/nlohmann/json/pull/1134 5800 template<typename BasicJsonType, typename T, 5801 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0> 5802 inline void to_json(BasicJsonType& j, const T& b) 5803 { 5804 j = { {b.key(), b.value()} }; 5805 } 5806 5807 template<typename BasicJsonType, typename Tuple, std::size_t... Idx> 5808 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/) 5809 { 5810 j = { std::get<Idx>(t)... }; 5811 } 5812 5813 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0> 5814 inline void to_json(BasicJsonType& j, const T& t) 5815 { 5816 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {}); 5817 } 5818 5819 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM 5820 template<typename BasicJsonType> 5821 inline void to_json(BasicJsonType& j, const std_fs::path& p) 5822 { 5823 j = p.string(); 5824 } 5825 #endif 5826 5827 struct to_json_fn 5828 { 5829 template<typename BasicJsonType, typename T> 5830 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) 5831 -> decltype(to_json(j, std::forward<T>(val)), void()) 5832 { 5833 return to_json(j, std::forward<T>(val)); 5834 } 5835 }; 5836 } // namespace detail 5837 5838 #ifndef JSON_HAS_CPP_17 5839 /// namespace to hold default `to_json` function 5840 /// to see why this is required: 5841 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html 5842 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) 5843 { 5844 #endif 5845 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) 5846 detail::static_const<detail::to_json_fn>::value; 5847 #ifndef JSON_HAS_CPP_17 5848 } // namespace 5849 #endif 5850 5851 NLOHMANN_JSON_NAMESPACE_END 5852 5853 // #include <nlohmann/detail/meta/identity_tag.hpp> 5854 5855 5856 NLOHMANN_JSON_NAMESPACE_BEGIN 5857 5858 /// @sa https://json.nlohmann.me/api/adl_serializer/ 5859 template<typename ValueType, typename> 5860 struct adl_serializer 5861 { 5862 /// @brief convert a JSON value to any value type 5863 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ 5864 template<typename BasicJsonType, typename TargetType = ValueType> 5865 static auto from_json(BasicJsonType && j, TargetType& val) noexcept( 5866 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) 5867 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()) 5868 { 5869 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val); 5870 } 5871 5872 /// @brief convert a JSON value to any value type 5873 /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/ 5874 template<typename BasicJsonType, typename TargetType = ValueType> 5875 static auto from_json(BasicJsonType && j) noexcept( 5876 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))) 5877 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})) 5878 { 5879 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}); 5880 } 5881 5882 /// @brief convert any value type to a JSON value 5883 /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/ 5884 template<typename BasicJsonType, typename TargetType = ValueType> 5885 static auto to_json(BasicJsonType& j, TargetType && val) noexcept( 5886 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val)))) 5887 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void()) 5888 { 5889 ::nlohmann::to_json(j, std::forward<TargetType>(val)); 5890 } 5891 }; 5892 5893 NLOHMANN_JSON_NAMESPACE_END 5894 5895 // #include <nlohmann/byte_container_with_subtype.hpp> 5896 // __ _____ _____ _____ 5897 // __| | __| | | | JSON for Modern C++ 5898 // | | |__ | | | | | | version 3.11.3 5899 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 5900 // 5901 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 5902 // SPDX-License-Identifier: MIT 5903 5904 5905 5906 #include <cstdint> // uint8_t, uint64_t 5907 #include <tuple> // tie 5908 #include <utility> // move 5909 5910 // #include <nlohmann/detail/abi_macros.hpp> 5911 5912 5913 NLOHMANN_JSON_NAMESPACE_BEGIN 5914 5915 /// @brief an internal type for a backed binary type 5916 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ 5917 template<typename BinaryType> 5918 class byte_container_with_subtype : public BinaryType 5919 { 5920 public: 5921 using container_type = BinaryType; 5922 using subtype_type = std::uint64_t; 5923 5924 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5925 byte_container_with_subtype() noexcept(noexcept(container_type())) 5926 : container_type() 5927 {} 5928 5929 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5930 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) 5931 : container_type(b) 5932 {} 5933 5934 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5935 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) 5936 : container_type(std::move(b)) 5937 {} 5938 5939 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5940 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b))) 5941 : container_type(b) 5942 , m_subtype(subtype_) 5943 , m_has_subtype(true) 5944 {} 5945 5946 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/ 5947 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b)))) 5948 : container_type(std::move(b)) 5949 , m_subtype(subtype_) 5950 , m_has_subtype(true) 5951 {} 5952 5953 bool operator==(const byte_container_with_subtype& rhs) const 5954 { 5955 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) == 5956 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype); 5957 } 5958 5959 bool operator!=(const byte_container_with_subtype& rhs) const 5960 { 5961 return !(rhs == *this); 5962 } 5963 5964 /// @brief sets the binary subtype 5965 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/ 5966 void set_subtype(subtype_type subtype_) noexcept 5967 { 5968 m_subtype = subtype_; 5969 m_has_subtype = true; 5970 } 5971 5972 /// @brief return the binary subtype 5973 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/ 5974 constexpr subtype_type subtype() const noexcept 5975 { 5976 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1); 5977 } 5978 5979 /// @brief return whether the value has a subtype 5980 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/ 5981 constexpr bool has_subtype() const noexcept 5982 { 5983 return m_has_subtype; 5984 } 5985 5986 /// @brief clears the binary subtype 5987 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/ 5988 void clear_subtype() noexcept 5989 { 5990 m_subtype = 0; 5991 m_has_subtype = false; 5992 } 5993 5994 private: 5995 subtype_type m_subtype = 0; 5996 bool m_has_subtype = false; 5997 }; 5998 5999 NLOHMANN_JSON_NAMESPACE_END 6000 6001 // #include <nlohmann/detail/conversions/from_json.hpp> 6002 6003 // #include <nlohmann/detail/conversions/to_json.hpp> 6004 6005 // #include <nlohmann/detail/exceptions.hpp> 6006 6007 // #include <nlohmann/detail/hash.hpp> 6008 // __ _____ _____ _____ 6009 // __| | __| | | | JSON for Modern C++ 6010 // | | |__ | | | | | | version 3.11.3 6011 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6012 // 6013 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 6014 // SPDX-License-Identifier: MIT 6015 6016 6017 6018 #include <cstdint> // uint8_t 6019 #include <cstddef> // size_t 6020 #include <functional> // hash 6021 6022 // #include <nlohmann/detail/abi_macros.hpp> 6023 6024 // #include <nlohmann/detail/value_t.hpp> 6025 6026 6027 NLOHMANN_JSON_NAMESPACE_BEGIN 6028 namespace detail 6029 { 6030 6031 // boost::hash_combine 6032 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept 6033 { 6034 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); 6035 return seed; 6036 } 6037 6038 /*! 6039 @brief hash a JSON value 6040 6041 The hash function tries to rely on std::hash where possible. Furthermore, the 6042 type of the JSON value is taken into account to have different hash values for 6043 null, 0, 0U, and false, etc. 6044 6045 @tparam BasicJsonType basic_json specialization 6046 @param j JSON value to hash 6047 @return hash value of j 6048 */ 6049 template<typename BasicJsonType> 6050 std::size_t hash(const BasicJsonType& j) 6051 { 6052 using string_t = typename BasicJsonType::string_t; 6053 using number_integer_t = typename BasicJsonType::number_integer_t; 6054 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 6055 using number_float_t = typename BasicJsonType::number_float_t; 6056 6057 const auto type = static_cast<std::size_t>(j.type()); 6058 switch (j.type()) 6059 { 6060 case BasicJsonType::value_t::null: 6061 case BasicJsonType::value_t::discarded: 6062 { 6063 return combine(type, 0); 6064 } 6065 6066 case BasicJsonType::value_t::object: 6067 { 6068 auto seed = combine(type, j.size()); 6069 for (const auto& element : j.items()) 6070 { 6071 const auto h = std::hash<string_t> {}(element.key()); 6072 seed = combine(seed, h); 6073 seed = combine(seed, hash(element.value())); 6074 } 6075 return seed; 6076 } 6077 6078 case BasicJsonType::value_t::array: 6079 { 6080 auto seed = combine(type, j.size()); 6081 for (const auto& element : j) 6082 { 6083 seed = combine(seed, hash(element)); 6084 } 6085 return seed; 6086 } 6087 6088 case BasicJsonType::value_t::string: 6089 { 6090 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>()); 6091 return combine(type, h); 6092 } 6093 6094 case BasicJsonType::value_t::boolean: 6095 { 6096 const auto h = std::hash<bool> {}(j.template get<bool>()); 6097 return combine(type, h); 6098 } 6099 6100 case BasicJsonType::value_t::number_integer: 6101 { 6102 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>()); 6103 return combine(type, h); 6104 } 6105 6106 case BasicJsonType::value_t::number_unsigned: 6107 { 6108 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>()); 6109 return combine(type, h); 6110 } 6111 6112 case BasicJsonType::value_t::number_float: 6113 { 6114 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>()); 6115 return combine(type, h); 6116 } 6117 6118 case BasicJsonType::value_t::binary: 6119 { 6120 auto seed = combine(type, j.get_binary().size()); 6121 const auto h = std::hash<bool> {}(j.get_binary().has_subtype()); 6122 seed = combine(seed, h); 6123 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype())); 6124 for (const auto byte : j.get_binary()) 6125 { 6126 seed = combine(seed, std::hash<std::uint8_t> {}(byte)); 6127 } 6128 return seed; 6129 } 6130 6131 default: // LCOV_EXCL_LINE 6132 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 6133 return 0; // LCOV_EXCL_LINE 6134 } 6135 } 6136 6137 } // namespace detail 6138 NLOHMANN_JSON_NAMESPACE_END 6139 6140 // #include <nlohmann/detail/input/binary_reader.hpp> 6141 // __ _____ _____ _____ 6142 // __| | __| | | | JSON for Modern C++ 6143 // | | |__ | | | | | | version 3.11.3 6144 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6145 // 6146 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 6147 // SPDX-License-Identifier: MIT 6148 6149 6150 6151 #include <algorithm> // generate_n 6152 #include <array> // array 6153 #include <cmath> // ldexp 6154 #include <cstddef> // size_t 6155 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t 6156 #include <cstdio> // snprintf 6157 #include <cstring> // memcpy 6158 #include <iterator> // back_inserter 6159 #include <limits> // numeric_limits 6160 #include <string> // char_traits, string 6161 #include <utility> // make_pair, move 6162 #include <vector> // vector 6163 6164 // #include <nlohmann/detail/exceptions.hpp> 6165 6166 // #include <nlohmann/detail/input/input_adapters.hpp> 6167 // __ _____ _____ _____ 6168 // __| | __| | | | JSON for Modern C++ 6169 // | | |__ | | | | | | version 3.11.3 6170 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6171 // 6172 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 6173 // SPDX-License-Identifier: MIT 6174 6175 6176 6177 #include <array> // array 6178 #include <cstddef> // size_t 6179 #include <cstring> // strlen 6180 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next 6181 #include <memory> // shared_ptr, make_shared, addressof 6182 #include <numeric> // accumulate 6183 #include <string> // string, char_traits 6184 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer 6185 #include <utility> // pair, declval 6186 6187 #ifndef JSON_NO_IO 6188 #include <cstdio> // FILE * 6189 #include <istream> // istream 6190 #endif // JSON_NO_IO 6191 6192 // #include <nlohmann/detail/iterators/iterator_traits.hpp> 6193 6194 // #include <nlohmann/detail/macro_scope.hpp> 6195 6196 // #include <nlohmann/detail/meta/type_traits.hpp> 6197 6198 6199 NLOHMANN_JSON_NAMESPACE_BEGIN 6200 namespace detail 6201 { 6202 6203 /// the supported input formats 6204 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; 6205 6206 //////////////////// 6207 // input adapters // 6208 //////////////////// 6209 6210 #ifndef JSON_NO_IO 6211 /*! 6212 Input adapter for stdio file access. This adapter read only 1 byte and do not use any 6213 buffer. This adapter is a very low level adapter. 6214 */ 6215 class file_input_adapter 6216 { 6217 public: 6218 using char_type = char; 6219 6220 JSON_HEDLEY_NON_NULL(2) 6221 explicit file_input_adapter(std::FILE* f) noexcept 6222 : m_file(f) 6223 { 6224 JSON_ASSERT(m_file != nullptr); 6225 } 6226 6227 // make class move-only 6228 file_input_adapter(const file_input_adapter&) = delete; 6229 file_input_adapter(file_input_adapter&&) noexcept = default; 6230 file_input_adapter& operator=(const file_input_adapter&) = delete; 6231 file_input_adapter& operator=(file_input_adapter&&) = delete; 6232 ~file_input_adapter() = default; 6233 6234 std::char_traits<char>::int_type get_character() noexcept 6235 { 6236 return std::fgetc(m_file); 6237 } 6238 6239 private: 6240 /// the file pointer to read from 6241 std::FILE* m_file; 6242 }; 6243 6244 /*! 6245 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at 6246 beginning of input. Does not support changing the underlying std::streambuf 6247 in mid-input. Maintains underlying std::istream and std::streambuf to support 6248 subsequent use of standard std::istream operations to process any input 6249 characters following those used in parsing the JSON input. Clears the 6250 std::istream flags; any input errors (e.g., EOF) will be detected by the first 6251 subsequent call for input from the std::istream. 6252 */ 6253 class input_stream_adapter 6254 { 6255 public: 6256 using char_type = char; 6257 6258 ~input_stream_adapter() 6259 { 6260 // clear stream flags; we use underlying streambuf I/O, do not 6261 // maintain ifstream flags, except eof 6262 if (is != nullptr) 6263 { 6264 is->clear(is->rdstate() & std::ios::eofbit); 6265 } 6266 } 6267 6268 explicit input_stream_adapter(std::istream& i) 6269 : is(&i), sb(i.rdbuf()) 6270 {} 6271 6272 // delete because of pointer members 6273 input_stream_adapter(const input_stream_adapter&) = delete; 6274 input_stream_adapter& operator=(input_stream_adapter&) = delete; 6275 input_stream_adapter& operator=(input_stream_adapter&&) = delete; 6276 6277 input_stream_adapter(input_stream_adapter&& rhs) noexcept 6278 : is(rhs.is), sb(rhs.sb) 6279 { 6280 rhs.is = nullptr; 6281 rhs.sb = nullptr; 6282 } 6283 6284 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to 6285 // ensure that std::char_traits<char>::eof() and the character 0xFF do not 6286 // end up as the same value, e.g. 0xFFFFFFFF. 6287 std::char_traits<char>::int_type get_character() 6288 { 6289 auto res = sb->sbumpc(); 6290 // set eof manually, as we don't use the istream interface. 6291 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) 6292 { 6293 is->clear(is->rdstate() | std::ios::eofbit); 6294 } 6295 return res; 6296 } 6297 6298 private: 6299 /// the associated input stream 6300 std::istream* is = nullptr; 6301 std::streambuf* sb = nullptr; 6302 }; 6303 #endif // JSON_NO_IO 6304 6305 // General-purpose iterator-based adapter. It might not be as fast as 6306 // theoretically possible for some containers, but it is extremely versatile. 6307 template<typename IteratorType> 6308 class iterator_input_adapter 6309 { 6310 public: 6311 using char_type = typename std::iterator_traits<IteratorType>::value_type; 6312 6313 iterator_input_adapter(IteratorType first, IteratorType last) 6314 : current(std::move(first)), end(std::move(last)) 6315 {} 6316 6317 typename char_traits<char_type>::int_type get_character() 6318 { 6319 if (JSON_HEDLEY_LIKELY(current != end)) 6320 { 6321 auto result = char_traits<char_type>::to_int_type(*current); 6322 std::advance(current, 1); 6323 return result; 6324 } 6325 6326 return char_traits<char_type>::eof(); 6327 } 6328 6329 private: 6330 IteratorType current; 6331 IteratorType end; 6332 6333 template<typename BaseInputAdapter, size_t T> 6334 friend struct wide_string_input_helper; 6335 6336 bool empty() const 6337 { 6338 return current == end; 6339 } 6340 }; 6341 6342 template<typename BaseInputAdapter, size_t T> 6343 struct wide_string_input_helper; 6344 6345 template<typename BaseInputAdapter> 6346 struct wide_string_input_helper<BaseInputAdapter, 4> 6347 { 6348 // UTF-32 6349 static void fill_buffer(BaseInputAdapter& input, 6350 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, 6351 size_t& utf8_bytes_index, 6352 size_t& utf8_bytes_filled) 6353 { 6354 utf8_bytes_index = 0; 6355 6356 if (JSON_HEDLEY_UNLIKELY(input.empty())) 6357 { 6358 utf8_bytes[0] = std::char_traits<char>::eof(); 6359 utf8_bytes_filled = 1; 6360 } 6361 else 6362 { 6363 // get the current character 6364 const auto wc = input.get_character(); 6365 6366 // UTF-32 to UTF-8 encoding 6367 if (wc < 0x80) 6368 { 6369 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6370 utf8_bytes_filled = 1; 6371 } 6372 else if (wc <= 0x7FF) 6373 { 6374 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu)); 6375 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6376 utf8_bytes_filled = 2; 6377 } 6378 else if (wc <= 0xFFFF) 6379 { 6380 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu)); 6381 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); 6382 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6383 utf8_bytes_filled = 3; 6384 } 6385 else if (wc <= 0x10FFFF) 6386 { 6387 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u)); 6388 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu)); 6389 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); 6390 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6391 utf8_bytes_filled = 4; 6392 } 6393 else 6394 { 6395 // unknown character 6396 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6397 utf8_bytes_filled = 1; 6398 } 6399 } 6400 } 6401 }; 6402 6403 template<typename BaseInputAdapter> 6404 struct wide_string_input_helper<BaseInputAdapter, 2> 6405 { 6406 // UTF-16 6407 static void fill_buffer(BaseInputAdapter& input, 6408 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, 6409 size_t& utf8_bytes_index, 6410 size_t& utf8_bytes_filled) 6411 { 6412 utf8_bytes_index = 0; 6413 6414 if (JSON_HEDLEY_UNLIKELY(input.empty())) 6415 { 6416 utf8_bytes[0] = std::char_traits<char>::eof(); 6417 utf8_bytes_filled = 1; 6418 } 6419 else 6420 { 6421 // get the current character 6422 const auto wc = input.get_character(); 6423 6424 // UTF-16 to UTF-8 encoding 6425 if (wc < 0x80) 6426 { 6427 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6428 utf8_bytes_filled = 1; 6429 } 6430 else if (wc <= 0x7FF) 6431 { 6432 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u))); 6433 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6434 utf8_bytes_filled = 2; 6435 } 6436 else if (0xD800 > wc || wc >= 0xE000) 6437 { 6438 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u))); 6439 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); 6440 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); 6441 utf8_bytes_filled = 3; 6442 } 6443 else 6444 { 6445 if (JSON_HEDLEY_UNLIKELY(!input.empty())) 6446 { 6447 const auto wc2 = static_cast<unsigned int>(input.get_character()); 6448 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); 6449 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u)); 6450 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); 6451 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); 6452 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu)); 6453 utf8_bytes_filled = 4; 6454 } 6455 else 6456 { 6457 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); 6458 utf8_bytes_filled = 1; 6459 } 6460 } 6461 } 6462 } 6463 }; 6464 6465 // Wraps another input adapter to convert wide character types into individual bytes. 6466 template<typename BaseInputAdapter, typename WideCharType> 6467 class wide_string_input_adapter 6468 { 6469 public: 6470 using char_type = char; 6471 6472 wide_string_input_adapter(BaseInputAdapter base) 6473 : base_adapter(base) {} 6474 6475 typename std::char_traits<char>::int_type get_character() noexcept 6476 { 6477 // check if buffer needs to be filled 6478 if (utf8_bytes_index == utf8_bytes_filled) 6479 { 6480 fill_buffer<sizeof(WideCharType)>(); 6481 6482 JSON_ASSERT(utf8_bytes_filled > 0); 6483 JSON_ASSERT(utf8_bytes_index == 0); 6484 } 6485 6486 // use buffer 6487 JSON_ASSERT(utf8_bytes_filled > 0); 6488 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); 6489 return utf8_bytes[utf8_bytes_index++]; 6490 } 6491 6492 private: 6493 BaseInputAdapter base_adapter; 6494 6495 template<size_t T> 6496 void fill_buffer() 6497 { 6498 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); 6499 } 6500 6501 /// a buffer for UTF-8 bytes 6502 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; 6503 6504 /// index to the utf8_codes array for the next valid byte 6505 std::size_t utf8_bytes_index = 0; 6506 /// number of valid bytes in the utf8_codes array 6507 std::size_t utf8_bytes_filled = 0; 6508 }; 6509 6510 template<typename IteratorType, typename Enable = void> 6511 struct iterator_input_adapter_factory 6512 { 6513 using iterator_type = IteratorType; 6514 using char_type = typename std::iterator_traits<iterator_type>::value_type; 6515 using adapter_type = iterator_input_adapter<iterator_type>; 6516 6517 static adapter_type create(IteratorType first, IteratorType last) 6518 { 6519 return adapter_type(std::move(first), std::move(last)); 6520 } 6521 }; 6522 6523 template<typename T> 6524 struct is_iterator_of_multibyte 6525 { 6526 using value_type = typename std::iterator_traits<T>::value_type; 6527 enum 6528 { 6529 value = sizeof(value_type) > 1 6530 }; 6531 }; 6532 6533 template<typename IteratorType> 6534 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>> 6535 { 6536 using iterator_type = IteratorType; 6537 using char_type = typename std::iterator_traits<iterator_type>::value_type; 6538 using base_adapter_type = iterator_input_adapter<iterator_type>; 6539 using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>; 6540 6541 static adapter_type create(IteratorType first, IteratorType last) 6542 { 6543 return adapter_type(base_adapter_type(std::move(first), std::move(last))); 6544 } 6545 }; 6546 6547 // General purpose iterator-based input 6548 template<typename IteratorType> 6549 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last) 6550 { 6551 using factory_type = iterator_input_adapter_factory<IteratorType>; 6552 return factory_type::create(first, last); 6553 } 6554 6555 // Convenience shorthand from container to iterator 6556 // Enables ADL on begin(container) and end(container) 6557 // Encloses the using declarations in namespace for not to leak them to outside scope 6558 6559 namespace container_input_adapter_factory_impl 6560 { 6561 6562 using std::begin; 6563 using std::end; 6564 6565 template<typename ContainerType, typename Enable = void> 6566 struct container_input_adapter_factory {}; 6567 6568 template<typename ContainerType> 6569 struct container_input_adapter_factory< ContainerType, 6570 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>> 6571 { 6572 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))); 6573 6574 static adapter_type create(const ContainerType& container) 6575 { 6576 return input_adapter(begin(container), end(container)); 6577 } 6578 }; 6579 6580 } // namespace container_input_adapter_factory_impl 6581 6582 template<typename ContainerType> 6583 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container) 6584 { 6585 return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container); 6586 } 6587 6588 #ifndef JSON_NO_IO 6589 // Special cases with fast paths 6590 inline file_input_adapter input_adapter(std::FILE* file) 6591 { 6592 return file_input_adapter(file); 6593 } 6594 6595 inline input_stream_adapter input_adapter(std::istream& stream) 6596 { 6597 return input_stream_adapter(stream); 6598 } 6599 6600 inline input_stream_adapter input_adapter(std::istream&& stream) 6601 { 6602 return input_stream_adapter(stream); 6603 } 6604 #endif // JSON_NO_IO 6605 6606 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>())); 6607 6608 // Null-delimited strings, and the like. 6609 template < typename CharT, 6610 typename std::enable_if < 6611 std::is_pointer<CharT>::value&& 6612 !std::is_array<CharT>::value&& 6613 std::is_integral<typename std::remove_pointer<CharT>::type>::value&& 6614 sizeof(typename std::remove_pointer<CharT>::type) == 1, 6615 int >::type = 0 > 6616 contiguous_bytes_input_adapter input_adapter(CharT b) 6617 { 6618 auto length = std::strlen(reinterpret_cast<const char*>(b)); 6619 const auto* ptr = reinterpret_cast<const char*>(b); 6620 return input_adapter(ptr, ptr + length); 6621 } 6622 6623 template<typename T, std::size_t N> 6624 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) 6625 { 6626 return input_adapter(array, array + N); 6627 } 6628 6629 // This class only handles inputs of input_buffer_adapter type. 6630 // It's required so that expressions like {ptr, len} can be implicitly cast 6631 // to the correct adapter. 6632 class span_input_adapter 6633 { 6634 public: 6635 template < typename CharT, 6636 typename std::enable_if < 6637 std::is_pointer<CharT>::value&& 6638 std::is_integral<typename std::remove_pointer<CharT>::type>::value&& 6639 sizeof(typename std::remove_pointer<CharT>::type) == 1, 6640 int >::type = 0 > 6641 span_input_adapter(CharT b, std::size_t l) 6642 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {} 6643 6644 template<class IteratorType, 6645 typename std::enable_if< 6646 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, 6647 int>::type = 0> 6648 span_input_adapter(IteratorType first, IteratorType last) 6649 : ia(input_adapter(first, last)) {} 6650 6651 contiguous_bytes_input_adapter&& get() 6652 { 6653 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) 6654 } 6655 6656 private: 6657 contiguous_bytes_input_adapter ia; 6658 }; 6659 6660 } // namespace detail 6661 NLOHMANN_JSON_NAMESPACE_END 6662 6663 // #include <nlohmann/detail/input/json_sax.hpp> 6664 // __ _____ _____ _____ 6665 // __| | __| | | | JSON for Modern C++ 6666 // | | |__ | | | | | | version 3.11.3 6667 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 6668 // 6669 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 6670 // SPDX-License-Identifier: MIT 6671 6672 6673 6674 #include <cstddef> 6675 #include <string> // string 6676 #include <utility> // move 6677 #include <vector> // vector 6678 6679 // #include <nlohmann/detail/exceptions.hpp> 6680 6681 // #include <nlohmann/detail/macro_scope.hpp> 6682 6683 // #include <nlohmann/detail/string_concat.hpp> 6684 6685 6686 NLOHMANN_JSON_NAMESPACE_BEGIN 6687 6688 /*! 6689 @brief SAX interface 6690 6691 This class describes the SAX interface used by @ref nlohmann::json::sax_parse. 6692 Each function is called in different situations while the input is parsed. The 6693 boolean return value informs the parser whether to continue processing the 6694 input. 6695 */ 6696 template<typename BasicJsonType> 6697 struct json_sax 6698 { 6699 using number_integer_t = typename BasicJsonType::number_integer_t; 6700 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 6701 using number_float_t = typename BasicJsonType::number_float_t; 6702 using string_t = typename BasicJsonType::string_t; 6703 using binary_t = typename BasicJsonType::binary_t; 6704 6705 /*! 6706 @brief a null value was read 6707 @return whether parsing should proceed 6708 */ 6709 virtual bool null() = 0; 6710 6711 /*! 6712 @brief a boolean value was read 6713 @param[in] val boolean value 6714 @return whether parsing should proceed 6715 */ 6716 virtual bool boolean(bool val) = 0; 6717 6718 /*! 6719 @brief an integer number was read 6720 @param[in] val integer value 6721 @return whether parsing should proceed 6722 */ 6723 virtual bool number_integer(number_integer_t val) = 0; 6724 6725 /*! 6726 @brief an unsigned integer number was read 6727 @param[in] val unsigned integer value 6728 @return whether parsing should proceed 6729 */ 6730 virtual bool number_unsigned(number_unsigned_t val) = 0; 6731 6732 /*! 6733 @brief a floating-point number was read 6734 @param[in] val floating-point value 6735 @param[in] s raw token value 6736 @return whether parsing should proceed 6737 */ 6738 virtual bool number_float(number_float_t val, const string_t& s) = 0; 6739 6740 /*! 6741 @brief a string value was read 6742 @param[in] val string value 6743 @return whether parsing should proceed 6744 @note It is safe to move the passed string value. 6745 */ 6746 virtual bool string(string_t& val) = 0; 6747 6748 /*! 6749 @brief a binary value was read 6750 @param[in] val binary value 6751 @return whether parsing should proceed 6752 @note It is safe to move the passed binary value. 6753 */ 6754 virtual bool binary(binary_t& val) = 0; 6755 6756 /*! 6757 @brief the beginning of an object was read 6758 @param[in] elements number of object elements or -1 if unknown 6759 @return whether parsing should proceed 6760 @note binary formats may report the number of elements 6761 */ 6762 virtual bool start_object(std::size_t elements) = 0; 6763 6764 /*! 6765 @brief an object key was read 6766 @param[in] val object key 6767 @return whether parsing should proceed 6768 @note It is safe to move the passed string. 6769 */ 6770 virtual bool key(string_t& val) = 0; 6771 6772 /*! 6773 @brief the end of an object was read 6774 @return whether parsing should proceed 6775 */ 6776 virtual bool end_object() = 0; 6777 6778 /*! 6779 @brief the beginning of an array was read 6780 @param[in] elements number of array elements or -1 if unknown 6781 @return whether parsing should proceed 6782 @note binary formats may report the number of elements 6783 */ 6784 virtual bool start_array(std::size_t elements) = 0; 6785 6786 /*! 6787 @brief the end of an array was read 6788 @return whether parsing should proceed 6789 */ 6790 virtual bool end_array() = 0; 6791 6792 /*! 6793 @brief a parse error occurred 6794 @param[in] position the position in the input where the error occurs 6795 @param[in] last_token the last read token 6796 @param[in] ex an exception object describing the error 6797 @return whether parsing should proceed (must return false) 6798 */ 6799 virtual bool parse_error(std::size_t position, 6800 const std::string& last_token, 6801 const detail::exception& ex) = 0; 6802 6803 json_sax() = default; 6804 json_sax(const json_sax&) = default; 6805 json_sax(json_sax&&) noexcept = default; 6806 json_sax& operator=(const json_sax&) = default; 6807 json_sax& operator=(json_sax&&) noexcept = default; 6808 virtual ~json_sax() = default; 6809 }; 6810 6811 namespace detail 6812 { 6813 /*! 6814 @brief SAX implementation to create a JSON value from SAX events 6815 6816 This class implements the @ref json_sax interface and processes the SAX events 6817 to create a JSON value which makes it basically a DOM parser. The structure or 6818 hierarchy of the JSON value is managed by the stack `ref_stack` which contains 6819 a pointer to the respective array or object for each recursion depth. 6820 6821 After successful parsing, the value that is passed by reference to the 6822 constructor contains the parsed value. 6823 6824 @tparam BasicJsonType the JSON type 6825 */ 6826 template<typename BasicJsonType> 6827 class json_sax_dom_parser 6828 { 6829 public: 6830 using number_integer_t = typename BasicJsonType::number_integer_t; 6831 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 6832 using number_float_t = typename BasicJsonType::number_float_t; 6833 using string_t = typename BasicJsonType::string_t; 6834 using binary_t = typename BasicJsonType::binary_t; 6835 6836 /*! 6837 @param[in,out] r reference to a JSON value that is manipulated while 6838 parsing 6839 @param[in] allow_exceptions_ whether parse errors yield exceptions 6840 */ 6841 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) 6842 : root(r), allow_exceptions(allow_exceptions_) 6843 {} 6844 6845 // make class move-only 6846 json_sax_dom_parser(const json_sax_dom_parser&) = delete; 6847 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 6848 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; 6849 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 6850 ~json_sax_dom_parser() = default; 6851 6852 bool null() 6853 { 6854 handle_value(nullptr); 6855 return true; 6856 } 6857 6858 bool boolean(bool val) 6859 { 6860 handle_value(val); 6861 return true; 6862 } 6863 6864 bool number_integer(number_integer_t val) 6865 { 6866 handle_value(val); 6867 return true; 6868 } 6869 6870 bool number_unsigned(number_unsigned_t val) 6871 { 6872 handle_value(val); 6873 return true; 6874 } 6875 6876 bool number_float(number_float_t val, const string_t& /*unused*/) 6877 { 6878 handle_value(val); 6879 return true; 6880 } 6881 6882 bool string(string_t& val) 6883 { 6884 handle_value(val); 6885 return true; 6886 } 6887 6888 bool binary(binary_t& val) 6889 { 6890 handle_value(std::move(val)); 6891 return true; 6892 } 6893 6894 bool start_object(std::size_t len) 6895 { 6896 ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); 6897 6898 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 6899 { 6900 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); 6901 } 6902 6903 return true; 6904 } 6905 6906 bool key(string_t& val) 6907 { 6908 JSON_ASSERT(!ref_stack.empty()); 6909 JSON_ASSERT(ref_stack.back()->is_object()); 6910 6911 // add null at given key and store the reference for later 6912 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); 6913 return true; 6914 } 6915 6916 bool end_object() 6917 { 6918 JSON_ASSERT(!ref_stack.empty()); 6919 JSON_ASSERT(ref_stack.back()->is_object()); 6920 6921 ref_stack.back()->set_parents(); 6922 ref_stack.pop_back(); 6923 return true; 6924 } 6925 6926 bool start_array(std::size_t len) 6927 { 6928 ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); 6929 6930 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 6931 { 6932 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); 6933 } 6934 6935 return true; 6936 } 6937 6938 bool end_array() 6939 { 6940 JSON_ASSERT(!ref_stack.empty()); 6941 JSON_ASSERT(ref_stack.back()->is_array()); 6942 6943 ref_stack.back()->set_parents(); 6944 ref_stack.pop_back(); 6945 return true; 6946 } 6947 6948 template<class Exception> 6949 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, 6950 const Exception& ex) 6951 { 6952 errored = true; 6953 static_cast<void>(ex); 6954 if (allow_exceptions) 6955 { 6956 JSON_THROW(ex); 6957 } 6958 return false; 6959 } 6960 6961 constexpr bool is_errored() const 6962 { 6963 return errored; 6964 } 6965 6966 private: 6967 /*! 6968 @invariant If the ref stack is empty, then the passed value will be the new 6969 root. 6970 @invariant If the ref stack contains a value, then it is an array or an 6971 object to which we can add elements 6972 */ 6973 template<typename Value> 6974 JSON_HEDLEY_RETURNS_NON_NULL 6975 BasicJsonType* handle_value(Value&& v) 6976 { 6977 if (ref_stack.empty()) 6978 { 6979 root = BasicJsonType(std::forward<Value>(v)); 6980 return &root; 6981 } 6982 6983 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); 6984 6985 if (ref_stack.back()->is_array()) 6986 { 6987 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v)); 6988 return &(ref_stack.back()->m_data.m_value.array->back()); 6989 } 6990 6991 JSON_ASSERT(ref_stack.back()->is_object()); 6992 JSON_ASSERT(object_element); 6993 *object_element = BasicJsonType(std::forward<Value>(v)); 6994 return object_element; 6995 } 6996 6997 /// the parsed JSON value 6998 BasicJsonType& root; 6999 /// stack to model hierarchy of values 7000 std::vector<BasicJsonType*> ref_stack {}; 7001 /// helper to hold the reference for the next object element 7002 BasicJsonType* object_element = nullptr; 7003 /// whether a syntax error occurred 7004 bool errored = false; 7005 /// whether to throw exceptions in case of errors 7006 const bool allow_exceptions = true; 7007 }; 7008 7009 template<typename BasicJsonType> 7010 class json_sax_dom_callback_parser 7011 { 7012 public: 7013 using number_integer_t = typename BasicJsonType::number_integer_t; 7014 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 7015 using number_float_t = typename BasicJsonType::number_float_t; 7016 using string_t = typename BasicJsonType::string_t; 7017 using binary_t = typename BasicJsonType::binary_t; 7018 using parser_callback_t = typename BasicJsonType::parser_callback_t; 7019 using parse_event_t = typename BasicJsonType::parse_event_t; 7020 7021 json_sax_dom_callback_parser(BasicJsonType& r, 7022 const parser_callback_t cb, 7023 const bool allow_exceptions_ = true) 7024 : root(r), callback(cb), allow_exceptions(allow_exceptions_) 7025 { 7026 keep_stack.push_back(true); 7027 } 7028 7029 // make class move-only 7030 json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; 7031 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7032 json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; 7033 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7034 ~json_sax_dom_callback_parser() = default; 7035 7036 bool null() 7037 { 7038 handle_value(nullptr); 7039 return true; 7040 } 7041 7042 bool boolean(bool val) 7043 { 7044 handle_value(val); 7045 return true; 7046 } 7047 7048 bool number_integer(number_integer_t val) 7049 { 7050 handle_value(val); 7051 return true; 7052 } 7053 7054 bool number_unsigned(number_unsigned_t val) 7055 { 7056 handle_value(val); 7057 return true; 7058 } 7059 7060 bool number_float(number_float_t val, const string_t& /*unused*/) 7061 { 7062 handle_value(val); 7063 return true; 7064 } 7065 7066 bool string(string_t& val) 7067 { 7068 handle_value(val); 7069 return true; 7070 } 7071 7072 bool binary(binary_t& val) 7073 { 7074 handle_value(std::move(val)); 7075 return true; 7076 } 7077 7078 bool start_object(std::size_t len) 7079 { 7080 // check callback for object start 7081 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded); 7082 keep_stack.push_back(keep); 7083 7084 auto val = handle_value(BasicJsonType::value_t::object, true); 7085 ref_stack.push_back(val.second); 7086 7087 // check object limit 7088 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 7089 { 7090 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); 7091 } 7092 7093 return true; 7094 } 7095 7096 bool key(string_t& val) 7097 { 7098 BasicJsonType k = BasicJsonType(val); 7099 7100 // check callback for key 7101 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k); 7102 key_keep_stack.push_back(keep); 7103 7104 // add discarded value at given key and store the reference for later 7105 if (keep && ref_stack.back()) 7106 { 7107 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); 7108 } 7109 7110 return true; 7111 } 7112 7113 bool end_object() 7114 { 7115 if (ref_stack.back()) 7116 { 7117 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) 7118 { 7119 // discard object 7120 *ref_stack.back() = discarded; 7121 } 7122 else 7123 { 7124 ref_stack.back()->set_parents(); 7125 } 7126 } 7127 7128 JSON_ASSERT(!ref_stack.empty()); 7129 JSON_ASSERT(!keep_stack.empty()); 7130 ref_stack.pop_back(); 7131 keep_stack.pop_back(); 7132 7133 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) 7134 { 7135 // remove discarded value 7136 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) 7137 { 7138 if (it->is_discarded()) 7139 { 7140 ref_stack.back()->erase(it); 7141 break; 7142 } 7143 } 7144 } 7145 7146 return true; 7147 } 7148 7149 bool start_array(std::size_t len) 7150 { 7151 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded); 7152 keep_stack.push_back(keep); 7153 7154 auto val = handle_value(BasicJsonType::value_t::array, true); 7155 ref_stack.push_back(val.second); 7156 7157 // check array limit 7158 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size())) 7159 { 7160 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); 7161 } 7162 7163 return true; 7164 } 7165 7166 bool end_array() 7167 { 7168 bool keep = true; 7169 7170 if (ref_stack.back()) 7171 { 7172 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); 7173 if (keep) 7174 { 7175 ref_stack.back()->set_parents(); 7176 } 7177 else 7178 { 7179 // discard array 7180 *ref_stack.back() = discarded; 7181 } 7182 } 7183 7184 JSON_ASSERT(!ref_stack.empty()); 7185 JSON_ASSERT(!keep_stack.empty()); 7186 ref_stack.pop_back(); 7187 keep_stack.pop_back(); 7188 7189 // remove discarded value 7190 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) 7191 { 7192 ref_stack.back()->m_data.m_value.array->pop_back(); 7193 } 7194 7195 return true; 7196 } 7197 7198 template<class Exception> 7199 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, 7200 const Exception& ex) 7201 { 7202 errored = true; 7203 static_cast<void>(ex); 7204 if (allow_exceptions) 7205 { 7206 JSON_THROW(ex); 7207 } 7208 return false; 7209 } 7210 7211 constexpr bool is_errored() const 7212 { 7213 return errored; 7214 } 7215 7216 private: 7217 /*! 7218 @param[in] v value to add to the JSON value we build during parsing 7219 @param[in] skip_callback whether we should skip calling the callback 7220 function; this is required after start_array() and 7221 start_object() SAX events, because otherwise we would call the 7222 callback function with an empty array or object, respectively. 7223 7224 @invariant If the ref stack is empty, then the passed value will be the new 7225 root. 7226 @invariant If the ref stack contains a value, then it is an array or an 7227 object to which we can add elements 7228 7229 @return pair of boolean (whether value should be kept) and pointer (to the 7230 passed value in the ref_stack hierarchy; nullptr if not kept) 7231 */ 7232 template<typename Value> 7233 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false) 7234 { 7235 JSON_ASSERT(!keep_stack.empty()); 7236 7237 // do not handle this value if we know it would be added to a discarded 7238 // container 7239 if (!keep_stack.back()) 7240 { 7241 return {false, nullptr}; 7242 } 7243 7244 // create value 7245 auto value = BasicJsonType(std::forward<Value>(v)); 7246 7247 // check callback 7248 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value); 7249 7250 // do not handle this value if we just learnt it shall be discarded 7251 if (!keep) 7252 { 7253 return {false, nullptr}; 7254 } 7255 7256 if (ref_stack.empty()) 7257 { 7258 root = std::move(value); 7259 return {true, & root}; 7260 } 7261 7262 // skip this value if we already decided to skip the parent 7263 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) 7264 if (!ref_stack.back()) 7265 { 7266 return {false, nullptr}; 7267 } 7268 7269 // we now only expect arrays and objects 7270 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); 7271 7272 // array 7273 if (ref_stack.back()->is_array()) 7274 { 7275 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); 7276 return {true, & (ref_stack.back()->m_data.m_value.array->back())}; 7277 } 7278 7279 // object 7280 JSON_ASSERT(ref_stack.back()->is_object()); 7281 // check if we should store an element for the current key 7282 JSON_ASSERT(!key_keep_stack.empty()); 7283 const bool store_element = key_keep_stack.back(); 7284 key_keep_stack.pop_back(); 7285 7286 if (!store_element) 7287 { 7288 return {false, nullptr}; 7289 } 7290 7291 JSON_ASSERT(object_element); 7292 *object_element = std::move(value); 7293 return {true, object_element}; 7294 } 7295 7296 /// the parsed JSON value 7297 BasicJsonType& root; 7298 /// stack to model hierarchy of values 7299 std::vector<BasicJsonType*> ref_stack {}; 7300 /// stack to manage which values to keep 7301 std::vector<bool> keep_stack {}; 7302 /// stack to manage which object keys to keep 7303 std::vector<bool> key_keep_stack {}; 7304 /// helper to hold the reference for the next object element 7305 BasicJsonType* object_element = nullptr; 7306 /// whether a syntax error occurred 7307 bool errored = false; 7308 /// callback function 7309 const parser_callback_t callback = nullptr; 7310 /// whether to throw exceptions in case of errors 7311 const bool allow_exceptions = true; 7312 /// a discarded value for the callback 7313 BasicJsonType discarded = BasicJsonType::value_t::discarded; 7314 }; 7315 7316 template<typename BasicJsonType> 7317 class json_sax_acceptor 7318 { 7319 public: 7320 using number_integer_t = typename BasicJsonType::number_integer_t; 7321 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 7322 using number_float_t = typename BasicJsonType::number_float_t; 7323 using string_t = typename BasicJsonType::string_t; 7324 using binary_t = typename BasicJsonType::binary_t; 7325 7326 bool null() 7327 { 7328 return true; 7329 } 7330 7331 bool boolean(bool /*unused*/) 7332 { 7333 return true; 7334 } 7335 7336 bool number_integer(number_integer_t /*unused*/) 7337 { 7338 return true; 7339 } 7340 7341 bool number_unsigned(number_unsigned_t /*unused*/) 7342 { 7343 return true; 7344 } 7345 7346 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) 7347 { 7348 return true; 7349 } 7350 7351 bool string(string_t& /*unused*/) 7352 { 7353 return true; 7354 } 7355 7356 bool binary(binary_t& /*unused*/) 7357 { 7358 return true; 7359 } 7360 7361 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) 7362 { 7363 return true; 7364 } 7365 7366 bool key(string_t& /*unused*/) 7367 { 7368 return true; 7369 } 7370 7371 bool end_object() 7372 { 7373 return true; 7374 } 7375 7376 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) 7377 { 7378 return true; 7379 } 7380 7381 bool end_array() 7382 { 7383 return true; 7384 } 7385 7386 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) 7387 { 7388 return false; 7389 } 7390 }; 7391 7392 } // namespace detail 7393 NLOHMANN_JSON_NAMESPACE_END 7394 7395 // #include <nlohmann/detail/input/lexer.hpp> 7396 // __ _____ _____ _____ 7397 // __| | __| | | | JSON for Modern C++ 7398 // | | |__ | | | | | | version 3.11.3 7399 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 7400 // 7401 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 7402 // SPDX-License-Identifier: MIT 7403 7404 7405 7406 #include <array> // array 7407 #include <clocale> // localeconv 7408 #include <cstddef> // size_t 7409 #include <cstdio> // snprintf 7410 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull 7411 #include <initializer_list> // initializer_list 7412 #include <string> // char_traits, string 7413 #include <utility> // move 7414 #include <vector> // vector 7415 7416 // #include <nlohmann/detail/input/input_adapters.hpp> 7417 7418 // #include <nlohmann/detail/input/position_t.hpp> 7419 7420 // #include <nlohmann/detail/macro_scope.hpp> 7421 7422 // #include <nlohmann/detail/meta/type_traits.hpp> 7423 7424 7425 NLOHMANN_JSON_NAMESPACE_BEGIN 7426 namespace detail 7427 { 7428 7429 /////////// 7430 // lexer // 7431 /////////// 7432 7433 template<typename BasicJsonType> 7434 class lexer_base 7435 { 7436 public: 7437 /// token types for the parser 7438 enum class token_type 7439 { 7440 uninitialized, ///< indicating the scanner is uninitialized 7441 literal_true, ///< the `true` literal 7442 literal_false, ///< the `false` literal 7443 literal_null, ///< the `null` literal 7444 value_string, ///< a string -- use get_string() for actual value 7445 value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value 7446 value_integer, ///< a signed integer -- use get_number_integer() for actual value 7447 value_float, ///< an floating point number -- use get_number_float() for actual value 7448 begin_array, ///< the character for array begin `[` 7449 begin_object, ///< the character for object begin `{` 7450 end_array, ///< the character for array end `]` 7451 end_object, ///< the character for object end `}` 7452 name_separator, ///< the name separator `:` 7453 value_separator, ///< the value separator `,` 7454 parse_error, ///< indicating a parse error 7455 end_of_input, ///< indicating the end of the input buffer 7456 literal_or_value ///< a literal or the begin of a value (only for diagnostics) 7457 }; 7458 7459 /// return name of values of type token_type (only used for errors) 7460 JSON_HEDLEY_RETURNS_NON_NULL 7461 JSON_HEDLEY_CONST 7462 static const char* token_type_name(const token_type t) noexcept 7463 { 7464 switch (t) 7465 { 7466 case token_type::uninitialized: 7467 return "<uninitialized>"; 7468 case token_type::literal_true: 7469 return "true literal"; 7470 case token_type::literal_false: 7471 return "false literal"; 7472 case token_type::literal_null: 7473 return "null literal"; 7474 case token_type::value_string: 7475 return "string literal"; 7476 case token_type::value_unsigned: 7477 case token_type::value_integer: 7478 case token_type::value_float: 7479 return "number literal"; 7480 case token_type::begin_array: 7481 return "'['"; 7482 case token_type::begin_object: 7483 return "'{'"; 7484 case token_type::end_array: 7485 return "']'"; 7486 case token_type::end_object: 7487 return "'}'"; 7488 case token_type::name_separator: 7489 return "':'"; 7490 case token_type::value_separator: 7491 return "','"; 7492 case token_type::parse_error: 7493 return "<parse error>"; 7494 case token_type::end_of_input: 7495 return "end of input"; 7496 case token_type::literal_or_value: 7497 return "'[', '{', or a literal"; 7498 // LCOV_EXCL_START 7499 default: // catch non-enum values 7500 return "unknown token"; 7501 // LCOV_EXCL_STOP 7502 } 7503 } 7504 }; 7505 /*! 7506 @brief lexical analysis 7507 7508 This class organizes the lexical analysis during JSON deserialization. 7509 */ 7510 template<typename BasicJsonType, typename InputAdapterType> 7511 class lexer : public lexer_base<BasicJsonType> 7512 { 7513 using number_integer_t = typename BasicJsonType::number_integer_t; 7514 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 7515 using number_float_t = typename BasicJsonType::number_float_t; 7516 using string_t = typename BasicJsonType::string_t; 7517 using char_type = typename InputAdapterType::char_type; 7518 using char_int_type = typename char_traits<char_type>::int_type; 7519 7520 public: 7521 using token_type = typename lexer_base<BasicJsonType>::token_type; 7522 7523 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept 7524 : ia(std::move(adapter)) 7525 , ignore_comments(ignore_comments_) 7526 , decimal_point_char(static_cast<char_int_type>(get_decimal_point())) 7527 {} 7528 7529 // delete because of pointer members 7530 lexer(const lexer&) = delete; 7531 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7532 lexer& operator=(lexer&) = delete; 7533 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 7534 ~lexer() = default; 7535 7536 private: 7537 ///////////////////// 7538 // locales 7539 ///////////////////// 7540 7541 /// return the locale-dependent decimal point 7542 JSON_HEDLEY_PURE 7543 static char get_decimal_point() noexcept 7544 { 7545 const auto* loc = localeconv(); 7546 JSON_ASSERT(loc != nullptr); 7547 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); 7548 } 7549 7550 ///////////////////// 7551 // scan functions 7552 ///////////////////// 7553 7554 /*! 7555 @brief get codepoint from 4 hex characters following `\u` 7556 7557 For input "\u c1 c2 c3 c4" the codepoint is: 7558 (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 7559 = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) 7560 7561 Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' 7562 must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The 7563 conversion is done by subtracting the offset (0x30, 0x37, and 0x57) 7564 between the ASCII value of the character and the desired integer value. 7565 7566 @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or 7567 non-hex character) 7568 */ 7569 int get_codepoint() 7570 { 7571 // this function only makes sense after reading `\u` 7572 JSON_ASSERT(current == 'u'); 7573 int codepoint = 0; 7574 7575 const auto factors = { 12u, 8u, 4u, 0u }; 7576 for (const auto factor : factors) 7577 { 7578 get(); 7579 7580 if (current >= '0' && current <= '9') 7581 { 7582 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor); 7583 } 7584 else if (current >= 'A' && current <= 'F') 7585 { 7586 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor); 7587 } 7588 else if (current >= 'a' && current <= 'f') 7589 { 7590 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor); 7591 } 7592 else 7593 { 7594 return -1; 7595 } 7596 } 7597 7598 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); 7599 return codepoint; 7600 } 7601 7602 /*! 7603 @brief check if the next byte(s) are inside a given range 7604 7605 Adds the current byte and, for each passed range, reads a new byte and 7606 checks if it is inside the range. If a violation was detected, set up an 7607 error message and return false. Otherwise, return true. 7608 7609 @param[in] ranges list of integers; interpreted as list of pairs of 7610 inclusive lower and upper bound, respectively 7611 7612 @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, 7613 1, 2, or 3 pairs. This precondition is enforced by an assertion. 7614 7615 @return true if and only if no range violation was detected 7616 */ 7617 bool next_byte_in_range(std::initializer_list<char_int_type> ranges) 7618 { 7619 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); 7620 add(current); 7621 7622 for (auto range = ranges.begin(); range != ranges.end(); ++range) 7623 { 7624 get(); 7625 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions) 7626 { 7627 add(current); 7628 } 7629 else 7630 { 7631 error_message = "invalid string: ill-formed UTF-8 byte"; 7632 return false; 7633 } 7634 } 7635 7636 return true; 7637 } 7638 7639 /*! 7640 @brief scan a string literal 7641 7642 This function scans a string according to Sect. 7 of RFC 8259. While 7643 scanning, bytes are escaped and copied into buffer token_buffer. Then the 7644 function returns successfully, token_buffer is *not* null-terminated (as it 7645 may contain \0 bytes), and token_buffer.size() is the number of bytes in the 7646 string. 7647 7648 @return token_type::value_string if string could be successfully scanned, 7649 token_type::parse_error otherwise 7650 7651 @note In case of errors, variable error_message contains a textual 7652 description. 7653 */ 7654 token_type scan_string() 7655 { 7656 // reset token_buffer (ignore opening quote) 7657 reset(); 7658 7659 // we entered the function by reading an open quote 7660 JSON_ASSERT(current == '\"'); 7661 7662 while (true) 7663 { 7664 // get next character 7665 switch (get()) 7666 { 7667 // end of file while parsing string 7668 case char_traits<char_type>::eof(): 7669 { 7670 error_message = "invalid string: missing closing quote"; 7671 return token_type::parse_error; 7672 } 7673 7674 // closing quote 7675 case '\"': 7676 { 7677 return token_type::value_string; 7678 } 7679 7680 // escapes 7681 case '\\': 7682 { 7683 switch (get()) 7684 { 7685 // quotation mark 7686 case '\"': 7687 add('\"'); 7688 break; 7689 // reverse solidus 7690 case '\\': 7691 add('\\'); 7692 break; 7693 // solidus 7694 case '/': 7695 add('/'); 7696 break; 7697 // backspace 7698 case 'b': 7699 add('\b'); 7700 break; 7701 // form feed 7702 case 'f': 7703 add('\f'); 7704 break; 7705 // line feed 7706 case 'n': 7707 add('\n'); 7708 break; 7709 // carriage return 7710 case 'r': 7711 add('\r'); 7712 break; 7713 // tab 7714 case 't': 7715 add('\t'); 7716 break; 7717 7718 // unicode escapes 7719 case 'u': 7720 { 7721 const int codepoint1 = get_codepoint(); 7722 int codepoint = codepoint1; // start with codepoint1 7723 7724 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) 7725 { 7726 error_message = "invalid string: '\\u' must be followed by 4 hex digits"; 7727 return token_type::parse_error; 7728 } 7729 7730 // check if code point is a high surrogate 7731 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) 7732 { 7733 // expect next \uxxxx entry 7734 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) 7735 { 7736 const int codepoint2 = get_codepoint(); 7737 7738 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) 7739 { 7740 error_message = "invalid string: '\\u' must be followed by 4 hex digits"; 7741 return token_type::parse_error; 7742 } 7743 7744 // check if codepoint2 is a low surrogate 7745 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) 7746 { 7747 // overwrite codepoint 7748 codepoint = static_cast<int>( 7749 // high surrogate occupies the most significant 22 bits 7750 (static_cast<unsigned int>(codepoint1) << 10u) 7751 // low surrogate occupies the least significant 15 bits 7752 + static_cast<unsigned int>(codepoint2) 7753 // there is still the 0xD800, 0xDC00 and 0x10000 noise 7754 // in the result, so we have to subtract with: 7755 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 7756 - 0x35FDC00u); 7757 } 7758 else 7759 { 7760 // ICU PATCH - See ICU-23090 7761 codepoint = codepoint1; 7762 } 7763 } 7764 else 7765 { 7766 // ICU PATCH - See ICU-23090 7767 codepoint = codepoint1; 7768 } 7769 } 7770 else 7771 { 7772 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) 7773 { 7774 // ICU PATCH - See ICU-23090 7775 codepoint = codepoint1; 7776 } 7777 } 7778 7779 // result of the above calculation yields a proper codepoint 7780 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); 7781 7782 // translate codepoint into bytes 7783 if (codepoint < 0x80) 7784 { 7785 // 1-byte characters: 0xxxxxxx (ASCII) 7786 add(static_cast<char_int_type>(codepoint)); 7787 } 7788 else if (codepoint <= 0x7FF) 7789 { 7790 // 2-byte characters: 110xxxxx 10xxxxxx 7791 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u))); 7792 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); 7793 } 7794 else if (codepoint <= 0xFFFF) 7795 { 7796 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx 7797 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u))); 7798 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu))); 7799 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); 7800 } 7801 else 7802 { 7803 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 7804 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u))); 7805 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu))); 7806 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu))); 7807 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu))); 7808 } 7809 7810 break; 7811 } 7812 7813 // other characters after escape 7814 default: 7815 error_message = "invalid string: forbidden character after backslash"; 7816 return token_type::parse_error; 7817 } 7818 7819 break; 7820 } 7821 7822 // invalid control characters 7823 case 0x00: 7824 { 7825 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; 7826 return token_type::parse_error; 7827 } 7828 7829 case 0x01: 7830 { 7831 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; 7832 return token_type::parse_error; 7833 } 7834 7835 case 0x02: 7836 { 7837 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; 7838 return token_type::parse_error; 7839 } 7840 7841 case 0x03: 7842 { 7843 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; 7844 return token_type::parse_error; 7845 } 7846 7847 case 0x04: 7848 { 7849 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; 7850 return token_type::parse_error; 7851 } 7852 7853 case 0x05: 7854 { 7855 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; 7856 return token_type::parse_error; 7857 } 7858 7859 case 0x06: 7860 { 7861 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; 7862 return token_type::parse_error; 7863 } 7864 7865 case 0x07: 7866 { 7867 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; 7868 return token_type::parse_error; 7869 } 7870 7871 case 0x08: 7872 { 7873 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; 7874 return token_type::parse_error; 7875 } 7876 7877 case 0x09: 7878 { 7879 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; 7880 return token_type::parse_error; 7881 } 7882 7883 case 0x0A: 7884 { 7885 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; 7886 return token_type::parse_error; 7887 } 7888 7889 case 0x0B: 7890 { 7891 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; 7892 return token_type::parse_error; 7893 } 7894 7895 case 0x0C: 7896 { 7897 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; 7898 return token_type::parse_error; 7899 } 7900 7901 case 0x0D: 7902 { 7903 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; 7904 return token_type::parse_error; 7905 } 7906 7907 case 0x0E: 7908 { 7909 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; 7910 return token_type::parse_error; 7911 } 7912 7913 case 0x0F: 7914 { 7915 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; 7916 return token_type::parse_error; 7917 } 7918 7919 case 0x10: 7920 { 7921 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; 7922 return token_type::parse_error; 7923 } 7924 7925 case 0x11: 7926 { 7927 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; 7928 return token_type::parse_error; 7929 } 7930 7931 case 0x12: 7932 { 7933 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; 7934 return token_type::parse_error; 7935 } 7936 7937 case 0x13: 7938 { 7939 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; 7940 return token_type::parse_error; 7941 } 7942 7943 case 0x14: 7944 { 7945 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; 7946 return token_type::parse_error; 7947 } 7948 7949 case 0x15: 7950 { 7951 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; 7952 return token_type::parse_error; 7953 } 7954 7955 case 0x16: 7956 { 7957 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; 7958 return token_type::parse_error; 7959 } 7960 7961 case 0x17: 7962 { 7963 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; 7964 return token_type::parse_error; 7965 } 7966 7967 case 0x18: 7968 { 7969 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; 7970 return token_type::parse_error; 7971 } 7972 7973 case 0x19: 7974 { 7975 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; 7976 return token_type::parse_error; 7977 } 7978 7979 case 0x1A: 7980 { 7981 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; 7982 return token_type::parse_error; 7983 } 7984 7985 case 0x1B: 7986 { 7987 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; 7988 return token_type::parse_error; 7989 } 7990 7991 case 0x1C: 7992 { 7993 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; 7994 return token_type::parse_error; 7995 } 7996 7997 case 0x1D: 7998 { 7999 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; 8000 return token_type::parse_error; 8001 } 8002 8003 case 0x1E: 8004 { 8005 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; 8006 return token_type::parse_error; 8007 } 8008 8009 case 0x1F: 8010 { 8011 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; 8012 return token_type::parse_error; 8013 } 8014 8015 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) 8016 case 0x20: 8017 case 0x21: 8018 case 0x23: 8019 case 0x24: 8020 case 0x25: 8021 case 0x26: 8022 case 0x27: 8023 case 0x28: 8024 case 0x29: 8025 case 0x2A: 8026 case 0x2B: 8027 case 0x2C: 8028 case 0x2D: 8029 case 0x2E: 8030 case 0x2F: 8031 case 0x30: 8032 case 0x31: 8033 case 0x32: 8034 case 0x33: 8035 case 0x34: 8036 case 0x35: 8037 case 0x36: 8038 case 0x37: 8039 case 0x38: 8040 case 0x39: 8041 case 0x3A: 8042 case 0x3B: 8043 case 0x3C: 8044 case 0x3D: 8045 case 0x3E: 8046 case 0x3F: 8047 case 0x40: 8048 case 0x41: 8049 case 0x42: 8050 case 0x43: 8051 case 0x44: 8052 case 0x45: 8053 case 0x46: 8054 case 0x47: 8055 case 0x48: 8056 case 0x49: 8057 case 0x4A: 8058 case 0x4B: 8059 case 0x4C: 8060 case 0x4D: 8061 case 0x4E: 8062 case 0x4F: 8063 case 0x50: 8064 case 0x51: 8065 case 0x52: 8066 case 0x53: 8067 case 0x54: 8068 case 0x55: 8069 case 0x56: 8070 case 0x57: 8071 case 0x58: 8072 case 0x59: 8073 case 0x5A: 8074 case 0x5B: 8075 case 0x5D: 8076 case 0x5E: 8077 case 0x5F: 8078 case 0x60: 8079 case 0x61: 8080 case 0x62: 8081 case 0x63: 8082 case 0x64: 8083 case 0x65: 8084 case 0x66: 8085 case 0x67: 8086 case 0x68: 8087 case 0x69: 8088 case 0x6A: 8089 case 0x6B: 8090 case 0x6C: 8091 case 0x6D: 8092 case 0x6E: 8093 case 0x6F: 8094 case 0x70: 8095 case 0x71: 8096 case 0x72: 8097 case 0x73: 8098 case 0x74: 8099 case 0x75: 8100 case 0x76: 8101 case 0x77: 8102 case 0x78: 8103 case 0x79: 8104 case 0x7A: 8105 case 0x7B: 8106 case 0x7C: 8107 case 0x7D: 8108 case 0x7E: 8109 case 0x7F: 8110 { 8111 add(current); 8112 break; 8113 } 8114 8115 // U+0080..U+07FF: bytes C2..DF 80..BF 8116 case 0xC2: 8117 case 0xC3: 8118 case 0xC4: 8119 case 0xC5: 8120 case 0xC6: 8121 case 0xC7: 8122 case 0xC8: 8123 case 0xC9: 8124 case 0xCA: 8125 case 0xCB: 8126 case 0xCC: 8127 case 0xCD: 8128 case 0xCE: 8129 case 0xCF: 8130 case 0xD0: 8131 case 0xD1: 8132 case 0xD2: 8133 case 0xD3: 8134 case 0xD4: 8135 case 0xD5: 8136 case 0xD6: 8137 case 0xD7: 8138 case 0xD8: 8139 case 0xD9: 8140 case 0xDA: 8141 case 0xDB: 8142 case 0xDC: 8143 case 0xDD: 8144 case 0xDE: 8145 case 0xDF: 8146 { 8147 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) 8148 { 8149 return token_type::parse_error; 8150 } 8151 break; 8152 } 8153 8154 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF 8155 case 0xE0: 8156 { 8157 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) 8158 { 8159 return token_type::parse_error; 8160 } 8161 break; 8162 } 8163 8164 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF 8165 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF 8166 case 0xE1: 8167 case 0xE2: 8168 case 0xE3: 8169 case 0xE4: 8170 case 0xE5: 8171 case 0xE6: 8172 case 0xE7: 8173 case 0xE8: 8174 case 0xE9: 8175 case 0xEA: 8176 case 0xEB: 8177 case 0xEC: 8178 case 0xEE: 8179 case 0xEF: 8180 { 8181 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) 8182 { 8183 return token_type::parse_error; 8184 } 8185 break; 8186 } 8187 8188 // U+D000..U+D7FF: bytes ED 80..9F 80..BF 8189 case 0xED: 8190 { 8191 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) 8192 { 8193 return token_type::parse_error; 8194 } 8195 break; 8196 } 8197 8198 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF 8199 case 0xF0: 8200 { 8201 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) 8202 { 8203 return token_type::parse_error; 8204 } 8205 break; 8206 } 8207 8208 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF 8209 case 0xF1: 8210 case 0xF2: 8211 case 0xF3: 8212 { 8213 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) 8214 { 8215 return token_type::parse_error; 8216 } 8217 break; 8218 } 8219 8220 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF 8221 case 0xF4: 8222 { 8223 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) 8224 { 8225 return token_type::parse_error; 8226 } 8227 break; 8228 } 8229 8230 // remaining bytes (80..C1 and F5..FF) are ill-formed 8231 default: 8232 { 8233 error_message = "invalid string: ill-formed UTF-8 byte"; 8234 return token_type::parse_error; 8235 } 8236 } 8237 } 8238 } 8239 8240 /*! 8241 * @brief scan a comment 8242 * @return whether comment could be scanned successfully 8243 */ 8244 bool scan_comment() 8245 { 8246 switch (get()) 8247 { 8248 // single-line comments skip input until a newline or EOF is read 8249 case '/': 8250 { 8251 while (true) 8252 { 8253 switch (get()) 8254 { 8255 case '\n': 8256 case '\r': 8257 case char_traits<char_type>::eof(): 8258 case '\0': 8259 return true; 8260 8261 default: 8262 break; 8263 } 8264 } 8265 } 8266 8267 // multi-line comments skip input until */ is read 8268 case '*': 8269 { 8270 while (true) 8271 { 8272 switch (get()) 8273 { 8274 case char_traits<char_type>::eof(): 8275 case '\0': 8276 { 8277 error_message = "invalid comment; missing closing '*/'"; 8278 return false; 8279 } 8280 8281 case '*': 8282 { 8283 switch (get()) 8284 { 8285 case '/': 8286 return true; 8287 8288 default: 8289 { 8290 unget(); 8291 continue; 8292 } 8293 } 8294 } 8295 8296 default: 8297 continue; 8298 } 8299 } 8300 } 8301 8302 // unexpected character after reading '/' 8303 default: 8304 { 8305 error_message = "invalid comment; expecting '/' or '*' after '/'"; 8306 return false; 8307 } 8308 } 8309 } 8310 8311 JSON_HEDLEY_NON_NULL(2) 8312 static void strtof(float& f, const char* str, char** endptr) noexcept 8313 { 8314 f = std::strtof(str, endptr); 8315 } 8316 8317 JSON_HEDLEY_NON_NULL(2) 8318 static void strtof(double& f, const char* str, char** endptr) noexcept 8319 { 8320 f = std::strtod(str, endptr); 8321 } 8322 8323 JSON_HEDLEY_NON_NULL(2) 8324 static void strtof(long double& f, const char* str, char** endptr) noexcept 8325 { 8326 f = std::strtold(str, endptr); 8327 } 8328 8329 /*! 8330 @brief scan a number literal 8331 8332 This function scans a string according to Sect. 6 of RFC 8259. 8333 8334 The function is realized with a deterministic finite state machine derived 8335 from the grammar described in RFC 8259. Starting in state "init", the 8336 input is read and used to determined the next state. Only state "done" 8337 accepts the number. State "error" is a trap state to model errors. In the 8338 table below, "anything" means any character but the ones listed before. 8339 8340 state | 0 | 1-9 | e E | + | - | . | anything 8341 ---------|----------|----------|----------|---------|---------|----------|----------- 8342 init | zero | any1 | [error] | [error] | minus | [error] | [error] 8343 minus | zero | any1 | [error] | [error] | [error] | [error] | [error] 8344 zero | done | done | exponent | done | done | decimal1 | done 8345 any1 | any1 | any1 | exponent | done | done | decimal1 | done 8346 decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] 8347 decimal2 | decimal2 | decimal2 | exponent | done | done | done | done 8348 exponent | any2 | any2 | [error] | sign | sign | [error] | [error] 8349 sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] 8350 any2 | any2 | any2 | done | done | done | done | done 8351 8352 The state machine is realized with one label per state (prefixed with 8353 "scan_number_") and `goto` statements between them. The state machine 8354 contains cycles, but any cycle can be left when EOF is read. Therefore, 8355 the function is guaranteed to terminate. 8356 8357 During scanning, the read bytes are stored in token_buffer. This string is 8358 then converted to a signed integer, an unsigned integer, or a 8359 floating-point number. 8360 8361 @return token_type::value_unsigned, token_type::value_integer, or 8362 token_type::value_float if number could be successfully scanned, 8363 token_type::parse_error otherwise 8364 8365 @note The scanner is independent of the current locale. Internally, the 8366 locale's decimal point is used instead of `.` to work with the 8367 locale-dependent converters. 8368 */ 8369 token_type scan_number() // lgtm [cpp/use-of-goto] 8370 { 8371 // reset token_buffer to store the number's bytes 8372 reset(); 8373 8374 // the type of the parsed number; initially set to unsigned; will be 8375 // changed if minus sign, decimal point or exponent is read 8376 token_type number_type = token_type::value_unsigned; 8377 8378 // state (init): we just found out we need to scan a number 8379 switch (current) 8380 { 8381 case '-': 8382 { 8383 add(current); 8384 goto scan_number_minus; 8385 } 8386 8387 case '0': 8388 { 8389 add(current); 8390 goto scan_number_zero; 8391 } 8392 8393 case '1': 8394 case '2': 8395 case '3': 8396 case '4': 8397 case '5': 8398 case '6': 8399 case '7': 8400 case '8': 8401 case '9': 8402 { 8403 add(current); 8404 goto scan_number_any1; 8405 } 8406 8407 // all other characters are rejected outside scan_number() 8408 default: // LCOV_EXCL_LINE 8409 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 8410 } 8411 8412 scan_number_minus: 8413 // state: we just parsed a leading minus sign 8414 number_type = token_type::value_integer; 8415 switch (get()) 8416 { 8417 case '0': 8418 { 8419 add(current); 8420 goto scan_number_zero; 8421 } 8422 8423 case '1': 8424 case '2': 8425 case '3': 8426 case '4': 8427 case '5': 8428 case '6': 8429 case '7': 8430 case '8': 8431 case '9': 8432 { 8433 add(current); 8434 goto scan_number_any1; 8435 } 8436 8437 default: 8438 { 8439 error_message = "invalid number; expected digit after '-'"; 8440 return token_type::parse_error; 8441 } 8442 } 8443 8444 scan_number_zero: 8445 // state: we just parse a zero (maybe with a leading minus sign) 8446 switch (get()) 8447 { 8448 case '.': 8449 { 8450 add(decimal_point_char); 8451 goto scan_number_decimal1; 8452 } 8453 8454 case 'e': 8455 case 'E': 8456 { 8457 add(current); 8458 goto scan_number_exponent; 8459 } 8460 8461 default: 8462 goto scan_number_done; 8463 } 8464 8465 scan_number_any1: 8466 // state: we just parsed a number 0-9 (maybe with a leading minus sign) 8467 switch (get()) 8468 { 8469 case '0': 8470 case '1': 8471 case '2': 8472 case '3': 8473 case '4': 8474 case '5': 8475 case '6': 8476 case '7': 8477 case '8': 8478 case '9': 8479 { 8480 add(current); 8481 goto scan_number_any1; 8482 } 8483 8484 case '.': 8485 { 8486 add(decimal_point_char); 8487 goto scan_number_decimal1; 8488 } 8489 8490 case 'e': 8491 case 'E': 8492 { 8493 add(current); 8494 goto scan_number_exponent; 8495 } 8496 8497 default: 8498 goto scan_number_done; 8499 } 8500 8501 scan_number_decimal1: 8502 // state: we just parsed a decimal point 8503 number_type = token_type::value_float; 8504 switch (get()) 8505 { 8506 case '0': 8507 case '1': 8508 case '2': 8509 case '3': 8510 case '4': 8511 case '5': 8512 case '6': 8513 case '7': 8514 case '8': 8515 case '9': 8516 { 8517 add(current); 8518 goto scan_number_decimal2; 8519 } 8520 8521 default: 8522 { 8523 error_message = "invalid number; expected digit after '.'"; 8524 return token_type::parse_error; 8525 } 8526 } 8527 8528 scan_number_decimal2: 8529 // we just parsed at least one number after a decimal point 8530 switch (get()) 8531 { 8532 case '0': 8533 case '1': 8534 case '2': 8535 case '3': 8536 case '4': 8537 case '5': 8538 case '6': 8539 case '7': 8540 case '8': 8541 case '9': 8542 { 8543 add(current); 8544 goto scan_number_decimal2; 8545 } 8546 8547 case 'e': 8548 case 'E': 8549 { 8550 add(current); 8551 goto scan_number_exponent; 8552 } 8553 8554 default: 8555 goto scan_number_done; 8556 } 8557 8558 scan_number_exponent: 8559 // we just parsed an exponent 8560 number_type = token_type::value_float; 8561 switch (get()) 8562 { 8563 case '+': 8564 case '-': 8565 { 8566 add(current); 8567 goto scan_number_sign; 8568 } 8569 8570 case '0': 8571 case '1': 8572 case '2': 8573 case '3': 8574 case '4': 8575 case '5': 8576 case '6': 8577 case '7': 8578 case '8': 8579 case '9': 8580 { 8581 add(current); 8582 goto scan_number_any2; 8583 } 8584 8585 default: 8586 { 8587 error_message = 8588 "invalid number; expected '+', '-', or digit after exponent"; 8589 return token_type::parse_error; 8590 } 8591 } 8592 8593 scan_number_sign: 8594 // we just parsed an exponent sign 8595 switch (get()) 8596 { 8597 case '0': 8598 case '1': 8599 case '2': 8600 case '3': 8601 case '4': 8602 case '5': 8603 case '6': 8604 case '7': 8605 case '8': 8606 case '9': 8607 { 8608 add(current); 8609 goto scan_number_any2; 8610 } 8611 8612 default: 8613 { 8614 error_message = "invalid number; expected digit after exponent sign"; 8615 return token_type::parse_error; 8616 } 8617 } 8618 8619 scan_number_any2: 8620 // we just parsed a number after the exponent or exponent sign 8621 switch (get()) 8622 { 8623 case '0': 8624 case '1': 8625 case '2': 8626 case '3': 8627 case '4': 8628 case '5': 8629 case '6': 8630 case '7': 8631 case '8': 8632 case '9': 8633 { 8634 add(current); 8635 goto scan_number_any2; 8636 } 8637 8638 default: 8639 goto scan_number_done; 8640 } 8641 8642 scan_number_done: 8643 // unget the character after the number (we only read it to know that 8644 // we are done scanning a number) 8645 unget(); 8646 8647 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 8648 errno = 0; 8649 8650 // try to parse integers first and fall back to floats 8651 if (number_type == token_type::value_unsigned) 8652 { 8653 const auto x = std::strtoull(token_buffer.data(), &endptr, 10); 8654 8655 // we checked the number format before 8656 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); 8657 8658 if (errno == 0) 8659 { 8660 value_unsigned = static_cast<number_unsigned_t>(x); 8661 if (value_unsigned == x) 8662 { 8663 return token_type::value_unsigned; 8664 } 8665 } 8666 } 8667 else if (number_type == token_type::value_integer) 8668 { 8669 const auto x = std::strtoll(token_buffer.data(), &endptr, 10); 8670 8671 // we checked the number format before 8672 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); 8673 8674 if (errno == 0) 8675 { 8676 value_integer = static_cast<number_integer_t>(x); 8677 if (value_integer == x) 8678 { 8679 return token_type::value_integer; 8680 } 8681 } 8682 } 8683 8684 // this code is reached if we parse a floating-point number or if an 8685 // integer conversion above failed 8686 strtof(value_float, token_buffer.data(), &endptr); 8687 8688 // we checked the number format before 8689 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); 8690 8691 return token_type::value_float; 8692 } 8693 8694 /*! 8695 @param[in] literal_text the literal text to expect 8696 @param[in] length the length of the passed literal text 8697 @param[in] return_type the token type to return on success 8698 */ 8699 JSON_HEDLEY_NON_NULL(2) 8700 token_type scan_literal(const char_type* literal_text, const std::size_t length, 8701 token_type return_type) 8702 { 8703 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]); 8704 for (std::size_t i = 1; i < length; ++i) 8705 { 8706 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i])) 8707 { 8708 error_message = "invalid literal"; 8709 return token_type::parse_error; 8710 } 8711 } 8712 return return_type; 8713 } 8714 8715 ///////////////////// 8716 // input management 8717 ///////////////////// 8718 8719 /// reset token_buffer; current character is beginning of token 8720 void reset() noexcept 8721 { 8722 token_buffer.clear(); 8723 token_string.clear(); 8724 token_string.push_back(char_traits<char_type>::to_char_type(current)); 8725 } 8726 8727 /* 8728 @brief get next character from the input 8729 8730 This function provides the interface to the used input adapter. It does 8731 not throw in case the input reached EOF, but returns a 8732 `char_traits<char>::eof()` in that case. Stores the scanned characters 8733 for use in error messages. 8734 8735 @return character read from the input 8736 */ 8737 char_int_type get() 8738 { 8739 ++position.chars_read_total; 8740 ++position.chars_read_current_line; 8741 8742 if (next_unget) 8743 { 8744 // just reset the next_unget variable and work with current 8745 next_unget = false; 8746 } 8747 else 8748 { 8749 current = ia.get_character(); 8750 } 8751 8752 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) 8753 { 8754 token_string.push_back(char_traits<char_type>::to_char_type(current)); 8755 } 8756 8757 if (current == '\n') 8758 { 8759 ++position.lines_read; 8760 position.chars_read_current_line = 0; 8761 } 8762 8763 return current; 8764 } 8765 8766 /*! 8767 @brief unget current character (read it again on next get) 8768 8769 We implement unget by setting variable next_unget to true. The input is not 8770 changed - we just simulate ungetting by modifying chars_read_total, 8771 chars_read_current_line, and token_string. The next call to get() will 8772 behave as if the unget character is read again. 8773 */ 8774 void unget() 8775 { 8776 next_unget = true; 8777 8778 --position.chars_read_total; 8779 8780 // in case we "unget" a newline, we have to also decrement the lines_read 8781 if (position.chars_read_current_line == 0) 8782 { 8783 if (position.lines_read > 0) 8784 { 8785 --position.lines_read; 8786 } 8787 } 8788 else 8789 { 8790 --position.chars_read_current_line; 8791 } 8792 8793 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof())) 8794 { 8795 JSON_ASSERT(!token_string.empty()); 8796 token_string.pop_back(); 8797 } 8798 } 8799 8800 /// add a character to token_buffer 8801 void add(char_int_type c) 8802 { 8803 token_buffer.push_back(static_cast<typename string_t::value_type>(c)); 8804 } 8805 8806 public: 8807 ///////////////////// 8808 // value getters 8809 ///////////////////// 8810 8811 /// return integer value 8812 constexpr number_integer_t get_number_integer() const noexcept 8813 { 8814 return value_integer; 8815 } 8816 8817 /// return unsigned integer value 8818 constexpr number_unsigned_t get_number_unsigned() const noexcept 8819 { 8820 return value_unsigned; 8821 } 8822 8823 /// return floating-point value 8824 constexpr number_float_t get_number_float() const noexcept 8825 { 8826 return value_float; 8827 } 8828 8829 /// return current string value (implicitly resets the token; useful only once) 8830 string_t& get_string() 8831 { 8832 return token_buffer; 8833 } 8834 8835 ///////////////////// 8836 // diagnostics 8837 ///////////////////// 8838 8839 /// return position of last read token 8840 constexpr position_t get_position() const noexcept 8841 { 8842 return position; 8843 } 8844 8845 /// return the last read token (for errors only). Will never contain EOF 8846 /// (an arbitrary value that is not a valid char value, often -1), because 8847 /// 255 may legitimately occur. May contain NUL, which should be escaped. 8848 std::string get_token_string() const 8849 { 8850 // escape control characters 8851 std::string result; 8852 for (const auto c : token_string) 8853 { 8854 if (static_cast<unsigned char>(c) <= '\x1F') 8855 { 8856 // escape control characters 8857 std::array<char, 9> cs{{}}; 8858 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 8859 result += cs.data(); 8860 } 8861 else 8862 { 8863 // add character as is 8864 result.push_back(static_cast<std::string::value_type>(c)); 8865 } 8866 } 8867 8868 return result; 8869 } 8870 8871 /// return syntax error message 8872 JSON_HEDLEY_RETURNS_NON_NULL 8873 constexpr const char* get_error_message() const noexcept 8874 { 8875 return error_message; 8876 } 8877 8878 ///////////////////// 8879 // actual scanner 8880 ///////////////////// 8881 8882 /*! 8883 @brief skip the UTF-8 byte order mark 8884 @return true iff there is no BOM or the correct BOM has been skipped 8885 */ 8886 bool skip_bom() 8887 { 8888 if (get() == 0xEF) 8889 { 8890 // check if we completely parse the BOM 8891 return get() == 0xBB && get() == 0xBF; 8892 } 8893 8894 // the first character is not the beginning of the BOM; unget it to 8895 // process is later 8896 unget(); 8897 return true; 8898 } 8899 8900 void skip_whitespace() 8901 { 8902 do 8903 { 8904 get(); 8905 } 8906 while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); 8907 } 8908 8909 token_type scan() 8910 { 8911 // initially, skip the BOM 8912 if (position.chars_read_total == 0 && !skip_bom()) 8913 { 8914 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; 8915 return token_type::parse_error; 8916 } 8917 8918 // read next character and ignore whitespace 8919 skip_whitespace(); 8920 8921 // ignore comments 8922 while (ignore_comments && current == '/') 8923 { 8924 if (!scan_comment()) 8925 { 8926 return token_type::parse_error; 8927 } 8928 8929 // skip following whitespace 8930 skip_whitespace(); 8931 } 8932 8933 switch (current) 8934 { 8935 // structural characters 8936 case '[': 8937 return token_type::begin_array; 8938 case ']': 8939 return token_type::end_array; 8940 case '{': 8941 return token_type::begin_object; 8942 case '}': 8943 return token_type::end_object; 8944 case ':': 8945 return token_type::name_separator; 8946 case ',': 8947 return token_type::value_separator; 8948 8949 // literals 8950 case 't': 8951 { 8952 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')}}; 8953 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); 8954 } 8955 case 'f': 8956 { 8957 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')}}; 8958 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); 8959 } 8960 case 'n': 8961 { 8962 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')}}; 8963 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); 8964 } 8965 8966 // string 8967 case '\"': 8968 return scan_string(); 8969 8970 // number 8971 case '-': 8972 case '0': 8973 case '1': 8974 case '2': 8975 case '3': 8976 case '4': 8977 case '5': 8978 case '6': 8979 case '7': 8980 case '8': 8981 case '9': 8982 return scan_number(); 8983 8984 // end of input (the null byte is needed when parsing from 8985 // string literals) 8986 case '\0': 8987 case char_traits<char_type>::eof(): 8988 return token_type::end_of_input; 8989 8990 // error 8991 default: 8992 error_message = "invalid literal"; 8993 return token_type::parse_error; 8994 } 8995 } 8996 8997 private: 8998 /// input adapter 8999 InputAdapterType ia; 9000 9001 /// whether comments should be ignored (true) or signaled as errors (false) 9002 const bool ignore_comments = false; 9003 9004 /// the current character 9005 char_int_type current = char_traits<char_type>::eof(); 9006 9007 /// whether the next get() call should just return current 9008 bool next_unget = false; 9009 9010 /// the start position of the current token 9011 position_t position {}; 9012 9013 /// raw input token string (for error messages) 9014 std::vector<char_type> token_string {}; 9015 9016 /// buffer for variable-length tokens (numbers, strings) 9017 string_t token_buffer {}; 9018 9019 /// a description of occurred lexer errors 9020 const char* error_message = ""; 9021 9022 // number values 9023 number_integer_t value_integer = 0; 9024 number_unsigned_t value_unsigned = 0; 9025 number_float_t value_float = 0; 9026 9027 /// the decimal point 9028 const char_int_type decimal_point_char = '.'; 9029 }; 9030 9031 } // namespace detail 9032 NLOHMANN_JSON_NAMESPACE_END 9033 9034 // #include <nlohmann/detail/macro_scope.hpp> 9035 9036 // #include <nlohmann/detail/meta/is_sax.hpp> 9037 // __ _____ _____ _____ 9038 // __| | __| | | | JSON for Modern C++ 9039 // | | |__ | | | | | | version 3.11.3 9040 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 9041 // 9042 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 9043 // SPDX-License-Identifier: MIT 9044 9045 9046 9047 #include <cstdint> // size_t 9048 #include <utility> // declval 9049 #include <string> // string 9050 9051 // #include <nlohmann/detail/abi_macros.hpp> 9052 9053 // #include <nlohmann/detail/meta/detected.hpp> 9054 9055 // #include <nlohmann/detail/meta/type_traits.hpp> 9056 9057 9058 NLOHMANN_JSON_NAMESPACE_BEGIN 9059 namespace detail 9060 { 9061 9062 template<typename T> 9063 using null_function_t = decltype(std::declval<T&>().null()); 9064 9065 template<typename T> 9066 using boolean_function_t = 9067 decltype(std::declval<T&>().boolean(std::declval<bool>())); 9068 9069 template<typename T, typename Integer> 9070 using number_integer_function_t = 9071 decltype(std::declval<T&>().number_integer(std::declval<Integer>())); 9072 9073 template<typename T, typename Unsigned> 9074 using number_unsigned_function_t = 9075 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>())); 9076 9077 template<typename T, typename Float, typename String> 9078 using number_float_function_t = decltype(std::declval<T&>().number_float( 9079 std::declval<Float>(), std::declval<const String&>())); 9080 9081 template<typename T, typename String> 9082 using string_function_t = 9083 decltype(std::declval<T&>().string(std::declval<String&>())); 9084 9085 template<typename T, typename Binary> 9086 using binary_function_t = 9087 decltype(std::declval<T&>().binary(std::declval<Binary&>())); 9088 9089 template<typename T> 9090 using start_object_function_t = 9091 decltype(std::declval<T&>().start_object(std::declval<std::size_t>())); 9092 9093 template<typename T, typename String> 9094 using key_function_t = 9095 decltype(std::declval<T&>().key(std::declval<String&>())); 9096 9097 template<typename T> 9098 using end_object_function_t = decltype(std::declval<T&>().end_object()); 9099 9100 template<typename T> 9101 using start_array_function_t = 9102 decltype(std::declval<T&>().start_array(std::declval<std::size_t>())); 9103 9104 template<typename T> 9105 using end_array_function_t = decltype(std::declval<T&>().end_array()); 9106 9107 template<typename T, typename Exception> 9108 using parse_error_function_t = decltype(std::declval<T&>().parse_error( 9109 std::declval<std::size_t>(), std::declval<const std::string&>(), 9110 std::declval<const Exception&>())); 9111 9112 template<typename SAX, typename BasicJsonType> 9113 struct is_sax 9114 { 9115 private: 9116 static_assert(is_basic_json<BasicJsonType>::value, 9117 "BasicJsonType must be of type basic_json<...>"); 9118 9119 using number_integer_t = typename BasicJsonType::number_integer_t; 9120 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 9121 using number_float_t = typename BasicJsonType::number_float_t; 9122 using string_t = typename BasicJsonType::string_t; 9123 using binary_t = typename BasicJsonType::binary_t; 9124 using exception_t = typename BasicJsonType::exception; 9125 9126 public: 9127 static constexpr bool value = 9128 is_detected_exact<bool, null_function_t, SAX>::value && 9129 is_detected_exact<bool, boolean_function_t, SAX>::value && 9130 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value && 9131 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value && 9132 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value && 9133 is_detected_exact<bool, string_function_t, SAX, string_t>::value && 9134 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value && 9135 is_detected_exact<bool, start_object_function_t, SAX>::value && 9136 is_detected_exact<bool, key_function_t, SAX, string_t>::value && 9137 is_detected_exact<bool, end_object_function_t, SAX>::value && 9138 is_detected_exact<bool, start_array_function_t, SAX>::value && 9139 is_detected_exact<bool, end_array_function_t, SAX>::value && 9140 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value; 9141 }; 9142 9143 template<typename SAX, typename BasicJsonType> 9144 struct is_sax_static_asserts 9145 { 9146 private: 9147 static_assert(is_basic_json<BasicJsonType>::value, 9148 "BasicJsonType must be of type basic_json<...>"); 9149 9150 using number_integer_t = typename BasicJsonType::number_integer_t; 9151 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 9152 using number_float_t = typename BasicJsonType::number_float_t; 9153 using string_t = typename BasicJsonType::string_t; 9154 using binary_t = typename BasicJsonType::binary_t; 9155 using exception_t = typename BasicJsonType::exception; 9156 9157 public: 9158 static_assert(is_detected_exact<bool, null_function_t, SAX>::value, 9159 "Missing/invalid function: bool null()"); 9160 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, 9161 "Missing/invalid function: bool boolean(bool)"); 9162 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, 9163 "Missing/invalid function: bool boolean(bool)"); 9164 static_assert( 9165 is_detected_exact<bool, number_integer_function_t, SAX, 9166 number_integer_t>::value, 9167 "Missing/invalid function: bool number_integer(number_integer_t)"); 9168 static_assert( 9169 is_detected_exact<bool, number_unsigned_function_t, SAX, 9170 number_unsigned_t>::value, 9171 "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); 9172 static_assert(is_detected_exact<bool, number_float_function_t, SAX, 9173 number_float_t, string_t>::value, 9174 "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); 9175 static_assert( 9176 is_detected_exact<bool, string_function_t, SAX, string_t>::value, 9177 "Missing/invalid function: bool string(string_t&)"); 9178 static_assert( 9179 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value, 9180 "Missing/invalid function: bool binary(binary_t&)"); 9181 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value, 9182 "Missing/invalid function: bool start_object(std::size_t)"); 9183 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value, 9184 "Missing/invalid function: bool key(string_t&)"); 9185 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value, 9186 "Missing/invalid function: bool end_object()"); 9187 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value, 9188 "Missing/invalid function: bool start_array(std::size_t)"); 9189 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value, 9190 "Missing/invalid function: bool end_array()"); 9191 static_assert( 9192 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value, 9193 "Missing/invalid function: bool parse_error(std::size_t, const " 9194 "std::string&, const exception&)"); 9195 }; 9196 9197 } // namespace detail 9198 NLOHMANN_JSON_NAMESPACE_END 9199 9200 // #include <nlohmann/detail/meta/type_traits.hpp> 9201 9202 // #include <nlohmann/detail/string_concat.hpp> 9203 9204 // #include <nlohmann/detail/value_t.hpp> 9205 9206 9207 NLOHMANN_JSON_NAMESPACE_BEGIN 9208 namespace detail 9209 { 9210 9211 /// how to treat CBOR tags 9212 enum class cbor_tag_handler_t 9213 { 9214 error, ///< throw a parse_error exception in case of a tag 9215 ignore, ///< ignore tags 9216 store ///< store tags as binary type 9217 }; 9218 9219 /*! 9220 @brief determine system byte order 9221 9222 @return true if and only if system's byte order is little endian 9223 9224 @note from https://stackoverflow.com/a/1001328/266378 9225 */ 9226 static inline bool little_endianness(int num = 1) noexcept 9227 { 9228 return *reinterpret_cast<char*>(&num) == 1; 9229 } 9230 9231 /////////////////// 9232 // binary reader // 9233 /////////////////// 9234 9235 /*! 9236 @brief deserialization of CBOR, MessagePack, and UBJSON values 9237 */ 9238 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>> 9239 class binary_reader 9240 { 9241 using number_integer_t = typename BasicJsonType::number_integer_t; 9242 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 9243 using number_float_t = typename BasicJsonType::number_float_t; 9244 using string_t = typename BasicJsonType::string_t; 9245 using binary_t = typename BasicJsonType::binary_t; 9246 using json_sax_t = SAX; 9247 using char_type = typename InputAdapterType::char_type; 9248 using char_int_type = typename char_traits<char_type>::int_type; 9249 9250 public: 9251 /*! 9252 @brief create a binary reader 9253 9254 @param[in] adapter input adapter to read from 9255 */ 9256 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) 9257 { 9258 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; 9259 } 9260 9261 // make class move-only 9262 binary_reader(const binary_reader&) = delete; 9263 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9264 binary_reader& operator=(const binary_reader&) = delete; 9265 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) 9266 ~binary_reader() = default; 9267 9268 /*! 9269 @param[in] format the binary format to parse 9270 @param[in] sax_ a SAX event processor 9271 @param[in] strict whether to expect the input to be consumed completed 9272 @param[in] tag_handler how to treat CBOR tags 9273 9274 @return whether parsing was successful 9275 */ 9276 JSON_HEDLEY_NON_NULL(3) 9277 bool sax_parse(const input_format_t format, 9278 json_sax_t* sax_, 9279 const bool strict = true, 9280 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 9281 { 9282 sax = sax_; 9283 bool result = false; 9284 9285 switch (format) 9286 { 9287 case input_format_t::bson: 9288 result = parse_bson_internal(); 9289 break; 9290 9291 case input_format_t::cbor: 9292 result = parse_cbor_internal(true, tag_handler); 9293 break; 9294 9295 case input_format_t::msgpack: 9296 result = parse_msgpack_internal(); 9297 break; 9298 9299 case input_format_t::ubjson: 9300 case input_format_t::bjdata: 9301 result = parse_ubjson_internal(); 9302 break; 9303 9304 case input_format_t::json: // LCOV_EXCL_LINE 9305 default: // LCOV_EXCL_LINE 9306 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 9307 } 9308 9309 // strict mode: next byte must be EOF 9310 if (result && strict) 9311 { 9312 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) 9313 { 9314 get_ignore_noop(); 9315 } 9316 else 9317 { 9318 get(); 9319 } 9320 9321 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof())) 9322 { 9323 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, 9324 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); 9325 } 9326 } 9327 9328 return result; 9329 } 9330 9331 private: 9332 ////////// 9333 // BSON // 9334 ////////// 9335 9336 /*! 9337 @brief Reads in a BSON-object and passes it to the SAX-parser. 9338 @return whether a valid BSON-value was passed to the SAX parser 9339 */ 9340 bool parse_bson_internal() 9341 { 9342 std::int32_t document_size{}; 9343 get_number<std::int32_t, true>(input_format_t::bson, document_size); 9344 9345 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 9346 { 9347 return false; 9348 } 9349 9350 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) 9351 { 9352 return false; 9353 } 9354 9355 return sax->end_object(); 9356 } 9357 9358 /*! 9359 @brief Parses a C-style string from the BSON input. 9360 @param[in,out] result A reference to the string variable where the read 9361 string is to be stored. 9362 @return `true` if the \x00-byte indicating the end of the string was 9363 encountered before the EOF; false` indicates an unexpected EOF. 9364 */ 9365 bool get_bson_cstr(string_t& result) 9366 { 9367 auto out = std::back_inserter(result); 9368 while (true) 9369 { 9370 get(); 9371 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) 9372 { 9373 return false; 9374 } 9375 if (current == 0x00) 9376 { 9377 return true; 9378 } 9379 *out++ = static_cast<typename string_t::value_type>(current); 9380 } 9381 } 9382 9383 /*! 9384 @brief Parses a zero-terminated string of length @a len from the BSON 9385 input. 9386 @param[in] len The length (including the zero-byte at the end) of the 9387 string to be read. 9388 @param[in,out] result A reference to the string variable where the read 9389 string is to be stored. 9390 @tparam NumberType The type of the length @a len 9391 @pre len >= 1 9392 @return `true` if the string was successfully parsed 9393 */ 9394 template<typename NumberType> 9395 bool get_bson_string(const NumberType len, string_t& result) 9396 { 9397 if (JSON_HEDLEY_UNLIKELY(len < 1)) 9398 { 9399 auto last_token = get_token_string(); 9400 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 9401 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); 9402 } 9403 9404 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof(); 9405 } 9406 9407 /*! 9408 @brief Parses a byte array input of length @a len from the BSON input. 9409 @param[in] len The length of the byte array to be read. 9410 @param[in,out] result A reference to the binary variable where the read 9411 array is to be stored. 9412 @tparam NumberType The type of the length @a len 9413 @pre len >= 0 9414 @return `true` if the byte array was successfully parsed 9415 */ 9416 template<typename NumberType> 9417 bool get_bson_binary(const NumberType len, binary_t& result) 9418 { 9419 if (JSON_HEDLEY_UNLIKELY(len < 0)) 9420 { 9421 auto last_token = get_token_string(); 9422 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 9423 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); 9424 } 9425 9426 // All BSON binary values have a subtype 9427 std::uint8_t subtype{}; 9428 get_number<std::uint8_t>(input_format_t::bson, subtype); 9429 result.set_subtype(subtype); 9430 9431 return get_binary(input_format_t::bson, len, result); 9432 } 9433 9434 /*! 9435 @brief Read a BSON document element of the given @a element_type. 9436 @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html 9437 @param[in] element_type_parse_position The position in the input stream, 9438 where the `element_type` was read. 9439 @warning Not all BSON element types are supported yet. An unsupported 9440 @a element_type will give rise to a parse_error.114: 9441 Unsupported BSON record type 0x... 9442 @return whether a valid BSON-object/array was passed to the SAX parser 9443 */ 9444 bool parse_bson_element_internal(const char_int_type element_type, 9445 const std::size_t element_type_parse_position) 9446 { 9447 switch (element_type) 9448 { 9449 case 0x01: // double 9450 { 9451 double number{}; 9452 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), ""); 9453 } 9454 9455 case 0x02: // string 9456 { 9457 std::int32_t len{}; 9458 string_t value; 9459 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); 9460 } 9461 9462 case 0x03: // object 9463 { 9464 return parse_bson_internal(); 9465 } 9466 9467 case 0x04: // array 9468 { 9469 return parse_bson_array(); 9470 } 9471 9472 case 0x05: // binary 9473 { 9474 std::int32_t len{}; 9475 binary_t value; 9476 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); 9477 } 9478 9479 case 0x08: // boolean 9480 { 9481 return sax->boolean(get() != 0); 9482 } 9483 9484 case 0x0A: // null 9485 { 9486 return sax->null(); 9487 } 9488 9489 case 0x10: // int32 9490 { 9491 std::int32_t value{}; 9492 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value); 9493 } 9494 9495 case 0x12: // int64 9496 { 9497 std::int64_t value{}; 9498 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value); 9499 } 9500 9501 default: // anything else not supported (yet) 9502 { 9503 std::array<char, 3> cr{{}}; 9504 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 9505 const std::string cr_str{cr.data()}; 9506 return sax->parse_error(element_type_parse_position, cr_str, 9507 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)); 9508 } 9509 } 9510 } 9511 9512 /*! 9513 @brief Read a BSON element list (as specified in the BSON-spec) 9514 9515 The same binary layout is used for objects and arrays, hence it must be 9516 indicated with the argument @a is_array which one is expected 9517 (true --> array, false --> object). 9518 9519 @param[in] is_array Determines if the element list being read is to be 9520 treated as an object (@a is_array == false), or as an 9521 array (@a is_array == true). 9522 @return whether a valid BSON-object/array was passed to the SAX parser 9523 */ 9524 bool parse_bson_element_list(const bool is_array) 9525 { 9526 string_t key; 9527 9528 while (auto element_type = get()) 9529 { 9530 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) 9531 { 9532 return false; 9533 } 9534 9535 const std::size_t element_type_parse_position = chars_read; 9536 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) 9537 { 9538 return false; 9539 } 9540 9541 if (!is_array && !sax->key(key)) 9542 { 9543 return false; 9544 } 9545 9546 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) 9547 { 9548 return false; 9549 } 9550 9551 // get_bson_cstr only appends 9552 key.clear(); 9553 } 9554 9555 return true; 9556 } 9557 9558 /*! 9559 @brief Reads an array from the BSON input and passes it to the SAX-parser. 9560 @return whether a valid BSON-array was passed to the SAX parser 9561 */ 9562 bool parse_bson_array() 9563 { 9564 std::int32_t document_size{}; 9565 get_number<std::int32_t, true>(input_format_t::bson, document_size); 9566 9567 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 9568 { 9569 return false; 9570 } 9571 9572 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) 9573 { 9574 return false; 9575 } 9576 9577 return sax->end_array(); 9578 } 9579 9580 ////////// 9581 // CBOR // 9582 ////////// 9583 9584 /*! 9585 @param[in] get_char whether a new character should be retrieved from the 9586 input (true) or whether the last read character should 9587 be considered instead (false) 9588 @param[in] tag_handler how CBOR tags should be treated 9589 9590 @return whether a valid CBOR value was passed to the SAX parser 9591 */ 9592 bool parse_cbor_internal(const bool get_char, 9593 const cbor_tag_handler_t tag_handler) 9594 { 9595 switch (get_char ? get() : current) 9596 { 9597 // EOF 9598 case char_traits<char_type>::eof(): 9599 return unexpect_eof(input_format_t::cbor, "value"); 9600 9601 // Integer 0x00..0x17 (0..23) 9602 case 0x00: 9603 case 0x01: 9604 case 0x02: 9605 case 0x03: 9606 case 0x04: 9607 case 0x05: 9608 case 0x06: 9609 case 0x07: 9610 case 0x08: 9611 case 0x09: 9612 case 0x0A: 9613 case 0x0B: 9614 case 0x0C: 9615 case 0x0D: 9616 case 0x0E: 9617 case 0x0F: 9618 case 0x10: 9619 case 0x11: 9620 case 0x12: 9621 case 0x13: 9622 case 0x14: 9623 case 0x15: 9624 case 0x16: 9625 case 0x17: 9626 return sax->number_unsigned(static_cast<number_unsigned_t>(current)); 9627 9628 case 0x18: // Unsigned integer (one-byte uint8_t follows) 9629 { 9630 std::uint8_t number{}; 9631 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9632 } 9633 9634 case 0x19: // Unsigned integer (two-byte uint16_t follows) 9635 { 9636 std::uint16_t number{}; 9637 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9638 } 9639 9640 case 0x1A: // Unsigned integer (four-byte uint32_t follows) 9641 { 9642 std::uint32_t number{}; 9643 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9644 } 9645 9646 case 0x1B: // Unsigned integer (eight-byte uint64_t follows) 9647 { 9648 std::uint64_t number{}; 9649 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); 9650 } 9651 9652 // Negative integer -1-0x00..-1-0x17 (-1..-24) 9653 case 0x20: 9654 case 0x21: 9655 case 0x22: 9656 case 0x23: 9657 case 0x24: 9658 case 0x25: 9659 case 0x26: 9660 case 0x27: 9661 case 0x28: 9662 case 0x29: 9663 case 0x2A: 9664 case 0x2B: 9665 case 0x2C: 9666 case 0x2D: 9667 case 0x2E: 9668 case 0x2F: 9669 case 0x30: 9670 case 0x31: 9671 case 0x32: 9672 case 0x33: 9673 case 0x34: 9674 case 0x35: 9675 case 0x36: 9676 case 0x37: 9677 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current)); 9678 9679 case 0x38: // Negative integer (one-byte uint8_t follows) 9680 { 9681 std::uint8_t number{}; 9682 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); 9683 } 9684 9685 case 0x39: // Negative integer -1-n (two-byte uint16_t follows) 9686 { 9687 std::uint16_t number{}; 9688 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); 9689 } 9690 9691 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) 9692 { 9693 std::uint32_t number{}; 9694 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number); 9695 } 9696 9697 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) 9698 { 9699 std::uint64_t number{}; 9700 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) 9701 - static_cast<number_integer_t>(number)); 9702 } 9703 9704 // Binary data (0x00..0x17 bytes follow) 9705 case 0x40: 9706 case 0x41: 9707 case 0x42: 9708 case 0x43: 9709 case 0x44: 9710 case 0x45: 9711 case 0x46: 9712 case 0x47: 9713 case 0x48: 9714 case 0x49: 9715 case 0x4A: 9716 case 0x4B: 9717 case 0x4C: 9718 case 0x4D: 9719 case 0x4E: 9720 case 0x4F: 9721 case 0x50: 9722 case 0x51: 9723 case 0x52: 9724 case 0x53: 9725 case 0x54: 9726 case 0x55: 9727 case 0x56: 9728 case 0x57: 9729 case 0x58: // Binary data (one-byte uint8_t for n follows) 9730 case 0x59: // Binary data (two-byte uint16_t for n follow) 9731 case 0x5A: // Binary data (four-byte uint32_t for n follow) 9732 case 0x5B: // Binary data (eight-byte uint64_t for n follow) 9733 case 0x5F: // Binary data (indefinite length) 9734 { 9735 binary_t b; 9736 return get_cbor_binary(b) && sax->binary(b); 9737 } 9738 9739 // UTF-8 string (0x00..0x17 bytes follow) 9740 case 0x60: 9741 case 0x61: 9742 case 0x62: 9743 case 0x63: 9744 case 0x64: 9745 case 0x65: 9746 case 0x66: 9747 case 0x67: 9748 case 0x68: 9749 case 0x69: 9750 case 0x6A: 9751 case 0x6B: 9752 case 0x6C: 9753 case 0x6D: 9754 case 0x6E: 9755 case 0x6F: 9756 case 0x70: 9757 case 0x71: 9758 case 0x72: 9759 case 0x73: 9760 case 0x74: 9761 case 0x75: 9762 case 0x76: 9763 case 0x77: 9764 case 0x78: // UTF-8 string (one-byte uint8_t for n follows) 9765 case 0x79: // UTF-8 string (two-byte uint16_t for n follow) 9766 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) 9767 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) 9768 case 0x7F: // UTF-8 string (indefinite length) 9769 { 9770 string_t s; 9771 return get_cbor_string(s) && sax->string(s); 9772 } 9773 9774 // array (0x00..0x17 data items follow) 9775 case 0x80: 9776 case 0x81: 9777 case 0x82: 9778 case 0x83: 9779 case 0x84: 9780 case 0x85: 9781 case 0x86: 9782 case 0x87: 9783 case 0x88: 9784 case 0x89: 9785 case 0x8A: 9786 case 0x8B: 9787 case 0x8C: 9788 case 0x8D: 9789 case 0x8E: 9790 case 0x8F: 9791 case 0x90: 9792 case 0x91: 9793 case 0x92: 9794 case 0x93: 9795 case 0x94: 9796 case 0x95: 9797 case 0x96: 9798 case 0x97: 9799 return get_cbor_array( 9800 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler); 9801 9802 case 0x98: // array (one-byte uint8_t for n follows) 9803 { 9804 std::uint8_t len{}; 9805 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler); 9806 } 9807 9808 case 0x99: // array (two-byte uint16_t for n follow) 9809 { 9810 std::uint16_t len{}; 9811 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler); 9812 } 9813 9814 case 0x9A: // array (four-byte uint32_t for n follow) 9815 { 9816 std::uint32_t len{}; 9817 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler); 9818 } 9819 9820 case 0x9B: // array (eight-byte uint64_t for n follow) 9821 { 9822 std::uint64_t len{}; 9823 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler); 9824 } 9825 9826 case 0x9F: // array (indefinite length) 9827 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler); 9828 9829 // map (0x00..0x17 pairs of data items follow) 9830 case 0xA0: 9831 case 0xA1: 9832 case 0xA2: 9833 case 0xA3: 9834 case 0xA4: 9835 case 0xA5: 9836 case 0xA6: 9837 case 0xA7: 9838 case 0xA8: 9839 case 0xA9: 9840 case 0xAA: 9841 case 0xAB: 9842 case 0xAC: 9843 case 0xAD: 9844 case 0xAE: 9845 case 0xAF: 9846 case 0xB0: 9847 case 0xB1: 9848 case 0xB2: 9849 case 0xB3: 9850 case 0xB4: 9851 case 0xB5: 9852 case 0xB6: 9853 case 0xB7: 9854 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler); 9855 9856 case 0xB8: // map (one-byte uint8_t for n follows) 9857 { 9858 std::uint8_t len{}; 9859 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler); 9860 } 9861 9862 case 0xB9: // map (two-byte uint16_t for n follow) 9863 { 9864 std::uint16_t len{}; 9865 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler); 9866 } 9867 9868 case 0xBA: // map (four-byte uint32_t for n follow) 9869 { 9870 std::uint32_t len{}; 9871 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler); 9872 } 9873 9874 case 0xBB: // map (eight-byte uint64_t for n follow) 9875 { 9876 std::uint64_t len{}; 9877 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler); 9878 } 9879 9880 case 0xBF: // map (indefinite length) 9881 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler); 9882 9883 case 0xC6: // tagged item 9884 case 0xC7: 9885 case 0xC8: 9886 case 0xC9: 9887 case 0xCA: 9888 case 0xCB: 9889 case 0xCC: 9890 case 0xCD: 9891 case 0xCE: 9892 case 0xCF: 9893 case 0xD0: 9894 case 0xD1: 9895 case 0xD2: 9896 case 0xD3: 9897 case 0xD4: 9898 case 0xD8: // tagged item (1 bytes follow) 9899 case 0xD9: // tagged item (2 bytes follow) 9900 case 0xDA: // tagged item (4 bytes follow) 9901 case 0xDB: // tagged item (8 bytes follow) 9902 { 9903 switch (tag_handler) 9904 { 9905 case cbor_tag_handler_t::error: 9906 { 9907 auto last_token = get_token_string(); 9908 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 9909 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); 9910 } 9911 9912 case cbor_tag_handler_t::ignore: 9913 { 9914 // ignore binary subtype 9915 switch (current) 9916 { 9917 case 0xD8: 9918 { 9919 std::uint8_t subtype_to_ignore{}; 9920 get_number(input_format_t::cbor, subtype_to_ignore); 9921 break; 9922 } 9923 case 0xD9: 9924 { 9925 std::uint16_t subtype_to_ignore{}; 9926 get_number(input_format_t::cbor, subtype_to_ignore); 9927 break; 9928 } 9929 case 0xDA: 9930 { 9931 std::uint32_t subtype_to_ignore{}; 9932 get_number(input_format_t::cbor, subtype_to_ignore); 9933 break; 9934 } 9935 case 0xDB: 9936 { 9937 std::uint64_t subtype_to_ignore{}; 9938 get_number(input_format_t::cbor, subtype_to_ignore); 9939 break; 9940 } 9941 default: 9942 break; 9943 } 9944 return parse_cbor_internal(true, tag_handler); 9945 } 9946 9947 case cbor_tag_handler_t::store: 9948 { 9949 binary_t b; 9950 // use binary subtype and store in binary container 9951 switch (current) 9952 { 9953 case 0xD8: 9954 { 9955 std::uint8_t subtype{}; 9956 get_number(input_format_t::cbor, subtype); 9957 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 9958 break; 9959 } 9960 case 0xD9: 9961 { 9962 std::uint16_t subtype{}; 9963 get_number(input_format_t::cbor, subtype); 9964 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 9965 break; 9966 } 9967 case 0xDA: 9968 { 9969 std::uint32_t subtype{}; 9970 get_number(input_format_t::cbor, subtype); 9971 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 9972 break; 9973 } 9974 case 0xDB: 9975 { 9976 std::uint64_t subtype{}; 9977 get_number(input_format_t::cbor, subtype); 9978 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype)); 9979 break; 9980 } 9981 default: 9982 return parse_cbor_internal(true, tag_handler); 9983 } 9984 get(); 9985 return get_cbor_binary(b) && sax->binary(b); 9986 } 9987 9988 default: // LCOV_EXCL_LINE 9989 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 9990 return false; // LCOV_EXCL_LINE 9991 } 9992 } 9993 9994 case 0xF4: // false 9995 return sax->boolean(false); 9996 9997 case 0xF5: // true 9998 return sax->boolean(true); 9999 10000 case 0xF6: // null 10001 return sax->null(); 10002 10003 case 0xF9: // Half-Precision Float (two-byte IEEE 754) 10004 { 10005 const auto byte1_raw = get(); 10006 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) 10007 { 10008 return false; 10009 } 10010 const auto byte2_raw = get(); 10011 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) 10012 { 10013 return false; 10014 } 10015 10016 const auto byte1 = static_cast<unsigned char>(byte1_raw); 10017 const auto byte2 = static_cast<unsigned char>(byte2_raw); 10018 10019 // code from RFC 7049, Appendix D, Figure 3: 10020 // As half-precision floating-point numbers were only added 10021 // to IEEE 754 in 2008, today's programming platforms often 10022 // still only have limited support for them. It is very 10023 // easy to include at least decoding support for them even 10024 // without such support. An example of a small decoder for 10025 // half-precision floating-point numbers in the C language 10026 // is shown in Fig. 3. 10027 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2); 10028 const double val = [&half] 10029 { 10030 const int exp = (half >> 10u) & 0x1Fu; 10031 const unsigned int mant = half & 0x3FFu; 10032 JSON_ASSERT(0 <= exp&& exp <= 32); 10033 JSON_ASSERT(mant <= 1024); 10034 switch (exp) 10035 { 10036 case 0: 10037 return std::ldexp(mant, -24); 10038 case 31: 10039 return (mant == 0) 10040 ? std::numeric_limits<double>::infinity() 10041 : std::numeric_limits<double>::quiet_NaN(); 10042 default: 10043 return std::ldexp(mant + 1024, exp - 25); 10044 } 10045 }(); 10046 return sax->number_float((half & 0x8000u) != 0 10047 ? static_cast<number_float_t>(-val) 10048 : static_cast<number_float_t>(val), ""); 10049 } 10050 10051 case 0xFA: // Single-Precision Float (four-byte IEEE 754) 10052 { 10053 float number{}; 10054 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10055 } 10056 10057 case 0xFB: // Double-Precision Float (eight-byte IEEE 754) 10058 { 10059 double number{}; 10060 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10061 } 10062 10063 default: // anything else (0xFF is handled inside the other types) 10064 { 10065 auto last_token = get_token_string(); 10066 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 10067 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); 10068 } 10069 } 10070 } 10071 10072 /*! 10073 @brief reads a CBOR string 10074 10075 This function first reads starting bytes to determine the expected 10076 string length and then copies this number of bytes into a string. 10077 Additionally, CBOR's strings with indefinite lengths are supported. 10078 10079 @param[out] result created string 10080 10081 @return whether string creation completed 10082 */ 10083 bool get_cbor_string(string_t& result) 10084 { 10085 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) 10086 { 10087 return false; 10088 } 10089 10090 switch (current) 10091 { 10092 // UTF-8 string (0x00..0x17 bytes follow) 10093 case 0x60: 10094 case 0x61: 10095 case 0x62: 10096 case 0x63: 10097 case 0x64: 10098 case 0x65: 10099 case 0x66: 10100 case 0x67: 10101 case 0x68: 10102 case 0x69: 10103 case 0x6A: 10104 case 0x6B: 10105 case 0x6C: 10106 case 0x6D: 10107 case 0x6E: 10108 case 0x6F: 10109 case 0x70: 10110 case 0x71: 10111 case 0x72: 10112 case 0x73: 10113 case 0x74: 10114 case 0x75: 10115 case 0x76: 10116 case 0x77: 10117 { 10118 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result); 10119 } 10120 10121 case 0x78: // UTF-8 string (one-byte uint8_t for n follows) 10122 { 10123 std::uint8_t len{}; 10124 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10125 } 10126 10127 case 0x79: // UTF-8 string (two-byte uint16_t for n follow) 10128 { 10129 std::uint16_t len{}; 10130 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10131 } 10132 10133 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) 10134 { 10135 std::uint32_t len{}; 10136 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10137 } 10138 10139 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) 10140 { 10141 std::uint64_t len{}; 10142 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); 10143 } 10144 10145 case 0x7F: // UTF-8 string (indefinite length) 10146 { 10147 while (get() != 0xFF) 10148 { 10149 string_t chunk; 10150 if (!get_cbor_string(chunk)) 10151 { 10152 return false; 10153 } 10154 result.append(chunk); 10155 } 10156 return true; 10157 } 10158 10159 default: 10160 { 10161 auto last_token = get_token_string(); 10162 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 10163 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); 10164 } 10165 } 10166 } 10167 10168 /*! 10169 @brief reads a CBOR byte array 10170 10171 This function first reads starting bytes to determine the expected 10172 byte array length and then copies this number of bytes into the byte array. 10173 Additionally, CBOR's byte arrays with indefinite lengths are supported. 10174 10175 @param[out] result created byte array 10176 10177 @return whether byte array creation completed 10178 */ 10179 bool get_cbor_binary(binary_t& result) 10180 { 10181 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) 10182 { 10183 return false; 10184 } 10185 10186 switch (current) 10187 { 10188 // Binary data (0x00..0x17 bytes follow) 10189 case 0x40: 10190 case 0x41: 10191 case 0x42: 10192 case 0x43: 10193 case 0x44: 10194 case 0x45: 10195 case 0x46: 10196 case 0x47: 10197 case 0x48: 10198 case 0x49: 10199 case 0x4A: 10200 case 0x4B: 10201 case 0x4C: 10202 case 0x4D: 10203 case 0x4E: 10204 case 0x4F: 10205 case 0x50: 10206 case 0x51: 10207 case 0x52: 10208 case 0x53: 10209 case 0x54: 10210 case 0x55: 10211 case 0x56: 10212 case 0x57: 10213 { 10214 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result); 10215 } 10216 10217 case 0x58: // Binary data (one-byte uint8_t for n follows) 10218 { 10219 std::uint8_t len{}; 10220 return get_number(input_format_t::cbor, len) && 10221 get_binary(input_format_t::cbor, len, result); 10222 } 10223 10224 case 0x59: // Binary data (two-byte uint16_t for n follow) 10225 { 10226 std::uint16_t len{}; 10227 return get_number(input_format_t::cbor, len) && 10228 get_binary(input_format_t::cbor, len, result); 10229 } 10230 10231 case 0x5A: // Binary data (four-byte uint32_t for n follow) 10232 { 10233 std::uint32_t len{}; 10234 return get_number(input_format_t::cbor, len) && 10235 get_binary(input_format_t::cbor, len, result); 10236 } 10237 10238 case 0x5B: // Binary data (eight-byte uint64_t for n follow) 10239 { 10240 std::uint64_t len{}; 10241 return get_number(input_format_t::cbor, len) && 10242 get_binary(input_format_t::cbor, len, result); 10243 } 10244 10245 case 0x5F: // Binary data (indefinite length) 10246 { 10247 while (get() != 0xFF) 10248 { 10249 binary_t chunk; 10250 if (!get_cbor_binary(chunk)) 10251 { 10252 return false; 10253 } 10254 result.insert(result.end(), chunk.begin(), chunk.end()); 10255 } 10256 return true; 10257 } 10258 10259 default: 10260 { 10261 auto last_token = get_token_string(); 10262 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 10263 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)); 10264 } 10265 } 10266 } 10267 10268 /*! 10269 @param[in] len the length of the array or static_cast<std::size_t>(-1) for an 10270 array of indefinite size 10271 @param[in] tag_handler how CBOR tags should be treated 10272 @return whether array creation completed 10273 */ 10274 bool get_cbor_array(const std::size_t len, 10275 const cbor_tag_handler_t tag_handler) 10276 { 10277 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) 10278 { 10279 return false; 10280 } 10281 10282 if (len != static_cast<std::size_t>(-1)) 10283 { 10284 for (std::size_t i = 0; i < len; ++i) 10285 { 10286 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) 10287 { 10288 return false; 10289 } 10290 } 10291 } 10292 else 10293 { 10294 while (get() != 0xFF) 10295 { 10296 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) 10297 { 10298 return false; 10299 } 10300 } 10301 } 10302 10303 return sax->end_array(); 10304 } 10305 10306 /*! 10307 @param[in] len the length of the object or static_cast<std::size_t>(-1) for an 10308 object of indefinite size 10309 @param[in] tag_handler how CBOR tags should be treated 10310 @return whether object creation completed 10311 */ 10312 bool get_cbor_object(const std::size_t len, 10313 const cbor_tag_handler_t tag_handler) 10314 { 10315 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) 10316 { 10317 return false; 10318 } 10319 10320 if (len != 0) 10321 { 10322 string_t key; 10323 if (len != static_cast<std::size_t>(-1)) 10324 { 10325 for (std::size_t i = 0; i < len; ++i) 10326 { 10327 get(); 10328 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) 10329 { 10330 return false; 10331 } 10332 10333 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) 10334 { 10335 return false; 10336 } 10337 key.clear(); 10338 } 10339 } 10340 else 10341 { 10342 while (get() != 0xFF) 10343 { 10344 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) 10345 { 10346 return false; 10347 } 10348 10349 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) 10350 { 10351 return false; 10352 } 10353 key.clear(); 10354 } 10355 } 10356 } 10357 10358 return sax->end_object(); 10359 } 10360 10361 ///////////// 10362 // MsgPack // 10363 ///////////// 10364 10365 /*! 10366 @return whether a valid MessagePack value was passed to the SAX parser 10367 */ 10368 bool parse_msgpack_internal() 10369 { 10370 switch (get()) 10371 { 10372 // EOF 10373 case char_traits<char_type>::eof(): 10374 return unexpect_eof(input_format_t::msgpack, "value"); 10375 10376 // positive fixint 10377 case 0x00: 10378 case 0x01: 10379 case 0x02: 10380 case 0x03: 10381 case 0x04: 10382 case 0x05: 10383 case 0x06: 10384 case 0x07: 10385 case 0x08: 10386 case 0x09: 10387 case 0x0A: 10388 case 0x0B: 10389 case 0x0C: 10390 case 0x0D: 10391 case 0x0E: 10392 case 0x0F: 10393 case 0x10: 10394 case 0x11: 10395 case 0x12: 10396 case 0x13: 10397 case 0x14: 10398 case 0x15: 10399 case 0x16: 10400 case 0x17: 10401 case 0x18: 10402 case 0x19: 10403 case 0x1A: 10404 case 0x1B: 10405 case 0x1C: 10406 case 0x1D: 10407 case 0x1E: 10408 case 0x1F: 10409 case 0x20: 10410 case 0x21: 10411 case 0x22: 10412 case 0x23: 10413 case 0x24: 10414 case 0x25: 10415 case 0x26: 10416 case 0x27: 10417 case 0x28: 10418 case 0x29: 10419 case 0x2A: 10420 case 0x2B: 10421 case 0x2C: 10422 case 0x2D: 10423 case 0x2E: 10424 case 0x2F: 10425 case 0x30: 10426 case 0x31: 10427 case 0x32: 10428 case 0x33: 10429 case 0x34: 10430 case 0x35: 10431 case 0x36: 10432 case 0x37: 10433 case 0x38: 10434 case 0x39: 10435 case 0x3A: 10436 case 0x3B: 10437 case 0x3C: 10438 case 0x3D: 10439 case 0x3E: 10440 case 0x3F: 10441 case 0x40: 10442 case 0x41: 10443 case 0x42: 10444 case 0x43: 10445 case 0x44: 10446 case 0x45: 10447 case 0x46: 10448 case 0x47: 10449 case 0x48: 10450 case 0x49: 10451 case 0x4A: 10452 case 0x4B: 10453 case 0x4C: 10454 case 0x4D: 10455 case 0x4E: 10456 case 0x4F: 10457 case 0x50: 10458 case 0x51: 10459 case 0x52: 10460 case 0x53: 10461 case 0x54: 10462 case 0x55: 10463 case 0x56: 10464 case 0x57: 10465 case 0x58: 10466 case 0x59: 10467 case 0x5A: 10468 case 0x5B: 10469 case 0x5C: 10470 case 0x5D: 10471 case 0x5E: 10472 case 0x5F: 10473 case 0x60: 10474 case 0x61: 10475 case 0x62: 10476 case 0x63: 10477 case 0x64: 10478 case 0x65: 10479 case 0x66: 10480 case 0x67: 10481 case 0x68: 10482 case 0x69: 10483 case 0x6A: 10484 case 0x6B: 10485 case 0x6C: 10486 case 0x6D: 10487 case 0x6E: 10488 case 0x6F: 10489 case 0x70: 10490 case 0x71: 10491 case 0x72: 10492 case 0x73: 10493 case 0x74: 10494 case 0x75: 10495 case 0x76: 10496 case 0x77: 10497 case 0x78: 10498 case 0x79: 10499 case 0x7A: 10500 case 0x7B: 10501 case 0x7C: 10502 case 0x7D: 10503 case 0x7E: 10504 case 0x7F: 10505 return sax->number_unsigned(static_cast<number_unsigned_t>(current)); 10506 10507 // fixmap 10508 case 0x80: 10509 case 0x81: 10510 case 0x82: 10511 case 0x83: 10512 case 0x84: 10513 case 0x85: 10514 case 0x86: 10515 case 0x87: 10516 case 0x88: 10517 case 0x89: 10518 case 0x8A: 10519 case 0x8B: 10520 case 0x8C: 10521 case 0x8D: 10522 case 0x8E: 10523 case 0x8F: 10524 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu)); 10525 10526 // fixarray 10527 case 0x90: 10528 case 0x91: 10529 case 0x92: 10530 case 0x93: 10531 case 0x94: 10532 case 0x95: 10533 case 0x96: 10534 case 0x97: 10535 case 0x98: 10536 case 0x99: 10537 case 0x9A: 10538 case 0x9B: 10539 case 0x9C: 10540 case 0x9D: 10541 case 0x9E: 10542 case 0x9F: 10543 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu)); 10544 10545 // fixstr 10546 case 0xA0: 10547 case 0xA1: 10548 case 0xA2: 10549 case 0xA3: 10550 case 0xA4: 10551 case 0xA5: 10552 case 0xA6: 10553 case 0xA7: 10554 case 0xA8: 10555 case 0xA9: 10556 case 0xAA: 10557 case 0xAB: 10558 case 0xAC: 10559 case 0xAD: 10560 case 0xAE: 10561 case 0xAF: 10562 case 0xB0: 10563 case 0xB1: 10564 case 0xB2: 10565 case 0xB3: 10566 case 0xB4: 10567 case 0xB5: 10568 case 0xB6: 10569 case 0xB7: 10570 case 0xB8: 10571 case 0xB9: 10572 case 0xBA: 10573 case 0xBB: 10574 case 0xBC: 10575 case 0xBD: 10576 case 0xBE: 10577 case 0xBF: 10578 case 0xD9: // str 8 10579 case 0xDA: // str 16 10580 case 0xDB: // str 32 10581 { 10582 string_t s; 10583 return get_msgpack_string(s) && sax->string(s); 10584 } 10585 10586 case 0xC0: // nil 10587 return sax->null(); 10588 10589 case 0xC2: // false 10590 return sax->boolean(false); 10591 10592 case 0xC3: // true 10593 return sax->boolean(true); 10594 10595 case 0xC4: // bin 8 10596 case 0xC5: // bin 16 10597 case 0xC6: // bin 32 10598 case 0xC7: // ext 8 10599 case 0xC8: // ext 16 10600 case 0xC9: // ext 32 10601 case 0xD4: // fixext 1 10602 case 0xD5: // fixext 2 10603 case 0xD6: // fixext 4 10604 case 0xD7: // fixext 8 10605 case 0xD8: // fixext 16 10606 { 10607 binary_t b; 10608 return get_msgpack_binary(b) && sax->binary(b); 10609 } 10610 10611 case 0xCA: // float 32 10612 { 10613 float number{}; 10614 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10615 } 10616 10617 case 0xCB: // float 64 10618 { 10619 double number{}; 10620 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), ""); 10621 } 10622 10623 case 0xCC: // uint 8 10624 { 10625 std::uint8_t number{}; 10626 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10627 } 10628 10629 case 0xCD: // uint 16 10630 { 10631 std::uint16_t number{}; 10632 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10633 } 10634 10635 case 0xCE: // uint 32 10636 { 10637 std::uint32_t number{}; 10638 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10639 } 10640 10641 case 0xCF: // uint 64 10642 { 10643 std::uint64_t number{}; 10644 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); 10645 } 10646 10647 case 0xD0: // int 8 10648 { 10649 std::int8_t number{}; 10650 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10651 } 10652 10653 case 0xD1: // int 16 10654 { 10655 std::int16_t number{}; 10656 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10657 } 10658 10659 case 0xD2: // int 32 10660 { 10661 std::int32_t number{}; 10662 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10663 } 10664 10665 case 0xD3: // int 64 10666 { 10667 std::int64_t number{}; 10668 return get_number(input_format_t::msgpack, number) && sax->number_integer(number); 10669 } 10670 10671 case 0xDC: // array 16 10672 { 10673 std::uint16_t len{}; 10674 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len)); 10675 } 10676 10677 case 0xDD: // array 32 10678 { 10679 std::uint32_t len{}; 10680 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len)); 10681 } 10682 10683 case 0xDE: // map 16 10684 { 10685 std::uint16_t len{}; 10686 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len)); 10687 } 10688 10689 case 0xDF: // map 32 10690 { 10691 std::uint32_t len{}; 10692 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len)); 10693 } 10694 10695 // negative fixint 10696 case 0xE0: 10697 case 0xE1: 10698 case 0xE2: 10699 case 0xE3: 10700 case 0xE4: 10701 case 0xE5: 10702 case 0xE6: 10703 case 0xE7: 10704 case 0xE8: 10705 case 0xE9: 10706 case 0xEA: 10707 case 0xEB: 10708 case 0xEC: 10709 case 0xED: 10710 case 0xEE: 10711 case 0xEF: 10712 case 0xF0: 10713 case 0xF1: 10714 case 0xF2: 10715 case 0xF3: 10716 case 0xF4: 10717 case 0xF5: 10718 case 0xF6: 10719 case 0xF7: 10720 case 0xF8: 10721 case 0xF9: 10722 case 0xFA: 10723 case 0xFB: 10724 case 0xFC: 10725 case 0xFD: 10726 case 0xFE: 10727 case 0xFF: 10728 return sax->number_integer(static_cast<std::int8_t>(current)); 10729 10730 default: // anything else 10731 { 10732 auto last_token = get_token_string(); 10733 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 10734 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); 10735 } 10736 } 10737 } 10738 10739 /*! 10740 @brief reads a MessagePack string 10741 10742 This function first reads starting bytes to determine the expected 10743 string length and then copies this number of bytes into a string. 10744 10745 @param[out] result created string 10746 10747 @return whether string creation completed 10748 */ 10749 bool get_msgpack_string(string_t& result) 10750 { 10751 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) 10752 { 10753 return false; 10754 } 10755 10756 switch (current) 10757 { 10758 // fixstr 10759 case 0xA0: 10760 case 0xA1: 10761 case 0xA2: 10762 case 0xA3: 10763 case 0xA4: 10764 case 0xA5: 10765 case 0xA6: 10766 case 0xA7: 10767 case 0xA8: 10768 case 0xA9: 10769 case 0xAA: 10770 case 0xAB: 10771 case 0xAC: 10772 case 0xAD: 10773 case 0xAE: 10774 case 0xAF: 10775 case 0xB0: 10776 case 0xB1: 10777 case 0xB2: 10778 case 0xB3: 10779 case 0xB4: 10780 case 0xB5: 10781 case 0xB6: 10782 case 0xB7: 10783 case 0xB8: 10784 case 0xB9: 10785 case 0xBA: 10786 case 0xBB: 10787 case 0xBC: 10788 case 0xBD: 10789 case 0xBE: 10790 case 0xBF: 10791 { 10792 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result); 10793 } 10794 10795 case 0xD9: // str 8 10796 { 10797 std::uint8_t len{}; 10798 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); 10799 } 10800 10801 case 0xDA: // str 16 10802 { 10803 std::uint16_t len{}; 10804 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); 10805 } 10806 10807 case 0xDB: // str 32 10808 { 10809 std::uint32_t len{}; 10810 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); 10811 } 10812 10813 default: 10814 { 10815 auto last_token = get_token_string(); 10816 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 10817 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); 10818 } 10819 } 10820 } 10821 10822 /*! 10823 @brief reads a MessagePack byte array 10824 10825 This function first reads starting bytes to determine the expected 10826 byte array length and then copies this number of bytes into a byte array. 10827 10828 @param[out] result created byte array 10829 10830 @return whether byte array creation completed 10831 */ 10832 bool get_msgpack_binary(binary_t& result) 10833 { 10834 // helper function to set the subtype 10835 auto assign_and_return_true = [&result](std::int8_t subtype) 10836 { 10837 result.set_subtype(static_cast<std::uint8_t>(subtype)); 10838 return true; 10839 }; 10840 10841 switch (current) 10842 { 10843 case 0xC4: // bin 8 10844 { 10845 std::uint8_t len{}; 10846 return get_number(input_format_t::msgpack, len) && 10847 get_binary(input_format_t::msgpack, len, result); 10848 } 10849 10850 case 0xC5: // bin 16 10851 { 10852 std::uint16_t len{}; 10853 return get_number(input_format_t::msgpack, len) && 10854 get_binary(input_format_t::msgpack, len, result); 10855 } 10856 10857 case 0xC6: // bin 32 10858 { 10859 std::uint32_t len{}; 10860 return get_number(input_format_t::msgpack, len) && 10861 get_binary(input_format_t::msgpack, len, result); 10862 } 10863 10864 case 0xC7: // ext 8 10865 { 10866 std::uint8_t len{}; 10867 std::int8_t subtype{}; 10868 return get_number(input_format_t::msgpack, len) && 10869 get_number(input_format_t::msgpack, subtype) && 10870 get_binary(input_format_t::msgpack, len, result) && 10871 assign_and_return_true(subtype); 10872 } 10873 10874 case 0xC8: // ext 16 10875 { 10876 std::uint16_t len{}; 10877 std::int8_t subtype{}; 10878 return get_number(input_format_t::msgpack, len) && 10879 get_number(input_format_t::msgpack, subtype) && 10880 get_binary(input_format_t::msgpack, len, result) && 10881 assign_and_return_true(subtype); 10882 } 10883 10884 case 0xC9: // ext 32 10885 { 10886 std::uint32_t len{}; 10887 std::int8_t subtype{}; 10888 return get_number(input_format_t::msgpack, len) && 10889 get_number(input_format_t::msgpack, subtype) && 10890 get_binary(input_format_t::msgpack, len, result) && 10891 assign_and_return_true(subtype); 10892 } 10893 10894 case 0xD4: // fixext 1 10895 { 10896 std::int8_t subtype{}; 10897 return get_number(input_format_t::msgpack, subtype) && 10898 get_binary(input_format_t::msgpack, 1, result) && 10899 assign_and_return_true(subtype); 10900 } 10901 10902 case 0xD5: // fixext 2 10903 { 10904 std::int8_t subtype{}; 10905 return get_number(input_format_t::msgpack, subtype) && 10906 get_binary(input_format_t::msgpack, 2, result) && 10907 assign_and_return_true(subtype); 10908 } 10909 10910 case 0xD6: // fixext 4 10911 { 10912 std::int8_t subtype{}; 10913 return get_number(input_format_t::msgpack, subtype) && 10914 get_binary(input_format_t::msgpack, 4, result) && 10915 assign_and_return_true(subtype); 10916 } 10917 10918 case 0xD7: // fixext 8 10919 { 10920 std::int8_t subtype{}; 10921 return get_number(input_format_t::msgpack, subtype) && 10922 get_binary(input_format_t::msgpack, 8, result) && 10923 assign_and_return_true(subtype); 10924 } 10925 10926 case 0xD8: // fixext 16 10927 { 10928 std::int8_t subtype{}; 10929 return get_number(input_format_t::msgpack, subtype) && 10930 get_binary(input_format_t::msgpack, 16, result) && 10931 assign_and_return_true(subtype); 10932 } 10933 10934 default: // LCOV_EXCL_LINE 10935 return false; // LCOV_EXCL_LINE 10936 } 10937 } 10938 10939 /*! 10940 @param[in] len the length of the array 10941 @return whether array creation completed 10942 */ 10943 bool get_msgpack_array(const std::size_t len) 10944 { 10945 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) 10946 { 10947 return false; 10948 } 10949 10950 for (std::size_t i = 0; i < len; ++i) 10951 { 10952 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) 10953 { 10954 return false; 10955 } 10956 } 10957 10958 return sax->end_array(); 10959 } 10960 10961 /*! 10962 @param[in] len the length of the object 10963 @return whether object creation completed 10964 */ 10965 bool get_msgpack_object(const std::size_t len) 10966 { 10967 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) 10968 { 10969 return false; 10970 } 10971 10972 string_t key; 10973 for (std::size_t i = 0; i < len; ++i) 10974 { 10975 get(); 10976 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) 10977 { 10978 return false; 10979 } 10980 10981 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) 10982 { 10983 return false; 10984 } 10985 key.clear(); 10986 } 10987 10988 return sax->end_object(); 10989 } 10990 10991 //////////// 10992 // UBJSON // 10993 //////////// 10994 10995 /*! 10996 @param[in] get_char whether a new character should be retrieved from the 10997 input (true, default) or whether the last read 10998 character should be considered instead 10999 11000 @return whether a valid UBJSON value was passed to the SAX parser 11001 */ 11002 bool parse_ubjson_internal(const bool get_char = true) 11003 { 11004 return get_ubjson_value(get_char ? get_ignore_noop() : current); 11005 } 11006 11007 /*! 11008 @brief reads a UBJSON string 11009 11010 This function is either called after reading the 'S' byte explicitly 11011 indicating a string, or in case of an object key where the 'S' byte can be 11012 left out. 11013 11014 @param[out] result created string 11015 @param[in] get_char whether a new character should be retrieved from the 11016 input (true, default) or whether the last read 11017 character should be considered instead 11018 11019 @return whether string creation completed 11020 */ 11021 bool get_ubjson_string(string_t& result, const bool get_char = true) 11022 { 11023 if (get_char) 11024 { 11025 get(); // TODO(niels): may we ignore N here? 11026 } 11027 11028 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) 11029 { 11030 return false; 11031 } 11032 11033 switch (current) 11034 { 11035 case 'U': 11036 { 11037 std::uint8_t len{}; 11038 return get_number(input_format, len) && get_string(input_format, len, result); 11039 } 11040 11041 case 'i': 11042 { 11043 std::int8_t len{}; 11044 return get_number(input_format, len) && get_string(input_format, len, result); 11045 } 11046 11047 case 'I': 11048 { 11049 std::int16_t len{}; 11050 return get_number(input_format, len) && get_string(input_format, len, result); 11051 } 11052 11053 case 'l': 11054 { 11055 std::int32_t len{}; 11056 return get_number(input_format, len) && get_string(input_format, len, result); 11057 } 11058 11059 case 'L': 11060 { 11061 std::int64_t len{}; 11062 return get_number(input_format, len) && get_string(input_format, len, result); 11063 } 11064 11065 case 'u': 11066 { 11067 if (input_format != input_format_t::bjdata) 11068 { 11069 break; 11070 } 11071 std::uint16_t len{}; 11072 return get_number(input_format, len) && get_string(input_format, len, result); 11073 } 11074 11075 case 'm': 11076 { 11077 if (input_format != input_format_t::bjdata) 11078 { 11079 break; 11080 } 11081 std::uint32_t len{}; 11082 return get_number(input_format, len) && get_string(input_format, len, result); 11083 } 11084 11085 case 'M': 11086 { 11087 if (input_format != input_format_t::bjdata) 11088 { 11089 break; 11090 } 11091 std::uint64_t len{}; 11092 return get_number(input_format, len) && get_string(input_format, len, result); 11093 } 11094 11095 default: 11096 break; 11097 } 11098 auto last_token = get_token_string(); 11099 std::string message; 11100 11101 if (input_format != input_format_t::bjdata) 11102 { 11103 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token; 11104 } 11105 else 11106 { 11107 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; 11108 } 11109 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); 11110 } 11111 11112 /*! 11113 @param[out] dim an integer vector storing the ND array dimensions 11114 @return whether reading ND array size vector is successful 11115 */ 11116 bool get_ubjson_ndarray_size(std::vector<size_t>& dim) 11117 { 11118 std::pair<std::size_t, char_int_type> size_and_type; 11119 size_t dimlen = 0; 11120 bool no_ndarray = true; 11121 11122 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) 11123 { 11124 return false; 11125 } 11126 11127 if (size_and_type.first != npos) 11128 { 11129 if (size_and_type.second != 0) 11130 { 11131 if (size_and_type.second != 'N') 11132 { 11133 for (std::size_t i = 0; i < size_and_type.first; ++i) 11134 { 11135 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) 11136 { 11137 return false; 11138 } 11139 dim.push_back(dimlen); 11140 } 11141 } 11142 } 11143 else 11144 { 11145 for (std::size_t i = 0; i < size_and_type.first; ++i) 11146 { 11147 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) 11148 { 11149 return false; 11150 } 11151 dim.push_back(dimlen); 11152 } 11153 } 11154 } 11155 else 11156 { 11157 while (current != ']') 11158 { 11159 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) 11160 { 11161 return false; 11162 } 11163 dim.push_back(dimlen); 11164 get_ignore_noop(); 11165 } 11166 } 11167 return true; 11168 } 11169 11170 /*! 11171 @param[out] result determined size 11172 @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector 11173 or ndarray dimension is not allowed; `false` means ndarray 11174 is allowed; for output, `true` means an ndarray is found; 11175 is_ndarray can only return `true` when its initial value 11176 is `false` 11177 @param[in] prefix type marker if already read, otherwise set to 0 11178 11179 @return whether size determination completed 11180 */ 11181 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) 11182 { 11183 if (prefix == 0) 11184 { 11185 prefix = get_ignore_noop(); 11186 } 11187 11188 switch (prefix) 11189 { 11190 case 'U': 11191 { 11192 std::uint8_t number{}; 11193 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11194 { 11195 return false; 11196 } 11197 result = static_cast<std::size_t>(number); 11198 return true; 11199 } 11200 11201 case 'i': 11202 { 11203 std::int8_t number{}; 11204 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11205 { 11206 return false; 11207 } 11208 if (number < 0) 11209 { 11210 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11211 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11212 } 11213 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char 11214 return true; 11215 } 11216 11217 case 'I': 11218 { 11219 std::int16_t number{}; 11220 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11221 { 11222 return false; 11223 } 11224 if (number < 0) 11225 { 11226 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11227 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11228 } 11229 result = static_cast<std::size_t>(number); 11230 return true; 11231 } 11232 11233 case 'l': 11234 { 11235 std::int32_t number{}; 11236 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11237 { 11238 return false; 11239 } 11240 if (number < 0) 11241 { 11242 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11243 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11244 } 11245 result = static_cast<std::size_t>(number); 11246 return true; 11247 } 11248 11249 case 'L': 11250 { 11251 std::int64_t number{}; 11252 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11253 { 11254 return false; 11255 } 11256 if (number < 0) 11257 { 11258 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, 11259 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); 11260 } 11261 if (!value_in_range_of<std::size_t>(number)) 11262 { 11263 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, 11264 exception_message(input_format, "integer value overflow", "size"), nullptr)); 11265 } 11266 result = static_cast<std::size_t>(number); 11267 return true; 11268 } 11269 11270 case 'u': 11271 { 11272 if (input_format != input_format_t::bjdata) 11273 { 11274 break; 11275 } 11276 std::uint16_t number{}; 11277 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11278 { 11279 return false; 11280 } 11281 result = static_cast<std::size_t>(number); 11282 return true; 11283 } 11284 11285 case 'm': 11286 { 11287 if (input_format != input_format_t::bjdata) 11288 { 11289 break; 11290 } 11291 std::uint32_t number{}; 11292 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11293 { 11294 return false; 11295 } 11296 result = conditional_static_cast<std::size_t>(number); 11297 return true; 11298 } 11299 11300 case 'M': 11301 { 11302 if (input_format != input_format_t::bjdata) 11303 { 11304 break; 11305 } 11306 std::uint64_t number{}; 11307 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) 11308 { 11309 return false; 11310 } 11311 if (!value_in_range_of<std::size_t>(number)) 11312 { 11313 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, 11314 exception_message(input_format, "integer value overflow", "size"), nullptr)); 11315 } 11316 result = detail::conditional_static_cast<std::size_t>(number); 11317 return true; 11318 } 11319 11320 case '[': 11321 { 11322 if (input_format != input_format_t::bjdata) 11323 { 11324 break; 11325 } 11326 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array 11327 { 11328 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)); 11329 } 11330 std::vector<size_t> dim; 11331 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) 11332 { 11333 return false; 11334 } 11335 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector 11336 { 11337 result = dim.at(dim.size() - 1); 11338 return true; 11339 } 11340 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format 11341 { 11342 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container 11343 { 11344 if ( i == 0 ) 11345 { 11346 result = 0; 11347 return true; 11348 } 11349 } 11350 11351 string_t key = "_ArraySize_"; 11352 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) 11353 { 11354 return false; 11355 } 11356 result = 1; 11357 for (auto i : dim) 11358 { 11359 result *= i; 11360 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() 11361 { 11362 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)); 11363 } 11364 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i)))) 11365 { 11366 return false; 11367 } 11368 } 11369 is_ndarray = true; 11370 return sax->end_array(); 11371 } 11372 result = 0; 11373 return true; 11374 } 11375 11376 default: 11377 break; 11378 } 11379 auto last_token = get_token_string(); 11380 std::string message; 11381 11382 if (input_format != input_format_t::bjdata) 11383 { 11384 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token; 11385 } 11386 else 11387 { 11388 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; 11389 } 11390 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); 11391 } 11392 11393 /*! 11394 @brief determine the type and size for a container 11395 11396 In the optimized UBJSON format, a type and a size can be provided to allow 11397 for a more compact representation. 11398 11399 @param[out] result pair of the size and the type 11400 @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector 11401 11402 @return whether pair creation completed 11403 */ 11404 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false) 11405 { 11406 result.first = npos; // size 11407 result.second = 0; // type 11408 bool is_ndarray = false; 11409 11410 get_ignore_noop(); 11411 11412 if (current == '$') 11413 { 11414 result.second = get(); // must not ignore 'N', because 'N' maybe the type 11415 if (input_format == input_format_t::bjdata 11416 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) 11417 { 11418 auto last_token = get_token_string(); 11419 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11420 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); 11421 } 11422 11423 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) 11424 { 11425 return false; 11426 } 11427 11428 get_ignore_noop(); 11429 if (JSON_HEDLEY_UNLIKELY(current != '#')) 11430 { 11431 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) 11432 { 11433 return false; 11434 } 11435 auto last_token = get_token_string(); 11436 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11437 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); 11438 } 11439 11440 const bool is_error = get_ubjson_size_value(result.first, is_ndarray); 11441 if (input_format == input_format_t::bjdata && is_ndarray) 11442 { 11443 if (inside_ndarray) 11444 { 11445 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, 11446 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr)); 11447 } 11448 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters 11449 } 11450 return is_error; 11451 } 11452 11453 if (current == '#') 11454 { 11455 const bool is_error = get_ubjson_size_value(result.first, is_ndarray); 11456 if (input_format == input_format_t::bjdata && is_ndarray) 11457 { 11458 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, 11459 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); 11460 } 11461 return is_error; 11462 } 11463 11464 return true; 11465 } 11466 11467 /*! 11468 @param prefix the previously read or set type prefix 11469 @return whether value creation completed 11470 */ 11471 bool get_ubjson_value(const char_int_type prefix) 11472 { 11473 switch (prefix) 11474 { 11475 case char_traits<char_type>::eof(): // EOF 11476 return unexpect_eof(input_format, "value"); 11477 11478 case 'T': // true 11479 return sax->boolean(true); 11480 case 'F': // false 11481 return sax->boolean(false); 11482 11483 case 'Z': // null 11484 return sax->null(); 11485 11486 case 'U': 11487 { 11488 std::uint8_t number{}; 11489 return get_number(input_format, number) && sax->number_unsigned(number); 11490 } 11491 11492 case 'i': 11493 { 11494 std::int8_t number{}; 11495 return get_number(input_format, number) && sax->number_integer(number); 11496 } 11497 11498 case 'I': 11499 { 11500 std::int16_t number{}; 11501 return get_number(input_format, number) && sax->number_integer(number); 11502 } 11503 11504 case 'l': 11505 { 11506 std::int32_t number{}; 11507 return get_number(input_format, number) && sax->number_integer(number); 11508 } 11509 11510 case 'L': 11511 { 11512 std::int64_t number{}; 11513 return get_number(input_format, number) && sax->number_integer(number); 11514 } 11515 11516 case 'u': 11517 { 11518 if (input_format != input_format_t::bjdata) 11519 { 11520 break; 11521 } 11522 std::uint16_t number{}; 11523 return get_number(input_format, number) && sax->number_unsigned(number); 11524 } 11525 11526 case 'm': 11527 { 11528 if (input_format != input_format_t::bjdata) 11529 { 11530 break; 11531 } 11532 std::uint32_t number{}; 11533 return get_number(input_format, number) && sax->number_unsigned(number); 11534 } 11535 11536 case 'M': 11537 { 11538 if (input_format != input_format_t::bjdata) 11539 { 11540 break; 11541 } 11542 std::uint64_t number{}; 11543 return get_number(input_format, number) && sax->number_unsigned(number); 11544 } 11545 11546 case 'h': 11547 { 11548 if (input_format != input_format_t::bjdata) 11549 { 11550 break; 11551 } 11552 const auto byte1_raw = get(); 11553 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) 11554 { 11555 return false; 11556 } 11557 const auto byte2_raw = get(); 11558 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) 11559 { 11560 return false; 11561 } 11562 11563 const auto byte1 = static_cast<unsigned char>(byte1_raw); 11564 const auto byte2 = static_cast<unsigned char>(byte2_raw); 11565 11566 // code from RFC 7049, Appendix D, Figure 3: 11567 // As half-precision floating-point numbers were only added 11568 // to IEEE 754 in 2008, today's programming platforms often 11569 // still only have limited support for them. It is very 11570 // easy to include at least decoding support for them even 11571 // without such support. An example of a small decoder for 11572 // half-precision floating-point numbers in the C language 11573 // is shown in Fig. 3. 11574 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1); 11575 const double val = [&half] 11576 { 11577 const int exp = (half >> 10u) & 0x1Fu; 11578 const unsigned int mant = half & 0x3FFu; 11579 JSON_ASSERT(0 <= exp&& exp <= 32); 11580 JSON_ASSERT(mant <= 1024); 11581 switch (exp) 11582 { 11583 case 0: 11584 return std::ldexp(mant, -24); 11585 case 31: 11586 return (mant == 0) 11587 ? std::numeric_limits<double>::infinity() 11588 : std::numeric_limits<double>::quiet_NaN(); 11589 default: 11590 return std::ldexp(mant + 1024, exp - 25); 11591 } 11592 }(); 11593 return sax->number_float((half & 0x8000u) != 0 11594 ? static_cast<number_float_t>(-val) 11595 : static_cast<number_float_t>(val), ""); 11596 } 11597 11598 case 'd': 11599 { 11600 float number{}; 11601 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), ""); 11602 } 11603 11604 case 'D': 11605 { 11606 double number{}; 11607 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), ""); 11608 } 11609 11610 case 'H': 11611 { 11612 return get_ubjson_high_precision_number(); 11613 } 11614 11615 case 'C': // char 11616 { 11617 get(); 11618 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) 11619 { 11620 return false; 11621 } 11622 if (JSON_HEDLEY_UNLIKELY(current > 127)) 11623 { 11624 auto last_token = get_token_string(); 11625 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, 11626 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)); 11627 } 11628 string_t s(1, static_cast<typename string_t::value_type>(current)); 11629 return sax->string(s); 11630 } 11631 11632 case 'S': // string 11633 { 11634 string_t s; 11635 return get_ubjson_string(s) && sax->string(s); 11636 } 11637 11638 case '[': // array 11639 return get_ubjson_array(); 11640 11641 case '{': // object 11642 return get_ubjson_object(); 11643 11644 default: // anything else 11645 break; 11646 } 11647 auto last_token = get_token_string(); 11648 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)); 11649 } 11650 11651 /*! 11652 @return whether array creation completed 11653 */ 11654 bool get_ubjson_array() 11655 { 11656 std::pair<std::size_t, char_int_type> size_and_type; 11657 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) 11658 { 11659 return false; 11660 } 11661 11662 // 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): 11663 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} 11664 11665 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) 11666 { 11667 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 11668 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) 11669 { 11670 return p.first < t; 11671 }); 11672 string_t key = "_ArrayType_"; 11673 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) 11674 { 11675 auto last_token = get_token_string(); 11676 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11677 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); 11678 } 11679 11680 string_t type = it->second; // sax->string() takes a reference 11681 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) 11682 { 11683 return false; 11684 } 11685 11686 if (size_and_type.second == 'C') 11687 { 11688 size_and_type.second = 'U'; 11689 } 11690 11691 key = "_ArrayData_"; 11692 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) 11693 { 11694 return false; 11695 } 11696 11697 for (std::size_t i = 0; i < size_and_type.first; ++i) 11698 { 11699 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) 11700 { 11701 return false; 11702 } 11703 } 11704 11705 return (sax->end_array() && sax->end_object()); 11706 } 11707 11708 if (size_and_type.first != npos) 11709 { 11710 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) 11711 { 11712 return false; 11713 } 11714 11715 if (size_and_type.second != 0) 11716 { 11717 if (size_and_type.second != 'N') 11718 { 11719 for (std::size_t i = 0; i < size_and_type.first; ++i) 11720 { 11721 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) 11722 { 11723 return false; 11724 } 11725 } 11726 } 11727 } 11728 else 11729 { 11730 for (std::size_t i = 0; i < size_and_type.first; ++i) 11731 { 11732 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) 11733 { 11734 return false; 11735 } 11736 } 11737 } 11738 } 11739 else 11740 { 11741 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 11742 { 11743 return false; 11744 } 11745 11746 while (current != ']') 11747 { 11748 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) 11749 { 11750 return false; 11751 } 11752 get_ignore_noop(); 11753 } 11754 } 11755 11756 return sax->end_array(); 11757 } 11758 11759 /*! 11760 @return whether object creation completed 11761 */ 11762 bool get_ubjson_object() 11763 { 11764 std::pair<std::size_t, char_int_type> size_and_type; 11765 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) 11766 { 11767 return false; 11768 } 11769 11770 // do not accept ND-array size in objects in BJData 11771 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) 11772 { 11773 auto last_token = get_token_string(); 11774 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, 11775 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); 11776 } 11777 11778 string_t key; 11779 if (size_and_type.first != npos) 11780 { 11781 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) 11782 { 11783 return false; 11784 } 11785 11786 if (size_and_type.second != 0) 11787 { 11788 for (std::size_t i = 0; i < size_and_type.first; ++i) 11789 { 11790 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) 11791 { 11792 return false; 11793 } 11794 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) 11795 { 11796 return false; 11797 } 11798 key.clear(); 11799 } 11800 } 11801 else 11802 { 11803 for (std::size_t i = 0; i < size_and_type.first; ++i) 11804 { 11805 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) 11806 { 11807 return false; 11808 } 11809 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) 11810 { 11811 return false; 11812 } 11813 key.clear(); 11814 } 11815 } 11816 } 11817 else 11818 { 11819 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 11820 { 11821 return false; 11822 } 11823 11824 while (current != '}') 11825 { 11826 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) 11827 { 11828 return false; 11829 } 11830 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) 11831 { 11832 return false; 11833 } 11834 get_ignore_noop(); 11835 key.clear(); 11836 } 11837 } 11838 11839 return sax->end_object(); 11840 } 11841 11842 // Note, no reader for UBJSON binary types is implemented because they do 11843 // not exist 11844 11845 bool get_ubjson_high_precision_number() 11846 { 11847 // get size of following number string 11848 std::size_t size{}; 11849 bool no_ndarray = true; 11850 auto res = get_ubjson_size_value(size, no_ndarray); 11851 if (JSON_HEDLEY_UNLIKELY(!res)) 11852 { 11853 return res; 11854 } 11855 11856 // get number string 11857 std::vector<char> number_vector; 11858 for (std::size_t i = 0; i < size; ++i) 11859 { 11860 get(); 11861 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) 11862 { 11863 return false; 11864 } 11865 number_vector.push_back(static_cast<char>(current)); 11866 } 11867 11868 // parse number string 11869 using ia_type = decltype(detail::input_adapter(number_vector)); 11870 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false); 11871 const auto result_number = number_lexer.scan(); 11872 const auto number_string = number_lexer.get_token_string(); 11873 const auto result_remainder = number_lexer.scan(); 11874 11875 using token_type = typename detail::lexer_base<BasicJsonType>::token_type; 11876 11877 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) 11878 { 11879 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, 11880 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); 11881 } 11882 11883 switch (result_number) 11884 { 11885 case token_type::value_integer: 11886 return sax->number_integer(number_lexer.get_number_integer()); 11887 case token_type::value_unsigned: 11888 return sax->number_unsigned(number_lexer.get_number_unsigned()); 11889 case token_type::value_float: 11890 return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); 11891 case token_type::uninitialized: 11892 case token_type::literal_true: 11893 case token_type::literal_false: 11894 case token_type::literal_null: 11895 case token_type::value_string: 11896 case token_type::begin_array: 11897 case token_type::begin_object: 11898 case token_type::end_array: 11899 case token_type::end_object: 11900 case token_type::name_separator: 11901 case token_type::value_separator: 11902 case token_type::parse_error: 11903 case token_type::end_of_input: 11904 case token_type::literal_or_value: 11905 default: 11906 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, 11907 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); 11908 } 11909 } 11910 11911 /////////////////////// 11912 // Utility functions // 11913 /////////////////////// 11914 11915 /*! 11916 @brief get next character from the input 11917 11918 This function provides the interface to the used input adapter. It does 11919 not throw in case the input reached EOF, but returns a -'ve valued 11920 `char_traits<char_type>::eof()` in that case. 11921 11922 @return character read from the input 11923 */ 11924 char_int_type get() 11925 { 11926 ++chars_read; 11927 return current = ia.get_character(); 11928 } 11929 11930 /*! 11931 @return character read from the input after ignoring all 'N' entries 11932 */ 11933 char_int_type get_ignore_noop() 11934 { 11935 do 11936 { 11937 get(); 11938 } 11939 while (current == 'N'); 11940 11941 return current; 11942 } 11943 11944 /* 11945 @brief read a number from the input 11946 11947 @tparam NumberType the type of the number 11948 @param[in] format the current format (for diagnostics) 11949 @param[out] result number of type @a NumberType 11950 11951 @return whether conversion completed 11952 11953 @note This function needs to respect the system's endianness, because 11954 bytes in CBOR, MessagePack, and UBJSON are stored in network order 11955 (big endian) and therefore need reordering on little endian systems. 11956 On the other hand, BSON and BJData use little endian and should reorder 11957 on big endian systems. 11958 */ 11959 template<typename NumberType, bool InputIsLittleEndian = false> 11960 bool get_number(const input_format_t format, NumberType& result) 11961 { 11962 // step 1: read input into array with system's byte order 11963 std::array<std::uint8_t, sizeof(NumberType)> vec{}; 11964 for (std::size_t i = 0; i < sizeof(NumberType); ++i) 11965 { 11966 get(); 11967 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) 11968 { 11969 return false; 11970 } 11971 11972 // reverse byte order prior to conversion if necessary 11973 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) 11974 { 11975 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current); 11976 } 11977 else 11978 { 11979 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE 11980 } 11981 } 11982 11983 // step 2: convert array into number of type T and return 11984 std::memcpy(&result, vec.data(), sizeof(NumberType)); 11985 return true; 11986 } 11987 11988 /*! 11989 @brief create a string by reading characters from the input 11990 11991 @tparam NumberType the type of the number 11992 @param[in] format the current format (for diagnostics) 11993 @param[in] len number of characters to read 11994 @param[out] result string created by reading @a len bytes 11995 11996 @return whether string creation completed 11997 11998 @note We can not reserve @a len bytes for the result, because @a len 11999 may be too large. Usually, @ref unexpect_eof() detects the end of 12000 the input before we run out of string memory. 12001 */ 12002 template<typename NumberType> 12003 bool get_string(const input_format_t format, 12004 const NumberType len, 12005 string_t& result) 12006 { 12007 bool success = true; 12008 for (NumberType i = 0; i < len; i++) 12009 { 12010 get(); 12011 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) 12012 { 12013 success = false; 12014 break; 12015 } 12016 result.push_back(static_cast<typename string_t::value_type>(current)); 12017 } 12018 return success; 12019 } 12020 12021 /*! 12022 @brief create a byte array by reading bytes from the input 12023 12024 @tparam NumberType the type of the number 12025 @param[in] format the current format (for diagnostics) 12026 @param[in] len number of bytes to read 12027 @param[out] result byte array created by reading @a len bytes 12028 12029 @return whether byte array creation completed 12030 12031 @note We can not reserve @a len bytes for the result, because @a len 12032 may be too large. Usually, @ref unexpect_eof() detects the end of 12033 the input before we run out of memory. 12034 */ 12035 template<typename NumberType> 12036 bool get_binary(const input_format_t format, 12037 const NumberType len, 12038 binary_t& result) 12039 { 12040 bool success = true; 12041 for (NumberType i = 0; i < len; i++) 12042 { 12043 get(); 12044 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) 12045 { 12046 success = false; 12047 break; 12048 } 12049 result.push_back(static_cast<std::uint8_t>(current)); 12050 } 12051 return success; 12052 } 12053 12054 /*! 12055 @param[in] format the current format (for diagnostics) 12056 @param[in] context further context information (for diagnostics) 12057 @return whether the last read character is not EOF 12058 */ 12059 JSON_HEDLEY_NON_NULL(3) 12060 bool unexpect_eof(const input_format_t format, const char* context) const 12061 { 12062 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof())) 12063 { 12064 return sax->parse_error(chars_read, "<end of file>", 12065 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); 12066 } 12067 return true; 12068 } 12069 12070 /*! 12071 @return a string representation of the last read byte 12072 */ 12073 std::string get_token_string() const 12074 { 12075 std::array<char, 3> cr{{}}; 12076 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 12077 return std::string{cr.data()}; 12078 } 12079 12080 /*! 12081 @param[in] format the current format 12082 @param[in] detail a detailed error message 12083 @param[in] context further context information 12084 @return a message string to use in the parse_error exceptions 12085 */ 12086 std::string exception_message(const input_format_t format, 12087 const std::string& detail, 12088 const std::string& context) const 12089 { 12090 std::string error_msg = "syntax error while parsing "; 12091 12092 switch (format) 12093 { 12094 case input_format_t::cbor: 12095 error_msg += "CBOR"; 12096 break; 12097 12098 case input_format_t::msgpack: 12099 error_msg += "MessagePack"; 12100 break; 12101 12102 case input_format_t::ubjson: 12103 error_msg += "UBJSON"; 12104 break; 12105 12106 case input_format_t::bson: 12107 error_msg += "BSON"; 12108 break; 12109 12110 case input_format_t::bjdata: 12111 error_msg += "BJData"; 12112 break; 12113 12114 case input_format_t::json: // LCOV_EXCL_LINE 12115 default: // LCOV_EXCL_LINE 12116 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 12117 } 12118 12119 return concat(error_msg, ' ', context, ": ", detail); 12120 } 12121 12122 private: 12123 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1); 12124 12125 /// input adapter 12126 InputAdapterType ia; 12127 12128 /// the current character 12129 char_int_type current = char_traits<char_type>::eof(); 12130 12131 /// the number of characters read 12132 std::size_t chars_read = 0; 12133 12134 /// whether we can assume little endianness 12135 const bool is_little_endian = little_endianness(); 12136 12137 /// input format 12138 const input_format_t input_format = input_format_t::json; 12139 12140 /// the SAX parser 12141 json_sax_t* sax = nullptr; 12142 12143 // excluded markers in bjdata optimized type 12144 #define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ 12145 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{') 12146 12147 #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ 12148 make_array<bjd_type>( \ 12149 bjd_type{'C', "char"}, \ 12150 bjd_type{'D', "double"}, \ 12151 bjd_type{'I', "int16"}, \ 12152 bjd_type{'L', "int64"}, \ 12153 bjd_type{'M', "uint64"}, \ 12154 bjd_type{'U', "uint8"}, \ 12155 bjd_type{'d', "single"}, \ 12156 bjd_type{'i', "int8"}, \ 12157 bjd_type{'l', "int32"}, \ 12158 bjd_type{'m', "uint32"}, \ 12159 bjd_type{'u', "uint16"}) 12160 12161 JSON_PRIVATE_UNLESS_TESTED: 12162 // lookup tables 12163 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) 12164 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers = 12165 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_; 12166 12167 using bjd_type = std::pair<char_int_type, string_t>; 12168 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) 12169 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map = 12170 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_; 12171 12172 #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ 12173 #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ 12174 }; 12175 12176 #ifndef JSON_HAS_CPP_17 12177 template<typename BasicJsonType, typename InputAdapterType, typename SAX> 12178 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos; 12179 #endif 12180 12181 } // namespace detail 12182 NLOHMANN_JSON_NAMESPACE_END 12183 12184 // #include <nlohmann/detail/input/input_adapters.hpp> 12185 12186 // #include <nlohmann/detail/input/lexer.hpp> 12187 12188 // #include <nlohmann/detail/input/parser.hpp> 12189 // __ _____ _____ _____ 12190 // __| | __| | | | JSON for Modern C++ 12191 // | | |__ | | | | | | version 3.11.3 12192 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12193 // 12194 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 12195 // SPDX-License-Identifier: MIT 12196 12197 12198 12199 #include <cmath> // isfinite 12200 #include <cstdint> // uint8_t 12201 #include <functional> // function 12202 #include <string> // string 12203 #include <utility> // move 12204 #include <vector> // vector 12205 12206 // #include <nlohmann/detail/exceptions.hpp> 12207 12208 // #include <nlohmann/detail/input/input_adapters.hpp> 12209 12210 // #include <nlohmann/detail/input/json_sax.hpp> 12211 12212 // #include <nlohmann/detail/input/lexer.hpp> 12213 12214 // #include <nlohmann/detail/macro_scope.hpp> 12215 12216 // #include <nlohmann/detail/meta/is_sax.hpp> 12217 12218 // #include <nlohmann/detail/string_concat.hpp> 12219 12220 // #include <nlohmann/detail/value_t.hpp> 12221 12222 12223 NLOHMANN_JSON_NAMESPACE_BEGIN 12224 namespace detail 12225 { 12226 //////////// 12227 // parser // 12228 //////////// 12229 12230 enum class parse_event_t : std::uint8_t 12231 { 12232 /// the parser read `{` and started to process a JSON object 12233 object_start, 12234 /// the parser read `}` and finished processing a JSON object 12235 object_end, 12236 /// the parser read `[` and started to process a JSON array 12237 array_start, 12238 /// the parser read `]` and finished processing a JSON array 12239 array_end, 12240 /// the parser read a key of a value in an object 12241 key, 12242 /// the parser finished reading a JSON value 12243 value 12244 }; 12245 12246 template<typename BasicJsonType> 12247 using parser_callback_t = 12248 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>; 12249 12250 /*! 12251 @brief syntax analysis 12252 12253 This class implements a recursive descent parser. 12254 */ 12255 template<typename BasicJsonType, typename InputAdapterType> 12256 class parser 12257 { 12258 using number_integer_t = typename BasicJsonType::number_integer_t; 12259 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 12260 using number_float_t = typename BasicJsonType::number_float_t; 12261 using string_t = typename BasicJsonType::string_t; 12262 using lexer_t = lexer<BasicJsonType, InputAdapterType>; 12263 using token_type = typename lexer_t::token_type; 12264 12265 public: 12266 /// a parser reading from an input adapter 12267 explicit parser(InputAdapterType&& adapter, 12268 const parser_callback_t<BasicJsonType> cb = nullptr, 12269 const bool allow_exceptions_ = true, 12270 const bool skip_comments = false) 12271 : callback(cb) 12272 , m_lexer(std::move(adapter), skip_comments) 12273 , allow_exceptions(allow_exceptions_) 12274 { 12275 // read first token 12276 get_token(); 12277 } 12278 12279 /*! 12280 @brief public parser interface 12281 12282 @param[in] strict whether to expect the last token to be EOF 12283 @param[in,out] result parsed JSON value 12284 12285 @throw parse_error.101 in case of an unexpected token 12286 @throw parse_error.102 if to_unicode fails or surrogate error 12287 @throw parse_error.103 if to_unicode fails 12288 */ 12289 void parse(const bool strict, BasicJsonType& result) 12290 { 12291 if (callback) 12292 { 12293 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); 12294 sax_parse_internal(&sdp); 12295 12296 // in strict mode, input must be completely read 12297 if (strict && (get_token() != token_type::end_of_input)) 12298 { 12299 sdp.parse_error(m_lexer.get_position(), 12300 m_lexer.get_token_string(), 12301 parse_error::create(101, m_lexer.get_position(), 12302 exception_message(token_type::end_of_input, "value"), nullptr)); 12303 } 12304 12305 // in case of an error, return discarded value 12306 if (sdp.is_errored()) 12307 { 12308 result = value_t::discarded; 12309 return; 12310 } 12311 12312 // set top-level value to null if it was discarded by the callback 12313 // function 12314 if (result.is_discarded()) 12315 { 12316 result = nullptr; 12317 } 12318 } 12319 else 12320 { 12321 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); 12322 sax_parse_internal(&sdp); 12323 12324 // in strict mode, input must be completely read 12325 if (strict && (get_token() != token_type::end_of_input)) 12326 { 12327 sdp.parse_error(m_lexer.get_position(), 12328 m_lexer.get_token_string(), 12329 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); 12330 } 12331 12332 // in case of an error, return discarded value 12333 if (sdp.is_errored()) 12334 { 12335 result = value_t::discarded; 12336 return; 12337 } 12338 } 12339 12340 result.assert_invariant(); 12341 } 12342 12343 /*! 12344 @brief public accept interface 12345 12346 @param[in] strict whether to expect the last token to be EOF 12347 @return whether the input is a proper JSON text 12348 */ 12349 bool accept(const bool strict = true) 12350 { 12351 json_sax_acceptor<BasicJsonType> sax_acceptor; 12352 return sax_parse(&sax_acceptor, strict); 12353 } 12354 12355 template<typename SAX> 12356 JSON_HEDLEY_NON_NULL(2) 12357 bool sax_parse(SAX* sax, const bool strict = true) 12358 { 12359 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; 12360 const bool result = sax_parse_internal(sax); 12361 12362 // strict mode: next byte must be EOF 12363 if (result && strict && (get_token() != token_type::end_of_input)) 12364 { 12365 return sax->parse_error(m_lexer.get_position(), 12366 m_lexer.get_token_string(), 12367 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); 12368 } 12369 12370 return result; 12371 } 12372 12373 private: 12374 template<typename SAX> 12375 JSON_HEDLEY_NON_NULL(2) 12376 bool sax_parse_internal(SAX* sax) 12377 { 12378 // stack to remember the hierarchy of structured values we are parsing 12379 // true = array; false = object 12380 std::vector<bool> states; 12381 // value to avoid a goto (see comment where set to true) 12382 bool skip_to_state_evaluation = false; 12383 12384 while (true) 12385 { 12386 if (!skip_to_state_evaluation) 12387 { 12388 // invariant: get_token() was called before each iteration 12389 switch (last_token) 12390 { 12391 case token_type::begin_object: 12392 { 12393 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) 12394 { 12395 return false; 12396 } 12397 12398 // closing } -> we are done 12399 if (get_token() == token_type::end_object) 12400 { 12401 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) 12402 { 12403 return false; 12404 } 12405 break; 12406 } 12407 12408 // parse key 12409 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) 12410 { 12411 return sax->parse_error(m_lexer.get_position(), 12412 m_lexer.get_token_string(), 12413 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); 12414 } 12415 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) 12416 { 12417 return false; 12418 } 12419 12420 // parse separator (:) 12421 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) 12422 { 12423 return sax->parse_error(m_lexer.get_position(), 12424 m_lexer.get_token_string(), 12425 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); 12426 } 12427 12428 // remember we are now inside an object 12429 states.push_back(false); 12430 12431 // parse values 12432 get_token(); 12433 continue; 12434 } 12435 12436 case token_type::begin_array: 12437 { 12438 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) 12439 { 12440 return false; 12441 } 12442 12443 // closing ] -> we are done 12444 if (get_token() == token_type::end_array) 12445 { 12446 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) 12447 { 12448 return false; 12449 } 12450 break; 12451 } 12452 12453 // remember we are now inside an array 12454 states.push_back(true); 12455 12456 // parse values (no need to call get_token) 12457 continue; 12458 } 12459 12460 case token_type::value_float: 12461 { 12462 const auto res = m_lexer.get_number_float(); 12463 12464 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) 12465 { 12466 return sax->parse_error(m_lexer.get_position(), 12467 m_lexer.get_token_string(), 12468 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); 12469 } 12470 12471 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) 12472 { 12473 return false; 12474 } 12475 12476 break; 12477 } 12478 12479 case token_type::literal_false: 12480 { 12481 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) 12482 { 12483 return false; 12484 } 12485 break; 12486 } 12487 12488 case token_type::literal_null: 12489 { 12490 if (JSON_HEDLEY_UNLIKELY(!sax->null())) 12491 { 12492 return false; 12493 } 12494 break; 12495 } 12496 12497 case token_type::literal_true: 12498 { 12499 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) 12500 { 12501 return false; 12502 } 12503 break; 12504 } 12505 12506 case token_type::value_integer: 12507 { 12508 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) 12509 { 12510 return false; 12511 } 12512 break; 12513 } 12514 12515 case token_type::value_string: 12516 { 12517 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) 12518 { 12519 return false; 12520 } 12521 break; 12522 } 12523 12524 case token_type::value_unsigned: 12525 { 12526 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) 12527 { 12528 return false; 12529 } 12530 break; 12531 } 12532 12533 case token_type::parse_error: 12534 { 12535 // using "uninitialized" to avoid "expected" message 12536 return sax->parse_error(m_lexer.get_position(), 12537 m_lexer.get_token_string(), 12538 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); 12539 } 12540 case token_type::end_of_input: 12541 { 12542 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) 12543 { 12544 return sax->parse_error(m_lexer.get_position(), 12545 m_lexer.get_token_string(), 12546 parse_error::create(101, m_lexer.get_position(), 12547 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); 12548 } 12549 12550 return sax->parse_error(m_lexer.get_position(), 12551 m_lexer.get_token_string(), 12552 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); 12553 } 12554 case token_type::uninitialized: 12555 case token_type::end_array: 12556 case token_type::end_object: 12557 case token_type::name_separator: 12558 case token_type::value_separator: 12559 case token_type::literal_or_value: 12560 default: // the last token was unexpected 12561 { 12562 return sax->parse_error(m_lexer.get_position(), 12563 m_lexer.get_token_string(), 12564 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); 12565 } 12566 } 12567 } 12568 else 12569 { 12570 skip_to_state_evaluation = false; 12571 } 12572 12573 // we reached this line after we successfully parsed a value 12574 if (states.empty()) 12575 { 12576 // empty stack: we reached the end of the hierarchy: done 12577 return true; 12578 } 12579 12580 if (states.back()) // array 12581 { 12582 // comma -> next value 12583 if (get_token() == token_type::value_separator) 12584 { 12585 // parse a new value 12586 get_token(); 12587 continue; 12588 } 12589 12590 // closing ] 12591 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) 12592 { 12593 if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) 12594 { 12595 return false; 12596 } 12597 12598 // We are done with this array. Before we can parse a 12599 // new value, we need to evaluate the new state first. 12600 // By setting skip_to_state_evaluation to false, we 12601 // are effectively jumping to the beginning of this if. 12602 JSON_ASSERT(!states.empty()); 12603 states.pop_back(); 12604 skip_to_state_evaluation = true; 12605 continue; 12606 } 12607 12608 return sax->parse_error(m_lexer.get_position(), 12609 m_lexer.get_token_string(), 12610 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); 12611 } 12612 12613 // states.back() is false -> object 12614 12615 // comma -> next value 12616 if (get_token() == token_type::value_separator) 12617 { 12618 // parse key 12619 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) 12620 { 12621 return sax->parse_error(m_lexer.get_position(), 12622 m_lexer.get_token_string(), 12623 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); 12624 } 12625 12626 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) 12627 { 12628 return false; 12629 } 12630 12631 // parse separator (:) 12632 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) 12633 { 12634 return sax->parse_error(m_lexer.get_position(), 12635 m_lexer.get_token_string(), 12636 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); 12637 } 12638 12639 // parse values 12640 get_token(); 12641 continue; 12642 } 12643 12644 // closing } 12645 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) 12646 { 12647 if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) 12648 { 12649 return false; 12650 } 12651 12652 // We are done with this object. Before we can parse a 12653 // new value, we need to evaluate the new state first. 12654 // By setting skip_to_state_evaluation to false, we 12655 // are effectively jumping to the beginning of this if. 12656 JSON_ASSERT(!states.empty()); 12657 states.pop_back(); 12658 skip_to_state_evaluation = true; 12659 continue; 12660 } 12661 12662 return sax->parse_error(m_lexer.get_position(), 12663 m_lexer.get_token_string(), 12664 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); 12665 } 12666 } 12667 12668 /// get next token from lexer 12669 token_type get_token() 12670 { 12671 return last_token = m_lexer.scan(); 12672 } 12673 12674 std::string exception_message(const token_type expected, const std::string& context) 12675 { 12676 std::string error_msg = "syntax error "; 12677 12678 if (!context.empty()) 12679 { 12680 error_msg += concat("while parsing ", context, ' '); 12681 } 12682 12683 error_msg += "- "; 12684 12685 if (last_token == token_type::parse_error) 12686 { 12687 error_msg += concat(m_lexer.get_error_message(), "; last read: '", 12688 m_lexer.get_token_string(), '\''); 12689 } 12690 else 12691 { 12692 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); 12693 } 12694 12695 if (expected != token_type::uninitialized) 12696 { 12697 error_msg += concat("; expected ", lexer_t::token_type_name(expected)); 12698 } 12699 12700 return error_msg; 12701 } 12702 12703 private: 12704 /// callback function 12705 const parser_callback_t<BasicJsonType> callback = nullptr; 12706 /// the type of the last read token 12707 token_type last_token = token_type::uninitialized; 12708 /// the lexer 12709 lexer_t m_lexer; 12710 /// whether to throw exceptions in case of errors 12711 const bool allow_exceptions = true; 12712 }; 12713 12714 } // namespace detail 12715 NLOHMANN_JSON_NAMESPACE_END 12716 12717 // #include <nlohmann/detail/iterators/internal_iterator.hpp> 12718 // __ _____ _____ _____ 12719 // __| | __| | | | JSON for Modern C++ 12720 // | | |__ | | | | | | version 3.11.3 12721 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12722 // 12723 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 12724 // SPDX-License-Identifier: MIT 12725 12726 12727 12728 // #include <nlohmann/detail/abi_macros.hpp> 12729 12730 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> 12731 // __ _____ _____ _____ 12732 // __| | __| | | | JSON for Modern C++ 12733 // | | |__ | | | | | | version 3.11.3 12734 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12735 // 12736 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 12737 // SPDX-License-Identifier: MIT 12738 12739 12740 12741 #include <cstddef> // ptrdiff_t 12742 #include <limits> // numeric_limits 12743 12744 // #include <nlohmann/detail/macro_scope.hpp> 12745 12746 12747 NLOHMANN_JSON_NAMESPACE_BEGIN 12748 namespace detail 12749 { 12750 12751 /* 12752 @brief an iterator for primitive JSON types 12753 12754 This class models an iterator for primitive JSON types (boolean, number, 12755 string). It's only purpose is to allow the iterator/const_iterator classes 12756 to "iterate" over primitive values. Internally, the iterator is modeled by 12757 a `difference_type` variable. Value begin_value (`0`) models the begin, 12758 end_value (`1`) models past the end. 12759 */ 12760 class primitive_iterator_t 12761 { 12762 private: 12763 using difference_type = std::ptrdiff_t; 12764 static constexpr difference_type begin_value = 0; 12765 static constexpr difference_type end_value = begin_value + 1; 12766 12767 JSON_PRIVATE_UNLESS_TESTED: 12768 /// iterator as signed integer type 12769 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)(); 12770 12771 public: 12772 constexpr difference_type get_value() const noexcept 12773 { 12774 return m_it; 12775 } 12776 12777 /// set iterator to a defined beginning 12778 void set_begin() noexcept 12779 { 12780 m_it = begin_value; 12781 } 12782 12783 /// set iterator to a defined past the end 12784 void set_end() noexcept 12785 { 12786 m_it = end_value; 12787 } 12788 12789 /// return whether the iterator can be dereferenced 12790 constexpr bool is_begin() const noexcept 12791 { 12792 return m_it == begin_value; 12793 } 12794 12795 /// return whether the iterator is at end 12796 constexpr bool is_end() const noexcept 12797 { 12798 return m_it == end_value; 12799 } 12800 12801 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept 12802 { 12803 return lhs.m_it == rhs.m_it; 12804 } 12805 12806 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept 12807 { 12808 return lhs.m_it < rhs.m_it; 12809 } 12810 12811 primitive_iterator_t operator+(difference_type n) noexcept 12812 { 12813 auto result = *this; 12814 result += n; 12815 return result; 12816 } 12817 12818 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept 12819 { 12820 return lhs.m_it - rhs.m_it; 12821 } 12822 12823 primitive_iterator_t& operator++() noexcept 12824 { 12825 ++m_it; 12826 return *this; 12827 } 12828 12829 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp) 12830 { 12831 auto result = *this; 12832 ++m_it; 12833 return result; 12834 } 12835 12836 primitive_iterator_t& operator--() noexcept 12837 { 12838 --m_it; 12839 return *this; 12840 } 12841 12842 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp) 12843 { 12844 auto result = *this; 12845 --m_it; 12846 return result; 12847 } 12848 12849 primitive_iterator_t& operator+=(difference_type n) noexcept 12850 { 12851 m_it += n; 12852 return *this; 12853 } 12854 12855 primitive_iterator_t& operator-=(difference_type n) noexcept 12856 { 12857 m_it -= n; 12858 return *this; 12859 } 12860 }; 12861 12862 } // namespace detail 12863 NLOHMANN_JSON_NAMESPACE_END 12864 12865 12866 NLOHMANN_JSON_NAMESPACE_BEGIN 12867 namespace detail 12868 { 12869 12870 /*! 12871 @brief an iterator value 12872 12873 @note This structure could easily be a union, but MSVC currently does not allow 12874 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. 12875 */ 12876 template<typename BasicJsonType> struct internal_iterator 12877 { 12878 /// iterator for JSON objects 12879 typename BasicJsonType::object_t::iterator object_iterator {}; 12880 /// iterator for JSON arrays 12881 typename BasicJsonType::array_t::iterator array_iterator {}; 12882 /// generic iterator for all other types 12883 primitive_iterator_t primitive_iterator {}; 12884 }; 12885 12886 } // namespace detail 12887 NLOHMANN_JSON_NAMESPACE_END 12888 12889 // #include <nlohmann/detail/iterators/iter_impl.hpp> 12890 // __ _____ _____ _____ 12891 // __| | __| | | | JSON for Modern C++ 12892 // | | |__ | | | | | | version 3.11.3 12893 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 12894 // 12895 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 12896 // SPDX-License-Identifier: MIT 12897 12898 12899 12900 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next 12901 #include <type_traits> // conditional, is_const, remove_const 12902 12903 // #include <nlohmann/detail/exceptions.hpp> 12904 12905 // #include <nlohmann/detail/iterators/internal_iterator.hpp> 12906 12907 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> 12908 12909 // #include <nlohmann/detail/macro_scope.hpp> 12910 12911 // #include <nlohmann/detail/meta/cpp_future.hpp> 12912 12913 // #include <nlohmann/detail/meta/type_traits.hpp> 12914 12915 // #include <nlohmann/detail/value_t.hpp> 12916 12917 12918 NLOHMANN_JSON_NAMESPACE_BEGIN 12919 namespace detail 12920 { 12921 12922 // forward declare, to be able to friend it later on 12923 template<typename IteratorType> class iteration_proxy; 12924 template<typename IteratorType> class iteration_proxy_value; 12925 12926 /*! 12927 @brief a template for a bidirectional iterator for the @ref basic_json class 12928 This class implements a both iterators (iterator and const_iterator) for the 12929 @ref basic_json class. 12930 @note An iterator is called *initialized* when a pointer to a JSON value has 12931 been set (e.g., by a constructor or a copy assignment). If the iterator is 12932 default-constructed, it is *uninitialized* and most methods are undefined. 12933 **The library uses assertions to detect calls on uninitialized iterators.** 12934 @requirement The class satisfies the following concept requirements: 12935 - 12936 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 12937 The iterator that can be moved can be moved in both directions (i.e. 12938 incremented and decremented). 12939 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional 12940 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) 12941 */ 12942 template<typename BasicJsonType> 12943 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 12944 { 12945 /// the iterator with BasicJsonType of different const-ness 12946 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>; 12947 /// allow basic_json to access private members 12948 friend other_iter_impl; 12949 friend BasicJsonType; 12950 friend iteration_proxy<iter_impl>; 12951 friend iteration_proxy_value<iter_impl>; 12952 12953 using object_t = typename BasicJsonType::object_t; 12954 using array_t = typename BasicJsonType::array_t; 12955 // make sure BasicJsonType is basic_json or const basic_json 12956 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value, 12957 "iter_impl only accepts (const) basic_json"); 12958 // superficial check for the LegacyBidirectionalIterator named requirement 12959 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value 12960 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value, 12961 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement."); 12962 12963 public: 12964 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. 12965 /// The C++ Standard has never required user-defined iterators to derive from std::iterator. 12966 /// A user-defined iterator should provide publicly accessible typedefs named 12967 /// iterator_category, value_type, difference_type, pointer, and reference. 12968 /// Note that value_type is required to be non-const, even for constant iterators. 12969 using iterator_category = std::bidirectional_iterator_tag; 12970 12971 /// the type of the values when the iterator is dereferenced 12972 using value_type = typename BasicJsonType::value_type; 12973 /// a type to represent differences between iterators 12974 using difference_type = typename BasicJsonType::difference_type; 12975 /// defines a pointer to the type iterated over (value_type) 12976 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value, 12977 typename BasicJsonType::const_pointer, 12978 typename BasicJsonType::pointer>::type; 12979 /// defines a reference to the type iterated over (value_type) 12980 using reference = 12981 typename std::conditional<std::is_const<BasicJsonType>::value, 12982 typename BasicJsonType::const_reference, 12983 typename BasicJsonType::reference>::type; 12984 12985 iter_impl() = default; 12986 ~iter_impl() = default; 12987 iter_impl(iter_impl&&) noexcept = default; 12988 iter_impl& operator=(iter_impl&&) noexcept = default; 12989 12990 /*! 12991 @brief constructor for a given JSON instance 12992 @param[in] object pointer to a JSON object for this iterator 12993 @pre object != nullptr 12994 @post The iterator is initialized; i.e. `m_object != nullptr`. 12995 */ 12996 explicit iter_impl(pointer object) noexcept : m_object(object) 12997 { 12998 JSON_ASSERT(m_object != nullptr); 12999 13000 switch (m_object->m_data.m_type) 13001 { 13002 case value_t::object: 13003 { 13004 m_it.object_iterator = typename object_t::iterator(); 13005 break; 13006 } 13007 13008 case value_t::array: 13009 { 13010 m_it.array_iterator = typename array_t::iterator(); 13011 break; 13012 } 13013 13014 case value_t::null: 13015 case value_t::string: 13016 case value_t::boolean: 13017 case value_t::number_integer: 13018 case value_t::number_unsigned: 13019 case value_t::number_float: 13020 case value_t::binary: 13021 case value_t::discarded: 13022 default: 13023 { 13024 m_it.primitive_iterator = primitive_iterator_t(); 13025 break; 13026 } 13027 } 13028 } 13029 13030 /*! 13031 @note The conventional copy constructor and copy assignment are implicitly 13032 defined. Combined with the following converting constructor and 13033 assignment, they support: (1) copy from iterator to iterator, (2) 13034 copy from const iterator to const iterator, and (3) conversion from 13035 iterator to const iterator. However conversion from const iterator 13036 to iterator is not defined. 13037 */ 13038 13039 /*! 13040 @brief const copy constructor 13041 @param[in] other const iterator to copy from 13042 @note This copy constructor had to be defined explicitly to circumvent a bug 13043 occurring on msvc v19.0 compiler (VS 2015) debug build. For more 13044 information refer to: https://github.com/nlohmann/json/issues/1608 13045 */ 13046 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept 13047 : m_object(other.m_object), m_it(other.m_it) 13048 {} 13049 13050 /*! 13051 @brief converting assignment 13052 @param[in] other const iterator to copy from 13053 @return const/non-const iterator 13054 @note It is not checked whether @a other is initialized. 13055 */ 13056 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept 13057 { 13058 if (&other != this) 13059 { 13060 m_object = other.m_object; 13061 m_it = other.m_it; 13062 } 13063 return *this; 13064 } 13065 13066 /*! 13067 @brief converting constructor 13068 @param[in] other non-const iterator to copy from 13069 @note It is not checked whether @a other is initialized. 13070 */ 13071 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept 13072 : m_object(other.m_object), m_it(other.m_it) 13073 {} 13074 13075 /*! 13076 @brief converting assignment 13077 @param[in] other non-const iterator to copy from 13078 @return const/non-const iterator 13079 @note It is not checked whether @a other is initialized. 13080 */ 13081 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp) 13082 { 13083 m_object = other.m_object; 13084 m_it = other.m_it; 13085 return *this; 13086 } 13087 13088 JSON_PRIVATE_UNLESS_TESTED: 13089 /*! 13090 @brief set the iterator to the first value 13091 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13092 */ 13093 void set_begin() noexcept 13094 { 13095 JSON_ASSERT(m_object != nullptr); 13096 13097 switch (m_object->m_data.m_type) 13098 { 13099 case value_t::object: 13100 { 13101 m_it.object_iterator = m_object->m_data.m_value.object->begin(); 13102 break; 13103 } 13104 13105 case value_t::array: 13106 { 13107 m_it.array_iterator = m_object->m_data.m_value.array->begin(); 13108 break; 13109 } 13110 13111 case value_t::null: 13112 { 13113 // set to end so begin()==end() is true: null is empty 13114 m_it.primitive_iterator.set_end(); 13115 break; 13116 } 13117 13118 case value_t::string: 13119 case value_t::boolean: 13120 case value_t::number_integer: 13121 case value_t::number_unsigned: 13122 case value_t::number_float: 13123 case value_t::binary: 13124 case value_t::discarded: 13125 default: 13126 { 13127 m_it.primitive_iterator.set_begin(); 13128 break; 13129 } 13130 } 13131 } 13132 13133 /*! 13134 @brief set the iterator past the last value 13135 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13136 */ 13137 void set_end() noexcept 13138 { 13139 JSON_ASSERT(m_object != nullptr); 13140 13141 switch (m_object->m_data.m_type) 13142 { 13143 case value_t::object: 13144 { 13145 m_it.object_iterator = m_object->m_data.m_value.object->end(); 13146 break; 13147 } 13148 13149 case value_t::array: 13150 { 13151 m_it.array_iterator = m_object->m_data.m_value.array->end(); 13152 break; 13153 } 13154 13155 case value_t::null: 13156 case value_t::string: 13157 case value_t::boolean: 13158 case value_t::number_integer: 13159 case value_t::number_unsigned: 13160 case value_t::number_float: 13161 case value_t::binary: 13162 case value_t::discarded: 13163 default: 13164 { 13165 m_it.primitive_iterator.set_end(); 13166 break; 13167 } 13168 } 13169 } 13170 13171 public: 13172 /*! 13173 @brief return a reference to the value pointed to by the iterator 13174 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13175 */ 13176 reference operator*() const 13177 { 13178 JSON_ASSERT(m_object != nullptr); 13179 13180 switch (m_object->m_data.m_type) 13181 { 13182 case value_t::object: 13183 { 13184 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); 13185 return m_it.object_iterator->second; 13186 } 13187 13188 case value_t::array: 13189 { 13190 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); 13191 return *m_it.array_iterator; 13192 } 13193 13194 case value_t::null: 13195 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13196 13197 case value_t::string: 13198 case value_t::boolean: 13199 case value_t::number_integer: 13200 case value_t::number_unsigned: 13201 case value_t::number_float: 13202 case value_t::binary: 13203 case value_t::discarded: 13204 default: 13205 { 13206 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) 13207 { 13208 return *m_object; 13209 } 13210 13211 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13212 } 13213 } 13214 } 13215 13216 /*! 13217 @brief dereference the iterator 13218 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13219 */ 13220 pointer operator->() const 13221 { 13222 JSON_ASSERT(m_object != nullptr); 13223 13224 switch (m_object->m_data.m_type) 13225 { 13226 case value_t::object: 13227 { 13228 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); 13229 return &(m_it.object_iterator->second); 13230 } 13231 13232 case value_t::array: 13233 { 13234 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); 13235 return &*m_it.array_iterator; 13236 } 13237 13238 case value_t::null: 13239 case value_t::string: 13240 case value_t::boolean: 13241 case value_t::number_integer: 13242 case value_t::number_unsigned: 13243 case value_t::number_float: 13244 case value_t::binary: 13245 case value_t::discarded: 13246 default: 13247 { 13248 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) 13249 { 13250 return m_object; 13251 } 13252 13253 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13254 } 13255 } 13256 } 13257 13258 /*! 13259 @brief post-increment (it++) 13260 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13261 */ 13262 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp) 13263 { 13264 auto result = *this; 13265 ++(*this); 13266 return result; 13267 } 13268 13269 /*! 13270 @brief pre-increment (++it) 13271 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13272 */ 13273 iter_impl& operator++() 13274 { 13275 JSON_ASSERT(m_object != nullptr); 13276 13277 switch (m_object->m_data.m_type) 13278 { 13279 case value_t::object: 13280 { 13281 std::advance(m_it.object_iterator, 1); 13282 break; 13283 } 13284 13285 case value_t::array: 13286 { 13287 std::advance(m_it.array_iterator, 1); 13288 break; 13289 } 13290 13291 case value_t::null: 13292 case value_t::string: 13293 case value_t::boolean: 13294 case value_t::number_integer: 13295 case value_t::number_unsigned: 13296 case value_t::number_float: 13297 case value_t::binary: 13298 case value_t::discarded: 13299 default: 13300 { 13301 ++m_it.primitive_iterator; 13302 break; 13303 } 13304 } 13305 13306 return *this; 13307 } 13308 13309 /*! 13310 @brief post-decrement (it--) 13311 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13312 */ 13313 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp) 13314 { 13315 auto result = *this; 13316 --(*this); 13317 return result; 13318 } 13319 13320 /*! 13321 @brief pre-decrement (--it) 13322 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13323 */ 13324 iter_impl& operator--() 13325 { 13326 JSON_ASSERT(m_object != nullptr); 13327 13328 switch (m_object->m_data.m_type) 13329 { 13330 case value_t::object: 13331 { 13332 std::advance(m_it.object_iterator, -1); 13333 break; 13334 } 13335 13336 case value_t::array: 13337 { 13338 std::advance(m_it.array_iterator, -1); 13339 break; 13340 } 13341 13342 case value_t::null: 13343 case value_t::string: 13344 case value_t::boolean: 13345 case value_t::number_integer: 13346 case value_t::number_unsigned: 13347 case value_t::number_float: 13348 case value_t::binary: 13349 case value_t::discarded: 13350 default: 13351 { 13352 --m_it.primitive_iterator; 13353 break; 13354 } 13355 } 13356 13357 return *this; 13358 } 13359 13360 /*! 13361 @brief comparison: equal 13362 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13363 */ 13364 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 > 13365 bool operator==(const IterImpl& other) const 13366 { 13367 // if objects are not the same, the comparison is undefined 13368 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) 13369 { 13370 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); 13371 } 13372 13373 JSON_ASSERT(m_object != nullptr); 13374 13375 switch (m_object->m_data.m_type) 13376 { 13377 case value_t::object: 13378 return (m_it.object_iterator == other.m_it.object_iterator); 13379 13380 case value_t::array: 13381 return (m_it.array_iterator == other.m_it.array_iterator); 13382 13383 case value_t::null: 13384 case value_t::string: 13385 case value_t::boolean: 13386 case value_t::number_integer: 13387 case value_t::number_unsigned: 13388 case value_t::number_float: 13389 case value_t::binary: 13390 case value_t::discarded: 13391 default: 13392 return (m_it.primitive_iterator == other.m_it.primitive_iterator); 13393 } 13394 } 13395 13396 /*! 13397 @brief comparison: not equal 13398 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13399 */ 13400 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 > 13401 bool operator!=(const IterImpl& other) const 13402 { 13403 return !operator==(other); 13404 } 13405 13406 /*! 13407 @brief comparison: smaller 13408 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13409 */ 13410 bool operator<(const iter_impl& other) const 13411 { 13412 // if objects are not the same, the comparison is undefined 13413 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) 13414 { 13415 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); 13416 } 13417 13418 JSON_ASSERT(m_object != nullptr); 13419 13420 switch (m_object->m_data.m_type) 13421 { 13422 case value_t::object: 13423 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); 13424 13425 case value_t::array: 13426 return (m_it.array_iterator < other.m_it.array_iterator); 13427 13428 case value_t::null: 13429 case value_t::string: 13430 case value_t::boolean: 13431 case value_t::number_integer: 13432 case value_t::number_unsigned: 13433 case value_t::number_float: 13434 case value_t::binary: 13435 case value_t::discarded: 13436 default: 13437 return (m_it.primitive_iterator < other.m_it.primitive_iterator); 13438 } 13439 } 13440 13441 /*! 13442 @brief comparison: less than or equal 13443 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13444 */ 13445 bool operator<=(const iter_impl& other) const 13446 { 13447 return !other.operator < (*this); 13448 } 13449 13450 /*! 13451 @brief comparison: greater than 13452 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13453 */ 13454 bool operator>(const iter_impl& other) const 13455 { 13456 return !operator<=(other); 13457 } 13458 13459 /*! 13460 @brief comparison: greater than or equal 13461 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13462 */ 13463 bool operator>=(const iter_impl& other) const 13464 { 13465 return !operator<(other); 13466 } 13467 13468 /*! 13469 @brief add to iterator 13470 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13471 */ 13472 iter_impl& operator+=(difference_type i) 13473 { 13474 JSON_ASSERT(m_object != nullptr); 13475 13476 switch (m_object->m_data.m_type) 13477 { 13478 case value_t::object: 13479 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); 13480 13481 case value_t::array: 13482 { 13483 std::advance(m_it.array_iterator, i); 13484 break; 13485 } 13486 13487 case value_t::null: 13488 case value_t::string: 13489 case value_t::boolean: 13490 case value_t::number_integer: 13491 case value_t::number_unsigned: 13492 case value_t::number_float: 13493 case value_t::binary: 13494 case value_t::discarded: 13495 default: 13496 { 13497 m_it.primitive_iterator += i; 13498 break; 13499 } 13500 } 13501 13502 return *this; 13503 } 13504 13505 /*! 13506 @brief subtract from iterator 13507 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13508 */ 13509 iter_impl& operator-=(difference_type i) 13510 { 13511 return operator+=(-i); 13512 } 13513 13514 /*! 13515 @brief add to iterator 13516 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13517 */ 13518 iter_impl operator+(difference_type i) const 13519 { 13520 auto result = *this; 13521 result += i; 13522 return result; 13523 } 13524 13525 /*! 13526 @brief addition of distance and iterator 13527 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13528 */ 13529 friend iter_impl operator+(difference_type i, const iter_impl& it) 13530 { 13531 auto result = it; 13532 result += i; 13533 return result; 13534 } 13535 13536 /*! 13537 @brief subtract from iterator 13538 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13539 */ 13540 iter_impl operator-(difference_type i) const 13541 { 13542 auto result = *this; 13543 result -= i; 13544 return result; 13545 } 13546 13547 /*! 13548 @brief return difference 13549 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13550 */ 13551 difference_type operator-(const iter_impl& other) const 13552 { 13553 JSON_ASSERT(m_object != nullptr); 13554 13555 switch (m_object->m_data.m_type) 13556 { 13557 case value_t::object: 13558 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); 13559 13560 case value_t::array: 13561 return m_it.array_iterator - other.m_it.array_iterator; 13562 13563 case value_t::null: 13564 case value_t::string: 13565 case value_t::boolean: 13566 case value_t::number_integer: 13567 case value_t::number_unsigned: 13568 case value_t::number_float: 13569 case value_t::binary: 13570 case value_t::discarded: 13571 default: 13572 return m_it.primitive_iterator - other.m_it.primitive_iterator; 13573 } 13574 } 13575 13576 /*! 13577 @brief access to successor 13578 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13579 */ 13580 reference operator[](difference_type n) const 13581 { 13582 JSON_ASSERT(m_object != nullptr); 13583 13584 switch (m_object->m_data.m_type) 13585 { 13586 case value_t::object: 13587 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); 13588 13589 case value_t::array: 13590 return *std::next(m_it.array_iterator, n); 13591 13592 case value_t::null: 13593 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13594 13595 case value_t::string: 13596 case value_t::boolean: 13597 case value_t::number_integer: 13598 case value_t::number_unsigned: 13599 case value_t::number_float: 13600 case value_t::binary: 13601 case value_t::discarded: 13602 default: 13603 { 13604 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) 13605 { 13606 return *m_object; 13607 } 13608 13609 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); 13610 } 13611 } 13612 } 13613 13614 /*! 13615 @brief return the key of an object iterator 13616 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13617 */ 13618 const typename object_t::key_type& key() const 13619 { 13620 JSON_ASSERT(m_object != nullptr); 13621 13622 if (JSON_HEDLEY_LIKELY(m_object->is_object())) 13623 { 13624 return m_it.object_iterator->first; 13625 } 13626 13627 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object)); 13628 } 13629 13630 /*! 13631 @brief return the value of an iterator 13632 @pre The iterator is initialized; i.e. `m_object != nullptr`. 13633 */ 13634 reference value() const 13635 { 13636 return operator*(); 13637 } 13638 13639 JSON_PRIVATE_UNLESS_TESTED: 13640 /// associated JSON instance 13641 pointer m_object = nullptr; 13642 /// the actual iterator of the associated instance 13643 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {}; 13644 }; 13645 13646 } // namespace detail 13647 NLOHMANN_JSON_NAMESPACE_END 13648 13649 // #include <nlohmann/detail/iterators/iteration_proxy.hpp> 13650 13651 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp> 13652 // __ _____ _____ _____ 13653 // __| | __| | | | JSON for Modern C++ 13654 // | | |__ | | | | | | version 3.11.3 13655 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 13656 // 13657 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 13658 // SPDX-License-Identifier: MIT 13659 13660 13661 13662 #include <cstddef> // ptrdiff_t 13663 #include <iterator> // reverse_iterator 13664 #include <utility> // declval 13665 13666 // #include <nlohmann/detail/abi_macros.hpp> 13667 13668 13669 NLOHMANN_JSON_NAMESPACE_BEGIN 13670 namespace detail 13671 { 13672 13673 ////////////////////// 13674 // reverse_iterator // 13675 ////////////////////// 13676 13677 /*! 13678 @brief a template for a reverse iterator class 13679 13680 @tparam Base the base iterator type to reverse. Valid types are @ref 13681 iterator (to create @ref reverse_iterator) and @ref const_iterator (to 13682 create @ref const_reverse_iterator). 13683 13684 @requirement The class satisfies the following concept requirements: 13685 - 13686 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): 13687 The iterator that can be moved can be moved in both directions (i.e. 13688 incremented and decremented). 13689 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): 13690 It is possible to write to the pointed-to element (only if @a Base is 13691 @ref iterator). 13692 13693 @since version 1.0.0 13694 */ 13695 template<typename Base> 13696 class json_reverse_iterator : public std::reverse_iterator<Base> 13697 { 13698 public: 13699 using difference_type = std::ptrdiff_t; 13700 /// shortcut to the reverse iterator adapter 13701 using base_iterator = std::reverse_iterator<Base>; 13702 /// the reference type for the pointed-to element 13703 using reference = typename Base::reference; 13704 13705 /// create reverse iterator from iterator 13706 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept 13707 : base_iterator(it) {} 13708 13709 /// create reverse iterator from base class 13710 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} 13711 13712 /// post-increment (it++) 13713 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp) 13714 { 13715 return static_cast<json_reverse_iterator>(base_iterator::operator++(1)); 13716 } 13717 13718 /// pre-increment (++it) 13719 json_reverse_iterator& operator++() 13720 { 13721 return static_cast<json_reverse_iterator&>(base_iterator::operator++()); 13722 } 13723 13724 /// post-decrement (it--) 13725 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp) 13726 { 13727 return static_cast<json_reverse_iterator>(base_iterator::operator--(1)); 13728 } 13729 13730 /// pre-decrement (--it) 13731 json_reverse_iterator& operator--() 13732 { 13733 return static_cast<json_reverse_iterator&>(base_iterator::operator--()); 13734 } 13735 13736 /// add to iterator 13737 json_reverse_iterator& operator+=(difference_type i) 13738 { 13739 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i)); 13740 } 13741 13742 /// add to iterator 13743 json_reverse_iterator operator+(difference_type i) const 13744 { 13745 return static_cast<json_reverse_iterator>(base_iterator::operator+(i)); 13746 } 13747 13748 /// subtract from iterator 13749 json_reverse_iterator operator-(difference_type i) const 13750 { 13751 return static_cast<json_reverse_iterator>(base_iterator::operator-(i)); 13752 } 13753 13754 /// return difference 13755 difference_type operator-(const json_reverse_iterator& other) const 13756 { 13757 return base_iterator(*this) - base_iterator(other); 13758 } 13759 13760 /// access to successor 13761 reference operator[](difference_type n) const 13762 { 13763 return *(this->operator+(n)); 13764 } 13765 13766 /// return the key of an object iterator 13767 auto key() const -> decltype(std::declval<Base>().key()) 13768 { 13769 auto it = --this->base(); 13770 return it.key(); 13771 } 13772 13773 /// return the value of an iterator 13774 reference value() const 13775 { 13776 auto it = --this->base(); 13777 return it.operator * (); 13778 } 13779 }; 13780 13781 } // namespace detail 13782 NLOHMANN_JSON_NAMESPACE_END 13783 13784 // #include <nlohmann/detail/iterators/primitive_iterator.hpp> 13785 13786 // #include <nlohmann/detail/json_custom_base_class.hpp> 13787 // __ _____ _____ _____ 13788 // __| | __| | | | JSON for Modern C++ 13789 // | | |__ | | | | | | version 3.11.3 13790 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 13791 // 13792 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 13793 // SPDX-License-Identifier: MIT 13794 13795 13796 13797 #include <type_traits> // conditional, is_same 13798 13799 // #include <nlohmann/detail/abi_macros.hpp> 13800 13801 13802 NLOHMANN_JSON_NAMESPACE_BEGIN 13803 namespace detail 13804 { 13805 13806 /*! 13807 @brief Default base class of the @ref basic_json class. 13808 13809 So that the correct implementations of the copy / move ctors / assign operators 13810 of @ref basic_json do not require complex case distinctions 13811 (no base class / custom base class used as customization point), 13812 @ref basic_json always has a base class. 13813 By default, this class is used because it is empty and thus has no effect 13814 on the behavior of @ref basic_json. 13815 */ 13816 struct json_default_base {}; 13817 13818 template<class T> 13819 using json_base_class = typename std::conditional < 13820 std::is_same<T, void>::value, 13821 json_default_base, 13822 T 13823 >::type; 13824 13825 } // namespace detail 13826 NLOHMANN_JSON_NAMESPACE_END 13827 13828 // #include <nlohmann/detail/json_pointer.hpp> 13829 // __ _____ _____ _____ 13830 // __| | __| | | | JSON for Modern C++ 13831 // | | |__ | | | | | | version 3.11.3 13832 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 13833 // 13834 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 13835 // SPDX-License-Identifier: MIT 13836 13837 13838 13839 #include <algorithm> // all_of 13840 #include <cctype> // isdigit 13841 #include <cerrno> // errno, ERANGE 13842 #include <cstdlib> // strtoull 13843 #ifndef JSON_NO_IO 13844 #include <iosfwd> // ostream 13845 #endif // JSON_NO_IO 13846 #include <limits> // max 13847 #include <numeric> // accumulate 13848 #include <string> // string 13849 #include <utility> // move 13850 #include <vector> // vector 13851 13852 // #include <nlohmann/detail/exceptions.hpp> 13853 13854 // #include <nlohmann/detail/macro_scope.hpp> 13855 13856 // #include <nlohmann/detail/string_concat.hpp> 13857 13858 // #include <nlohmann/detail/string_escape.hpp> 13859 13860 // #include <nlohmann/detail/value_t.hpp> 13861 13862 13863 NLOHMANN_JSON_NAMESPACE_BEGIN 13864 13865 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document 13866 /// @sa https://json.nlohmann.me/api/json_pointer/ 13867 template<typename RefStringType> 13868 class json_pointer 13869 { 13870 // allow basic_json to access private members 13871 NLOHMANN_BASIC_JSON_TPL_DECLARATION 13872 friend class basic_json; 13873 13874 template<typename> 13875 friend class json_pointer; 13876 13877 template<typename T> 13878 struct string_t_helper 13879 { 13880 using type = T; 13881 }; 13882 13883 NLOHMANN_BASIC_JSON_TPL_DECLARATION 13884 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL> 13885 { 13886 using type = StringType; 13887 }; 13888 13889 public: 13890 // for backwards compatibility accept BasicJsonType 13891 using string_t = typename string_t_helper<RefStringType>::type; 13892 13893 /// @brief create JSON pointer 13894 /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ 13895 explicit json_pointer(const string_t& s = "") 13896 : reference_tokens(split(s)) 13897 {} 13898 13899 /// @brief return a string representation of the JSON pointer 13900 /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ 13901 string_t to_string() const 13902 { 13903 return std::accumulate(reference_tokens.begin(), reference_tokens.end(), 13904 string_t{}, 13905 [](const string_t& a, const string_t& b) 13906 { 13907 return detail::concat(a, '/', detail::escape(b)); 13908 }); 13909 } 13910 13911 /// @brief return a string representation of the JSON pointer 13912 /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ 13913 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) 13914 operator string_t() const 13915 { 13916 return to_string(); 13917 } 13918 13919 #ifndef JSON_NO_IO 13920 /// @brief write string representation of the JSON pointer to stream 13921 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 13922 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) 13923 { 13924 o << ptr.to_string(); 13925 return o; 13926 } 13927 #endif 13928 13929 /// @brief append another JSON pointer at the end of this JSON pointer 13930 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 13931 json_pointer& operator/=(const json_pointer& ptr) 13932 { 13933 reference_tokens.insert(reference_tokens.end(), 13934 ptr.reference_tokens.begin(), 13935 ptr.reference_tokens.end()); 13936 return *this; 13937 } 13938 13939 /// @brief append an unescaped reference token at the end of this JSON pointer 13940 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 13941 json_pointer& operator/=(string_t token) 13942 { 13943 push_back(std::move(token)); 13944 return *this; 13945 } 13946 13947 /// @brief append an array index at the end of this JSON pointer 13948 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ 13949 json_pointer& operator/=(std::size_t array_idx) 13950 { 13951 return *this /= std::to_string(array_idx); 13952 } 13953 13954 /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer 13955 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 13956 friend json_pointer operator/(const json_pointer& lhs, 13957 const json_pointer& rhs) 13958 { 13959 return json_pointer(lhs) /= rhs; 13960 } 13961 13962 /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer 13963 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 13964 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param) 13965 { 13966 return json_pointer(lhs) /= std::move(token); 13967 } 13968 13969 /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer 13970 /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ 13971 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx) 13972 { 13973 return json_pointer(lhs) /= array_idx; 13974 } 13975 13976 /// @brief returns the parent of this JSON pointer 13977 /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/ 13978 json_pointer parent_pointer() const 13979 { 13980 if (empty()) 13981 { 13982 return *this; 13983 } 13984 13985 json_pointer res = *this; 13986 res.pop_back(); 13987 return res; 13988 } 13989 13990 /// @brief remove last reference token 13991 /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/ 13992 void pop_back() 13993 { 13994 if (JSON_HEDLEY_UNLIKELY(empty())) 13995 { 13996 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); 13997 } 13998 13999 reference_tokens.pop_back(); 14000 } 14001 14002 /// @brief return last reference token 14003 /// @sa https://json.nlohmann.me/api/json_pointer/back/ 14004 const string_t& back() const 14005 { 14006 if (JSON_HEDLEY_UNLIKELY(empty())) 14007 { 14008 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); 14009 } 14010 14011 return reference_tokens.back(); 14012 } 14013 14014 /// @brief append an unescaped token at the end of the reference pointer 14015 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ 14016 void push_back(const string_t& token) 14017 { 14018 reference_tokens.push_back(token); 14019 } 14020 14021 /// @brief append an unescaped token at the end of the reference pointer 14022 /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ 14023 void push_back(string_t&& token) 14024 { 14025 reference_tokens.push_back(std::move(token)); 14026 } 14027 14028 /// @brief return whether pointer points to the root document 14029 /// @sa https://json.nlohmann.me/api/json_pointer/empty/ 14030 bool empty() const noexcept 14031 { 14032 return reference_tokens.empty(); 14033 } 14034 14035 private: 14036 /*! 14037 @param[in] s reference token to be converted into an array index 14038 14039 @return integer representation of @a s 14040 14041 @throw parse_error.106 if an array index begins with '0' 14042 @throw parse_error.109 if an array index begins not with a digit 14043 @throw out_of_range.404 if string @a s could not be converted to an integer 14044 @throw out_of_range.410 if an array index exceeds size_type 14045 */ 14046 template<typename BasicJsonType> 14047 static typename BasicJsonType::size_type array_index(const string_t& s) 14048 { 14049 using size_type = typename BasicJsonType::size_type; 14050 14051 // error condition (cf. RFC 6901, Sect. 4) 14052 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) 14053 { 14054 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); 14055 } 14056 14057 // error condition (cf. RFC 6901, Sect. 4) 14058 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) 14059 { 14060 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr)); 14061 } 14062 14063 const char* p = s.c_str(); 14064 char* p_end = nullptr; 14065 errno = 0; // strtoull doesn't reset errno 14066 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) 14067 if (p == p_end // invalid input or empty string 14068 || errno == ERANGE // out of range 14069 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read 14070 { 14071 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr)); 14072 } 14073 14074 // only triggered on special platforms (like 32bit), see also 14075 // https://github.com/nlohmann/json/pull/2203 14076 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int) 14077 { 14078 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE 14079 } 14080 14081 return static_cast<size_type>(res); 14082 } 14083 14084 JSON_PRIVATE_UNLESS_TESTED: 14085 json_pointer top() const 14086 { 14087 if (JSON_HEDLEY_UNLIKELY(empty())) 14088 { 14089 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); 14090 } 14091 14092 json_pointer result = *this; 14093 result.reference_tokens = {reference_tokens[0]}; 14094 return result; 14095 } 14096 14097 private: 14098 /*! 14099 @brief create and return a reference to the pointed to value 14100 14101 @complexity Linear in the number of reference tokens. 14102 14103 @throw parse_error.109 if array index is not a number 14104 @throw type_error.313 if value cannot be unflattened 14105 */ 14106 template<typename BasicJsonType> 14107 BasicJsonType& get_and_create(BasicJsonType& j) const 14108 { 14109 auto* result = &j; 14110 14111 // in case no reference tokens exist, return a reference to the JSON value 14112 // j which will be overwritten by a primitive value 14113 for (const auto& reference_token : reference_tokens) 14114 { 14115 switch (result->type()) 14116 { 14117 case detail::value_t::null: 14118 { 14119 if (reference_token == "0") 14120 { 14121 // start a new array if reference token is 0 14122 result = &result->operator[](0); 14123 } 14124 else 14125 { 14126 // start a new object otherwise 14127 result = &result->operator[](reference_token); 14128 } 14129 break; 14130 } 14131 14132 case detail::value_t::object: 14133 { 14134 // create an entry in the object 14135 result = &result->operator[](reference_token); 14136 break; 14137 } 14138 14139 case detail::value_t::array: 14140 { 14141 // create an entry in the array 14142 result = &result->operator[](array_index<BasicJsonType>(reference_token)); 14143 break; 14144 } 14145 14146 /* 14147 The following code is only reached if there exists a reference 14148 token _and_ the current value is primitive. In this case, we have 14149 an error situation, because primitive values may only occur as 14150 single value; that is, with an empty list of reference tokens. 14151 */ 14152 case detail::value_t::string: 14153 case detail::value_t::boolean: 14154 case detail::value_t::number_integer: 14155 case detail::value_t::number_unsigned: 14156 case detail::value_t::number_float: 14157 case detail::value_t::binary: 14158 case detail::value_t::discarded: 14159 default: 14160 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j)); 14161 } 14162 } 14163 14164 return *result; 14165 } 14166 14167 /*! 14168 @brief return a reference to the pointed to value 14169 14170 @note This version does not throw if a value is not present, but tries to 14171 create nested values instead. For instance, calling this function 14172 with pointer `"/this/that"` on a null value is equivalent to calling 14173 `operator[]("this").operator[]("that")` on that value, effectively 14174 changing the null value to an object. 14175 14176 @param[in] ptr a JSON value 14177 14178 @return reference to the JSON value pointed to by the JSON pointer 14179 14180 @complexity Linear in the length of the JSON pointer. 14181 14182 @throw parse_error.106 if an array index begins with '0' 14183 @throw parse_error.109 if an array index was not a number 14184 @throw out_of_range.404 if the JSON pointer can not be resolved 14185 */ 14186 template<typename BasicJsonType> 14187 BasicJsonType& get_unchecked(BasicJsonType* ptr) const 14188 { 14189 for (const auto& reference_token : reference_tokens) 14190 { 14191 // convert null values to arrays or objects before continuing 14192 if (ptr->is_null()) 14193 { 14194 // check if reference token is a number 14195 const bool nums = 14196 std::all_of(reference_token.begin(), reference_token.end(), 14197 [](const unsigned char x) 14198 { 14199 return std::isdigit(x); 14200 }); 14201 14202 // change value to array for numbers or "-" or to object otherwise 14203 *ptr = (nums || reference_token == "-") 14204 ? detail::value_t::array 14205 : detail::value_t::object; 14206 } 14207 14208 switch (ptr->type()) 14209 { 14210 case detail::value_t::object: 14211 { 14212 // use unchecked object access 14213 ptr = &ptr->operator[](reference_token); 14214 break; 14215 } 14216 14217 case detail::value_t::array: 14218 { 14219 if (reference_token == "-") 14220 { 14221 // explicitly treat "-" as index beyond the end 14222 ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); 14223 } 14224 else 14225 { 14226 // convert array index to number; unchecked access 14227 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); 14228 } 14229 break; 14230 } 14231 14232 case detail::value_t::null: 14233 case detail::value_t::string: 14234 case detail::value_t::boolean: 14235 case detail::value_t::number_integer: 14236 case detail::value_t::number_unsigned: 14237 case detail::value_t::number_float: 14238 case detail::value_t::binary: 14239 case detail::value_t::discarded: 14240 default: 14241 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14242 } 14243 } 14244 14245 return *ptr; 14246 } 14247 14248 /*! 14249 @throw parse_error.106 if an array index begins with '0' 14250 @throw parse_error.109 if an array index was not a number 14251 @throw out_of_range.402 if the array index '-' is used 14252 @throw out_of_range.404 if the JSON pointer can not be resolved 14253 */ 14254 template<typename BasicJsonType> 14255 BasicJsonType& get_checked(BasicJsonType* ptr) const 14256 { 14257 for (const auto& reference_token : reference_tokens) 14258 { 14259 switch (ptr->type()) 14260 { 14261 case detail::value_t::object: 14262 { 14263 // note: at performs range check 14264 ptr = &ptr->at(reference_token); 14265 break; 14266 } 14267 14268 case detail::value_t::array: 14269 { 14270 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14271 { 14272 // "-" always fails the range check 14273 JSON_THROW(detail::out_of_range::create(402, detail::concat( 14274 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), 14275 ") is out of range"), ptr)); 14276 } 14277 14278 // note: at performs range check 14279 ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); 14280 break; 14281 } 14282 14283 case detail::value_t::null: 14284 case detail::value_t::string: 14285 case detail::value_t::boolean: 14286 case detail::value_t::number_integer: 14287 case detail::value_t::number_unsigned: 14288 case detail::value_t::number_float: 14289 case detail::value_t::binary: 14290 case detail::value_t::discarded: 14291 default: 14292 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14293 } 14294 } 14295 14296 return *ptr; 14297 } 14298 14299 /*! 14300 @brief return a const reference to the pointed to value 14301 14302 @param[in] ptr a JSON value 14303 14304 @return const reference to the JSON value pointed to by the JSON 14305 pointer 14306 14307 @throw parse_error.106 if an array index begins with '0' 14308 @throw parse_error.109 if an array index was not a number 14309 @throw out_of_range.402 if the array index '-' is used 14310 @throw out_of_range.404 if the JSON pointer can not be resolved 14311 */ 14312 template<typename BasicJsonType> 14313 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const 14314 { 14315 for (const auto& reference_token : reference_tokens) 14316 { 14317 switch (ptr->type()) 14318 { 14319 case detail::value_t::object: 14320 { 14321 // use unchecked object access 14322 ptr = &ptr->operator[](reference_token); 14323 break; 14324 } 14325 14326 case detail::value_t::array: 14327 { 14328 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14329 { 14330 // "-" cannot be used for const access 14331 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); 14332 } 14333 14334 // use unchecked array access 14335 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token)); 14336 break; 14337 } 14338 14339 case detail::value_t::null: 14340 case detail::value_t::string: 14341 case detail::value_t::boolean: 14342 case detail::value_t::number_integer: 14343 case detail::value_t::number_unsigned: 14344 case detail::value_t::number_float: 14345 case detail::value_t::binary: 14346 case detail::value_t::discarded: 14347 default: 14348 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14349 } 14350 } 14351 14352 return *ptr; 14353 } 14354 14355 /*! 14356 @throw parse_error.106 if an array index begins with '0' 14357 @throw parse_error.109 if an array index was not a number 14358 @throw out_of_range.402 if the array index '-' is used 14359 @throw out_of_range.404 if the JSON pointer can not be resolved 14360 */ 14361 template<typename BasicJsonType> 14362 const BasicJsonType& get_checked(const BasicJsonType* ptr) const 14363 { 14364 for (const auto& reference_token : reference_tokens) 14365 { 14366 switch (ptr->type()) 14367 { 14368 case detail::value_t::object: 14369 { 14370 // note: at performs range check 14371 ptr = &ptr->at(reference_token); 14372 break; 14373 } 14374 14375 case detail::value_t::array: 14376 { 14377 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14378 { 14379 // "-" always fails the range check 14380 JSON_THROW(detail::out_of_range::create(402, detail::concat( 14381 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), 14382 ") is out of range"), ptr)); 14383 } 14384 14385 // note: at performs range check 14386 ptr = &ptr->at(array_index<BasicJsonType>(reference_token)); 14387 break; 14388 } 14389 14390 case detail::value_t::null: 14391 case detail::value_t::string: 14392 case detail::value_t::boolean: 14393 case detail::value_t::number_integer: 14394 case detail::value_t::number_unsigned: 14395 case detail::value_t::number_float: 14396 case detail::value_t::binary: 14397 case detail::value_t::discarded: 14398 default: 14399 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); 14400 } 14401 } 14402 14403 return *ptr; 14404 } 14405 14406 /*! 14407 @throw parse_error.106 if an array index begins with '0' 14408 @throw parse_error.109 if an array index was not a number 14409 */ 14410 template<typename BasicJsonType> 14411 bool contains(const BasicJsonType* ptr) const 14412 { 14413 for (const auto& reference_token : reference_tokens) 14414 { 14415 switch (ptr->type()) 14416 { 14417 case detail::value_t::object: 14418 { 14419 if (!ptr->contains(reference_token)) 14420 { 14421 // we did not find the key in the object 14422 return false; 14423 } 14424 14425 ptr = &ptr->operator[](reference_token); 14426 break; 14427 } 14428 14429 case detail::value_t::array: 14430 { 14431 if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) 14432 { 14433 // "-" always fails the range check 14434 return false; 14435 } 14436 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) 14437 { 14438 // invalid char 14439 return false; 14440 } 14441 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) 14442 { 14443 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) 14444 { 14445 // first char should be between '1' and '9' 14446 return false; 14447 } 14448 for (std::size_t i = 1; i < reference_token.size(); i++) 14449 { 14450 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) 14451 { 14452 // other char should be between '0' and '9' 14453 return false; 14454 } 14455 } 14456 } 14457 14458 const auto idx = array_index<BasicJsonType>(reference_token); 14459 if (idx >= ptr->size()) 14460 { 14461 // index out of range 14462 return false; 14463 } 14464 14465 ptr = &ptr->operator[](idx); 14466 break; 14467 } 14468 14469 case detail::value_t::null: 14470 case detail::value_t::string: 14471 case detail::value_t::boolean: 14472 case detail::value_t::number_integer: 14473 case detail::value_t::number_unsigned: 14474 case detail::value_t::number_float: 14475 case detail::value_t::binary: 14476 case detail::value_t::discarded: 14477 default: 14478 { 14479 // we do not expect primitive values if there is still a 14480 // reference token to process 14481 return false; 14482 } 14483 } 14484 } 14485 14486 // no reference token left means we found a primitive value 14487 return true; 14488 } 14489 14490 /*! 14491 @brief split the string input to reference tokens 14492 14493 @note This function is only called by the json_pointer constructor. 14494 All exceptions below are documented there. 14495 14496 @throw parse_error.107 if the pointer is not empty or begins with '/' 14497 @throw parse_error.108 if character '~' is not followed by '0' or '1' 14498 */ 14499 static std::vector<string_t> split(const string_t& reference_string) 14500 { 14501 std::vector<string_t> result; 14502 14503 // special case: empty reference string -> no reference tokens 14504 if (reference_string.empty()) 14505 { 14506 return result; 14507 } 14508 14509 // check if nonempty reference string begins with slash 14510 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) 14511 { 14512 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr)); 14513 } 14514 14515 // extract the reference tokens: 14516 // - slash: position of the last read slash (or end of string) 14517 // - start: position after the previous slash 14518 for ( 14519 // search for the first slash after the first character 14520 std::size_t slash = reference_string.find_first_of('/', 1), 14521 // set the beginning of the first reference token 14522 start = 1; 14523 // we can stop if start == 0 (if slash == string_t::npos) 14524 start != 0; 14525 // set the beginning of the next reference token 14526 // (will eventually be 0 if slash == string_t::npos) 14527 start = (slash == string_t::npos) ? 0 : slash + 1, 14528 // find next slash 14529 slash = reference_string.find_first_of('/', start)) 14530 { 14531 // use the text between the beginning of the reference token 14532 // (start) and the last slash (slash). 14533 auto reference_token = reference_string.substr(start, slash - start); 14534 14535 // check reference tokens are properly escaped 14536 for (std::size_t pos = reference_token.find_first_of('~'); 14537 pos != string_t::npos; 14538 pos = reference_token.find_first_of('~', pos + 1)) 14539 { 14540 JSON_ASSERT(reference_token[pos] == '~'); 14541 14542 // ~ must be followed by 0 or 1 14543 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || 14544 (reference_token[pos + 1] != '0' && 14545 reference_token[pos + 1] != '1'))) 14546 { 14547 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); 14548 } 14549 } 14550 14551 // finally, store the reference token 14552 detail::unescape(reference_token); 14553 result.push_back(reference_token); 14554 } 14555 14556 return result; 14557 } 14558 14559 private: 14560 /*! 14561 @param[in] reference_string the reference string to the current value 14562 @param[in] value the value to consider 14563 @param[in,out] result the result object to insert values to 14564 14565 @note Empty objects or arrays are flattened to `null`. 14566 */ 14567 template<typename BasicJsonType> 14568 static void flatten(const string_t& reference_string, 14569 const BasicJsonType& value, 14570 BasicJsonType& result) 14571 { 14572 switch (value.type()) 14573 { 14574 case detail::value_t::array: 14575 { 14576 if (value.m_data.m_value.array->empty()) 14577 { 14578 // flatten empty array as null 14579 result[reference_string] = nullptr; 14580 } 14581 else 14582 { 14583 // iterate array and use index as reference string 14584 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) 14585 { 14586 flatten(detail::concat(reference_string, '/', std::to_string(i)), 14587 value.m_data.m_value.array->operator[](i), result); 14588 } 14589 } 14590 break; 14591 } 14592 14593 case detail::value_t::object: 14594 { 14595 if (value.m_data.m_value.object->empty()) 14596 { 14597 // flatten empty object as null 14598 result[reference_string] = nullptr; 14599 } 14600 else 14601 { 14602 // iterate object and use keys as reference string 14603 for (const auto& element : *value.m_data.m_value.object) 14604 { 14605 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); 14606 } 14607 } 14608 break; 14609 } 14610 14611 case detail::value_t::null: 14612 case detail::value_t::string: 14613 case detail::value_t::boolean: 14614 case detail::value_t::number_integer: 14615 case detail::value_t::number_unsigned: 14616 case detail::value_t::number_float: 14617 case detail::value_t::binary: 14618 case detail::value_t::discarded: 14619 default: 14620 { 14621 // add primitive value with its reference string 14622 result[reference_string] = value; 14623 break; 14624 } 14625 } 14626 } 14627 14628 /*! 14629 @param[in] value flattened JSON 14630 14631 @return unflattened JSON 14632 14633 @throw parse_error.109 if array index is not a number 14634 @throw type_error.314 if value is not an object 14635 @throw type_error.315 if object values are not primitive 14636 @throw type_error.313 if value cannot be unflattened 14637 */ 14638 template<typename BasicJsonType> 14639 static BasicJsonType 14640 unflatten(const BasicJsonType& value) 14641 { 14642 if (JSON_HEDLEY_UNLIKELY(!value.is_object())) 14643 { 14644 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value)); 14645 } 14646 14647 BasicJsonType result; 14648 14649 // iterate the JSON object values 14650 for (const auto& element : *value.m_data.m_value.object) 14651 { 14652 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) 14653 { 14654 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second)); 14655 } 14656 14657 // assign value to reference pointed to by JSON pointer; Note that if 14658 // the JSON pointer is "" (i.e., points to the whole value), function 14659 // get_and_create returns a reference to result itself. An assignment 14660 // will then create a primitive value. 14661 json_pointer(element.first).get_and_create(result) = element.second; 14662 } 14663 14664 return result; 14665 } 14666 14667 // can't use conversion operator because of ambiguity 14668 json_pointer<string_t> convert() const& 14669 { 14670 json_pointer<string_t> result; 14671 result.reference_tokens = reference_tokens; 14672 return result; 14673 } 14674 14675 json_pointer<string_t> convert()&& 14676 { 14677 json_pointer<string_t> result; 14678 result.reference_tokens = std::move(reference_tokens); 14679 return result; 14680 } 14681 14682 public: 14683 #if JSON_HAS_THREE_WAY_COMPARISON 14684 /// @brief compares two JSON pointers for equality 14685 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14686 template<typename RefStringTypeRhs> 14687 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept 14688 { 14689 return reference_tokens == rhs.reference_tokens; 14690 } 14691 14692 /// @brief compares JSON pointer and string for equality 14693 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14694 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) 14695 bool operator==(const string_t& rhs) const 14696 { 14697 return *this == json_pointer(rhs); 14698 } 14699 14700 /// @brief 3-way compares two JSON pointers 14701 template<typename RefStringTypeRhs> 14702 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD* 14703 { 14704 return reference_tokens <=> rhs.reference_tokens; // *NOPAD* 14705 } 14706 #else 14707 /// @brief compares two JSON pointers for equality 14708 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14709 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14710 // NOLINTNEXTLINE(readability-redundant-declaration) 14711 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14712 const json_pointer<RefStringTypeRhs>& rhs) noexcept; 14713 14714 /// @brief compares JSON pointer and string for equality 14715 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14716 template<typename RefStringTypeLhs, typename StringType> 14717 // NOLINTNEXTLINE(readability-redundant-declaration) 14718 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14719 const StringType& rhs); 14720 14721 /// @brief compares string and JSON pointer for equality 14722 /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ 14723 template<typename RefStringTypeRhs, typename StringType> 14724 // NOLINTNEXTLINE(readability-redundant-declaration) 14725 friend bool operator==(const StringType& lhs, 14726 const json_pointer<RefStringTypeRhs>& rhs); 14727 14728 /// @brief compares two JSON pointers for inequality 14729 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 14730 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14731 // NOLINTNEXTLINE(readability-redundant-declaration) 14732 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14733 const json_pointer<RefStringTypeRhs>& rhs) noexcept; 14734 14735 /// @brief compares JSON pointer and string for inequality 14736 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 14737 template<typename RefStringTypeLhs, typename StringType> 14738 // NOLINTNEXTLINE(readability-redundant-declaration) 14739 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14740 const StringType& rhs); 14741 14742 /// @brief compares string and JSON pointer for inequality 14743 /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ 14744 template<typename RefStringTypeRhs, typename StringType> 14745 // NOLINTNEXTLINE(readability-redundant-declaration) 14746 friend bool operator!=(const StringType& lhs, 14747 const json_pointer<RefStringTypeRhs>& rhs); 14748 14749 /// @brief compares two JSON pointer for less-than 14750 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14751 // NOLINTNEXTLINE(readability-redundant-declaration) 14752 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs, 14753 const json_pointer<RefStringTypeRhs>& rhs) noexcept; 14754 #endif 14755 14756 private: 14757 /// the reference tokens 14758 std::vector<string_t> reference_tokens; 14759 }; 14760 14761 #if !JSON_HAS_THREE_WAY_COMPARISON 14762 // functions cannot be defined inside class due to ODR violations 14763 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14764 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14765 const json_pointer<RefStringTypeRhs>& rhs) noexcept 14766 { 14767 return lhs.reference_tokens == rhs.reference_tokens; 14768 } 14769 14770 template<typename RefStringTypeLhs, 14771 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> 14772 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) 14773 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, 14774 const StringType& rhs) 14775 { 14776 return lhs == json_pointer<RefStringTypeLhs>(rhs); 14777 } 14778 14779 template<typename RefStringTypeRhs, 14780 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> 14781 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) 14782 inline bool operator==(const StringType& lhs, 14783 const json_pointer<RefStringTypeRhs>& rhs) 14784 { 14785 return json_pointer<RefStringTypeRhs>(lhs) == rhs; 14786 } 14787 14788 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14789 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14790 const json_pointer<RefStringTypeRhs>& rhs) noexcept 14791 { 14792 return !(lhs == rhs); 14793 } 14794 14795 template<typename RefStringTypeLhs, 14796 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t> 14797 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) 14798 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, 14799 const StringType& rhs) 14800 { 14801 return !(lhs == rhs); 14802 } 14803 14804 template<typename RefStringTypeRhs, 14805 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t> 14806 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) 14807 inline bool operator!=(const StringType& lhs, 14808 const json_pointer<RefStringTypeRhs>& rhs) 14809 { 14810 return !(lhs == rhs); 14811 } 14812 14813 template<typename RefStringTypeLhs, typename RefStringTypeRhs> 14814 inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs, 14815 const json_pointer<RefStringTypeRhs>& rhs) noexcept 14816 { 14817 return lhs.reference_tokens < rhs.reference_tokens; 14818 } 14819 #endif 14820 14821 NLOHMANN_JSON_NAMESPACE_END 14822 14823 // #include <nlohmann/detail/json_ref.hpp> 14824 // __ _____ _____ _____ 14825 // __| | __| | | | JSON for Modern C++ 14826 // | | |__ | | | | | | version 3.11.3 14827 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 14828 // 14829 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 14830 // SPDX-License-Identifier: MIT 14831 14832 14833 14834 #include <initializer_list> 14835 #include <utility> 14836 14837 // #include <nlohmann/detail/abi_macros.hpp> 14838 14839 // #include <nlohmann/detail/meta/type_traits.hpp> 14840 14841 14842 NLOHMANN_JSON_NAMESPACE_BEGIN 14843 namespace detail 14844 { 14845 14846 template<typename BasicJsonType> 14847 class json_ref 14848 { 14849 public: 14850 using value_type = BasicJsonType; 14851 14852 json_ref(value_type&& value) 14853 : owned_value(std::move(value)) 14854 {} 14855 14856 json_ref(const value_type& value) 14857 : value_ref(&value) 14858 {} 14859 14860 json_ref(std::initializer_list<json_ref> init) 14861 : owned_value(init) 14862 {} 14863 14864 template < 14865 class... Args, 14866 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 > 14867 json_ref(Args && ... args) 14868 : owned_value(std::forward<Args>(args)...) 14869 {} 14870 14871 // class should be movable only 14872 json_ref(json_ref&&) noexcept = default; 14873 json_ref(const json_ref&) = delete; 14874 json_ref& operator=(const json_ref&) = delete; 14875 json_ref& operator=(json_ref&&) = delete; 14876 ~json_ref() = default; 14877 14878 value_type moved_or_copied() const 14879 { 14880 if (value_ref == nullptr) 14881 { 14882 return std::move(owned_value); 14883 } 14884 return *value_ref; 14885 } 14886 14887 value_type const& operator*() const 14888 { 14889 return value_ref ? *value_ref : owned_value; 14890 } 14891 14892 value_type const* operator->() const 14893 { 14894 return &** this; 14895 } 14896 14897 private: 14898 mutable value_type owned_value = nullptr; 14899 value_type const* value_ref = nullptr; 14900 }; 14901 14902 } // namespace detail 14903 NLOHMANN_JSON_NAMESPACE_END 14904 14905 // #include <nlohmann/detail/macro_scope.hpp> 14906 14907 // #include <nlohmann/detail/string_concat.hpp> 14908 14909 // #include <nlohmann/detail/string_escape.hpp> 14910 14911 // #include <nlohmann/detail/meta/cpp_future.hpp> 14912 14913 // #include <nlohmann/detail/meta/type_traits.hpp> 14914 14915 // #include <nlohmann/detail/output/binary_writer.hpp> 14916 // __ _____ _____ _____ 14917 // __| | __| | | | JSON for Modern C++ 14918 // | | |__ | | | | | | version 3.11.3 14919 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 14920 // 14921 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 14922 // SPDX-License-Identifier: MIT 14923 14924 14925 14926 #include <algorithm> // reverse 14927 #include <array> // array 14928 #include <map> // map 14929 #include <cmath> // isnan, isinf 14930 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t 14931 #include <cstring> // memcpy 14932 #include <limits> // numeric_limits 14933 #include <string> // string 14934 #include <utility> // move 14935 #include <vector> // vector 14936 14937 // #include <nlohmann/detail/input/binary_reader.hpp> 14938 14939 // #include <nlohmann/detail/macro_scope.hpp> 14940 14941 // #include <nlohmann/detail/output/output_adapters.hpp> 14942 // __ _____ _____ _____ 14943 // __| | __| | | | JSON for Modern C++ 14944 // | | |__ | | | | | | version 3.11.3 14945 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 14946 // 14947 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 14948 // SPDX-License-Identifier: MIT 14949 14950 14951 14952 #include <algorithm> // copy 14953 #include <cstddef> // size_t 14954 #include <iterator> // back_inserter 14955 #include <memory> // shared_ptr, make_shared 14956 #include <string> // basic_string 14957 #include <vector> // vector 14958 14959 #ifndef JSON_NO_IO 14960 #include <ios> // streamsize 14961 #include <ostream> // basic_ostream 14962 #endif // JSON_NO_IO 14963 14964 // #include <nlohmann/detail/macro_scope.hpp> 14965 14966 14967 NLOHMANN_JSON_NAMESPACE_BEGIN 14968 namespace detail 14969 { 14970 14971 /// abstract output adapter interface 14972 template<typename CharType> struct output_adapter_protocol 14973 { 14974 virtual void write_character(CharType c) = 0; 14975 virtual void write_characters(const CharType* s, std::size_t length) = 0; 14976 virtual ~output_adapter_protocol() = default; 14977 14978 output_adapter_protocol() = default; 14979 output_adapter_protocol(const output_adapter_protocol&) = default; 14980 output_adapter_protocol(output_adapter_protocol&&) noexcept = default; 14981 output_adapter_protocol& operator=(const output_adapter_protocol&) = default; 14982 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default; 14983 }; 14984 14985 /// a type to simplify interfaces 14986 template<typename CharType> 14987 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>; 14988 14989 /// output adapter for byte vectors 14990 template<typename CharType, typename AllocatorType = std::allocator<CharType>> 14991 class output_vector_adapter : public output_adapter_protocol<CharType> 14992 { 14993 public: 14994 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept 14995 : v(vec) 14996 {} 14997 14998 void write_character(CharType c) override 14999 { 15000 v.push_back(c); 15001 } 15002 15003 JSON_HEDLEY_NON_NULL(2) 15004 void write_characters(const CharType* s, std::size_t length) override 15005 { 15006 v.insert(v.end(), s, s + length); 15007 } 15008 15009 private: 15010 std::vector<CharType, AllocatorType>& v; 15011 }; 15012 15013 #ifndef JSON_NO_IO 15014 /// output adapter for output streams 15015 template<typename CharType> 15016 class output_stream_adapter : public output_adapter_protocol<CharType> 15017 { 15018 public: 15019 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept 15020 : stream(s) 15021 {} 15022 15023 void write_character(CharType c) override 15024 { 15025 stream.put(c); 15026 } 15027 15028 JSON_HEDLEY_NON_NULL(2) 15029 void write_characters(const CharType* s, std::size_t length) override 15030 { 15031 stream.write(s, static_cast<std::streamsize>(length)); 15032 } 15033 15034 private: 15035 std::basic_ostream<CharType>& stream; 15036 }; 15037 #endif // JSON_NO_IO 15038 15039 /// output adapter for basic_string 15040 template<typename CharType, typename StringType = std::basic_string<CharType>> 15041 class output_string_adapter : public output_adapter_protocol<CharType> 15042 { 15043 public: 15044 explicit output_string_adapter(StringType& s) noexcept 15045 : str(s) 15046 {} 15047 15048 void write_character(CharType c) override 15049 { 15050 str.push_back(c); 15051 } 15052 15053 JSON_HEDLEY_NON_NULL(2) 15054 void write_characters(const CharType* s, std::size_t length) override 15055 { 15056 str.append(s, length); 15057 } 15058 15059 private: 15060 StringType& str; 15061 }; 15062 15063 template<typename CharType, typename StringType = std::basic_string<CharType>> 15064 class output_adapter 15065 { 15066 public: 15067 template<typename AllocatorType = std::allocator<CharType>> 15068 output_adapter(std::vector<CharType, AllocatorType>& vec) 15069 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {} 15070 15071 #ifndef JSON_NO_IO 15072 output_adapter(std::basic_ostream<CharType>& s) 15073 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {} 15074 #endif // JSON_NO_IO 15075 15076 output_adapter(StringType& s) 15077 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {} 15078 15079 operator output_adapter_t<CharType>() 15080 { 15081 return oa; 15082 } 15083 15084 private: 15085 output_adapter_t<CharType> oa = nullptr; 15086 }; 15087 15088 } // namespace detail 15089 NLOHMANN_JSON_NAMESPACE_END 15090 15091 // #include <nlohmann/detail/string_concat.hpp> 15092 15093 15094 NLOHMANN_JSON_NAMESPACE_BEGIN 15095 namespace detail 15096 { 15097 15098 /////////////////// 15099 // binary writer // 15100 /////////////////// 15101 15102 /*! 15103 @brief serialization to CBOR and MessagePack values 15104 */ 15105 template<typename BasicJsonType, typename CharType> 15106 class binary_writer 15107 { 15108 using string_t = typename BasicJsonType::string_t; 15109 using binary_t = typename BasicJsonType::binary_t; 15110 using number_float_t = typename BasicJsonType::number_float_t; 15111 15112 public: 15113 /*! 15114 @brief create a binary writer 15115 15116 @param[in] adapter output adapter to write to 15117 */ 15118 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter)) 15119 { 15120 JSON_ASSERT(oa); 15121 } 15122 15123 /*! 15124 @param[in] j JSON value to serialize 15125 @pre j.type() == value_t::object 15126 */ 15127 void write_bson(const BasicJsonType& j) 15128 { 15129 switch (j.type()) 15130 { 15131 case value_t::object: 15132 { 15133 write_bson_object(*j.m_data.m_value.object); 15134 break; 15135 } 15136 15137 case value_t::null: 15138 case value_t::array: 15139 case value_t::string: 15140 case value_t::boolean: 15141 case value_t::number_integer: 15142 case value_t::number_unsigned: 15143 case value_t::number_float: 15144 case value_t::binary: 15145 case value_t::discarded: 15146 default: 15147 { 15148 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j)); 15149 } 15150 } 15151 } 15152 15153 /*! 15154 @param[in] j JSON value to serialize 15155 */ 15156 void write_cbor(const BasicJsonType& j) 15157 { 15158 switch (j.type()) 15159 { 15160 case value_t::null: 15161 { 15162 oa->write_character(to_char_type(0xF6)); 15163 break; 15164 } 15165 15166 case value_t::boolean: 15167 { 15168 oa->write_character(j.m_data.m_value.boolean 15169 ? to_char_type(0xF5) 15170 : to_char_type(0xF4)); 15171 break; 15172 } 15173 15174 case value_t::number_integer: 15175 { 15176 if (j.m_data.m_value.number_integer >= 0) 15177 { 15178 // CBOR does not differentiate between positive signed 15179 // integers and unsigned integers. Therefore, we used the 15180 // code from the value_t::number_unsigned case here. 15181 if (j.m_data.m_value.number_integer <= 0x17) 15182 { 15183 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15184 } 15185 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) 15186 { 15187 oa->write_character(to_char_type(0x18)); 15188 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15189 } 15190 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()) 15191 { 15192 oa->write_character(to_char_type(0x19)); 15193 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer)); 15194 } 15195 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()) 15196 { 15197 oa->write_character(to_char_type(0x1A)); 15198 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer)); 15199 } 15200 else 15201 { 15202 oa->write_character(to_char_type(0x1B)); 15203 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer)); 15204 } 15205 } 15206 else 15207 { 15208 // The conversions below encode the sign in the first 15209 // byte, and the value is converted to a positive number. 15210 const auto positive_number = -1 - j.m_data.m_value.number_integer; 15211 if (j.m_data.m_value.number_integer >= -24) 15212 { 15213 write_number(static_cast<std::uint8_t>(0x20 + positive_number)); 15214 } 15215 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)()) 15216 { 15217 oa->write_character(to_char_type(0x38)); 15218 write_number(static_cast<std::uint8_t>(positive_number)); 15219 } 15220 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)()) 15221 { 15222 oa->write_character(to_char_type(0x39)); 15223 write_number(static_cast<std::uint16_t>(positive_number)); 15224 } 15225 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)()) 15226 { 15227 oa->write_character(to_char_type(0x3A)); 15228 write_number(static_cast<std::uint32_t>(positive_number)); 15229 } 15230 else 15231 { 15232 oa->write_character(to_char_type(0x3B)); 15233 write_number(static_cast<std::uint64_t>(positive_number)); 15234 } 15235 } 15236 break; 15237 } 15238 15239 case value_t::number_unsigned: 15240 { 15241 if (j.m_data.m_value.number_unsigned <= 0x17) 15242 { 15243 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned)); 15244 } 15245 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 15246 { 15247 oa->write_character(to_char_type(0x18)); 15248 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned)); 15249 } 15250 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 15251 { 15252 oa->write_character(to_char_type(0x19)); 15253 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned)); 15254 } 15255 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 15256 { 15257 oa->write_character(to_char_type(0x1A)); 15258 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned)); 15259 } 15260 else 15261 { 15262 oa->write_character(to_char_type(0x1B)); 15263 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned)); 15264 } 15265 break; 15266 } 15267 15268 case value_t::number_float: 15269 { 15270 if (std::isnan(j.m_data.m_value.number_float)) 15271 { 15272 // NaN is 0xf97e00 in CBOR 15273 oa->write_character(to_char_type(0xF9)); 15274 oa->write_character(to_char_type(0x7E)); 15275 oa->write_character(to_char_type(0x00)); 15276 } 15277 else if (std::isinf(j.m_data.m_value.number_float)) 15278 { 15279 // Infinity is 0xf97c00, -Infinity is 0xf9fc00 15280 oa->write_character(to_char_type(0xf9)); 15281 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); 15282 oa->write_character(to_char_type(0x00)); 15283 } 15284 else 15285 { 15286 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor); 15287 } 15288 break; 15289 } 15290 15291 case value_t::string: 15292 { 15293 // step 1: write control byte and the string length 15294 const auto N = j.m_data.m_value.string->size(); 15295 if (N <= 0x17) 15296 { 15297 write_number(static_cast<std::uint8_t>(0x60 + N)); 15298 } 15299 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15300 { 15301 oa->write_character(to_char_type(0x78)); 15302 write_number(static_cast<std::uint8_t>(N)); 15303 } 15304 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15305 { 15306 oa->write_character(to_char_type(0x79)); 15307 write_number(static_cast<std::uint16_t>(N)); 15308 } 15309 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15310 { 15311 oa->write_character(to_char_type(0x7A)); 15312 write_number(static_cast<std::uint32_t>(N)); 15313 } 15314 // LCOV_EXCL_START 15315 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15316 { 15317 oa->write_character(to_char_type(0x7B)); 15318 write_number(static_cast<std::uint64_t>(N)); 15319 } 15320 // LCOV_EXCL_STOP 15321 15322 // step 2: write the string 15323 oa->write_characters( 15324 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), 15325 j.m_data.m_value.string->size()); 15326 break; 15327 } 15328 15329 case value_t::array: 15330 { 15331 // step 1: write control byte and the array size 15332 const auto N = j.m_data.m_value.array->size(); 15333 if (N <= 0x17) 15334 { 15335 write_number(static_cast<std::uint8_t>(0x80 + N)); 15336 } 15337 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15338 { 15339 oa->write_character(to_char_type(0x98)); 15340 write_number(static_cast<std::uint8_t>(N)); 15341 } 15342 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15343 { 15344 oa->write_character(to_char_type(0x99)); 15345 write_number(static_cast<std::uint16_t>(N)); 15346 } 15347 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15348 { 15349 oa->write_character(to_char_type(0x9A)); 15350 write_number(static_cast<std::uint32_t>(N)); 15351 } 15352 // LCOV_EXCL_START 15353 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15354 { 15355 oa->write_character(to_char_type(0x9B)); 15356 write_number(static_cast<std::uint64_t>(N)); 15357 } 15358 // LCOV_EXCL_STOP 15359 15360 // step 2: write each element 15361 for (const auto& el : *j.m_data.m_value.array) 15362 { 15363 write_cbor(el); 15364 } 15365 break; 15366 } 15367 15368 case value_t::binary: 15369 { 15370 if (j.m_data.m_value.binary->has_subtype()) 15371 { 15372 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)()) 15373 { 15374 write_number(static_cast<std::uint8_t>(0xd8)); 15375 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype())); 15376 } 15377 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)()) 15378 { 15379 write_number(static_cast<std::uint8_t>(0xd9)); 15380 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype())); 15381 } 15382 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)()) 15383 { 15384 write_number(static_cast<std::uint8_t>(0xda)); 15385 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype())); 15386 } 15387 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)()) 15388 { 15389 write_number(static_cast<std::uint8_t>(0xdb)); 15390 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype())); 15391 } 15392 } 15393 15394 // step 1: write control byte and the binary array size 15395 const auto N = j.m_data.m_value.binary->size(); 15396 if (N <= 0x17) 15397 { 15398 write_number(static_cast<std::uint8_t>(0x40 + N)); 15399 } 15400 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15401 { 15402 oa->write_character(to_char_type(0x58)); 15403 write_number(static_cast<std::uint8_t>(N)); 15404 } 15405 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15406 { 15407 oa->write_character(to_char_type(0x59)); 15408 write_number(static_cast<std::uint16_t>(N)); 15409 } 15410 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15411 { 15412 oa->write_character(to_char_type(0x5A)); 15413 write_number(static_cast<std::uint32_t>(N)); 15414 } 15415 // LCOV_EXCL_START 15416 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15417 { 15418 oa->write_character(to_char_type(0x5B)); 15419 write_number(static_cast<std::uint64_t>(N)); 15420 } 15421 // LCOV_EXCL_STOP 15422 15423 // step 2: write each element 15424 oa->write_characters( 15425 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), 15426 N); 15427 15428 break; 15429 } 15430 15431 case value_t::object: 15432 { 15433 // step 1: write control byte and the object size 15434 const auto N = j.m_data.m_value.object->size(); 15435 if (N <= 0x17) 15436 { 15437 write_number(static_cast<std::uint8_t>(0xA0 + N)); 15438 } 15439 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15440 { 15441 oa->write_character(to_char_type(0xB8)); 15442 write_number(static_cast<std::uint8_t>(N)); 15443 } 15444 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15445 { 15446 oa->write_character(to_char_type(0xB9)); 15447 write_number(static_cast<std::uint16_t>(N)); 15448 } 15449 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15450 { 15451 oa->write_character(to_char_type(0xBA)); 15452 write_number(static_cast<std::uint32_t>(N)); 15453 } 15454 // LCOV_EXCL_START 15455 else if (N <= (std::numeric_limits<std::uint64_t>::max)()) 15456 { 15457 oa->write_character(to_char_type(0xBB)); 15458 write_number(static_cast<std::uint64_t>(N)); 15459 } 15460 // LCOV_EXCL_STOP 15461 15462 // step 2: write each element 15463 for (const auto& el : *j.m_data.m_value.object) 15464 { 15465 write_cbor(el.first); 15466 write_cbor(el.second); 15467 } 15468 break; 15469 } 15470 15471 case value_t::discarded: 15472 default: 15473 break; 15474 } 15475 } 15476 15477 /*! 15478 @param[in] j JSON value to serialize 15479 */ 15480 void write_msgpack(const BasicJsonType& j) 15481 { 15482 switch (j.type()) 15483 { 15484 case value_t::null: // nil 15485 { 15486 oa->write_character(to_char_type(0xC0)); 15487 break; 15488 } 15489 15490 case value_t::boolean: // true and false 15491 { 15492 oa->write_character(j.m_data.m_value.boolean 15493 ? to_char_type(0xC3) 15494 : to_char_type(0xC2)); 15495 break; 15496 } 15497 15498 case value_t::number_integer: 15499 { 15500 if (j.m_data.m_value.number_integer >= 0) 15501 { 15502 // MessagePack does not differentiate between positive 15503 // signed integers and unsigned integers. Therefore, we used 15504 // the code from the value_t::number_unsigned case here. 15505 if (j.m_data.m_value.number_unsigned < 128) 15506 { 15507 // positive fixnum 15508 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15509 } 15510 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 15511 { 15512 // uint 8 15513 oa->write_character(to_char_type(0xCC)); 15514 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15515 } 15516 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 15517 { 15518 // uint 16 15519 oa->write_character(to_char_type(0xCD)); 15520 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer)); 15521 } 15522 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 15523 { 15524 // uint 32 15525 oa->write_character(to_char_type(0xCE)); 15526 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer)); 15527 } 15528 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 15529 { 15530 // uint 64 15531 oa->write_character(to_char_type(0xCF)); 15532 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer)); 15533 } 15534 } 15535 else 15536 { 15537 if (j.m_data.m_value.number_integer >= -32) 15538 { 15539 // negative fixnum 15540 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer)); 15541 } 15542 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() && 15543 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) 15544 { 15545 // int 8 15546 oa->write_character(to_char_type(0xD0)); 15547 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer)); 15548 } 15549 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() && 15550 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) 15551 { 15552 // int 16 15553 oa->write_character(to_char_type(0xD1)); 15554 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer)); 15555 } 15556 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() && 15557 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) 15558 { 15559 // int 32 15560 oa->write_character(to_char_type(0xD2)); 15561 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer)); 15562 } 15563 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() && 15564 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) 15565 { 15566 // int 64 15567 oa->write_character(to_char_type(0xD3)); 15568 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer)); 15569 } 15570 } 15571 break; 15572 } 15573 15574 case value_t::number_unsigned: 15575 { 15576 if (j.m_data.m_value.number_unsigned < 128) 15577 { 15578 // positive fixnum 15579 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15580 } 15581 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)()) 15582 { 15583 // uint 8 15584 oa->write_character(to_char_type(0xCC)); 15585 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer)); 15586 } 15587 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)()) 15588 { 15589 // uint 16 15590 oa->write_character(to_char_type(0xCD)); 15591 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer)); 15592 } 15593 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)()) 15594 { 15595 // uint 32 15596 oa->write_character(to_char_type(0xCE)); 15597 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer)); 15598 } 15599 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 15600 { 15601 // uint 64 15602 oa->write_character(to_char_type(0xCF)); 15603 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer)); 15604 } 15605 break; 15606 } 15607 15608 case value_t::number_float: 15609 { 15610 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack); 15611 break; 15612 } 15613 15614 case value_t::string: 15615 { 15616 // step 1: write control byte and the string length 15617 const auto N = j.m_data.m_value.string->size(); 15618 if (N <= 31) 15619 { 15620 // fixstr 15621 write_number(static_cast<std::uint8_t>(0xA0 | N)); 15622 } 15623 else if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15624 { 15625 // str 8 15626 oa->write_character(to_char_type(0xD9)); 15627 write_number(static_cast<std::uint8_t>(N)); 15628 } 15629 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15630 { 15631 // str 16 15632 oa->write_character(to_char_type(0xDA)); 15633 write_number(static_cast<std::uint16_t>(N)); 15634 } 15635 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15636 { 15637 // str 32 15638 oa->write_character(to_char_type(0xDB)); 15639 write_number(static_cast<std::uint32_t>(N)); 15640 } 15641 15642 // step 2: write the string 15643 oa->write_characters( 15644 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), 15645 j.m_data.m_value.string->size()); 15646 break; 15647 } 15648 15649 case value_t::array: 15650 { 15651 // step 1: write control byte and the array size 15652 const auto N = j.m_data.m_value.array->size(); 15653 if (N <= 15) 15654 { 15655 // fixarray 15656 write_number(static_cast<std::uint8_t>(0x90 | N)); 15657 } 15658 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15659 { 15660 // array 16 15661 oa->write_character(to_char_type(0xDC)); 15662 write_number(static_cast<std::uint16_t>(N)); 15663 } 15664 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15665 { 15666 // array 32 15667 oa->write_character(to_char_type(0xDD)); 15668 write_number(static_cast<std::uint32_t>(N)); 15669 } 15670 15671 // step 2: write each element 15672 for (const auto& el : *j.m_data.m_value.array) 15673 { 15674 write_msgpack(el); 15675 } 15676 break; 15677 } 15678 15679 case value_t::binary: 15680 { 15681 // step 0: determine if the binary type has a set subtype to 15682 // determine whether or not to use the ext or fixext types 15683 const bool use_ext = j.m_data.m_value.binary->has_subtype(); 15684 15685 // step 1: write control byte and the byte string length 15686 const auto N = j.m_data.m_value.binary->size(); 15687 if (N <= (std::numeric_limits<std::uint8_t>::max)()) 15688 { 15689 std::uint8_t output_type{}; 15690 bool fixed = true; 15691 if (use_ext) 15692 { 15693 switch (N) 15694 { 15695 case 1: 15696 output_type = 0xD4; // fixext 1 15697 break; 15698 case 2: 15699 output_type = 0xD5; // fixext 2 15700 break; 15701 case 4: 15702 output_type = 0xD6; // fixext 4 15703 break; 15704 case 8: 15705 output_type = 0xD7; // fixext 8 15706 break; 15707 case 16: 15708 output_type = 0xD8; // fixext 16 15709 break; 15710 default: 15711 output_type = 0xC7; // ext 8 15712 fixed = false; 15713 break; 15714 } 15715 15716 } 15717 else 15718 { 15719 output_type = 0xC4; // bin 8 15720 fixed = false; 15721 } 15722 15723 oa->write_character(to_char_type(output_type)); 15724 if (!fixed) 15725 { 15726 write_number(static_cast<std::uint8_t>(N)); 15727 } 15728 } 15729 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15730 { 15731 const std::uint8_t output_type = use_ext 15732 ? 0xC8 // ext 16 15733 : 0xC5; // bin 16 15734 15735 oa->write_character(to_char_type(output_type)); 15736 write_number(static_cast<std::uint16_t>(N)); 15737 } 15738 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15739 { 15740 const std::uint8_t output_type = use_ext 15741 ? 0xC9 // ext 32 15742 : 0xC6; // bin 32 15743 15744 oa->write_character(to_char_type(output_type)); 15745 write_number(static_cast<std::uint32_t>(N)); 15746 } 15747 15748 // step 1.5: if this is an ext type, write the subtype 15749 if (use_ext) 15750 { 15751 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype())); 15752 } 15753 15754 // step 2: write the byte string 15755 oa->write_characters( 15756 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), 15757 N); 15758 15759 break; 15760 } 15761 15762 case value_t::object: 15763 { 15764 // step 1: write control byte and the object size 15765 const auto N = j.m_data.m_value.object->size(); 15766 if (N <= 15) 15767 { 15768 // fixmap 15769 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF))); 15770 } 15771 else if (N <= (std::numeric_limits<std::uint16_t>::max)()) 15772 { 15773 // map 16 15774 oa->write_character(to_char_type(0xDE)); 15775 write_number(static_cast<std::uint16_t>(N)); 15776 } 15777 else if (N <= (std::numeric_limits<std::uint32_t>::max)()) 15778 { 15779 // map 32 15780 oa->write_character(to_char_type(0xDF)); 15781 write_number(static_cast<std::uint32_t>(N)); 15782 } 15783 15784 // step 2: write each element 15785 for (const auto& el : *j.m_data.m_value.object) 15786 { 15787 write_msgpack(el.first); 15788 write_msgpack(el.second); 15789 } 15790 break; 15791 } 15792 15793 case value_t::discarded: 15794 default: 15795 break; 15796 } 15797 } 15798 15799 /*! 15800 @param[in] j JSON value to serialize 15801 @param[in] use_count whether to use '#' prefixes (optimized format) 15802 @param[in] use_type whether to use '$' prefixes (optimized format) 15803 @param[in] add_prefix whether prefixes need to be used for this value 15804 @param[in] use_bjdata whether write in BJData format, default is false 15805 */ 15806 void write_ubjson(const BasicJsonType& j, const bool use_count, 15807 const bool use_type, const bool add_prefix = true, 15808 const bool use_bjdata = false) 15809 { 15810 switch (j.type()) 15811 { 15812 case value_t::null: 15813 { 15814 if (add_prefix) 15815 { 15816 oa->write_character(to_char_type('Z')); 15817 } 15818 break; 15819 } 15820 15821 case value_t::boolean: 15822 { 15823 if (add_prefix) 15824 { 15825 oa->write_character(j.m_data.m_value.boolean 15826 ? to_char_type('T') 15827 : to_char_type('F')); 15828 } 15829 break; 15830 } 15831 15832 case value_t::number_integer: 15833 { 15834 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata); 15835 break; 15836 } 15837 15838 case value_t::number_unsigned: 15839 { 15840 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata); 15841 break; 15842 } 15843 15844 case value_t::number_float: 15845 { 15846 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata); 15847 break; 15848 } 15849 15850 case value_t::string: 15851 { 15852 if (add_prefix) 15853 { 15854 oa->write_character(to_char_type('S')); 15855 } 15856 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata); 15857 oa->write_characters( 15858 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), 15859 j.m_data.m_value.string->size()); 15860 break; 15861 } 15862 15863 case value_t::array: 15864 { 15865 if (add_prefix) 15866 { 15867 oa->write_character(to_char_type('[')); 15868 } 15869 15870 bool prefix_required = true; 15871 if (use_type && !j.m_data.m_value.array->empty()) 15872 { 15873 JSON_ASSERT(use_count); 15874 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); 15875 const bool same_prefix = std::all_of(j.begin() + 1, j.end(), 15876 [this, first_prefix, use_bjdata](const BasicJsonType & v) 15877 { 15878 return ubjson_prefix(v, use_bjdata) == first_prefix; 15879 }); 15880 15881 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type 15882 15883 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) 15884 { 15885 prefix_required = false; 15886 oa->write_character(to_char_type('$')); 15887 oa->write_character(first_prefix); 15888 } 15889 } 15890 15891 if (use_count) 15892 { 15893 oa->write_character(to_char_type('#')); 15894 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata); 15895 } 15896 15897 for (const auto& el : *j.m_data.m_value.array) 15898 { 15899 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata); 15900 } 15901 15902 if (!use_count) 15903 { 15904 oa->write_character(to_char_type(']')); 15905 } 15906 15907 break; 15908 } 15909 15910 case value_t::binary: 15911 { 15912 if (add_prefix) 15913 { 15914 oa->write_character(to_char_type('[')); 15915 } 15916 15917 if (use_type && !j.m_data.m_value.binary->empty()) 15918 { 15919 JSON_ASSERT(use_count); 15920 oa->write_character(to_char_type('$')); 15921 oa->write_character('U'); 15922 } 15923 15924 if (use_count) 15925 { 15926 oa->write_character(to_char_type('#')); 15927 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata); 15928 } 15929 15930 if (use_type) 15931 { 15932 oa->write_characters( 15933 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), 15934 j.m_data.m_value.binary->size()); 15935 } 15936 else 15937 { 15938 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) 15939 { 15940 oa->write_character(to_char_type('U')); 15941 oa->write_character(j.m_data.m_value.binary->data()[i]); 15942 } 15943 } 15944 15945 if (!use_count) 15946 { 15947 oa->write_character(to_char_type(']')); 15948 } 15949 15950 break; 15951 } 15952 15953 case value_t::object: 15954 { 15955 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end()) 15956 { 15957 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) 15958 { 15959 break; 15960 } 15961 } 15962 15963 if (add_prefix) 15964 { 15965 oa->write_character(to_char_type('{')); 15966 } 15967 15968 bool prefix_required = true; 15969 if (use_type && !j.m_data.m_value.object->empty()) 15970 { 15971 JSON_ASSERT(use_count); 15972 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); 15973 const bool same_prefix = std::all_of(j.begin(), j.end(), 15974 [this, first_prefix, use_bjdata](const BasicJsonType & v) 15975 { 15976 return ubjson_prefix(v, use_bjdata) == first_prefix; 15977 }); 15978 15979 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type 15980 15981 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end())) 15982 { 15983 prefix_required = false; 15984 oa->write_character(to_char_type('$')); 15985 oa->write_character(first_prefix); 15986 } 15987 } 15988 15989 if (use_count) 15990 { 15991 oa->write_character(to_char_type('#')); 15992 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata); 15993 } 15994 15995 for (const auto& el : *j.m_data.m_value.object) 15996 { 15997 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata); 15998 oa->write_characters( 15999 reinterpret_cast<const CharType*>(el.first.c_str()), 16000 el.first.size()); 16001 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata); 16002 } 16003 16004 if (!use_count) 16005 { 16006 oa->write_character(to_char_type('}')); 16007 } 16008 16009 break; 16010 } 16011 16012 case value_t::discarded: 16013 default: 16014 break; 16015 } 16016 } 16017 16018 private: 16019 ////////// 16020 // BSON // 16021 ////////// 16022 16023 /*! 16024 @return The size of a BSON document entry header, including the id marker 16025 and the entry name size (and its null-terminator). 16026 */ 16027 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j) 16028 { 16029 const auto it = name.find(static_cast<typename string_t::value_type>(0)); 16030 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) 16031 { 16032 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j)); 16033 static_cast<void>(j); 16034 } 16035 16036 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; 16037 } 16038 16039 /*! 16040 @brief Writes the given @a element_type and @a name to the output adapter 16041 */ 16042 void write_bson_entry_header(const string_t& name, 16043 const std::uint8_t element_type) 16044 { 16045 oa->write_character(to_char_type(element_type)); // boolean 16046 oa->write_characters( 16047 reinterpret_cast<const CharType*>(name.c_str()), 16048 name.size() + 1u); 16049 } 16050 16051 /*! 16052 @brief Writes a BSON element with key @a name and boolean value @a value 16053 */ 16054 void write_bson_boolean(const string_t& name, 16055 const bool value) 16056 { 16057 write_bson_entry_header(name, 0x08); 16058 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); 16059 } 16060 16061 /*! 16062 @brief Writes a BSON element with key @a name and double value @a value 16063 */ 16064 void write_bson_double(const string_t& name, 16065 const double value) 16066 { 16067 write_bson_entry_header(name, 0x01); 16068 write_number<double>(value, true); 16069 } 16070 16071 /*! 16072 @return The size of the BSON-encoded string in @a value 16073 */ 16074 static std::size_t calc_bson_string_size(const string_t& value) 16075 { 16076 return sizeof(std::int32_t) + value.size() + 1ul; 16077 } 16078 16079 /*! 16080 @brief Writes a BSON element with key @a name and string value @a value 16081 */ 16082 void write_bson_string(const string_t& name, 16083 const string_t& value) 16084 { 16085 write_bson_entry_header(name, 0x02); 16086 16087 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true); 16088 oa->write_characters( 16089 reinterpret_cast<const CharType*>(value.c_str()), 16090 value.size() + 1); 16091 } 16092 16093 /*! 16094 @brief Writes a BSON element with key @a name and null value 16095 */ 16096 void write_bson_null(const string_t& name) 16097 { 16098 write_bson_entry_header(name, 0x0A); 16099 } 16100 16101 /*! 16102 @return The size of the BSON-encoded integer @a value 16103 */ 16104 static std::size_t calc_bson_integer_size(const std::int64_t value) 16105 { 16106 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)() 16107 ? sizeof(std::int32_t) 16108 : sizeof(std::int64_t); 16109 } 16110 16111 /*! 16112 @brief Writes a BSON element with key @a name and integer @a value 16113 */ 16114 void write_bson_integer(const string_t& name, 16115 const std::int64_t value) 16116 { 16117 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()) 16118 { 16119 write_bson_entry_header(name, 0x10); // int32 16120 write_number<std::int32_t>(static_cast<std::int32_t>(value), true); 16121 } 16122 else 16123 { 16124 write_bson_entry_header(name, 0x12); // int64 16125 write_number<std::int64_t>(static_cast<std::int64_t>(value), true); 16126 } 16127 } 16128 16129 /*! 16130 @return The size of the BSON-encoded unsigned integer in @a j 16131 */ 16132 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept 16133 { 16134 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16135 ? sizeof(std::int32_t) 16136 : sizeof(std::int64_t); 16137 } 16138 16139 /*! 16140 @brief Writes a BSON element with key @a name and unsigned @a value 16141 */ 16142 void write_bson_unsigned(const string_t& name, 16143 const BasicJsonType& j) 16144 { 16145 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16146 { 16147 write_bson_entry_header(name, 0x10 /* int32 */); 16148 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true); 16149 } 16150 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 16151 { 16152 write_bson_entry_header(name, 0x12 /* int64 */); 16153 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true); 16154 } 16155 else 16156 { 16157 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); 16158 } 16159 } 16160 16161 /*! 16162 @brief Writes a BSON element with key @a name and object @a value 16163 */ 16164 void write_bson_object_entry(const string_t& name, 16165 const typename BasicJsonType::object_t& value) 16166 { 16167 write_bson_entry_header(name, 0x03); // object 16168 write_bson_object(value); 16169 } 16170 16171 /*! 16172 @return The size of the BSON-encoded array @a value 16173 */ 16174 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) 16175 { 16176 std::size_t array_index = 0ul; 16177 16178 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) 16179 { 16180 return result + calc_bson_element_size(std::to_string(array_index++), el); 16181 }); 16182 16183 return sizeof(std::int32_t) + embedded_document_size + 1ul; 16184 } 16185 16186 /*! 16187 @return The size of the BSON-encoded binary array @a value 16188 */ 16189 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) 16190 { 16191 return sizeof(std::int32_t) + value.size() + 1ul; 16192 } 16193 16194 /*! 16195 @brief Writes a BSON element with key @a name and array @a value 16196 */ 16197 void write_bson_array(const string_t& name, 16198 const typename BasicJsonType::array_t& value) 16199 { 16200 write_bson_entry_header(name, 0x04); // array 16201 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true); 16202 16203 std::size_t array_index = 0ul; 16204 16205 for (const auto& el : value) 16206 { 16207 write_bson_element(std::to_string(array_index++), el); 16208 } 16209 16210 oa->write_character(to_char_type(0x00)); 16211 } 16212 16213 /*! 16214 @brief Writes a BSON element with key @a name and binary value @a value 16215 */ 16216 void write_bson_binary(const string_t& name, 16217 const binary_t& value) 16218 { 16219 write_bson_entry_header(name, 0x05); 16220 16221 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true); 16222 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00)); 16223 16224 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size()); 16225 } 16226 16227 /*! 16228 @brief Calculates the size necessary to serialize the JSON value @a j with its @a name 16229 @return The calculated size for the BSON document entry for @a j with the given @a name. 16230 */ 16231 static std::size_t calc_bson_element_size(const string_t& name, 16232 const BasicJsonType& j) 16233 { 16234 const auto header_size = calc_bson_entry_header_size(name, j); 16235 switch (j.type()) 16236 { 16237 case value_t::object: 16238 return header_size + calc_bson_object_size(*j.m_data.m_value.object); 16239 16240 case value_t::array: 16241 return header_size + calc_bson_array_size(*j.m_data.m_value.array); 16242 16243 case value_t::binary: 16244 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary); 16245 16246 case value_t::boolean: 16247 return header_size + 1ul; 16248 16249 case value_t::number_float: 16250 return header_size + 8ul; 16251 16252 case value_t::number_integer: 16253 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer); 16254 16255 case value_t::number_unsigned: 16256 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned); 16257 16258 case value_t::string: 16259 return header_size + calc_bson_string_size(*j.m_data.m_value.string); 16260 16261 case value_t::null: 16262 return header_size + 0ul; 16263 16264 // LCOV_EXCL_START 16265 case value_t::discarded: 16266 default: 16267 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) 16268 return 0ul; 16269 // LCOV_EXCL_STOP 16270 } 16271 } 16272 16273 /*! 16274 @brief Serializes the JSON value @a j to BSON and associates it with the 16275 key @a name. 16276 @param name The name to associate with the JSON entity @a j within the 16277 current BSON document 16278 */ 16279 void write_bson_element(const string_t& name, 16280 const BasicJsonType& j) 16281 { 16282 switch (j.type()) 16283 { 16284 case value_t::object: 16285 return write_bson_object_entry(name, *j.m_data.m_value.object); 16286 16287 case value_t::array: 16288 return write_bson_array(name, *j.m_data.m_value.array); 16289 16290 case value_t::binary: 16291 return write_bson_binary(name, *j.m_data.m_value.binary); 16292 16293 case value_t::boolean: 16294 return write_bson_boolean(name, j.m_data.m_value.boolean); 16295 16296 case value_t::number_float: 16297 return write_bson_double(name, j.m_data.m_value.number_float); 16298 16299 case value_t::number_integer: 16300 return write_bson_integer(name, j.m_data.m_value.number_integer); 16301 16302 case value_t::number_unsigned: 16303 return write_bson_unsigned(name, j); 16304 16305 case value_t::string: 16306 return write_bson_string(name, *j.m_data.m_value.string); 16307 16308 case value_t::null: 16309 return write_bson_null(name); 16310 16311 // LCOV_EXCL_START 16312 case value_t::discarded: 16313 default: 16314 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) 16315 return; 16316 // LCOV_EXCL_STOP 16317 } 16318 } 16319 16320 /*! 16321 @brief Calculates the size of the BSON serialization of the given 16322 JSON-object @a j. 16323 @param[in] value JSON value to serialize 16324 @pre value.type() == value_t::object 16325 */ 16326 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) 16327 { 16328 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0), 16329 [](size_t result, const typename BasicJsonType::object_t::value_type & el) 16330 { 16331 return result += calc_bson_element_size(el.first, el.second); 16332 }); 16333 16334 return sizeof(std::int32_t) + document_size + 1ul; 16335 } 16336 16337 /*! 16338 @param[in] value JSON value to serialize 16339 @pre value.type() == value_t::object 16340 */ 16341 void write_bson_object(const typename BasicJsonType::object_t& value) 16342 { 16343 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true); 16344 16345 for (const auto& el : value) 16346 { 16347 write_bson_element(el.first, el.second); 16348 } 16349 16350 oa->write_character(to_char_type(0x00)); 16351 } 16352 16353 ////////// 16354 // CBOR // 16355 ////////// 16356 16357 static constexpr CharType get_cbor_float_prefix(float /*unused*/) 16358 { 16359 return to_char_type(0xFA); // Single-Precision Float 16360 } 16361 16362 static constexpr CharType get_cbor_float_prefix(double /*unused*/) 16363 { 16364 return to_char_type(0xFB); // Double-Precision Float 16365 } 16366 16367 ///////////// 16368 // MsgPack // 16369 ///////////// 16370 16371 static constexpr CharType get_msgpack_float_prefix(float /*unused*/) 16372 { 16373 return to_char_type(0xCA); // float 32 16374 } 16375 16376 static constexpr CharType get_msgpack_float_prefix(double /*unused*/) 16377 { 16378 return to_char_type(0xCB); // float 64 16379 } 16380 16381 //////////// 16382 // UBJSON // 16383 //////////// 16384 16385 // UBJSON: write number (floating point) 16386 template<typename NumberType, typename std::enable_if< 16387 std::is_floating_point<NumberType>::value, int>::type = 0> 16388 void write_number_with_ubjson_prefix(const NumberType n, 16389 const bool add_prefix, 16390 const bool use_bjdata) 16391 { 16392 if (add_prefix) 16393 { 16394 oa->write_character(get_ubjson_float_prefix(n)); 16395 } 16396 write_number(n, use_bjdata); 16397 } 16398 16399 // UBJSON: write number (unsigned integer) 16400 template<typename NumberType, typename std::enable_if< 16401 std::is_unsigned<NumberType>::value, int>::type = 0> 16402 void write_number_with_ubjson_prefix(const NumberType n, 16403 const bool add_prefix, 16404 const bool use_bjdata) 16405 { 16406 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) 16407 { 16408 if (add_prefix) 16409 { 16410 oa->write_character(to_char_type('i')); // int8 16411 } 16412 write_number(static_cast<std::uint8_t>(n), use_bjdata); 16413 } 16414 else if (n <= (std::numeric_limits<std::uint8_t>::max)()) 16415 { 16416 if (add_prefix) 16417 { 16418 oa->write_character(to_char_type('U')); // uint8 16419 } 16420 write_number(static_cast<std::uint8_t>(n), use_bjdata); 16421 } 16422 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) 16423 { 16424 if (add_prefix) 16425 { 16426 oa->write_character(to_char_type('I')); // int16 16427 } 16428 write_number(static_cast<std::int16_t>(n), use_bjdata); 16429 } 16430 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)())) 16431 { 16432 if (add_prefix) 16433 { 16434 oa->write_character(to_char_type('u')); // uint16 - bjdata only 16435 } 16436 write_number(static_cast<std::uint16_t>(n), use_bjdata); 16437 } 16438 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16439 { 16440 if (add_prefix) 16441 { 16442 oa->write_character(to_char_type('l')); // int32 16443 } 16444 write_number(static_cast<std::int32_t>(n), use_bjdata); 16445 } 16446 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)())) 16447 { 16448 if (add_prefix) 16449 { 16450 oa->write_character(to_char_type('m')); // uint32 - bjdata only 16451 } 16452 write_number(static_cast<std::uint32_t>(n), use_bjdata); 16453 } 16454 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 16455 { 16456 if (add_prefix) 16457 { 16458 oa->write_character(to_char_type('L')); // int64 16459 } 16460 write_number(static_cast<std::int64_t>(n), use_bjdata); 16461 } 16462 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)()) 16463 { 16464 if (add_prefix) 16465 { 16466 oa->write_character(to_char_type('M')); // uint64 - bjdata only 16467 } 16468 write_number(static_cast<std::uint64_t>(n), use_bjdata); 16469 } 16470 else 16471 { 16472 if (add_prefix) 16473 { 16474 oa->write_character(to_char_type('H')); // high-precision number 16475 } 16476 16477 const auto number = BasicJsonType(n).dump(); 16478 write_number_with_ubjson_prefix(number.size(), true, use_bjdata); 16479 for (std::size_t i = 0; i < number.size(); ++i) 16480 { 16481 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); 16482 } 16483 } 16484 } 16485 16486 // UBJSON: write number (signed integer) 16487 template < typename NumberType, typename std::enable_if < 16488 std::is_signed<NumberType>::value&& 16489 !std::is_floating_point<NumberType>::value, int >::type = 0 > 16490 void write_number_with_ubjson_prefix(const NumberType n, 16491 const bool add_prefix, 16492 const bool use_bjdata) 16493 { 16494 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)()) 16495 { 16496 if (add_prefix) 16497 { 16498 oa->write_character(to_char_type('i')); // int8 16499 } 16500 write_number(static_cast<std::int8_t>(n), use_bjdata); 16501 } 16502 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)())) 16503 { 16504 if (add_prefix) 16505 { 16506 oa->write_character(to_char_type('U')); // uint8 16507 } 16508 write_number(static_cast<std::uint8_t>(n), use_bjdata); 16509 } 16510 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)()) 16511 { 16512 if (add_prefix) 16513 { 16514 oa->write_character(to_char_type('I')); // int16 16515 } 16516 write_number(static_cast<std::int16_t>(n), use_bjdata); 16517 } 16518 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)()))) 16519 { 16520 if (add_prefix) 16521 { 16522 oa->write_character(to_char_type('u')); // uint16 - bjdata only 16523 } 16524 write_number(static_cast<uint16_t>(n), use_bjdata); 16525 } 16526 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)()) 16527 { 16528 if (add_prefix) 16529 { 16530 oa->write_character(to_char_type('l')); // int32 16531 } 16532 write_number(static_cast<std::int32_t>(n), use_bjdata); 16533 } 16534 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)()))) 16535 { 16536 if (add_prefix) 16537 { 16538 oa->write_character(to_char_type('m')); // uint32 - bjdata only 16539 } 16540 write_number(static_cast<uint32_t>(n), use_bjdata); 16541 } 16542 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) 16543 { 16544 if (add_prefix) 16545 { 16546 oa->write_character(to_char_type('L')); // int64 16547 } 16548 write_number(static_cast<std::int64_t>(n), use_bjdata); 16549 } 16550 // LCOV_EXCL_START 16551 else 16552 { 16553 if (add_prefix) 16554 { 16555 oa->write_character(to_char_type('H')); // high-precision number 16556 } 16557 16558 const auto number = BasicJsonType(n).dump(); 16559 write_number_with_ubjson_prefix(number.size(), true, use_bjdata); 16560 for (std::size_t i = 0; i < number.size(); ++i) 16561 { 16562 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); 16563 } 16564 } 16565 // LCOV_EXCL_STOP 16566 } 16567 16568 /*! 16569 @brief determine the type prefix of container values 16570 */ 16571 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept 16572 { 16573 switch (j.type()) 16574 { 16575 case value_t::null: 16576 return 'Z'; 16577 16578 case value_t::boolean: 16579 return j.m_data.m_value.boolean ? 'T' : 'F'; 16580 16581 case value_t::number_integer: 16582 { 16583 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)()) 16584 { 16585 return 'i'; 16586 } 16587 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)()) 16588 { 16589 return 'U'; 16590 } 16591 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)()) 16592 { 16593 return 'I'; 16594 } 16595 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())) 16596 { 16597 return 'u'; 16598 } 16599 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)()) 16600 { 16601 return 'l'; 16602 } 16603 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())) 16604 { 16605 return 'm'; 16606 } 16607 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)()) 16608 { 16609 return 'L'; 16610 } 16611 // anything else is treated as high-precision number 16612 return 'H'; // LCOV_EXCL_LINE 16613 } 16614 16615 case value_t::number_unsigned: 16616 { 16617 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) 16618 { 16619 return 'i'; 16620 } 16621 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)())) 16622 { 16623 return 'U'; 16624 } 16625 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) 16626 { 16627 return 'I'; 16628 } 16629 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)())) 16630 { 16631 return 'u'; 16632 } 16633 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) 16634 { 16635 return 'l'; 16636 } 16637 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)())) 16638 { 16639 return 'm'; 16640 } 16641 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) 16642 { 16643 return 'L'; 16644 } 16645 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) 16646 { 16647 return 'M'; 16648 } 16649 // anything else is treated as high-precision number 16650 return 'H'; // LCOV_EXCL_LINE 16651 } 16652 16653 case value_t::number_float: 16654 return get_ubjson_float_prefix(j.m_data.m_value.number_float); 16655 16656 case value_t::string: 16657 return 'S'; 16658 16659 case value_t::array: // fallthrough 16660 case value_t::binary: 16661 return '['; 16662 16663 case value_t::object: 16664 return '{'; 16665 16666 case value_t::discarded: 16667 default: // discarded values 16668 return 'N'; 16669 } 16670 } 16671 16672 static constexpr CharType get_ubjson_float_prefix(float /*unused*/) 16673 { 16674 return 'd'; // float 32 16675 } 16676 16677 static constexpr CharType get_ubjson_float_prefix(double /*unused*/) 16678 { 16679 return 'D'; // float 64 16680 } 16681 16682 /*! 16683 @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid 16684 */ 16685 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type) 16686 { 16687 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'}, 16688 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'} 16689 }; 16690 16691 string_t key = "_ArrayType_"; 16692 auto it = bjdtype.find(static_cast<string_t>(value.at(key))); 16693 if (it == bjdtype.end()) 16694 { 16695 return true; 16696 } 16697 CharType dtype = it->second; 16698 16699 key = "_ArraySize_"; 16700 std::size_t len = (value.at(key).empty() ? 0 : 1); 16701 for (const auto& el : value.at(key)) 16702 { 16703 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned); 16704 } 16705 16706 key = "_ArrayData_"; 16707 if (value.at(key).size() != len) 16708 { 16709 return true; 16710 } 16711 16712 oa->write_character('['); 16713 oa->write_character('$'); 16714 oa->write_character(dtype); 16715 oa->write_character('#'); 16716 16717 key = "_ArraySize_"; 16718 write_ubjson(value.at(key), use_count, use_type, true, true); 16719 16720 key = "_ArrayData_"; 16721 if (dtype == 'U' || dtype == 'C') 16722 { 16723 for (const auto& el : value.at(key)) 16724 { 16725 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true); 16726 } 16727 } 16728 else if (dtype == 'i') 16729 { 16730 for (const auto& el : value.at(key)) 16731 { 16732 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true); 16733 } 16734 } 16735 else if (dtype == 'u') 16736 { 16737 for (const auto& el : value.at(key)) 16738 { 16739 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true); 16740 } 16741 } 16742 else if (dtype == 'I') 16743 { 16744 for (const auto& el : value.at(key)) 16745 { 16746 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true); 16747 } 16748 } 16749 else if (dtype == 'm') 16750 { 16751 for (const auto& el : value.at(key)) 16752 { 16753 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true); 16754 } 16755 } 16756 else if (dtype == 'l') 16757 { 16758 for (const auto& el : value.at(key)) 16759 { 16760 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true); 16761 } 16762 } 16763 else if (dtype == 'M') 16764 { 16765 for (const auto& el : value.at(key)) 16766 { 16767 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true); 16768 } 16769 } 16770 else if (dtype == 'L') 16771 { 16772 for (const auto& el : value.at(key)) 16773 { 16774 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true); 16775 } 16776 } 16777 else if (dtype == 'd') 16778 { 16779 for (const auto& el : value.at(key)) 16780 { 16781 write_number(static_cast<float>(el.m_data.m_value.number_float), true); 16782 } 16783 } 16784 else if (dtype == 'D') 16785 { 16786 for (const auto& el : value.at(key)) 16787 { 16788 write_number(static_cast<double>(el.m_data.m_value.number_float), true); 16789 } 16790 } 16791 return false; 16792 } 16793 16794 /////////////////////// 16795 // Utility functions // 16796 /////////////////////// 16797 16798 /* 16799 @brief write a number to output input 16800 @param[in] n number of type @a NumberType 16801 @param[in] OutputIsLittleEndian Set to true if output data is 16802 required to be little endian 16803 @tparam NumberType the type of the number 16804 16805 @note This function needs to respect the system's endianness, because bytes 16806 in CBOR, MessagePack, and UBJSON are stored in network order (big 16807 endian) and therefore need reordering on little endian systems. 16808 On the other hand, BSON and BJData use little endian and should reorder 16809 on big endian systems. 16810 */ 16811 template<typename NumberType> 16812 void write_number(const NumberType n, const bool OutputIsLittleEndian = false) 16813 { 16814 // step 1: write number to array of length NumberType 16815 std::array<CharType, sizeof(NumberType)> vec{}; 16816 std::memcpy(vec.data(), &n, sizeof(NumberType)); 16817 16818 // step 2: write array to output (with possible reordering) 16819 if (is_little_endian != OutputIsLittleEndian) 16820 { 16821 // reverse byte order prior to conversion if necessary 16822 std::reverse(vec.begin(), vec.end()); 16823 } 16824 16825 oa->write_characters(vec.data(), sizeof(NumberType)); 16826 } 16827 16828 void write_compact_float(const number_float_t n, detail::input_format_t format) 16829 { 16830 #ifdef __GNUC__ 16831 #pragma GCC diagnostic push 16832 #pragma GCC diagnostic ignored "-Wfloat-equal" 16833 #endif 16834 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) && 16835 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) && 16836 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n)) 16837 { 16838 oa->write_character(format == detail::input_format_t::cbor 16839 ? get_cbor_float_prefix(static_cast<float>(n)) 16840 : get_msgpack_float_prefix(static_cast<float>(n))); 16841 write_number(static_cast<float>(n)); 16842 } 16843 else 16844 { 16845 oa->write_character(format == detail::input_format_t::cbor 16846 ? get_cbor_float_prefix(n) 16847 : get_msgpack_float_prefix(n)); 16848 write_number(n); 16849 } 16850 #ifdef __GNUC__ 16851 #pragma GCC diagnostic pop 16852 #endif 16853 } 16854 16855 public: 16856 // The following to_char_type functions are implement the conversion 16857 // between uint8_t and CharType. In case CharType is not unsigned, 16858 // such a conversion is required to allow values greater than 128. 16859 // See <https://github.com/nlohmann/json/issues/1286> for a discussion. 16860 template < typename C = CharType, 16861 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr > 16862 static constexpr CharType to_char_type(std::uint8_t x) noexcept 16863 { 16864 return *reinterpret_cast<char*>(&x); 16865 } 16866 16867 template < typename C = CharType, 16868 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr > 16869 static CharType to_char_type(std::uint8_t x) noexcept 16870 { 16871 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); 16872 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial"); 16873 CharType result; 16874 std::memcpy(&result, &x, sizeof(x)); 16875 return result; 16876 } 16877 16878 template<typename C = CharType, 16879 enable_if_t<std::is_unsigned<C>::value>* = nullptr> 16880 static constexpr CharType to_char_type(std::uint8_t x) noexcept 16881 { 16882 return x; 16883 } 16884 16885 template < typename InputCharType, typename C = CharType, 16886 enable_if_t < 16887 std::is_signed<C>::value && 16888 std::is_signed<char>::value && 16889 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value 16890 > * = nullptr > 16891 static constexpr CharType to_char_type(InputCharType x) noexcept 16892 { 16893 return x; 16894 } 16895 16896 private: 16897 /// whether we can assume little endianness 16898 const bool is_little_endian = little_endianness(); 16899 16900 /// the output 16901 output_adapter_t<CharType> oa = nullptr; 16902 }; 16903 16904 } // namespace detail 16905 NLOHMANN_JSON_NAMESPACE_END 16906 16907 // #include <nlohmann/detail/output/output_adapters.hpp> 16908 16909 // #include <nlohmann/detail/output/serializer.hpp> 16910 // __ _____ _____ _____ 16911 // __| | __| | | | JSON for Modern C++ 16912 // | | |__ | | | | | | version 3.11.3 16913 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 16914 // 16915 // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de> 16916 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 16917 // SPDX-License-Identifier: MIT 16918 16919 16920 16921 #include <algorithm> // reverse, remove, fill, find, none_of 16922 #include <array> // array 16923 #include <clocale> // localeconv, lconv 16924 #include <cmath> // labs, isfinite, isnan, signbit 16925 #include <cstddef> // size_t, ptrdiff_t 16926 #include <cstdint> // uint8_t 16927 #include <cstdio> // snprintf 16928 #include <limits> // numeric_limits 16929 #include <string> // string, char_traits 16930 #include <iomanip> // setfill, setw 16931 #include <type_traits> // is_same 16932 #include <utility> // move 16933 16934 // #include <nlohmann/detail/conversions/to_chars.hpp> 16935 // __ _____ _____ _____ 16936 // __| | __| | | | JSON for Modern C++ 16937 // | | |__ | | | | | | version 3.11.3 16938 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 16939 // 16940 // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/> 16941 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 16942 // SPDX-License-Identifier: MIT 16943 16944 16945 16946 #include <array> // array 16947 #include <cmath> // signbit, isfinite 16948 #include <cstdint> // intN_t, uintN_t 16949 #include <cstring> // memcpy, memmove 16950 #include <limits> // numeric_limits 16951 #include <type_traits> // conditional 16952 16953 // #include <nlohmann/detail/macro_scope.hpp> 16954 16955 16956 NLOHMANN_JSON_NAMESPACE_BEGIN 16957 namespace detail 16958 { 16959 16960 /*! 16961 @brief implements the Grisu2 algorithm for binary to decimal floating-point 16962 conversion. 16963 16964 This implementation is a slightly modified version of the reference 16965 implementation which may be obtained from 16966 http://florian.loitsch.com/publications (bench.tar.gz). 16967 16968 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. 16969 16970 For a detailed description of the algorithm see: 16971 16972 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with 16973 Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming 16974 Language Design and Implementation, PLDI 2010 16975 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", 16976 Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language 16977 Design and Implementation, PLDI 1996 16978 */ 16979 namespace dtoa_impl 16980 { 16981 16982 template<typename Target, typename Source> 16983 Target reinterpret_bits(const Source source) 16984 { 16985 static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); 16986 16987 Target target; 16988 std::memcpy(&target, &source, sizeof(Source)); 16989 return target; 16990 } 16991 16992 struct diyfp // f * 2^e 16993 { 16994 static constexpr int kPrecision = 64; // = q 16995 16996 std::uint64_t f = 0; 16997 int e = 0; 16998 16999 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} 17000 17001 /*! 17002 @brief returns x - y 17003 @pre x.e == y.e and x.f >= y.f 17004 */ 17005 static diyfp sub(const diyfp& x, const diyfp& y) noexcept 17006 { 17007 JSON_ASSERT(x.e == y.e); 17008 JSON_ASSERT(x.f >= y.f); 17009 17010 return {x.f - y.f, x.e}; 17011 } 17012 17013 /*! 17014 @brief returns x * y 17015 @note The result is rounded. (Only the upper q bits are returned.) 17016 */ 17017 static diyfp mul(const diyfp& x, const diyfp& y) noexcept 17018 { 17019 static_assert(kPrecision == 64, "internal error"); 17020 17021 // Computes: 17022 // f = round((x.f * y.f) / 2^q) 17023 // e = x.e + y.e + q 17024 17025 // Emulate the 64-bit * 64-bit multiplication: 17026 // 17027 // p = u * v 17028 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) 17029 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) 17030 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) 17031 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) 17032 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) 17033 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) 17034 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) 17035 // 17036 // (Since Q might be larger than 2^32 - 1) 17037 // 17038 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) 17039 // 17040 // (Q_hi + H does not overflow a 64-bit int) 17041 // 17042 // = p_lo + 2^64 p_hi 17043 17044 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; 17045 const std::uint64_t u_hi = x.f >> 32u; 17046 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; 17047 const std::uint64_t v_hi = y.f >> 32u; 17048 17049 const std::uint64_t p0 = u_lo * v_lo; 17050 const std::uint64_t p1 = u_lo * v_hi; 17051 const std::uint64_t p2 = u_hi * v_lo; 17052 const std::uint64_t p3 = u_hi * v_hi; 17053 17054 const std::uint64_t p0_hi = p0 >> 32u; 17055 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; 17056 const std::uint64_t p1_hi = p1 >> 32u; 17057 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; 17058 const std::uint64_t p2_hi = p2 >> 32u; 17059 17060 std::uint64_t Q = p0_hi + p1_lo + p2_lo; 17061 17062 // The full product might now be computed as 17063 // 17064 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) 17065 // p_lo = p0_lo + (Q << 32) 17066 // 17067 // But in this particular case here, the full p_lo is not required. 17068 // Effectively we only need to add the highest bit in p_lo to p_hi (and 17069 // Q_hi + 1 does not overflow). 17070 17071 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up 17072 17073 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); 17074 17075 return {h, x.e + y.e + 64}; 17076 } 17077 17078 /*! 17079 @brief normalize x such that the significand is >= 2^(q-1) 17080 @pre x.f != 0 17081 */ 17082 static diyfp normalize(diyfp x) noexcept 17083 { 17084 JSON_ASSERT(x.f != 0); 17085 17086 while ((x.f >> 63u) == 0) 17087 { 17088 x.f <<= 1u; 17089 x.e--; 17090 } 17091 17092 return x; 17093 } 17094 17095 /*! 17096 @brief normalize x such that the result has the exponent E 17097 @pre e >= x.e and the upper e - x.e bits of x.f must be zero. 17098 */ 17099 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept 17100 { 17101 const int delta = x.e - target_exponent; 17102 17103 JSON_ASSERT(delta >= 0); 17104 JSON_ASSERT(((x.f << delta) >> delta) == x.f); 17105 17106 return {x.f << delta, target_exponent}; 17107 } 17108 }; 17109 17110 struct boundaries 17111 { 17112 diyfp w; 17113 diyfp minus; 17114 diyfp plus; 17115 }; 17116 17117 /*! 17118 Compute the (normalized) diyfp representing the input number 'value' and its 17119 boundaries. 17120 17121 @pre value must be finite and positive 17122 */ 17123 template<typename FloatType> 17124 boundaries compute_boundaries(FloatType value) 17125 { 17126 JSON_ASSERT(std::isfinite(value)); 17127 JSON_ASSERT(value > 0); 17128 17129 // Convert the IEEE representation into a diyfp. 17130 // 17131 // If v is denormal: 17132 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) 17133 // If v is normalized: 17134 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) 17135 17136 static_assert(std::numeric_limits<FloatType>::is_iec559, 17137 "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); 17138 17139 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit) 17140 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1); 17141 constexpr int kMinExp = 1 - kBias; 17142 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) 17143 17144 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type; 17145 17146 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value)); 17147 const std::uint64_t E = bits >> (kPrecision - 1); 17148 const std::uint64_t F = bits & (kHiddenBit - 1); 17149 17150 const bool is_denormal = E == 0; 17151 const diyfp v = is_denormal 17152 ? diyfp(F, kMinExp) 17153 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias); 17154 17155 // Compute the boundaries m- and m+ of the floating-point value 17156 // v = f * 2^e. 17157 // 17158 // Determine v- and v+, the floating-point predecessor and successor if v, 17159 // respectively. 17160 // 17161 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) 17162 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) 17163 // 17164 // v+ = v + 2^e 17165 // 17166 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ 17167 // between m- and m+ round to v, regardless of how the input rounding 17168 // algorithm breaks ties. 17169 // 17170 // ---+-------------+-------------+-------------+-------------+--- (A) 17171 // v- m- v m+ v+ 17172 // 17173 // -----------------+------+------+-------------+-------------+--- (B) 17174 // v- m- v m+ v+ 17175 17176 const bool lower_boundary_is_closer = F == 0 && E > 1; 17177 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); 17178 const diyfp m_minus = lower_boundary_is_closer 17179 ? diyfp(4 * v.f - 1, v.e - 2) // (B) 17180 : diyfp(2 * v.f - 1, v.e - 1); // (A) 17181 17182 // Determine the normalized w+ = m+. 17183 const diyfp w_plus = diyfp::normalize(m_plus); 17184 17185 // Determine w- = m- such that e_(w-) = e_(w+). 17186 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); 17187 17188 return {diyfp::normalize(v), w_minus, w_plus}; 17189 } 17190 17191 // Given normalized diyfp w, Grisu needs to find a (normalized) cached 17192 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies 17193 // within a certain range [alpha, gamma] (Definition 3.2 from [1]) 17194 // 17195 // alpha <= e = e_c + e_w + q <= gamma 17196 // 17197 // or 17198 // 17199 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q 17200 // <= f_c * f_w * 2^gamma 17201 // 17202 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies 17203 // 17204 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma 17205 // 17206 // or 17207 // 17208 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) 17209 // 17210 // The choice of (alpha,gamma) determines the size of the table and the form of 17211 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well 17212 // in practice: 17213 // 17214 // The idea is to cut the number c * w = f * 2^e into two parts, which can be 17215 // processed independently: An integral part p1, and a fractional part p2: 17216 // 17217 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e 17218 // = (f div 2^-e) + (f mod 2^-e) * 2^e 17219 // = p1 + p2 * 2^e 17220 // 17221 // The conversion of p1 into decimal form requires a series of divisions and 17222 // modulos by (a power of) 10. These operations are faster for 32-bit than for 17223 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be 17224 // achieved by choosing 17225 // 17226 // -e >= 32 or e <= -32 := gamma 17227 // 17228 // In order to convert the fractional part 17229 // 17230 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... 17231 // 17232 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits 17233 // d[-i] are extracted in order: 17234 // 17235 // (10 * p2) div 2^-e = d[-1] 17236 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ... 17237 // 17238 // The multiplication by 10 must not overflow. It is sufficient to choose 17239 // 17240 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. 17241 // 17242 // Since p2 = f mod 2^-e < 2^-e, 17243 // 17244 // -e <= 60 or e >= -60 := alpha 17245 17246 constexpr int kAlpha = -60; 17247 constexpr int kGamma = -32; 17248 17249 struct cached_power // c = f * 2^e ~= 10^k 17250 { 17251 std::uint64_t f; 17252 int e; 17253 int k; 17254 }; 17255 17256 /*! 17257 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached 17258 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c 17259 satisfies (Definition 3.2 from [1]) 17260 17261 alpha <= e_c + e + q <= gamma. 17262 */ 17263 inline cached_power get_cached_power_for_binary_exponent(int e) 17264 { 17265 // Now 17266 // 17267 // alpha <= e_c + e + q <= gamma (1) 17268 // ==> f_c * 2^alpha <= c * 2^e * 2^q 17269 // 17270 // and since the c's are normalized, 2^(q-1) <= f_c, 17271 // 17272 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) 17273 // ==> 2^(alpha - e - 1) <= c 17274 // 17275 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as 17276 // 17277 // k = ceil( log_10( 2^(alpha - e - 1) ) ) 17278 // = ceil( (alpha - e - 1) * log_10(2) ) 17279 // 17280 // From the paper: 17281 // "In theory the result of the procedure could be wrong since c is rounded, 17282 // and the computation itself is approximated [...]. In practice, however, 17283 // this simple function is sufficient." 17284 // 17285 // For IEEE double precision floating-point numbers converted into 17286 // normalized diyfp's w = f * 2^e, with q = 64, 17287 // 17288 // e >= -1022 (min IEEE exponent) 17289 // -52 (p - 1) 17290 // -52 (p - 1, possibly normalize denormal IEEE numbers) 17291 // -11 (normalize the diyfp) 17292 // = -1137 17293 // 17294 // and 17295 // 17296 // e <= +1023 (max IEEE exponent) 17297 // -52 (p - 1) 17298 // -11 (normalize the diyfp) 17299 // = 960 17300 // 17301 // This binary exponent range [-1137,960] results in a decimal exponent 17302 // range [-307,324]. One does not need to store a cached power for each 17303 // k in this range. For each such k it suffices to find a cached power 17304 // such that the exponent of the product lies in [alpha,gamma]. 17305 // This implies that the difference of the decimal exponents of adjacent 17306 // table entries must be less than or equal to 17307 // 17308 // floor( (gamma - alpha) * log_10(2) ) = 8. 17309 // 17310 // (A smaller distance gamma-alpha would require a larger table.) 17311 17312 // NB: 17313 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. 17314 17315 constexpr int kCachedPowersMinDecExp = -300; 17316 constexpr int kCachedPowersDecStep = 8; 17317 17318 static constexpr std::array<cached_power, 79> kCachedPowers = 17319 { 17320 { 17321 { 0xAB70FE17C79AC6CA, -1060, -300 }, 17322 { 0xFF77B1FCBEBCDC4F, -1034, -292 }, 17323 { 0xBE5691EF416BD60C, -1007, -284 }, 17324 { 0x8DD01FAD907FFC3C, -980, -276 }, 17325 { 0xD3515C2831559A83, -954, -268 }, 17326 { 0x9D71AC8FADA6C9B5, -927, -260 }, 17327 { 0xEA9C227723EE8BCB, -901, -252 }, 17328 { 0xAECC49914078536D, -874, -244 }, 17329 { 0x823C12795DB6CE57, -847, -236 }, 17330 { 0xC21094364DFB5637, -821, -228 }, 17331 { 0x9096EA6F3848984F, -794, -220 }, 17332 { 0xD77485CB25823AC7, -768, -212 }, 17333 { 0xA086CFCD97BF97F4, -741, -204 }, 17334 { 0xEF340A98172AACE5, -715, -196 }, 17335 { 0xB23867FB2A35B28E, -688, -188 }, 17336 { 0x84C8D4DFD2C63F3B, -661, -180 }, 17337 { 0xC5DD44271AD3CDBA, -635, -172 }, 17338 { 0x936B9FCEBB25C996, -608, -164 }, 17339 { 0xDBAC6C247D62A584, -582, -156 }, 17340 { 0xA3AB66580D5FDAF6, -555, -148 }, 17341 { 0xF3E2F893DEC3F126, -529, -140 }, 17342 { 0xB5B5ADA8AAFF80B8, -502, -132 }, 17343 { 0x87625F056C7C4A8B, -475, -124 }, 17344 { 0xC9BCFF6034C13053, -449, -116 }, 17345 { 0x964E858C91BA2655, -422, -108 }, 17346 { 0xDFF9772470297EBD, -396, -100 }, 17347 { 0xA6DFBD9FB8E5B88F, -369, -92 }, 17348 { 0xF8A95FCF88747D94, -343, -84 }, 17349 { 0xB94470938FA89BCF, -316, -76 }, 17350 { 0x8A08F0F8BF0F156B, -289, -68 }, 17351 { 0xCDB02555653131B6, -263, -60 }, 17352 { 0x993FE2C6D07B7FAC, -236, -52 }, 17353 { 0xE45C10C42A2B3B06, -210, -44 }, 17354 { 0xAA242499697392D3, -183, -36 }, 17355 { 0xFD87B5F28300CA0E, -157, -28 }, 17356 { 0xBCE5086492111AEB, -130, -20 }, 17357 { 0x8CBCCC096F5088CC, -103, -12 }, 17358 { 0xD1B71758E219652C, -77, -4 }, 17359 { 0x9C40000000000000, -50, 4 }, 17360 { 0xE8D4A51000000000, -24, 12 }, 17361 { 0xAD78EBC5AC620000, 3, 20 }, 17362 { 0x813F3978F8940984, 30, 28 }, 17363 { 0xC097CE7BC90715B3, 56, 36 }, 17364 { 0x8F7E32CE7BEA5C70, 83, 44 }, 17365 { 0xD5D238A4ABE98068, 109, 52 }, 17366 { 0x9F4F2726179A2245, 136, 60 }, 17367 { 0xED63A231D4C4FB27, 162, 68 }, 17368 { 0xB0DE65388CC8ADA8, 189, 76 }, 17369 { 0x83C7088E1AAB65DB, 216, 84 }, 17370 { 0xC45D1DF942711D9A, 242, 92 }, 17371 { 0x924D692CA61BE758, 269, 100 }, 17372 { 0xDA01EE641A708DEA, 295, 108 }, 17373 { 0xA26DA3999AEF774A, 322, 116 }, 17374 { 0xF209787BB47D6B85, 348, 124 }, 17375 { 0xB454E4A179DD1877, 375, 132 }, 17376 { 0x865B86925B9BC5C2, 402, 140 }, 17377 { 0xC83553C5C8965D3D, 428, 148 }, 17378 { 0x952AB45CFA97A0B3, 455, 156 }, 17379 { 0xDE469FBD99A05FE3, 481, 164 }, 17380 { 0xA59BC234DB398C25, 508, 172 }, 17381 { 0xF6C69A72A3989F5C, 534, 180 }, 17382 { 0xB7DCBF5354E9BECE, 561, 188 }, 17383 { 0x88FCF317F22241E2, 588, 196 }, 17384 { 0xCC20CE9BD35C78A5, 614, 204 }, 17385 { 0x98165AF37B2153DF, 641, 212 }, 17386 { 0xE2A0B5DC971F303A, 667, 220 }, 17387 { 0xA8D9D1535CE3B396, 694, 228 }, 17388 { 0xFB9B7CD9A4A7443C, 720, 236 }, 17389 { 0xBB764C4CA7A44410, 747, 244 }, 17390 { 0x8BAB8EEFB6409C1A, 774, 252 }, 17391 { 0xD01FEF10A657842C, 800, 260 }, 17392 { 0x9B10A4E5E9913129, 827, 268 }, 17393 { 0xE7109BFBA19C0C9D, 853, 276 }, 17394 { 0xAC2820D9623BF429, 880, 284 }, 17395 { 0x80444B5E7AA7CF85, 907, 292 }, 17396 { 0xBF21E44003ACDD2D, 933, 300 }, 17397 { 0x8E679C2F5E44FF8F, 960, 308 }, 17398 { 0xD433179D9C8CB841, 986, 316 }, 17399 { 0x9E19DB92B4E31BA9, 1013, 324 }, 17400 } 17401 }; 17402 17403 // This computation gives exactly the same results for k as 17404 // k = ceil((kAlpha - e - 1) * 0.30102999566398114) 17405 // for |e| <= 1500, but doesn't require floating-point operations. 17406 // NB: log_10(2) ~= 78913 / 2^18 17407 JSON_ASSERT(e >= -1500); 17408 JSON_ASSERT(e <= 1500); 17409 const int f = kAlpha - e - 1; 17410 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0); 17411 17412 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; 17413 JSON_ASSERT(index >= 0); 17414 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size()); 17415 17416 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)]; 17417 JSON_ASSERT(kAlpha <= cached.e + e + 64); 17418 JSON_ASSERT(kGamma >= cached.e + e + 64); 17419 17420 return cached; 17421 } 17422 17423 /*! 17424 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. 17425 For n == 0, returns 1 and sets pow10 := 1. 17426 */ 17427 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) 17428 { 17429 // LCOV_EXCL_START 17430 if (n >= 1000000000) 17431 { 17432 pow10 = 1000000000; 17433 return 10; 17434 } 17435 // LCOV_EXCL_STOP 17436 if (n >= 100000000) 17437 { 17438 pow10 = 100000000; 17439 return 9; 17440 } 17441 if (n >= 10000000) 17442 { 17443 pow10 = 10000000; 17444 return 8; 17445 } 17446 if (n >= 1000000) 17447 { 17448 pow10 = 1000000; 17449 return 7; 17450 } 17451 if (n >= 100000) 17452 { 17453 pow10 = 100000; 17454 return 6; 17455 } 17456 if (n >= 10000) 17457 { 17458 pow10 = 10000; 17459 return 5; 17460 } 17461 if (n >= 1000) 17462 { 17463 pow10 = 1000; 17464 return 4; 17465 } 17466 if (n >= 100) 17467 { 17468 pow10 = 100; 17469 return 3; 17470 } 17471 if (n >= 10) 17472 { 17473 pow10 = 10; 17474 return 2; 17475 } 17476 17477 pow10 = 1; 17478 return 1; 17479 } 17480 17481 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, 17482 std::uint64_t rest, std::uint64_t ten_k) 17483 { 17484 JSON_ASSERT(len >= 1); 17485 JSON_ASSERT(dist <= delta); 17486 JSON_ASSERT(rest <= delta); 17487 JSON_ASSERT(ten_k > 0); 17488 17489 // <--------------------------- delta ----> 17490 // <---- dist ---------> 17491 // --------------[------------------+-------------------]-------------- 17492 // M- w M+ 17493 // 17494 // ten_k 17495 // <------> 17496 // <---- rest ----> 17497 // --------------[------------------+----+--------------]-------------- 17498 // w V 17499 // = buf * 10^k 17500 // 17501 // ten_k represents a unit-in-the-last-place in the decimal representation 17502 // stored in buf. 17503 // Decrement buf by ten_k while this takes buf closer to w. 17504 17505 // The tests are written in this order to avoid overflow in unsigned 17506 // integer arithmetic. 17507 17508 while (rest < dist 17509 && delta - rest >= ten_k 17510 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) 17511 { 17512 JSON_ASSERT(buf[len - 1] != '0'); 17513 buf[len - 1]--; 17514 rest += ten_k; 17515 } 17516 } 17517 17518 /*! 17519 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. 17520 M- and M+ must be normalized and share the same exponent -60 <= e <= -32. 17521 */ 17522 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, 17523 diyfp M_minus, diyfp w, diyfp M_plus) 17524 { 17525 static_assert(kAlpha >= -60, "internal error"); 17526 static_assert(kGamma <= -32, "internal error"); 17527 17528 // Generates the digits (and the exponent) of a decimal floating-point 17529 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's 17530 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. 17531 // 17532 // <--------------------------- delta ----> 17533 // <---- dist ---------> 17534 // --------------[------------------+-------------------]-------------- 17535 // M- w M+ 17536 // 17537 // Grisu2 generates the digits of M+ from left to right and stops as soon as 17538 // V is in [M-,M+]. 17539 17540 JSON_ASSERT(M_plus.e >= kAlpha); 17541 JSON_ASSERT(M_plus.e <= kGamma); 17542 17543 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) 17544 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) 17545 17546 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): 17547 // 17548 // M+ = f * 2^e 17549 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e 17550 // = ((p1 ) * 2^-e + (p2 )) * 2^e 17551 // = p1 + p2 * 2^e 17552 17553 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); 17554 17555 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.) 17556 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e 17557 17558 // 1) 17559 // 17560 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] 17561 17562 JSON_ASSERT(p1 > 0); 17563 17564 std::uint32_t pow10{}; 17565 const int k = find_largest_pow10(p1, pow10); 17566 17567 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) 17568 // 17569 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) 17570 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) 17571 // 17572 // M+ = p1 + p2 * 2^e 17573 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e 17574 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e 17575 // = d[k-1] * 10^(k-1) + ( rest) * 2^e 17576 // 17577 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) 17578 // 17579 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] 17580 // 17581 // but stop as soon as 17582 // 17583 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e 17584 17585 int n = k; 17586 while (n > 0) 17587 { 17588 // Invariants: 17589 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) 17590 // pow10 = 10^(n-1) <= p1 < 10^n 17591 // 17592 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) 17593 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) 17594 // 17595 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e 17596 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) 17597 // 17598 JSON_ASSERT(d <= 9); 17599 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d 17600 // 17601 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) 17602 // 17603 p1 = r; 17604 n--; 17605 // 17606 // M+ = buffer * 10^n + (p1 + p2 * 2^e) 17607 // pow10 = 10^n 17608 // 17609 17610 // Now check if enough digits have been generated. 17611 // Compute 17612 // 17613 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e 17614 // 17615 // Note: 17616 // Since rest and delta share the same exponent e, it suffices to 17617 // compare the significands. 17618 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; 17619 if (rest <= delta) 17620 { 17621 // V = buffer * 10^n, with M- <= V <= M+. 17622 17623 decimal_exponent += n; 17624 17625 // We may now just stop. But instead look if the buffer could be 17626 // decremented to bring V closer to w. 17627 // 17628 // pow10 = 10^n is now 1 ulp in the decimal representation V. 17629 // The rounding procedure works with diyfp's with an implicit 17630 // exponent of e. 17631 // 17632 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e 17633 // 17634 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; 17635 grisu2_round(buffer, length, dist, delta, rest, ten_n); 17636 17637 return; 17638 } 17639 17640 pow10 /= 10; 17641 // 17642 // pow10 = 10^(n-1) <= p1 < 10^n 17643 // Invariants restored. 17644 } 17645 17646 // 2) 17647 // 17648 // The digits of the integral part have been generated: 17649 // 17650 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e 17651 // = buffer + p2 * 2^e 17652 // 17653 // Now generate the digits of the fractional part p2 * 2^e. 17654 // 17655 // Note: 17656 // No decimal point is generated: the exponent is adjusted instead. 17657 // 17658 // p2 actually represents the fraction 17659 // 17660 // p2 * 2^e 17661 // = p2 / 2^-e 17662 // = d[-1] / 10^1 + d[-2] / 10^2 + ... 17663 // 17664 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) 17665 // 17666 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m 17667 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) 17668 // 17669 // using 17670 // 17671 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) 17672 // = ( d) * 2^-e + ( r) 17673 // 17674 // or 17675 // 10^m * p2 * 2^e = d + r * 2^e 17676 // 17677 // i.e. 17678 // 17679 // M+ = buffer + p2 * 2^e 17680 // = buffer + 10^-m * (d + r * 2^e) 17681 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e 17682 // 17683 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e 17684 17685 JSON_ASSERT(p2 > delta); 17686 17687 int m = 0; 17688 for (;;) 17689 { 17690 // Invariant: 17691 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e 17692 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e 17693 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e 17694 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e 17695 // 17696 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10); 17697 p2 *= 10; 17698 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e 17699 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e 17700 // 17701 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e 17702 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) 17703 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e 17704 // 17705 JSON_ASSERT(d <= 9); 17706 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d 17707 // 17708 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e 17709 // 17710 p2 = r; 17711 m++; 17712 // 17713 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e 17714 // Invariant restored. 17715 17716 // Check if enough digits have been generated. 17717 // 17718 // 10^-m * p2 * 2^e <= delta * 2^e 17719 // p2 * 2^e <= 10^m * delta * 2^e 17720 // p2 <= 10^m * delta 17721 delta *= 10; 17722 dist *= 10; 17723 if (p2 <= delta) 17724 { 17725 break; 17726 } 17727 } 17728 17729 // V = buffer * 10^-m, with M- <= V <= M+. 17730 17731 decimal_exponent -= m; 17732 17733 // 1 ulp in the decimal representation is now 10^-m. 17734 // Since delta and dist are now scaled by 10^m, we need to do the 17735 // same with ulp in order to keep the units in sync. 17736 // 17737 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e 17738 // 17739 const std::uint64_t ten_m = one.f; 17740 grisu2_round(buffer, length, dist, delta, p2, ten_m); 17741 17742 // By construction this algorithm generates the shortest possible decimal 17743 // number (Loitsch, Theorem 6.2) which rounds back to w. 17744 // For an input number of precision p, at least 17745 // 17746 // N = 1 + ceil(p * log_10(2)) 17747 // 17748 // decimal digits are sufficient to identify all binary floating-point 17749 // numbers (Matula, "In-and-Out conversions"). 17750 // This implies that the algorithm does not produce more than N decimal 17751 // digits. 17752 // 17753 // N = 17 for p = 53 (IEEE double precision) 17754 // N = 9 for p = 24 (IEEE single precision) 17755 } 17756 17757 /*! 17758 v = buf * 10^decimal_exponent 17759 len is the length of the buffer (number of decimal digits) 17760 The buffer must be large enough, i.e. >= max_digits10. 17761 */ 17762 JSON_HEDLEY_NON_NULL(1) 17763 inline void grisu2(char* buf, int& len, int& decimal_exponent, 17764 diyfp m_minus, diyfp v, diyfp m_plus) 17765 { 17766 JSON_ASSERT(m_plus.e == m_minus.e); 17767 JSON_ASSERT(m_plus.e == v.e); 17768 17769 // --------(-----------------------+-----------------------)-------- (A) 17770 // m- v m+ 17771 // 17772 // --------------------(-----------+-----------------------)-------- (B) 17773 // m- v m+ 17774 // 17775 // First scale v (and m- and m+) such that the exponent is in the range 17776 // [alpha, gamma]. 17777 17778 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); 17779 17780 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k 17781 17782 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] 17783 const diyfp w = diyfp::mul(v, c_minus_k); 17784 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); 17785 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); 17786 17787 // ----(---+---)---------------(---+---)---------------(---+---)---- 17788 // w- w w+ 17789 // = c*m- = c*v = c*m+ 17790 // 17791 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and 17792 // w+ are now off by a small amount. 17793 // In fact: 17794 // 17795 // w - v * 10^k < 1 ulp 17796 // 17797 // To account for this inaccuracy, add resp. subtract 1 ulp. 17798 // 17799 // --------+---[---------------(---+---)---------------]---+-------- 17800 // w- M- w M+ w+ 17801 // 17802 // Now any number in [M-, M+] (bounds included) will round to w when input, 17803 // regardless of how the input rounding algorithm breaks ties. 17804 // 17805 // And digit_gen generates the shortest possible such number in [M-, M+]. 17806 // Note that this does not mean that Grisu2 always generates the shortest 17807 // possible number in the interval (m-, m+). 17808 const diyfp M_minus(w_minus.f + 1, w_minus.e); 17809 const diyfp M_plus (w_plus.f - 1, w_plus.e ); 17810 17811 decimal_exponent = -cached.k; // = -(-k) = k 17812 17813 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); 17814 } 17815 17816 /*! 17817 v = buf * 10^decimal_exponent 17818 len is the length of the buffer (number of decimal digits) 17819 The buffer must be large enough, i.e. >= max_digits10. 17820 */ 17821 template<typename FloatType> 17822 JSON_HEDLEY_NON_NULL(1) 17823 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) 17824 { 17825 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3, 17826 "internal error: not enough precision"); 17827 17828 JSON_ASSERT(std::isfinite(value)); 17829 JSON_ASSERT(value > 0); 17830 17831 // If the neighbors (and boundaries) of 'value' are always computed for double-precision 17832 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting 17833 // decimal representations are not exactly "short". 17834 // 17835 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) 17836 // says "value is converted to a string as if by std::sprintf in the default ("C") locale" 17837 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars' 17838 // does. 17839 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the 17840 // representation using the corresponding std::from_chars function recovers value exactly". That 17841 // indicates that single precision floating-point numbers should be recovered using 17842 // 'std::strtof'. 17843 // 17844 // NB: If the neighbors are computed for single-precision numbers, there is a single float 17845 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision 17846 // value is off by 1 ulp. 17847 #if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) 17848 const boundaries w = compute_boundaries(static_cast<double>(value)); 17849 #else 17850 const boundaries w = compute_boundaries(value); 17851 #endif 17852 17853 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); 17854 } 17855 17856 /*! 17857 @brief appends a decimal representation of e to buf 17858 @return a pointer to the element following the exponent. 17859 @pre -1000 < e < 1000 17860 */ 17861 JSON_HEDLEY_NON_NULL(1) 17862 JSON_HEDLEY_RETURNS_NON_NULL 17863 inline char* append_exponent(char* buf, int e) 17864 { 17865 JSON_ASSERT(e > -1000); 17866 JSON_ASSERT(e < 1000); 17867 17868 if (e < 0) 17869 { 17870 e = -e; 17871 *buf++ = '-'; 17872 } 17873 else 17874 { 17875 *buf++ = '+'; 17876 } 17877 17878 auto k = static_cast<std::uint32_t>(e); 17879 if (k < 10) 17880 { 17881 // Always print at least two digits in the exponent. 17882 // This is for compatibility with printf("%g"). 17883 *buf++ = '0'; 17884 *buf++ = static_cast<char>('0' + k); 17885 } 17886 else if (k < 100) 17887 { 17888 *buf++ = static_cast<char>('0' + k / 10); 17889 k %= 10; 17890 *buf++ = static_cast<char>('0' + k); 17891 } 17892 else 17893 { 17894 *buf++ = static_cast<char>('0' + k / 100); 17895 k %= 100; 17896 *buf++ = static_cast<char>('0' + k / 10); 17897 k %= 10; 17898 *buf++ = static_cast<char>('0' + k); 17899 } 17900 17901 return buf; 17902 } 17903 17904 /*! 17905 @brief prettify v = buf * 10^decimal_exponent 17906 17907 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point 17908 notation. Otherwise it will be printed in exponential notation. 17909 17910 @pre min_exp < 0 17911 @pre max_exp > 0 17912 */ 17913 JSON_HEDLEY_NON_NULL(1) 17914 JSON_HEDLEY_RETURNS_NON_NULL 17915 inline char* format_buffer(char* buf, int len, int decimal_exponent, 17916 int min_exp, int max_exp) 17917 { 17918 JSON_ASSERT(min_exp < 0); 17919 JSON_ASSERT(max_exp > 0); 17920 17921 const int k = len; 17922 const int n = len + decimal_exponent; 17923 17924 // v = buf * 10^(n-k) 17925 // k is the length of the buffer (number of decimal digits) 17926 // n is the position of the decimal point relative to the start of the buffer. 17927 17928 if (k <= n && n <= max_exp) 17929 { 17930 // digits[000] 17931 // len <= max_exp + 2 17932 17933 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k)); 17934 // Make it look like a floating-point number (#362, #378) 17935 buf[n + 0] = '.'; 17936 buf[n + 1] = '0'; 17937 return buf + (static_cast<size_t>(n) + 2); 17938 } 17939 17940 if (0 < n && n <= max_exp) 17941 { 17942 // dig.its 17943 // len <= max_digits10 + 1 17944 17945 JSON_ASSERT(k > n); 17946 17947 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n)); 17948 buf[n] = '.'; 17949 return buf + (static_cast<size_t>(k) + 1U); 17950 } 17951 17952 if (min_exp < n && n <= 0) 17953 { 17954 // 0.[000]digits 17955 // len <= 2 + (-min_exp - 1) + max_digits10 17956 17957 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k)); 17958 buf[0] = '0'; 17959 buf[1] = '.'; 17960 std::memset(buf + 2, '0', static_cast<size_t>(-n)); 17961 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k)); 17962 } 17963 17964 if (k == 1) 17965 { 17966 // dE+123 17967 // len <= 1 + 5 17968 17969 buf += 1; 17970 } 17971 else 17972 { 17973 // d.igitsE+123 17974 // len <= max_digits10 + 1 + 5 17975 17976 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1); 17977 buf[1] = '.'; 17978 buf += 1 + static_cast<size_t>(k); 17979 } 17980 17981 *buf++ = 'e'; 17982 return append_exponent(buf, n - 1); 17983 } 17984 17985 } // namespace dtoa_impl 17986 17987 /*! 17988 @brief generates a decimal representation of the floating-point number value in [first, last). 17989 17990 The format of the resulting decimal representation is similar to printf's %g 17991 format. Returns an iterator pointing past-the-end of the decimal representation. 17992 17993 @note The input number must be finite, i.e. NaN's and Inf's are not supported. 17994 @note The buffer must be large enough. 17995 @note The result is NOT null-terminated. 17996 */ 17997 template<typename FloatType> 17998 JSON_HEDLEY_NON_NULL(1, 2) 17999 JSON_HEDLEY_RETURNS_NON_NULL 18000 char* to_chars(char* first, const char* last, FloatType value) 18001 { 18002 static_cast<void>(last); // maybe unused - fix warning 18003 JSON_ASSERT(std::isfinite(value)); 18004 18005 // Use signbit(value) instead of (value < 0) since signbit works for -0. 18006 if (std::signbit(value)) 18007 { 18008 value = -value; 18009 *first++ = '-'; 18010 } 18011 18012 #ifdef __GNUC__ 18013 #pragma GCC diagnostic push 18014 #pragma GCC diagnostic ignored "-Wfloat-equal" 18015 #endif 18016 if (value == 0) // +-0 18017 { 18018 *first++ = '0'; 18019 // Make it look like a floating-point number (#362, #378) 18020 *first++ = '.'; 18021 *first++ = '0'; 18022 return first; 18023 } 18024 #ifdef __GNUC__ 18025 #pragma GCC diagnostic pop 18026 #endif 18027 18028 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10); 18029 18030 // Compute v = buffer * 10^decimal_exponent. 18031 // The decimal digits are stored in the buffer, which needs to be interpreted 18032 // as an unsigned decimal integer. 18033 // len is the length of the buffer, i.e. the number of decimal digits. 18034 int len = 0; 18035 int decimal_exponent = 0; 18036 dtoa_impl::grisu2(first, len, decimal_exponent, value); 18037 18038 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10); 18039 18040 // Format the buffer like printf("%.*g", prec, value) 18041 constexpr int kMinExp = -4; 18042 // Use digits10 here to increase compatibility with version 2. 18043 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10; 18044 18045 JSON_ASSERT(last - first >= kMaxExp + 2); 18046 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10); 18047 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6); 18048 18049 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); 18050 } 18051 18052 } // namespace detail 18053 NLOHMANN_JSON_NAMESPACE_END 18054 18055 // #include <nlohmann/detail/exceptions.hpp> 18056 18057 // #include <nlohmann/detail/macro_scope.hpp> 18058 18059 // #include <nlohmann/detail/meta/cpp_future.hpp> 18060 18061 // #include <nlohmann/detail/output/binary_writer.hpp> 18062 18063 // #include <nlohmann/detail/output/output_adapters.hpp> 18064 18065 // #include <nlohmann/detail/string_concat.hpp> 18066 18067 // #include <nlohmann/detail/value_t.hpp> 18068 18069 18070 NLOHMANN_JSON_NAMESPACE_BEGIN 18071 namespace detail 18072 { 18073 18074 /////////////////// 18075 // serialization // 18076 /////////////////// 18077 18078 /// how to treat decoding errors 18079 enum class error_handler_t 18080 { 18081 strict, ///< throw a type_error exception in case of invalid UTF-8 18082 replace, ///< replace invalid UTF-8 sequences with U+FFFD 18083 ignore ///< ignore invalid UTF-8 sequences 18084 }; 18085 18086 template<typename BasicJsonType> 18087 class serializer 18088 { 18089 using string_t = typename BasicJsonType::string_t; 18090 using number_float_t = typename BasicJsonType::number_float_t; 18091 using number_integer_t = typename BasicJsonType::number_integer_t; 18092 using number_unsigned_t = typename BasicJsonType::number_unsigned_t; 18093 using binary_char_t = typename BasicJsonType::binary_t::value_type; 18094 static constexpr std::uint8_t UTF8_ACCEPT = 0; 18095 static constexpr std::uint8_t UTF8_REJECT = 1; 18096 18097 public: 18098 /*! 18099 @param[in] s output stream to serialize to 18100 @param[in] ichar indentation character to use 18101 @param[in] error_handler_ how to react on decoding errors 18102 */ 18103 serializer(output_adapter_t<char> s, const char ichar, 18104 error_handler_t error_handler_ = error_handler_t::strict) 18105 : o(std::move(s)) 18106 , loc(std::localeconv()) 18107 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep))) 18108 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point))) 18109 , indent_char(ichar) 18110 , indent_string(512, indent_char) 18111 , error_handler(error_handler_) 18112 {} 18113 18114 // delete because of pointer members 18115 serializer(const serializer&) = delete; 18116 serializer& operator=(const serializer&) = delete; 18117 serializer(serializer&&) = delete; 18118 serializer& operator=(serializer&&) = delete; 18119 ~serializer() = default; 18120 18121 /*! 18122 @brief internal implementation of the serialization function 18123 18124 This function is called by the public member function dump and organizes 18125 the serialization internally. The indentation level is propagated as 18126 additional parameter. In case of arrays and objects, the function is 18127 called recursively. 18128 18129 - strings and object keys are escaped using `escape_string()` 18130 - integer numbers are converted implicitly via `operator<<` 18131 - floating-point numbers are converted to a string using `"%g"` format 18132 - binary values are serialized as objects containing the subtype and the 18133 byte array 18134 18135 @param[in] val value to serialize 18136 @param[in] pretty_print whether the output shall be pretty-printed 18137 @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters 18138 in the output are escaped with `\uXXXX` sequences, and the result consists 18139 of ASCII characters only. 18140 @param[in] indent_step the indent level 18141 @param[in] current_indent the current indent level (only used internally) 18142 */ 18143 void dump(const BasicJsonType& val, 18144 const bool pretty_print, 18145 const bool ensure_ascii, 18146 const unsigned int indent_step, 18147 const unsigned int current_indent = 0) 18148 { 18149 switch (val.m_data.m_type) 18150 { 18151 case value_t::object: 18152 { 18153 if (val.m_data.m_value.object->empty()) 18154 { 18155 o->write_characters("{}", 2); 18156 return; 18157 } 18158 18159 if (pretty_print) 18160 { 18161 o->write_characters("{\n", 2); 18162 18163 // variable to hold indentation for recursive calls 18164 const auto new_indent = current_indent + indent_step; 18165 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 18166 { 18167 indent_string.resize(indent_string.size() * 2, ' '); 18168 } 18169 18170 // first n-1 elements 18171 auto i = val.m_data.m_value.object->cbegin(); 18172 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) 18173 { 18174 o->write_characters(indent_string.c_str(), new_indent); 18175 o->write_character('\"'); 18176 dump_escaped(i->first, ensure_ascii); 18177 o->write_characters("\": ", 3); 18178 dump(i->second, true, ensure_ascii, indent_step, new_indent); 18179 o->write_characters(",\n", 2); 18180 } 18181 18182 // last element 18183 JSON_ASSERT(i != val.m_data.m_value.object->cend()); 18184 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); 18185 o->write_characters(indent_string.c_str(), new_indent); 18186 o->write_character('\"'); 18187 dump_escaped(i->first, ensure_ascii); 18188 o->write_characters("\": ", 3); 18189 dump(i->second, true, ensure_ascii, indent_step, new_indent); 18190 18191 o->write_character('\n'); 18192 o->write_characters(indent_string.c_str(), current_indent); 18193 o->write_character('}'); 18194 } 18195 else 18196 { 18197 o->write_character('{'); 18198 18199 // first n-1 elements 18200 auto i = val.m_data.m_value.object->cbegin(); 18201 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) 18202 { 18203 o->write_character('\"'); 18204 dump_escaped(i->first, ensure_ascii); 18205 o->write_characters("\":", 2); 18206 dump(i->second, false, ensure_ascii, indent_step, current_indent); 18207 o->write_character(','); 18208 } 18209 18210 // last element 18211 JSON_ASSERT(i != val.m_data.m_value.object->cend()); 18212 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); 18213 o->write_character('\"'); 18214 dump_escaped(i->first, ensure_ascii); 18215 o->write_characters("\":", 2); 18216 dump(i->second, false, ensure_ascii, indent_step, current_indent); 18217 18218 o->write_character('}'); 18219 } 18220 18221 return; 18222 } 18223 18224 case value_t::array: 18225 { 18226 if (val.m_data.m_value.array->empty()) 18227 { 18228 o->write_characters("[]", 2); 18229 return; 18230 } 18231 18232 if (pretty_print) 18233 { 18234 o->write_characters("[\n", 2); 18235 18236 // variable to hold indentation for recursive calls 18237 const auto new_indent = current_indent + indent_step; 18238 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 18239 { 18240 indent_string.resize(indent_string.size() * 2, ' '); 18241 } 18242 18243 // first n-1 elements 18244 for (auto i = val.m_data.m_value.array->cbegin(); 18245 i != val.m_data.m_value.array->cend() - 1; ++i) 18246 { 18247 o->write_characters(indent_string.c_str(), new_indent); 18248 dump(*i, true, ensure_ascii, indent_step, new_indent); 18249 o->write_characters(",\n", 2); 18250 } 18251 18252 // last element 18253 JSON_ASSERT(!val.m_data.m_value.array->empty()); 18254 o->write_characters(indent_string.c_str(), new_indent); 18255 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); 18256 18257 o->write_character('\n'); 18258 o->write_characters(indent_string.c_str(), current_indent); 18259 o->write_character(']'); 18260 } 18261 else 18262 { 18263 o->write_character('['); 18264 18265 // first n-1 elements 18266 for (auto i = val.m_data.m_value.array->cbegin(); 18267 i != val.m_data.m_value.array->cend() - 1; ++i) 18268 { 18269 dump(*i, false, ensure_ascii, indent_step, current_indent); 18270 o->write_character(','); 18271 } 18272 18273 // last element 18274 JSON_ASSERT(!val.m_data.m_value.array->empty()); 18275 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); 18276 18277 o->write_character(']'); 18278 } 18279 18280 return; 18281 } 18282 18283 case value_t::string: 18284 { 18285 o->write_character('\"'); 18286 dump_escaped(*val.m_data.m_value.string, ensure_ascii); 18287 o->write_character('\"'); 18288 return; 18289 } 18290 18291 case value_t::binary: 18292 { 18293 if (pretty_print) 18294 { 18295 o->write_characters("{\n", 2); 18296 18297 // variable to hold indentation for recursive calls 18298 const auto new_indent = current_indent + indent_step; 18299 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) 18300 { 18301 indent_string.resize(indent_string.size() * 2, ' '); 18302 } 18303 18304 o->write_characters(indent_string.c_str(), new_indent); 18305 18306 o->write_characters("\"bytes\": [", 10); 18307 18308 if (!val.m_data.m_value.binary->empty()) 18309 { 18310 for (auto i = val.m_data.m_value.binary->cbegin(); 18311 i != val.m_data.m_value.binary->cend() - 1; ++i) 18312 { 18313 dump_integer(*i); 18314 o->write_characters(", ", 2); 18315 } 18316 dump_integer(val.m_data.m_value.binary->back()); 18317 } 18318 18319 o->write_characters("],\n", 3); 18320 o->write_characters(indent_string.c_str(), new_indent); 18321 18322 o->write_characters("\"subtype\": ", 11); 18323 if (val.m_data.m_value.binary->has_subtype()) 18324 { 18325 dump_integer(val.m_data.m_value.binary->subtype()); 18326 } 18327 else 18328 { 18329 o->write_characters("null", 4); 18330 } 18331 o->write_character('\n'); 18332 o->write_characters(indent_string.c_str(), current_indent); 18333 o->write_character('}'); 18334 } 18335 else 18336 { 18337 o->write_characters("{\"bytes\":[", 10); 18338 18339 if (!val.m_data.m_value.binary->empty()) 18340 { 18341 for (auto i = val.m_data.m_value.binary->cbegin(); 18342 i != val.m_data.m_value.binary->cend() - 1; ++i) 18343 { 18344 dump_integer(*i); 18345 o->write_character(','); 18346 } 18347 dump_integer(val.m_data.m_value.binary->back()); 18348 } 18349 18350 o->write_characters("],\"subtype\":", 12); 18351 if (val.m_data.m_value.binary->has_subtype()) 18352 { 18353 dump_integer(val.m_data.m_value.binary->subtype()); 18354 o->write_character('}'); 18355 } 18356 else 18357 { 18358 o->write_characters("null}", 5); 18359 } 18360 } 18361 return; 18362 } 18363 18364 case value_t::boolean: 18365 { 18366 if (val.m_data.m_value.boolean) 18367 { 18368 o->write_characters("true", 4); 18369 } 18370 else 18371 { 18372 o->write_characters("false", 5); 18373 } 18374 return; 18375 } 18376 18377 case value_t::number_integer: 18378 { 18379 dump_integer(val.m_data.m_value.number_integer); 18380 return; 18381 } 18382 18383 case value_t::number_unsigned: 18384 { 18385 dump_integer(val.m_data.m_value.number_unsigned); 18386 return; 18387 } 18388 18389 case value_t::number_float: 18390 { 18391 dump_float(val.m_data.m_value.number_float); 18392 return; 18393 } 18394 18395 case value_t::discarded: 18396 { 18397 o->write_characters("<discarded>", 11); 18398 return; 18399 } 18400 18401 case value_t::null: 18402 { 18403 o->write_characters("null", 4); 18404 return; 18405 } 18406 18407 default: // LCOV_EXCL_LINE 18408 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18409 } 18410 } 18411 18412 JSON_PRIVATE_UNLESS_TESTED: 18413 /*! 18414 @brief dump escaped string 18415 18416 Escape a string by replacing certain special characters by a sequence of an 18417 escape character (backslash) and another character and other control 18418 characters by a sequence of "\u" followed by a four-digit hex 18419 representation. The escaped string is written to output stream @a o. 18420 18421 @param[in] s the string to escape 18422 @param[in] ensure_ascii whether to escape non-ASCII characters with 18423 \uXXXX sequences 18424 18425 @complexity Linear in the length of string @a s. 18426 */ 18427 void dump_escaped(const string_t& s, const bool ensure_ascii) 18428 { 18429 std::uint32_t codepoint{}; 18430 std::uint8_t state = UTF8_ACCEPT; 18431 std::size_t bytes = 0; // number of bytes written to string_buffer 18432 18433 // number of bytes written at the point of the last valid byte 18434 std::size_t bytes_after_last_accept = 0; 18435 std::size_t undumped_chars = 0; 18436 18437 for (std::size_t i = 0; i < s.size(); ++i) 18438 { 18439 const auto byte = static_cast<std::uint8_t>(s[i]); 18440 18441 switch (decode(state, codepoint, byte)) 18442 { 18443 case UTF8_ACCEPT: // decode found a new code point 18444 { 18445 switch (codepoint) 18446 { 18447 case 0x08: // backspace 18448 { 18449 string_buffer[bytes++] = '\\'; 18450 string_buffer[bytes++] = 'b'; 18451 break; 18452 } 18453 18454 case 0x09: // horizontal tab 18455 { 18456 string_buffer[bytes++] = '\\'; 18457 string_buffer[bytes++] = 't'; 18458 break; 18459 } 18460 18461 case 0x0A: // newline 18462 { 18463 string_buffer[bytes++] = '\\'; 18464 string_buffer[bytes++] = 'n'; 18465 break; 18466 } 18467 18468 case 0x0C: // formfeed 18469 { 18470 string_buffer[bytes++] = '\\'; 18471 string_buffer[bytes++] = 'f'; 18472 break; 18473 } 18474 18475 case 0x0D: // carriage return 18476 { 18477 string_buffer[bytes++] = '\\'; 18478 string_buffer[bytes++] = 'r'; 18479 break; 18480 } 18481 18482 case 0x22: // quotation mark 18483 { 18484 string_buffer[bytes++] = '\\'; 18485 string_buffer[bytes++] = '\"'; 18486 break; 18487 } 18488 18489 case 0x5C: // reverse solidus 18490 { 18491 string_buffer[bytes++] = '\\'; 18492 string_buffer[bytes++] = '\\'; 18493 break; 18494 } 18495 18496 default: 18497 { 18498 // escape control characters (0x00..0x1F) or, if 18499 // ensure_ascii parameter is used, non-ASCII characters 18500 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) 18501 { 18502 if (codepoint <= 0xFFFF) 18503 { 18504 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18505 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", 18506 static_cast<std::uint16_t>(codepoint))); 18507 bytes += 6; 18508 } 18509 else 18510 { 18511 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18512 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", 18513 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)), 18514 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)))); 18515 bytes += 12; 18516 } 18517 } 18518 else 18519 { 18520 // copy byte to buffer (all previous bytes 18521 // been copied have in default case above) 18522 string_buffer[bytes++] = s[i]; 18523 } 18524 break; 18525 } 18526 } 18527 18528 // write buffer and reset index; there must be 13 bytes 18529 // left, as this is the maximal number of bytes to be 18530 // written ("\uxxxx\uxxxx\0") for one code point 18531 if (string_buffer.size() - bytes < 13) 18532 { 18533 o->write_characters(string_buffer.data(), bytes); 18534 bytes = 0; 18535 } 18536 18537 // remember the byte position of this accept 18538 bytes_after_last_accept = bytes; 18539 undumped_chars = 0; 18540 break; 18541 } 18542 18543 case UTF8_REJECT: // decode found invalid UTF-8 byte 18544 { 18545 switch (error_handler) 18546 { 18547 case error_handler_t::strict: 18548 { 18549 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr)); 18550 } 18551 18552 case error_handler_t::ignore: 18553 case error_handler_t::replace: 18554 { 18555 // in case we saw this character the first time, we 18556 // would like to read it again, because the byte 18557 // may be OK for itself, but just not OK for the 18558 // previous sequence 18559 if (undumped_chars > 0) 18560 { 18561 --i; 18562 } 18563 18564 // reset length buffer to the last accepted index; 18565 // thus removing/ignoring the invalid characters 18566 bytes = bytes_after_last_accept; 18567 18568 if (error_handler == error_handler_t::replace) 18569 { 18570 // add a replacement character 18571 if (ensure_ascii) 18572 { 18573 string_buffer[bytes++] = '\\'; 18574 string_buffer[bytes++] = 'u'; 18575 string_buffer[bytes++] = 'f'; 18576 string_buffer[bytes++] = 'f'; 18577 string_buffer[bytes++] = 'f'; 18578 string_buffer[bytes++] = 'd'; 18579 } 18580 else 18581 { 18582 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF'); 18583 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF'); 18584 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD'); 18585 } 18586 18587 // write buffer and reset index; there must be 13 bytes 18588 // left, as this is the maximal number of bytes to be 18589 // written ("\uxxxx\uxxxx\0") for one code point 18590 if (string_buffer.size() - bytes < 13) 18591 { 18592 o->write_characters(string_buffer.data(), bytes); 18593 bytes = 0; 18594 } 18595 18596 bytes_after_last_accept = bytes; 18597 } 18598 18599 undumped_chars = 0; 18600 18601 // continue processing the string 18602 state = UTF8_ACCEPT; 18603 break; 18604 } 18605 18606 default: // LCOV_EXCL_LINE 18607 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18608 } 18609 break; 18610 } 18611 18612 default: // decode found yet incomplete multi-byte code point 18613 { 18614 if (!ensure_ascii) 18615 { 18616 // code point will not be escaped - copy byte to buffer 18617 string_buffer[bytes++] = s[i]; 18618 } 18619 ++undumped_chars; 18620 break; 18621 } 18622 } 18623 } 18624 18625 // we finished processing the string 18626 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) 18627 { 18628 // write buffer 18629 if (bytes > 0) 18630 { 18631 o->write_characters(string_buffer.data(), bytes); 18632 } 18633 } 18634 else 18635 { 18636 // we finish reading, but do not accept: string was incomplete 18637 switch (error_handler) 18638 { 18639 case error_handler_t::strict: 18640 { 18641 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)); 18642 } 18643 18644 case error_handler_t::ignore: 18645 { 18646 // write all accepted bytes 18647 o->write_characters(string_buffer.data(), bytes_after_last_accept); 18648 break; 18649 } 18650 18651 case error_handler_t::replace: 18652 { 18653 // write all accepted bytes 18654 o->write_characters(string_buffer.data(), bytes_after_last_accept); 18655 // add a replacement character 18656 if (ensure_ascii) 18657 { 18658 o->write_characters("\\ufffd", 6); 18659 } 18660 else 18661 { 18662 o->write_characters("\xEF\xBF\xBD", 3); 18663 } 18664 break; 18665 } 18666 18667 default: // LCOV_EXCL_LINE 18668 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18669 } 18670 } 18671 } 18672 18673 private: 18674 /*! 18675 @brief count digits 18676 18677 Count the number of decimal (base 10) digits for an input unsigned integer. 18678 18679 @param[in] x unsigned integer number to count its digits 18680 @return number of decimal digits 18681 */ 18682 inline unsigned int count_digits(number_unsigned_t x) noexcept 18683 { 18684 unsigned int n_digits = 1; 18685 for (;;) 18686 { 18687 if (x < 10) 18688 { 18689 return n_digits; 18690 } 18691 if (x < 100) 18692 { 18693 return n_digits + 1; 18694 } 18695 if (x < 1000) 18696 { 18697 return n_digits + 2; 18698 } 18699 if (x < 10000) 18700 { 18701 return n_digits + 3; 18702 } 18703 x = x / 10000u; 18704 n_digits += 4; 18705 } 18706 } 18707 18708 /*! 18709 * @brief convert a byte to a uppercase hex representation 18710 * @param[in] byte byte to represent 18711 * @return representation ("00".."FF") 18712 */ 18713 static std::string hex_bytes(std::uint8_t byte) 18714 { 18715 std::string result = "FF"; 18716 constexpr const char* nibble_to_hex = "0123456789ABCDEF"; 18717 result[0] = nibble_to_hex[byte / 16]; 18718 result[1] = nibble_to_hex[byte % 16]; 18719 return result; 18720 } 18721 18722 // templates to avoid warnings about useless casts 18723 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0> 18724 bool is_negative_number(NumberType x) 18725 { 18726 return x < 0; 18727 } 18728 18729 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 > 18730 bool is_negative_number(NumberType /*unused*/) 18731 { 18732 return false; 18733 } 18734 18735 /*! 18736 @brief dump an integer 18737 18738 Dump a given integer to output stream @a o. Works internally with 18739 @a number_buffer. 18740 18741 @param[in] x integer number (signed or unsigned) to dump 18742 @tparam NumberType either @a number_integer_t or @a number_unsigned_t 18743 */ 18744 template < typename NumberType, detail::enable_if_t < 18745 std::is_integral<NumberType>::value || 18746 std::is_same<NumberType, number_unsigned_t>::value || 18747 std::is_same<NumberType, number_integer_t>::value || 18748 std::is_same<NumberType, binary_char_t>::value, 18749 int > = 0 > 18750 void dump_integer(NumberType x) 18751 { 18752 static constexpr std::array<std::array<char, 2>, 100> digits_to_99 18753 { 18754 { 18755 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, 18756 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, 18757 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, 18758 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, 18759 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, 18760 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, 18761 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, 18762 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, 18763 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, 18764 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, 18765 } 18766 }; 18767 18768 // special case for "0" 18769 if (x == 0) 18770 { 18771 o->write_character('0'); 18772 return; 18773 } 18774 18775 // use a pointer to fill the buffer 18776 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18777 18778 number_unsigned_t abs_value; 18779 18780 unsigned int n_chars{}; 18781 18782 if (is_negative_number(x)) 18783 { 18784 *buffer_ptr = '-'; 18785 abs_value = remove_sign(static_cast<number_integer_t>(x)); 18786 18787 // account one more byte for the minus sign 18788 n_chars = 1 + count_digits(abs_value); 18789 } 18790 else 18791 { 18792 abs_value = static_cast<number_unsigned_t>(x); 18793 n_chars = count_digits(abs_value); 18794 } 18795 18796 // spare 1 byte for '\0' 18797 JSON_ASSERT(n_chars < number_buffer.size() - 1); 18798 18799 // jump to the end to generate the string from backward, 18800 // so we later avoid reversing the result 18801 buffer_ptr += n_chars; 18802 18803 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu 18804 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg 18805 while (abs_value >= 100) 18806 { 18807 const auto digits_index = static_cast<unsigned>((abs_value % 100)); 18808 abs_value /= 100; 18809 *(--buffer_ptr) = digits_to_99[digits_index][1]; 18810 *(--buffer_ptr) = digits_to_99[digits_index][0]; 18811 } 18812 18813 if (abs_value >= 10) 18814 { 18815 const auto digits_index = static_cast<unsigned>(abs_value); 18816 *(--buffer_ptr) = digits_to_99[digits_index][1]; 18817 *(--buffer_ptr) = digits_to_99[digits_index][0]; 18818 } 18819 else 18820 { 18821 *(--buffer_ptr) = static_cast<char>('0' + abs_value); 18822 } 18823 18824 o->write_characters(number_buffer.data(), n_chars); 18825 } 18826 18827 /*! 18828 @brief dump a floating-point number 18829 18830 Dump a given floating-point number to output stream @a o. Works internally 18831 with @a number_buffer. 18832 18833 @param[in] x floating-point number to dump 18834 */ 18835 void dump_float(number_float_t x) 18836 { 18837 // NaN / inf 18838 if (!std::isfinite(x)) 18839 { 18840 o->write_characters("null", 4); 18841 return; 18842 } 18843 18844 // If number_float_t is an IEEE-754 single or double precision number, 18845 // use the Grisu2 algorithm to produce short numbers which are 18846 // guaranteed to round-trip, using strtof and strtod, resp. 18847 // 18848 // NB: The test below works if <long double> == <double>. 18849 static constexpr bool is_ieee_single_or_double 18850 = (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) || 18851 (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); 18852 18853 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>()); 18854 } 18855 18856 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) 18857 { 18858 auto* begin = number_buffer.data(); 18859 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); 18860 18861 o->write_characters(begin, static_cast<size_t>(end - begin)); 18862 } 18863 18864 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) 18865 { 18866 // get number of digits for a float -> text -> float round-trip 18867 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10; 18868 18869 // the actual conversion 18870 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 18871 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); 18872 18873 // negative value indicates an error 18874 JSON_ASSERT(len > 0); 18875 // check if buffer was large enough 18876 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size()); 18877 18878 // erase thousands separator 18879 if (thousands_sep != '\0') 18880 { 18881 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081 18882 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep); 18883 std::fill(end, number_buffer.end(), '\0'); 18884 JSON_ASSERT((end - number_buffer.begin()) <= len); 18885 len = (end - number_buffer.begin()); 18886 } 18887 18888 // convert decimal point to '.' 18889 if (decimal_point != '\0' && decimal_point != '.') 18890 { 18891 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081 18892 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); 18893 if (dec_pos != number_buffer.end()) 18894 { 18895 *dec_pos = '.'; 18896 } 18897 } 18898 18899 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len)); 18900 18901 // determine if we need to append ".0" 18902 const bool value_is_int_like = 18903 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, 18904 [](char c) 18905 { 18906 return c == '.' || c == 'e'; 18907 }); 18908 18909 if (value_is_int_like) 18910 { 18911 o->write_characters(".0", 2); 18912 } 18913 } 18914 18915 /*! 18916 @brief check whether a string is UTF-8 encoded 18917 18918 The function checks each byte of a string whether it is UTF-8 encoded. The 18919 result of the check is stored in the @a state parameter. The function must 18920 be called initially with state 0 (accept). State 1 means the string must 18921 be rejected, because the current byte is not allowed. If the string is 18922 completely processed, but the state is non-zero, the string ended 18923 prematurely; that is, the last byte indicated more bytes should have 18924 followed. 18925 18926 @param[in,out] state the state of the decoding 18927 @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) 18928 @param[in] byte next byte to decode 18929 @return new state 18930 18931 @note The function has been edited: a std::array is used. 18932 18933 @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de> 18934 @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ 18935 */ 18936 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept 18937 { 18938 static const std::array<std::uint8_t, 400> utf8d = 18939 { 18940 { 18941 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 18942 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 18943 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 18944 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 18945 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 18946 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 18947 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 18948 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF 18949 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF 18950 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 18951 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 18952 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 18953 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 18954 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 18955 } 18956 }; 18957 18958 JSON_ASSERT(byte < utf8d.size()); 18959 const std::uint8_t type = utf8d[byte]; 18960 18961 codep = (state != UTF8_ACCEPT) 18962 ? (byte & 0x3fu) | (codep << 6u) 18963 : (0xFFu >> type) & (byte); 18964 18965 const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type); 18966 JSON_ASSERT(index < utf8d.size()); 18967 state = utf8d[index]; 18968 return state; 18969 } 18970 18971 /* 18972 * Overload to make the compiler happy while it is instantiating 18973 * dump_integer for number_unsigned_t. 18974 * Must never be called. 18975 */ 18976 number_unsigned_t remove_sign(number_unsigned_t x) 18977 { 18978 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 18979 return x; // LCOV_EXCL_LINE 18980 } 18981 18982 /* 18983 * Helper function for dump_integer 18984 * 18985 * This function takes a negative signed integer and returns its absolute 18986 * value as unsigned integer. The plus/minus shuffling is necessary as we can 18987 * not directly remove the sign of an arbitrary signed integer as the 18988 * absolute values of INT_MIN and INT_MAX are usually not the same. See 18989 * #1708 for details. 18990 */ 18991 inline number_unsigned_t remove_sign(number_integer_t x) noexcept 18992 { 18993 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression) 18994 return static_cast<number_unsigned_t>(-(x + 1)) + 1; 18995 } 18996 18997 private: 18998 /// the output of the serializer 18999 output_adapter_t<char> o = nullptr; 19000 19001 /// a (hopefully) large enough character buffer 19002 std::array<char, 64> number_buffer{{}}; 19003 19004 /// the locale 19005 const std::lconv* loc = nullptr; 19006 /// the locale's thousand separator character 19007 const char thousands_sep = '\0'; 19008 /// the locale's decimal point character 19009 const char decimal_point = '\0'; 19010 19011 /// string buffer 19012 std::array<char, 512> string_buffer{{}}; 19013 19014 /// the indentation character 19015 const char indent_char; 19016 /// the indentation string 19017 string_t indent_string; 19018 19019 /// error_handler how to react on decoding errors 19020 const error_handler_t error_handler; 19021 }; 19022 19023 } // namespace detail 19024 NLOHMANN_JSON_NAMESPACE_END 19025 19026 // #include <nlohmann/detail/value_t.hpp> 19027 19028 // #include <nlohmann/json_fwd.hpp> 19029 19030 // #include <nlohmann/ordered_map.hpp> 19031 // __ _____ _____ _____ 19032 // __| | __| | | | JSON for Modern C++ 19033 // | | |__ | | | | | | version 3.11.3 19034 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 19035 // 19036 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 19037 // SPDX-License-Identifier: MIT 19038 19039 19040 19041 #include <functional> // equal_to, less 19042 #include <initializer_list> // initializer_list 19043 #include <iterator> // input_iterator_tag, iterator_traits 19044 #include <memory> // allocator 19045 #include <stdexcept> // for out_of_range 19046 #include <type_traits> // enable_if, is_convertible 19047 #include <utility> // pair 19048 #include <vector> // vector 19049 19050 // #include <nlohmann/detail/macro_scope.hpp> 19051 19052 // #include <nlohmann/detail/meta/type_traits.hpp> 19053 19054 19055 NLOHMANN_JSON_NAMESPACE_BEGIN 19056 19057 /// ordered_map: a minimal map-like container that preserves insertion order 19058 /// for use within nlohmann::basic_json<ordered_map> 19059 template <class Key, class T, class IgnoredLess = std::less<Key>, 19060 class Allocator = std::allocator<std::pair<const Key, T>>> 19061 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator> 19062 { 19063 using key_type = Key; 19064 using mapped_type = T; 19065 using Container = std::vector<std::pair<const Key, T>, Allocator>; 19066 using iterator = typename Container::iterator; 19067 using const_iterator = typename Container::const_iterator; 19068 using size_type = typename Container::size_type; 19069 using value_type = typename Container::value_type; 19070 #ifdef JSON_HAS_CPP_14 19071 using key_compare = std::equal_to<>; 19072 #else 19073 using key_compare = std::equal_to<Key>; 19074 #endif 19075 19076 // Explicit constructors instead of `using Container::Container` 19077 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) 19078 ordered_map() noexcept(noexcept(Container())) : Container{} {} 19079 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {} 19080 template <class It> 19081 ordered_map(It first, It last, const Allocator& alloc = Allocator()) 19082 : Container{first, last, alloc} {} 19083 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() ) 19084 : Container{init, alloc} {} 19085 19086 std::pair<iterator, bool> emplace(const key_type& key, T&& t) 19087 { 19088 for (auto it = this->begin(); it != this->end(); ++it) 19089 { 19090 if (m_compare(it->first, key)) 19091 { 19092 return {it, false}; 19093 } 19094 } 19095 Container::emplace_back(key, std::forward<T>(t)); 19096 return {std::prev(this->end()), true}; 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 std::pair<iterator, bool> emplace(KeyType && key, T && t) 19102 { 19103 for (auto it = this->begin(); it != this->end(); ++it) 19104 { 19105 if (m_compare(it->first, key)) 19106 { 19107 return {it, false}; 19108 } 19109 } 19110 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t)); 19111 return {std::prev(this->end()), true}; 19112 } 19113 19114 T& operator[](const key_type& key) 19115 { 19116 return emplace(key, T{}).first->second; 19117 } 19118 19119 template<class KeyType, detail::enable_if_t< 19120 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19121 T & operator[](KeyType && key) 19122 { 19123 return emplace(std::forward<KeyType>(key), T{}).first->second; 19124 } 19125 19126 const T& operator[](const key_type& key) const 19127 { 19128 return at(key); 19129 } 19130 19131 template<class KeyType, detail::enable_if_t< 19132 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19133 const T & operator[](KeyType && key) const 19134 { 19135 return at(std::forward<KeyType>(key)); 19136 } 19137 19138 T& at(const key_type& key) 19139 { 19140 for (auto it = this->begin(); it != this->end(); ++it) 19141 { 19142 if (m_compare(it->first, key)) 19143 { 19144 return it->second; 19145 } 19146 } 19147 19148 JSON_THROW(std::out_of_range("key not found")); 19149 } 19150 19151 template<class KeyType, detail::enable_if_t< 19152 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19153 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) 19154 { 19155 for (auto it = this->begin(); it != this->end(); ++it) 19156 { 19157 if (m_compare(it->first, key)) 19158 { 19159 return it->second; 19160 } 19161 } 19162 19163 JSON_THROW(std::out_of_range("key not found")); 19164 } 19165 19166 const T& at(const key_type& key) const 19167 { 19168 for (auto it = this->begin(); it != this->end(); ++it) 19169 { 19170 if (m_compare(it->first, key)) 19171 { 19172 return it->second; 19173 } 19174 } 19175 19176 JSON_THROW(std::out_of_range("key not found")); 19177 } 19178 19179 template<class KeyType, detail::enable_if_t< 19180 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19181 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) 19182 { 19183 for (auto it = this->begin(); it != this->end(); ++it) 19184 { 19185 if (m_compare(it->first, key)) 19186 { 19187 return it->second; 19188 } 19189 } 19190 19191 JSON_THROW(std::out_of_range("key not found")); 19192 } 19193 19194 size_type erase(const key_type& key) 19195 { 19196 for (auto it = this->begin(); it != this->end(); ++it) 19197 { 19198 if (m_compare(it->first, key)) 19199 { 19200 // Since we cannot move const Keys, re-construct them in place 19201 for (auto next = it; ++next != this->end(); ++it) 19202 { 19203 it->~value_type(); // Destroy but keep allocation 19204 new (&*it) value_type{std::move(*next)}; 19205 } 19206 Container::pop_back(); 19207 return 1; 19208 } 19209 } 19210 return 0; 19211 } 19212 19213 template<class KeyType, detail::enable_if_t< 19214 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19215 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) 19216 { 19217 for (auto it = this->begin(); it != this->end(); ++it) 19218 { 19219 if (m_compare(it->first, key)) 19220 { 19221 // Since we cannot move const Keys, re-construct them in place 19222 for (auto next = it; ++next != this->end(); ++it) 19223 { 19224 it->~value_type(); // Destroy but keep allocation 19225 new (&*it) value_type{std::move(*next)}; 19226 } 19227 Container::pop_back(); 19228 return 1; 19229 } 19230 } 19231 return 0; 19232 } 19233 19234 iterator erase(iterator pos) 19235 { 19236 return erase(pos, std::next(pos)); 19237 } 19238 19239 iterator erase(iterator first, iterator last) 19240 { 19241 if (first == last) 19242 { 19243 return first; 19244 } 19245 19246 const auto elements_affected = std::distance(first, last); 19247 const auto offset = std::distance(Container::begin(), first); 19248 19249 // This is the start situation. We need to delete elements_affected 19250 // elements (3 in this example: e, f, g), and need to return an 19251 // iterator past the last deleted element (h in this example). 19252 // Note that offset is the distance from the start of the vector 19253 // to first. We will need this later. 19254 19255 // [ a, b, c, d, e, f, g, h, i, j ] 19256 // ^ ^ 19257 // first last 19258 19259 // Since we cannot move const Keys, we re-construct them in place. 19260 // We start at first and re-construct (viz. copy) the elements from 19261 // the back of the vector. Example for first iteration: 19262 19263 // ,--------. 19264 // v | destroy e and re-construct with h 19265 // [ a, b, c, d, e, f, g, h, i, j ] 19266 // ^ ^ 19267 // it it + elements_affected 19268 19269 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) 19270 { 19271 it->~value_type(); // destroy but keep allocation 19272 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it 19273 } 19274 19275 // [ a, b, c, d, h, i, j, h, i, j ] 19276 // ^ ^ 19277 // first last 19278 19279 // remove the unneeded elements at the end of the vector 19280 Container::resize(this->size() - static_cast<size_type>(elements_affected)); 19281 19282 // [ a, b, c, d, h, i, j ] 19283 // ^ ^ 19284 // first last 19285 19286 // first is now pointing past the last deleted element, but we cannot 19287 // use this iterator, because it may have been invalidated by the 19288 // resize call. Instead, we can return begin() + offset. 19289 return Container::begin() + offset; 19290 } 19291 19292 size_type count(const key_type& key) const 19293 { 19294 for (auto it = this->begin(); it != this->end(); ++it) 19295 { 19296 if (m_compare(it->first, key)) 19297 { 19298 return 1; 19299 } 19300 } 19301 return 0; 19302 } 19303 19304 template<class KeyType, detail::enable_if_t< 19305 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19306 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) 19307 { 19308 for (auto it = this->begin(); it != this->end(); ++it) 19309 { 19310 if (m_compare(it->first, key)) 19311 { 19312 return 1; 19313 } 19314 } 19315 return 0; 19316 } 19317 19318 iterator find(const key_type& key) 19319 { 19320 for (auto it = this->begin(); it != this->end(); ++it) 19321 { 19322 if (m_compare(it->first, key)) 19323 { 19324 return it; 19325 } 19326 } 19327 return Container::end(); 19328 } 19329 19330 template<class KeyType, detail::enable_if_t< 19331 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> 19332 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) 19333 { 19334 for (auto it = this->begin(); it != this->end(); ++it) 19335 { 19336 if (m_compare(it->first, key)) 19337 { 19338 return it; 19339 } 19340 } 19341 return Container::end(); 19342 } 19343 19344 const_iterator find(const key_type& key) const 19345 { 19346 for (auto it = this->begin(); it != this->end(); ++it) 19347 { 19348 if (m_compare(it->first, key)) 19349 { 19350 return it; 19351 } 19352 } 19353 return Container::end(); 19354 } 19355 19356 std::pair<iterator, bool> insert( value_type&& value ) 19357 { 19358 return emplace(value.first, std::move(value.second)); 19359 } 19360 19361 std::pair<iterator, bool> insert( const value_type& value ) 19362 { 19363 for (auto it = this->begin(); it != this->end(); ++it) 19364 { 19365 if (m_compare(it->first, value.first)) 19366 { 19367 return {it, false}; 19368 } 19369 } 19370 Container::push_back(value); 19371 return {--this->end(), true}; 19372 } 19373 19374 template<typename InputIt> 19375 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category, 19376 std::input_iterator_tag>::value>::type; 19377 19378 template<typename InputIt, typename = require_input_iter<InputIt>> 19379 void insert(InputIt first, InputIt last) 19380 { 19381 for (auto it = first; it != last; ++it) 19382 { 19383 insert(*it); 19384 } 19385 } 19386 19387 private: 19388 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare(); 19389 }; 19390 19391 NLOHMANN_JSON_NAMESPACE_END 19392 19393 19394 #if defined(JSON_HAS_CPP_17) 19395 #if JSON_HAS_STATIC_RTTI 19396 #include <any> 19397 #endif 19398 #include <string_view> 19399 #endif 19400 19401 /*! 19402 @brief namespace for Niels Lohmann 19403 @see https://github.com/nlohmann 19404 @since version 1.0.0 19405 */ 19406 NLOHMANN_JSON_NAMESPACE_BEGIN 19407 19408 /*! 19409 @brief a class to store JSON values 19410 19411 @internal 19412 @invariant The member variables @a m_value and @a m_type have the following 19413 relationship: 19414 - If `m_type == value_t::object`, then `m_value.object != nullptr`. 19415 - If `m_type == value_t::array`, then `m_value.array != nullptr`. 19416 - If `m_type == value_t::string`, then `m_value.string != nullptr`. 19417 The invariants are checked by member function assert_invariant(). 19418 19419 @note ObjectType trick from https://stackoverflow.com/a/9860911 19420 @endinternal 19421 19422 @since version 1.0.0 19423 19424 @nosubgrouping 19425 */ 19426 NLOHMANN_BASIC_JSON_TPL_DECLARATION 19427 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 19428 : public ::nlohmann::detail::json_base_class<CustomBaseClass> 19429 { 19430 private: 19431 template<detail::value_t> friend struct detail::external_constructor; 19432 19433 template<typename> 19434 friend class ::nlohmann::json_pointer; 19435 // can be restored when json_pointer backwards compatibility is removed 19436 // friend ::nlohmann::json_pointer<StringType>; 19437 19438 template<typename BasicJsonType, typename InputType> 19439 friend class ::nlohmann::detail::parser; 19440 friend ::nlohmann::detail::serializer<basic_json>; 19441 template<typename BasicJsonType> 19442 friend class ::nlohmann::detail::iter_impl; 19443 template<typename BasicJsonType, typename CharType> 19444 friend class ::nlohmann::detail::binary_writer; 19445 template<typename BasicJsonType, typename InputType, typename SAX> 19446 friend class ::nlohmann::detail::binary_reader; 19447 template<typename BasicJsonType> 19448 friend class ::nlohmann::detail::json_sax_dom_parser; 19449 template<typename BasicJsonType> 19450 friend class ::nlohmann::detail::json_sax_dom_callback_parser; 19451 friend class ::nlohmann::detail::exception; 19452 19453 /// workaround type for MSVC 19454 using basic_json_t = NLOHMANN_BASIC_JSON_TPL; 19455 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>; 19456 19457 JSON_PRIVATE_UNLESS_TESTED: 19458 // convenience aliases for types residing in namespace detail; 19459 using lexer = ::nlohmann::detail::lexer_base<basic_json>; 19460 19461 template<typename InputAdapterType> 19462 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser( 19463 InputAdapterType adapter, 19464 detail::parser_callback_t<basic_json>cb = nullptr, 19465 const bool allow_exceptions = true, 19466 const bool ignore_comments = false 19467 ) 19468 { 19469 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter), 19470 std::move(cb), allow_exceptions, ignore_comments); 19471 } 19472 19473 private: 19474 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; 19475 template<typename BasicJsonType> 19476 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>; 19477 template<typename BasicJsonType> 19478 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>; 19479 template<typename Iterator> 19480 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>; 19481 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>; 19482 19483 template<typename CharType> 19484 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>; 19485 19486 template<typename InputType> 19487 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>; 19488 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>; 19489 19490 JSON_PRIVATE_UNLESS_TESTED: 19491 using serializer = ::nlohmann::detail::serializer<basic_json>; 19492 19493 public: 19494 using value_t = detail::value_t; 19495 /// JSON Pointer, see @ref nlohmann::json_pointer 19496 using json_pointer = ::nlohmann::json_pointer<StringType>; 19497 template<typename T, typename SFINAE> 19498 using json_serializer = JSONSerializer<T, SFINAE>; 19499 /// how to treat decoding errors 19500 using error_handler_t = detail::error_handler_t; 19501 /// how to treat CBOR tags 19502 using cbor_tag_handler_t = detail::cbor_tag_handler_t; 19503 /// helper type for initializer lists of basic_json values 19504 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; 19505 19506 using input_format_t = detail::input_format_t; 19507 /// SAX interface type, see @ref nlohmann::json_sax 19508 using json_sax_t = json_sax<basic_json>; 19509 19510 //////////////// 19511 // exceptions // 19512 //////////////// 19513 19514 /// @name exceptions 19515 /// Classes to implement user-defined exceptions. 19516 /// @{ 19517 19518 using exception = detail::exception; 19519 using parse_error = detail::parse_error; 19520 using invalid_iterator = detail::invalid_iterator; 19521 using type_error = detail::type_error; 19522 using out_of_range = detail::out_of_range; 19523 using other_error = detail::other_error; 19524 19525 /// @} 19526 19527 ///////////////////// 19528 // container types // 19529 ///////////////////// 19530 19531 /// @name container types 19532 /// The canonic container types to use @ref basic_json like any other STL 19533 /// container. 19534 /// @{ 19535 19536 /// the type of elements in a basic_json container 19537 using value_type = basic_json; 19538 19539 /// the type of an element reference 19540 using reference = value_type&; 19541 /// the type of an element const reference 19542 using const_reference = const value_type&; 19543 19544 /// a type to represent differences between iterators 19545 using difference_type = std::ptrdiff_t; 19546 /// a type to represent container sizes 19547 using size_type = std::size_t; 19548 19549 /// the allocator type 19550 using allocator_type = AllocatorType<basic_json>; 19551 19552 /// the type of an element pointer 19553 using pointer = typename std::allocator_traits<allocator_type>::pointer; 19554 /// the type of an element const pointer 19555 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; 19556 19557 /// an iterator for a basic_json container 19558 using iterator = iter_impl<basic_json>; 19559 /// a const iterator for a basic_json container 19560 using const_iterator = iter_impl<const basic_json>; 19561 /// a reverse iterator for a basic_json container 19562 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; 19563 /// a const reverse iterator for a basic_json container 19564 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>; 19565 19566 /// @} 19567 19568 /// @brief returns the allocator associated with the container 19569 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ 19570 static allocator_type get_allocator() 19571 { 19572 return allocator_type(); 19573 } 19574 19575 /// @brief returns version information on the library 19576 /// @sa https://json.nlohmann.me/api/basic_json/meta/ 19577 JSON_HEDLEY_WARN_UNUSED_RESULT 19578 static basic_json meta() 19579 { 19580 basic_json result; 19581 19582 result["copyright"] = "(C) 2013-2023 Niels Lohmann"; 19583 result["name"] = "JSON for Modern C++"; 19584 result["url"] = "https://github.com/nlohmann/json"; 19585 result["version"]["string"] = 19586 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.', 19587 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.', 19588 std::to_string(NLOHMANN_JSON_VERSION_PATCH)); 19589 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; 19590 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; 19591 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; 19592 19593 #ifdef _WIN32 19594 result["platform"] = "win32"; 19595 #elif defined __linux__ 19596 result["platform"] = "linux"; 19597 #elif defined __APPLE__ 19598 result["platform"] = "apple"; 19599 #elif defined __unix__ 19600 result["platform"] = "unix"; 19601 #else 19602 result["platform"] = "unknown"; 19603 #endif 19604 19605 #if defined(__ICC) || defined(__INTEL_COMPILER) 19606 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; 19607 #elif defined(__clang__) 19608 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; 19609 #elif defined(__GNUC__) || defined(__GNUG__) 19610 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat( 19611 std::to_string(__GNUC__), '.', 19612 std::to_string(__GNUC_MINOR__), '.', 19613 std::to_string(__GNUC_PATCHLEVEL__)) 19614 } 19615 }; 19616 #elif defined(__HP_cc) || defined(__HP_aCC) 19617 result["compiler"] = "hp" 19618 #elif defined(__IBMCPP__) 19619 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; 19620 #elif defined(_MSC_VER) 19621 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; 19622 #elif defined(__PGI) 19623 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; 19624 #elif defined(__SUNPRO_CC) 19625 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; 19626 #else 19627 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; 19628 #endif 19629 19630 #if defined(_MSVC_LANG) 19631 result["compiler"]["c++"] = std::to_string(_MSVC_LANG); 19632 #elif defined(__cplusplus) 19633 result["compiler"]["c++"] = std::to_string(__cplusplus); 19634 #else 19635 result["compiler"]["c++"] = "unknown"; 19636 #endif 19637 return result; 19638 } 19639 19640 /////////////////////////// 19641 // JSON value data types // 19642 /////////////////////////// 19643 19644 /// @name JSON value data types 19645 /// The data types to store a JSON value. These types are derived from 19646 /// the template arguments passed to class @ref basic_json. 19647 /// @{ 19648 19649 /// @brief default object key comparator type 19650 /// The actual object key comparator type (@ref object_comparator_t) may be 19651 /// different. 19652 /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/ 19653 #if defined(JSON_HAS_CPP_14) 19654 // use of transparent comparator avoids unnecessary repeated construction of temporaries 19655 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType) 19656 using default_object_comparator_t = std::less<>; 19657 #else 19658 using default_object_comparator_t = std::less<StringType>; 19659 #endif 19660 19661 /// @brief a type for an object 19662 /// @sa https://json.nlohmann.me/api/basic_json/object_t/ 19663 using object_t = ObjectType<StringType, 19664 basic_json, 19665 default_object_comparator_t, 19666 AllocatorType<std::pair<const StringType, 19667 basic_json>>>; 19668 19669 /// @brief a type for an array 19670 /// @sa https://json.nlohmann.me/api/basic_json/array_t/ 19671 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>; 19672 19673 /// @brief a type for a string 19674 /// @sa https://json.nlohmann.me/api/basic_json/string_t/ 19675 using string_t = StringType; 19676 19677 /// @brief a type for a boolean 19678 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/ 19679 using boolean_t = BooleanType; 19680 19681 /// @brief a type for a number (integer) 19682 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/ 19683 using number_integer_t = NumberIntegerType; 19684 19685 /// @brief a type for a number (unsigned) 19686 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/ 19687 using number_unsigned_t = NumberUnsignedType; 19688 19689 /// @brief a type for a number (floating-point) 19690 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/ 19691 using number_float_t = NumberFloatType; 19692 19693 /// @brief a type for a packed binary type 19694 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/ 19695 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>; 19696 19697 /// @brief object key comparator type 19698 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/ 19699 using object_comparator_t = detail::actual_object_comparator_t<basic_json>; 19700 19701 /// @} 19702 19703 private: 19704 19705 /// helper for exception-safe object creation 19706 template<typename T, typename... Args> 19707 JSON_HEDLEY_RETURNS_NON_NULL 19708 static T* create(Args&& ... args) 19709 { 19710 AllocatorType<T> alloc; 19711 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>; 19712 19713 auto deleter = [&](T * obj) 19714 { 19715 AllocatorTraits::deallocate(alloc, obj, 1); 19716 }; 19717 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter); 19718 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...); 19719 JSON_ASSERT(obj != nullptr); 19720 return obj.release(); 19721 } 19722 19723 //////////////////////// 19724 // JSON value storage // 19725 //////////////////////// 19726 19727 JSON_PRIVATE_UNLESS_TESTED: 19728 /*! 19729 @brief a JSON value 19730 19731 The actual storage for a JSON value of the @ref basic_json class. This 19732 union combines the different storage types for the JSON value types 19733 defined in @ref value_t. 19734 19735 JSON type | value_t type | used type 19736 --------- | --------------- | ------------------------ 19737 object | object | pointer to @ref object_t 19738 array | array | pointer to @ref array_t 19739 string | string | pointer to @ref string_t 19740 boolean | boolean | @ref boolean_t 19741 number | number_integer | @ref number_integer_t 19742 number | number_unsigned | @ref number_unsigned_t 19743 number | number_float | @ref number_float_t 19744 binary | binary | pointer to @ref binary_t 19745 null | null | *no value is stored* 19746 19747 @note Variable-length types (objects, arrays, and strings) are stored as 19748 pointers. The size of the union should not exceed 64 bits if the default 19749 value types are used. 19750 19751 @since version 1.0.0 19752 */ 19753 union json_value 19754 { 19755 /// object (stored with pointer to save storage) 19756 object_t* object; 19757 /// array (stored with pointer to save storage) 19758 array_t* array; 19759 /// string (stored with pointer to save storage) 19760 string_t* string; 19761 /// binary (stored with pointer to save storage) 19762 binary_t* binary; 19763 /// boolean 19764 boolean_t boolean; 19765 /// number (integer) 19766 number_integer_t number_integer; 19767 /// number (unsigned integer) 19768 number_unsigned_t number_unsigned; 19769 /// number (floating-point) 19770 number_float_t number_float; 19771 19772 /// default constructor (for null values) 19773 json_value() = default; 19774 /// constructor for booleans 19775 json_value(boolean_t v) noexcept : boolean(v) {} 19776 /// constructor for numbers (integer) 19777 json_value(number_integer_t v) noexcept : number_integer(v) {} 19778 /// constructor for numbers (unsigned) 19779 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} 19780 /// constructor for numbers (floating-point) 19781 json_value(number_float_t v) noexcept : number_float(v) {} 19782 /// constructor for empty values of a given type 19783 json_value(value_t t) 19784 { 19785 switch (t) 19786 { 19787 case value_t::object: 19788 { 19789 object = create<object_t>(); 19790 break; 19791 } 19792 19793 case value_t::array: 19794 { 19795 array = create<array_t>(); 19796 break; 19797 } 19798 19799 case value_t::string: 19800 { 19801 string = create<string_t>(""); 19802 break; 19803 } 19804 19805 case value_t::binary: 19806 { 19807 binary = create<binary_t>(); 19808 break; 19809 } 19810 19811 case value_t::boolean: 19812 { 19813 boolean = static_cast<boolean_t>(false); 19814 break; 19815 } 19816 19817 case value_t::number_integer: 19818 { 19819 number_integer = static_cast<number_integer_t>(0); 19820 break; 19821 } 19822 19823 case value_t::number_unsigned: 19824 { 19825 number_unsigned = static_cast<number_unsigned_t>(0); 19826 break; 19827 } 19828 19829 case value_t::number_float: 19830 { 19831 number_float = static_cast<number_float_t>(0.0); 19832 break; 19833 } 19834 19835 case value_t::null: 19836 { 19837 object = nullptr; // silence warning, see #821 19838 break; 19839 } 19840 19841 case value_t::discarded: 19842 default: 19843 { 19844 object = nullptr; // silence warning, see #821 19845 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) 19846 { 19847 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE 19848 } 19849 break; 19850 } 19851 } 19852 } 19853 19854 /// constructor for strings 19855 json_value(const string_t& value) : string(create<string_t>(value)) {} 19856 19857 /// constructor for rvalue strings 19858 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {} 19859 19860 /// constructor for objects 19861 json_value(const object_t& value) : object(create<object_t>(value)) {} 19862 19863 /// constructor for rvalue objects 19864 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {} 19865 19866 /// constructor for arrays 19867 json_value(const array_t& value) : array(create<array_t>(value)) {} 19868 19869 /// constructor for rvalue arrays 19870 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {} 19871 19872 /// constructor for binary arrays 19873 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {} 19874 19875 /// constructor for rvalue binary arrays 19876 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {} 19877 19878 /// constructor for binary arrays (internal type) 19879 json_value(const binary_t& value) : binary(create<binary_t>(value)) {} 19880 19881 /// constructor for rvalue binary arrays (internal type) 19882 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {} 19883 19884 void destroy(value_t t) 19885 { 19886 if ( 19887 (t == value_t::object && object == nullptr) || 19888 (t == value_t::array && array == nullptr) || 19889 (t == value_t::string && string == nullptr) || 19890 (t == value_t::binary && binary == nullptr) 19891 ) 19892 { 19893 //not initialized (e.g. due to exception in the ctor) 19894 return; 19895 } 19896 if (t == value_t::array || t == value_t::object) 19897 { 19898 // flatten the current json_value to a heap-allocated stack 19899 std::vector<basic_json> stack; 19900 19901 // move the top-level items to stack 19902 if (t == value_t::array) 19903 { 19904 stack.reserve(array->size()); 19905 std::move(array->begin(), array->end(), std::back_inserter(stack)); 19906 } 19907 else 19908 { 19909 stack.reserve(object->size()); 19910 for (auto&& it : *object) 19911 { 19912 stack.push_back(std::move(it.second)); 19913 } 19914 } 19915 19916 while (!stack.empty()) 19917 { 19918 // move the last item to local variable to be processed 19919 basic_json current_item(std::move(stack.back())); 19920 stack.pop_back(); 19921 19922 // if current_item is array/object, move 19923 // its children to the stack to be processed later 19924 if (current_item.is_array()) 19925 { 19926 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); 19927 19928 current_item.m_data.m_value.array->clear(); 19929 } 19930 else if (current_item.is_object()) 19931 { 19932 for (auto&& it : *current_item.m_data.m_value.object) 19933 { 19934 stack.push_back(std::move(it.second)); 19935 } 19936 19937 current_item.m_data.m_value.object->clear(); 19938 } 19939 19940 // it's now safe that current_item get destructed 19941 // since it doesn't have any children 19942 } 19943 } 19944 19945 switch (t) 19946 { 19947 case value_t::object: 19948 { 19949 AllocatorType<object_t> alloc; 19950 std::allocator_traits<decltype(alloc)>::destroy(alloc, object); 19951 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1); 19952 break; 19953 } 19954 19955 case value_t::array: 19956 { 19957 AllocatorType<array_t> alloc; 19958 std::allocator_traits<decltype(alloc)>::destroy(alloc, array); 19959 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1); 19960 break; 19961 } 19962 19963 case value_t::string: 19964 { 19965 AllocatorType<string_t> alloc; 19966 std::allocator_traits<decltype(alloc)>::destroy(alloc, string); 19967 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1); 19968 break; 19969 } 19970 19971 case value_t::binary: 19972 { 19973 AllocatorType<binary_t> alloc; 19974 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary); 19975 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1); 19976 break; 19977 } 19978 19979 case value_t::null: 19980 case value_t::boolean: 19981 case value_t::number_integer: 19982 case value_t::number_unsigned: 19983 case value_t::number_float: 19984 case value_t::discarded: 19985 default: 19986 { 19987 break; 19988 } 19989 } 19990 } 19991 }; 19992 19993 private: 19994 /*! 19995 @brief checks the class invariants 19996 19997 This function asserts the class invariants. It needs to be called at the 19998 end of every constructor to make sure that created objects respect the 19999 invariant. Furthermore, it has to be called each time the type of a JSON 20000 value is changed, because the invariant expresses a relationship between 20001 @a m_type and @a m_value. 20002 20003 Furthermore, the parent relation is checked for arrays and objects: If 20004 @a check_parents true and the value is an array or object, then the 20005 container's elements must have the current value as parent. 20006 20007 @param[in] check_parents whether the parent relation should be checked. 20008 The value is true by default and should only be set to false 20009 during destruction of objects when the invariant does not 20010 need to hold. 20011 */ 20012 void assert_invariant(bool check_parents = true) const noexcept 20013 { 20014 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr); 20015 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr); 20016 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr); 20017 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr); 20018 20019 #if JSON_DIAGNOSTICS 20020 JSON_TRY 20021 { 20022 // cppcheck-suppress assertWithSideEffect 20023 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) 20024 { 20025 return j.m_parent == this; 20026 })); 20027 } 20028 JSON_CATCH(...) {} // LCOV_EXCL_LINE 20029 #endif 20030 static_cast<void>(check_parents); 20031 } 20032 20033 void set_parents() 20034 { 20035 #if JSON_DIAGNOSTICS 20036 switch (m_data.m_type) 20037 { 20038 case value_t::array: 20039 { 20040 for (auto& element : *m_data.m_value.array) 20041 { 20042 element.m_parent = this; 20043 } 20044 break; 20045 } 20046 20047 case value_t::object: 20048 { 20049 for (auto& element : *m_data.m_value.object) 20050 { 20051 element.second.m_parent = this; 20052 } 20053 break; 20054 } 20055 20056 case value_t::null: 20057 case value_t::string: 20058 case value_t::boolean: 20059 case value_t::number_integer: 20060 case value_t::number_unsigned: 20061 case value_t::number_float: 20062 case value_t::binary: 20063 case value_t::discarded: 20064 default: 20065 break; 20066 } 20067 #endif 20068 } 20069 20070 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) 20071 { 20072 #if JSON_DIAGNOSTICS 20073 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) 20074 { 20075 (it + i)->m_parent = this; 20076 } 20077 #else 20078 static_cast<void>(count_set_parents); 20079 #endif 20080 return it; 20081 } 20082 20083 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1)) 20084 { 20085 #if JSON_DIAGNOSTICS 20086 if (old_capacity != static_cast<std::size_t>(-1)) 20087 { 20088 // see https://github.com/nlohmann/json/issues/2838 20089 JSON_ASSERT(type() == value_t::array); 20090 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) 20091 { 20092 // capacity has changed: update all parents 20093 set_parents(); 20094 return j; 20095 } 20096 } 20097 20098 // ordered_json uses a vector internally, so pointers could have 20099 // been invalidated; see https://github.com/nlohmann/json/issues/2962 20100 #ifdef JSON_HEDLEY_MSVC_VERSION 20101 #pragma warning(push ) 20102 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr 20103 #endif 20104 if (detail::is_ordered_map<object_t>::value) 20105 { 20106 set_parents(); 20107 return j; 20108 } 20109 #ifdef JSON_HEDLEY_MSVC_VERSION 20110 #pragma warning( pop ) 20111 #endif 20112 20113 j.m_parent = this; 20114 #else 20115 static_cast<void>(j); 20116 static_cast<void>(old_capacity); 20117 #endif 20118 return j; 20119 } 20120 20121 public: 20122 ////////////////////////// 20123 // JSON parser callback // 20124 ////////////////////////// 20125 20126 /// @brief parser event types 20127 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/ 20128 using parse_event_t = detail::parse_event_t; 20129 20130 /// @brief per-element parser callback type 20131 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/ 20132 using parser_callback_t = detail::parser_callback_t<basic_json>; 20133 20134 ////////////////// 20135 // constructors // 20136 ////////////////// 20137 20138 /// @name constructors and destructors 20139 /// Constructors of class @ref basic_json, copy/move constructor, copy 20140 /// assignment, static functions creating objects, and the destructor. 20141 /// @{ 20142 20143 /// @brief create an empty value with a given type 20144 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20145 basic_json(const value_t v) 20146 : m_data(v) 20147 { 20148 assert_invariant(); 20149 } 20150 20151 /// @brief create a null object 20152 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20153 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape) 20154 : basic_json(value_t::null) 20155 { 20156 assert_invariant(); 20157 } 20158 20159 /// @brief create a JSON value from compatible types 20160 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20161 template < typename CompatibleType, 20162 typename U = detail::uncvref_t<CompatibleType>, 20163 detail::enable_if_t < 20164 !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 > 20165 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) 20166 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), 20167 std::forward<CompatibleType>(val)))) 20168 { 20169 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val)); 20170 set_parents(); 20171 assert_invariant(); 20172 } 20173 20174 /// @brief create a JSON value from an existing one 20175 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20176 template < typename BasicJsonType, 20177 detail::enable_if_t < 20178 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 > 20179 basic_json(const BasicJsonType& val) 20180 { 20181 using other_boolean_t = typename BasicJsonType::boolean_t; 20182 using other_number_float_t = typename BasicJsonType::number_float_t; 20183 using other_number_integer_t = typename BasicJsonType::number_integer_t; 20184 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; 20185 using other_string_t = typename BasicJsonType::string_t; 20186 using other_object_t = typename BasicJsonType::object_t; 20187 using other_array_t = typename BasicJsonType::array_t; 20188 using other_binary_t = typename BasicJsonType::binary_t; 20189 20190 switch (val.type()) 20191 { 20192 case value_t::boolean: 20193 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>()); 20194 break; 20195 case value_t::number_float: 20196 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>()); 20197 break; 20198 case value_t::number_integer: 20199 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>()); 20200 break; 20201 case value_t::number_unsigned: 20202 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>()); 20203 break; 20204 case value_t::string: 20205 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>()); 20206 break; 20207 case value_t::object: 20208 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>()); 20209 break; 20210 case value_t::array: 20211 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>()); 20212 break; 20213 case value_t::binary: 20214 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>()); 20215 break; 20216 case value_t::null: 20217 *this = nullptr; 20218 break; 20219 case value_t::discarded: 20220 m_data.m_type = value_t::discarded; 20221 break; 20222 default: // LCOV_EXCL_LINE 20223 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 20224 } 20225 JSON_ASSERT(m_data.m_type == val.type()); 20226 set_parents(); 20227 assert_invariant(); 20228 } 20229 20230 /// @brief create a container (array or object) from an initializer list 20231 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20232 basic_json(initializer_list_t init, 20233 bool type_deduction = true, 20234 value_t manual_type = value_t::array) 20235 { 20236 // check if each element is an array with two elements whose first 20237 // element is a string 20238 bool is_an_object = std::all_of(init.begin(), init.end(), 20239 [](const detail::json_ref<basic_json>& element_ref) 20240 { 20241 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int; 20242 // (many string types can be constructed from 0 via its null-pointer guise, so we get a 20243 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows) 20244 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string(); 20245 }); 20246 20247 // adjust type if type deduction is not wanted 20248 if (!type_deduction) 20249 { 20250 // if array is wanted, do not create an object though possible 20251 if (manual_type == value_t::array) 20252 { 20253 is_an_object = false; 20254 } 20255 20256 // if object is wanted but impossible, throw an exception 20257 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) 20258 { 20259 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr)); 20260 } 20261 } 20262 20263 if (is_an_object) 20264 { 20265 // the initializer list is a list of pairs -> create object 20266 m_data.m_type = value_t::object; 20267 m_data.m_value = value_t::object; 20268 20269 for (auto& element_ref : init) 20270 { 20271 auto element = element_ref.moved_or_copied(); 20272 m_data.m_value.object->emplace( 20273 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)), 20274 std::move((*element.m_data.m_value.array)[1])); 20275 } 20276 } 20277 else 20278 { 20279 // the initializer list describes an array -> create array 20280 m_data.m_type = value_t::array; 20281 m_data.m_value.array = create<array_t>(init.begin(), init.end()); 20282 } 20283 20284 set_parents(); 20285 assert_invariant(); 20286 } 20287 20288 /// @brief explicitly create a binary array (without subtype) 20289 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20290 JSON_HEDLEY_WARN_UNUSED_RESULT 20291 static basic_json binary(const typename binary_t::container_type& init) 20292 { 20293 auto res = basic_json(); 20294 res.m_data.m_type = value_t::binary; 20295 res.m_data.m_value = init; 20296 return res; 20297 } 20298 20299 /// @brief explicitly create a binary array (with subtype) 20300 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20301 JSON_HEDLEY_WARN_UNUSED_RESULT 20302 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) 20303 { 20304 auto res = basic_json(); 20305 res.m_data.m_type = value_t::binary; 20306 res.m_data.m_value = binary_t(init, subtype); 20307 return res; 20308 } 20309 20310 /// @brief explicitly create a binary array 20311 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20312 JSON_HEDLEY_WARN_UNUSED_RESULT 20313 static basic_json binary(typename binary_t::container_type&& init) 20314 { 20315 auto res = basic_json(); 20316 res.m_data.m_type = value_t::binary; 20317 res.m_data.m_value = std::move(init); 20318 return res; 20319 } 20320 20321 /// @brief explicitly create a binary array (with subtype) 20322 /// @sa https://json.nlohmann.me/api/basic_json/binary/ 20323 JSON_HEDLEY_WARN_UNUSED_RESULT 20324 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) 20325 { 20326 auto res = basic_json(); 20327 res.m_data.m_type = value_t::binary; 20328 res.m_data.m_value = binary_t(std::move(init), subtype); 20329 return res; 20330 } 20331 20332 /// @brief explicitly create an array from an initializer list 20333 /// @sa https://json.nlohmann.me/api/basic_json/array/ 20334 JSON_HEDLEY_WARN_UNUSED_RESULT 20335 static basic_json array(initializer_list_t init = {}) 20336 { 20337 return basic_json(init, false, value_t::array); 20338 } 20339 20340 /// @brief explicitly create an object from an initializer list 20341 /// @sa https://json.nlohmann.me/api/basic_json/object/ 20342 JSON_HEDLEY_WARN_UNUSED_RESULT 20343 static basic_json object(initializer_list_t init = {}) 20344 { 20345 return basic_json(init, false, value_t::object); 20346 } 20347 20348 /// @brief construct an array with count copies of given value 20349 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20350 basic_json(size_type cnt, const basic_json& val): 20351 m_data{cnt, val} 20352 { 20353 set_parents(); 20354 assert_invariant(); 20355 } 20356 20357 /// @brief construct a JSON container given an iterator range 20358 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20359 template < class InputIT, typename std::enable_if < 20360 std::is_same<InputIT, typename basic_json_t::iterator>::value || 20361 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 > 20362 basic_json(InputIT first, InputIT last) 20363 { 20364 JSON_ASSERT(first.m_object != nullptr); 20365 JSON_ASSERT(last.m_object != nullptr); 20366 20367 // make sure iterator fits the current value 20368 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 20369 { 20370 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr)); 20371 } 20372 20373 // copy type from first iterator 20374 m_data.m_type = first.m_object->m_data.m_type; 20375 20376 // check if iterator range is complete for primitive values 20377 switch (m_data.m_type) 20378 { 20379 case value_t::boolean: 20380 case value_t::number_float: 20381 case value_t::number_integer: 20382 case value_t::number_unsigned: 20383 case value_t::string: 20384 { 20385 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() 20386 || !last.m_it.primitive_iterator.is_end())) 20387 { 20388 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object)); 20389 } 20390 break; 20391 } 20392 20393 case value_t::null: 20394 case value_t::object: 20395 case value_t::array: 20396 case value_t::binary: 20397 case value_t::discarded: 20398 default: 20399 break; 20400 } 20401 20402 switch (m_data.m_type) 20403 { 20404 case value_t::number_integer: 20405 { 20406 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer; 20407 break; 20408 } 20409 20410 case value_t::number_unsigned: 20411 { 20412 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned; 20413 break; 20414 } 20415 20416 case value_t::number_float: 20417 { 20418 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float; 20419 break; 20420 } 20421 20422 case value_t::boolean: 20423 { 20424 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean; 20425 break; 20426 } 20427 20428 case value_t::string: 20429 { 20430 m_data.m_value = *first.m_object->m_data.m_value.string; 20431 break; 20432 } 20433 20434 case value_t::object: 20435 { 20436 m_data.m_value.object = create<object_t>(first.m_it.object_iterator, 20437 last.m_it.object_iterator); 20438 break; 20439 } 20440 20441 case value_t::array: 20442 { 20443 m_data.m_value.array = create<array_t>(first.m_it.array_iterator, 20444 last.m_it.array_iterator); 20445 break; 20446 } 20447 20448 case value_t::binary: 20449 { 20450 m_data.m_value = *first.m_object->m_data.m_value.binary; 20451 break; 20452 } 20453 20454 case value_t::null: 20455 case value_t::discarded: 20456 default: 20457 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object)); 20458 } 20459 20460 set_parents(); 20461 assert_invariant(); 20462 } 20463 20464 /////////////////////////////////////// 20465 // other constructors and destructor // 20466 /////////////////////////////////////// 20467 20468 template<typename JsonRef, 20469 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>, 20470 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 > 20471 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} 20472 20473 /// @brief copy constructor 20474 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20475 basic_json(const basic_json& other) 20476 : json_base_class_t(other) 20477 { 20478 m_data.m_type = other.m_data.m_type; 20479 // check of passed value is valid 20480 other.assert_invariant(); 20481 20482 switch (m_data.m_type) 20483 { 20484 case value_t::object: 20485 { 20486 m_data.m_value = *other.m_data.m_value.object; 20487 break; 20488 } 20489 20490 case value_t::array: 20491 { 20492 m_data.m_value = *other.m_data.m_value.array; 20493 break; 20494 } 20495 20496 case value_t::string: 20497 { 20498 m_data.m_value = *other.m_data.m_value.string; 20499 break; 20500 } 20501 20502 case value_t::boolean: 20503 { 20504 m_data.m_value = other.m_data.m_value.boolean; 20505 break; 20506 } 20507 20508 case value_t::number_integer: 20509 { 20510 m_data.m_value = other.m_data.m_value.number_integer; 20511 break; 20512 } 20513 20514 case value_t::number_unsigned: 20515 { 20516 m_data.m_value = other.m_data.m_value.number_unsigned; 20517 break; 20518 } 20519 20520 case value_t::number_float: 20521 { 20522 m_data.m_value = other.m_data.m_value.number_float; 20523 break; 20524 } 20525 20526 case value_t::binary: 20527 { 20528 m_data.m_value = *other.m_data.m_value.binary; 20529 break; 20530 } 20531 20532 case value_t::null: 20533 case value_t::discarded: 20534 default: 20535 break; 20536 } 20537 20538 set_parents(); 20539 assert_invariant(); 20540 } 20541 20542 /// @brief move constructor 20543 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 20544 basic_json(basic_json&& other) noexcept 20545 : json_base_class_t(std::forward<json_base_class_t>(other)), 20546 m_data(std::move(other.m_data)) 20547 { 20548 // check that passed value is valid 20549 other.assert_invariant(false); 20550 20551 // invalidate payload 20552 other.m_data.m_type = value_t::null; 20553 other.m_data.m_value = {}; 20554 20555 set_parents(); 20556 assert_invariant(); 20557 } 20558 20559 /// @brief copy assignment 20560 /// @sa https://json.nlohmann.me/api/basic_json/operator=/ 20561 basic_json& operator=(basic_json other) noexcept ( 20562 std::is_nothrow_move_constructible<value_t>::value&& 20563 std::is_nothrow_move_assignable<value_t>::value&& 20564 std::is_nothrow_move_constructible<json_value>::value&& 20565 std::is_nothrow_move_assignable<json_value>::value&& 20566 std::is_nothrow_move_assignable<json_base_class_t>::value 20567 ) 20568 { 20569 // check that passed value is valid 20570 other.assert_invariant(); 20571 20572 using std::swap; 20573 swap(m_data.m_type, other.m_data.m_type); 20574 swap(m_data.m_value, other.m_data.m_value); 20575 json_base_class_t::operator=(std::move(other)); 20576 20577 set_parents(); 20578 assert_invariant(); 20579 return *this; 20580 } 20581 20582 /// @brief destructor 20583 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/ 20584 ~basic_json() noexcept 20585 { 20586 assert_invariant(false); 20587 } 20588 20589 /// @} 20590 20591 public: 20592 /////////////////////// 20593 // object inspection // 20594 /////////////////////// 20595 20596 /// @name object inspection 20597 /// Functions to inspect the type of a JSON value. 20598 /// @{ 20599 20600 /// @brief serialization 20601 /// @sa https://json.nlohmann.me/api/basic_json/dump/ 20602 string_t dump(const int indent = -1, 20603 const char indent_char = ' ', 20604 const bool ensure_ascii = false, 20605 const error_handler_t error_handler = error_handler_t::strict) const 20606 { 20607 string_t result; 20608 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler); 20609 20610 if (indent >= 0) 20611 { 20612 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent)); 20613 } 20614 else 20615 { 20616 s.dump(*this, false, ensure_ascii, 0); 20617 } 20618 20619 return result; 20620 } 20621 20622 /// @brief return the type of the JSON value (explicit) 20623 /// @sa https://json.nlohmann.me/api/basic_json/type/ 20624 constexpr value_t type() const noexcept 20625 { 20626 return m_data.m_type; 20627 } 20628 20629 /// @brief return whether type is primitive 20630 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/ 20631 constexpr bool is_primitive() const noexcept 20632 { 20633 return is_null() || is_string() || is_boolean() || is_number() || is_binary(); 20634 } 20635 20636 /// @brief return whether type is structured 20637 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/ 20638 constexpr bool is_structured() const noexcept 20639 { 20640 return is_array() || is_object(); 20641 } 20642 20643 /// @brief return whether value is null 20644 /// @sa https://json.nlohmann.me/api/basic_json/is_null/ 20645 constexpr bool is_null() const noexcept 20646 { 20647 return m_data.m_type == value_t::null; 20648 } 20649 20650 /// @brief return whether value is a boolean 20651 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ 20652 constexpr bool is_boolean() const noexcept 20653 { 20654 return m_data.m_type == value_t::boolean; 20655 } 20656 20657 /// @brief return whether value is a number 20658 /// @sa https://json.nlohmann.me/api/basic_json/is_number/ 20659 constexpr bool is_number() const noexcept 20660 { 20661 return is_number_integer() || is_number_float(); 20662 } 20663 20664 /// @brief return whether value is an integer number 20665 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ 20666 constexpr bool is_number_integer() const noexcept 20667 { 20668 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned; 20669 } 20670 20671 /// @brief return whether value is an unsigned integer number 20672 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ 20673 constexpr bool is_number_unsigned() const noexcept 20674 { 20675 return m_data.m_type == value_t::number_unsigned; 20676 } 20677 20678 /// @brief return whether value is a floating-point number 20679 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ 20680 constexpr bool is_number_float() const noexcept 20681 { 20682 return m_data.m_type == value_t::number_float; 20683 } 20684 20685 /// @brief return whether value is an object 20686 /// @sa https://json.nlohmann.me/api/basic_json/is_object/ 20687 constexpr bool is_object() const noexcept 20688 { 20689 return m_data.m_type == value_t::object; 20690 } 20691 20692 /// @brief return whether value is an array 20693 /// @sa https://json.nlohmann.me/api/basic_json/is_array/ 20694 constexpr bool is_array() const noexcept 20695 { 20696 return m_data.m_type == value_t::array; 20697 } 20698 20699 /// @brief return whether value is a string 20700 /// @sa https://json.nlohmann.me/api/basic_json/is_string/ 20701 constexpr bool is_string() const noexcept 20702 { 20703 return m_data.m_type == value_t::string; 20704 } 20705 20706 /// @brief return whether value is a binary array 20707 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ 20708 constexpr bool is_binary() const noexcept 20709 { 20710 return m_data.m_type == value_t::binary; 20711 } 20712 20713 /// @brief return whether value is discarded 20714 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ 20715 constexpr bool is_discarded() const noexcept 20716 { 20717 return m_data.m_type == value_t::discarded; 20718 } 20719 20720 /// @brief return the type of the JSON value (implicit) 20721 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ 20722 constexpr operator value_t() const noexcept 20723 { 20724 return m_data.m_type; 20725 } 20726 20727 /// @} 20728 20729 private: 20730 ////////////////// 20731 // value access // 20732 ////////////////// 20733 20734 /// get a boolean (explicit) 20735 boolean_t get_impl(boolean_t* /*unused*/) const 20736 { 20737 if (JSON_HEDLEY_LIKELY(is_boolean())) 20738 { 20739 return m_data.m_value.boolean; 20740 } 20741 20742 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this)); 20743 } 20744 20745 /// get a pointer to the value (object) 20746 object_t* get_impl_ptr(object_t* /*unused*/) noexcept 20747 { 20748 return is_object() ? m_data.m_value.object : nullptr; 20749 } 20750 20751 /// get a pointer to the value (object) 20752 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept 20753 { 20754 return is_object() ? m_data.m_value.object : nullptr; 20755 } 20756 20757 /// get a pointer to the value (array) 20758 array_t* get_impl_ptr(array_t* /*unused*/) noexcept 20759 { 20760 return is_array() ? m_data.m_value.array : nullptr; 20761 } 20762 20763 /// get a pointer to the value (array) 20764 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept 20765 { 20766 return is_array() ? m_data.m_value.array : nullptr; 20767 } 20768 20769 /// get a pointer to the value (string) 20770 string_t* get_impl_ptr(string_t* /*unused*/) noexcept 20771 { 20772 return is_string() ? m_data.m_value.string : nullptr; 20773 } 20774 20775 /// get a pointer to the value (string) 20776 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept 20777 { 20778 return is_string() ? m_data.m_value.string : nullptr; 20779 } 20780 20781 /// get a pointer to the value (boolean) 20782 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept 20783 { 20784 return is_boolean() ? &m_data.m_value.boolean : nullptr; 20785 } 20786 20787 /// get a pointer to the value (boolean) 20788 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept 20789 { 20790 return is_boolean() ? &m_data.m_value.boolean : nullptr; 20791 } 20792 20793 /// get a pointer to the value (integer number) 20794 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept 20795 { 20796 return is_number_integer() ? &m_data.m_value.number_integer : nullptr; 20797 } 20798 20799 /// get a pointer to the value (integer number) 20800 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept 20801 { 20802 return is_number_integer() ? &m_data.m_value.number_integer : nullptr; 20803 } 20804 20805 /// get a pointer to the value (unsigned number) 20806 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept 20807 { 20808 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; 20809 } 20810 20811 /// get a pointer to the value (unsigned number) 20812 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept 20813 { 20814 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; 20815 } 20816 20817 /// get a pointer to the value (floating-point number) 20818 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept 20819 { 20820 return is_number_float() ? &m_data.m_value.number_float : nullptr; 20821 } 20822 20823 /// get a pointer to the value (floating-point number) 20824 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept 20825 { 20826 return is_number_float() ? &m_data.m_value.number_float : nullptr; 20827 } 20828 20829 /// get a pointer to the value (binary) 20830 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept 20831 { 20832 return is_binary() ? m_data.m_value.binary : nullptr; 20833 } 20834 20835 /// get a pointer to the value (binary) 20836 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept 20837 { 20838 return is_binary() ? m_data.m_value.binary : nullptr; 20839 } 20840 20841 /*! 20842 @brief helper function to implement get_ref() 20843 20844 This function helps to implement get_ref() without code duplication for 20845 const and non-const overloads 20846 20847 @tparam ThisType will be deduced as `basic_json` or `const basic_json` 20848 20849 @throw type_error.303 if ReferenceType does not match underlying value 20850 type of the current JSON 20851 */ 20852 template<typename ReferenceType, typename ThisType> 20853 static ReferenceType get_ref_impl(ThisType& obj) 20854 { 20855 // delegate the call to get_ptr<>() 20856 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>(); 20857 20858 if (JSON_HEDLEY_LIKELY(ptr != nullptr)) 20859 { 20860 return *ptr; 20861 } 20862 20863 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj)); 20864 } 20865 20866 public: 20867 /// @name value access 20868 /// Direct access to the stored value of a JSON value. 20869 /// @{ 20870 20871 /// @brief get a pointer value (implicit) 20872 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 20873 template<typename PointerType, typename std::enable_if< 20874 std::is_pointer<PointerType>::value, int>::type = 0> 20875 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) 20876 { 20877 // delegate the call to get_impl_ptr<>() 20878 return get_impl_ptr(static_cast<PointerType>(nullptr)); 20879 } 20880 20881 /// @brief get a pointer value (implicit) 20882 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 20883 template < typename PointerType, typename std::enable_if < 20884 std::is_pointer<PointerType>::value&& 20885 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 > 20886 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) 20887 { 20888 // delegate the call to get_impl_ptr<>() const 20889 return get_impl_ptr(static_cast<PointerType>(nullptr)); 20890 } 20891 20892 private: 20893 /*! 20894 @brief get a value (explicit) 20895 20896 Explicit type conversion between the JSON value and a compatible value 20897 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 20898 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 20899 The value is converted by calling the @ref json_serializer<ValueType> 20900 `from_json()` method. 20901 20902 The function is equivalent to executing 20903 @code {.cpp} 20904 ValueType ret; 20905 JSONSerializer<ValueType>::from_json(*this, ret); 20906 return ret; 20907 @endcode 20908 20909 This overloads is chosen if: 20910 - @a ValueType is not @ref basic_json, 20911 - @ref json_serializer<ValueType> has a `from_json()` method of the form 20912 `void from_json(const basic_json&, ValueType&)`, and 20913 - @ref json_serializer<ValueType> does not have a `from_json()` method of 20914 the form `ValueType from_json(const basic_json&)` 20915 20916 @tparam ValueType the returned value type 20917 20918 @return copy of the JSON value, converted to @a ValueType 20919 20920 @throw what @ref json_serializer<ValueType> `from_json()` method throws 20921 20922 @liveexample{The example below shows several conversions from JSON values 20923 to other types. There a few things to note: (1) Floating-point numbers can 20924 be converted to integers\, (2) A JSON array can be converted to a standard 20925 `std::vector<short>`\, (3) A JSON object can be converted to C++ 20926 associative containers such as `std::unordered_map<std::string\, 20927 json>`.,get__ValueType_const} 20928 20929 @since version 2.1.0 20930 */ 20931 template < typename ValueType, 20932 detail::enable_if_t < 20933 detail::is_default_constructible<ValueType>::value&& 20934 detail::has_from_json<basic_json_t, ValueType>::value, 20935 int > = 0 > 20936 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( 20937 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) 20938 { 20939 auto ret = ValueType(); 20940 JSONSerializer<ValueType>::from_json(*this, ret); 20941 return ret; 20942 } 20943 20944 /*! 20945 @brief get a value (explicit); special case 20946 20947 Explicit type conversion between the JSON value and a compatible value 20948 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 20949 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 20950 The value is converted by calling the @ref json_serializer<ValueType> 20951 `from_json()` method. 20952 20953 The function is equivalent to executing 20954 @code {.cpp} 20955 return JSONSerializer<ValueType>::from_json(*this); 20956 @endcode 20957 20958 This overloads is chosen if: 20959 - @a ValueType is not @ref basic_json and 20960 - @ref json_serializer<ValueType> has a `from_json()` method of the form 20961 `ValueType from_json(const basic_json&)` 20962 20963 @note If @ref json_serializer<ValueType> has both overloads of 20964 `from_json()`, this one is chosen. 20965 20966 @tparam ValueType the returned value type 20967 20968 @return copy of the JSON value, converted to @a ValueType 20969 20970 @throw what @ref json_serializer<ValueType> `from_json()` method throws 20971 20972 @since version 2.1.0 20973 */ 20974 template < typename ValueType, 20975 detail::enable_if_t < 20976 detail::has_non_default_from_json<basic_json_t, ValueType>::value, 20977 int > = 0 > 20978 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( 20979 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>()))) 20980 { 20981 return JSONSerializer<ValueType>::from_json(*this); 20982 } 20983 20984 /*! 20985 @brief get special-case overload 20986 20987 This overloads converts the current @ref basic_json in a different 20988 @ref basic_json type 20989 20990 @tparam BasicJsonType == @ref basic_json 20991 20992 @return a copy of *this, converted into @a BasicJsonType 20993 20994 @complexity Depending on the implementation of the called `from_json()` 20995 method. 20996 20997 @since version 3.2.0 20998 */ 20999 template < typename BasicJsonType, 21000 detail::enable_if_t < 21001 detail::is_basic_json<BasicJsonType>::value, 21002 int > = 0 > 21003 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const 21004 { 21005 return *this; 21006 } 21007 21008 /*! 21009 @brief get special-case overload 21010 21011 This overloads avoids a lot of template boilerplate, it can be seen as the 21012 identity method 21013 21014 @tparam BasicJsonType == @ref basic_json 21015 21016 @return a copy of *this 21017 21018 @complexity Constant. 21019 21020 @since version 2.1.0 21021 */ 21022 template<typename BasicJsonType, 21023 detail::enable_if_t< 21024 std::is_same<BasicJsonType, basic_json_t>::value, 21025 int> = 0> 21026 basic_json get_impl(detail::priority_tag<3> /*unused*/) const 21027 { 21028 return *this; 21029 } 21030 21031 /*! 21032 @brief get a pointer value (explicit) 21033 @copydoc get() 21034 */ 21035 template<typename PointerType, 21036 detail::enable_if_t< 21037 std::is_pointer<PointerType>::value, 21038 int> = 0> 21039 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept 21040 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>()) 21041 { 21042 // delegate the call to get_ptr 21043 return get_ptr<PointerType>(); 21044 } 21045 21046 public: 21047 /*! 21048 @brief get a (pointer) value (explicit) 21049 21050 Performs explicit type conversion between the JSON value and a compatible value if required. 21051 21052 - If the requested type is a pointer to the internally stored JSON value that pointer is returned. 21053 No copies are made. 21054 21055 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible 21056 from the current @ref basic_json. 21057 21058 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()` 21059 method. 21060 21061 @tparam ValueTypeCV the provided value type 21062 @tparam ValueType the returned value type 21063 21064 @return copy of the JSON value, converted to @tparam ValueType if necessary 21065 21066 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required 21067 21068 @since version 2.1.0 21069 */ 21070 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>> 21071 #if defined(JSON_HAS_CPP_14) 21072 constexpr 21073 #endif 21074 auto get() const noexcept( 21075 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))) 21076 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})) 21077 { 21078 // we cannot static_assert on ValueTypeCV being non-const, because 21079 // there is support for get<const basic_json_t>(), which is why we 21080 // still need the uncvref 21081 static_assert(!std::is_reference<ValueTypeCV>::value, 21082 "get() cannot be used with reference types, you might want to use get_ref()"); 21083 return get_impl<ValueType>(detail::priority_tag<4> {}); 21084 } 21085 21086 /*! 21087 @brief get a pointer value (explicit) 21088 21089 Explicit pointer access to the internally stored JSON value. No copies are 21090 made. 21091 21092 @warning The pointer becomes invalid if the underlying JSON object 21093 changes. 21094 21095 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref 21096 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 21097 @ref number_unsigned_t, or @ref number_float_t. 21098 21099 @return pointer to the internally stored JSON value if the requested 21100 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise 21101 21102 @complexity Constant. 21103 21104 @liveexample{The example below shows how pointers to internal values of a 21105 JSON value can be requested. Note that no type conversions are made and a 21106 `nullptr` is returned if the value and the requested pointer type does not 21107 match.,get__PointerType} 21108 21109 @sa see @ref get_ptr() for explicit pointer-member access 21110 21111 @since version 1.0.0 21112 */ 21113 template<typename PointerType, typename std::enable_if< 21114 std::is_pointer<PointerType>::value, int>::type = 0> 21115 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>()) 21116 { 21117 // delegate the call to get_ptr 21118 return get_ptr<PointerType>(); 21119 } 21120 21121 /// @brief get a value (explicit) 21122 /// @sa https://json.nlohmann.me/api/basic_json/get_to/ 21123 template < typename ValueType, 21124 detail::enable_if_t < 21125 !detail::is_basic_json<ValueType>::value&& 21126 detail::has_from_json<basic_json_t, ValueType>::value, 21127 int > = 0 > 21128 ValueType & get_to(ValueType& v) const noexcept(noexcept( 21129 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v))) 21130 { 21131 JSONSerializer<ValueType>::from_json(*this, v); 21132 return v; 21133 } 21134 21135 // specialization to allow calling get_to with a basic_json value 21136 // see https://github.com/nlohmann/json/issues/2175 21137 template<typename ValueType, 21138 detail::enable_if_t < 21139 detail::is_basic_json<ValueType>::value, 21140 int> = 0> 21141 ValueType & get_to(ValueType& v) const 21142 { 21143 v = *this; 21144 return v; 21145 } 21146 21147 template < 21148 typename T, std::size_t N, 21149 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 21150 detail::enable_if_t < 21151 detail::has_from_json<basic_json_t, Array>::value, int > = 0 > 21152 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 21153 noexcept(noexcept(JSONSerializer<Array>::from_json( 21154 std::declval<const basic_json_t&>(), v))) 21155 { 21156 JSONSerializer<Array>::from_json(*this, v); 21157 return v; 21158 } 21159 21160 /// @brief get a reference value (implicit) 21161 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 21162 template<typename ReferenceType, typename std::enable_if< 21163 std::is_reference<ReferenceType>::value, int>::type = 0> 21164 ReferenceType get_ref() 21165 { 21166 // delegate call to get_ref_impl 21167 return get_ref_impl<ReferenceType>(*this); 21168 } 21169 21170 /// @brief get a reference value (implicit) 21171 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 21172 template < typename ReferenceType, typename std::enable_if < 21173 std::is_reference<ReferenceType>::value&& 21174 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 > 21175 ReferenceType get_ref() const 21176 { 21177 // delegate call to get_ref_impl 21178 return get_ref_impl<ReferenceType>(*this); 21179 } 21180 21181 /*! 21182 @brief get a value (implicit) 21183 21184 Implicit type conversion between the JSON value and a compatible value. 21185 The call is realized by calling @ref get() const. 21186 21187 @tparam ValueType non-pointer type compatible to the JSON value, for 21188 instance `int` for JSON integer numbers, `bool` for JSON booleans, or 21189 `std::vector` types for JSON arrays. The character type of @ref string_t 21190 as well as an initializer list of this type is excluded to avoid 21191 ambiguities as these types implicitly convert to `std::string`. 21192 21193 @return copy of the JSON value, converted to type @a ValueType 21194 21195 @throw type_error.302 in case passed type @a ValueType is incompatible 21196 to the JSON value type (e.g., the JSON value is of type boolean, but a 21197 string is requested); see example below 21198 21199 @complexity Linear in the size of the JSON value. 21200 21201 @liveexample{The example below shows several conversions from JSON values 21202 to other types. There a few things to note: (1) Floating-point numbers can 21203 be converted to integers\, (2) A JSON array can be converted to a standard 21204 `std::vector<short>`\, (3) A JSON object can be converted to C++ 21205 associative containers such as `std::unordered_map<std::string\, 21206 json>`.,operator__ValueType} 21207 21208 @since version 1.0.0 21209 */ 21210 template < typename ValueType, typename std::enable_if < 21211 detail::conjunction < 21212 detail::negation<std::is_pointer<ValueType>>, 21213 detail::negation<std::is_same<ValueType, std::nullptr_t>>, 21214 detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>, 21215 detail::negation<std::is_same<ValueType, typename string_t::value_type>>, 21216 detail::negation<detail::is_basic_json<ValueType>>, 21217 detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>, 21218 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) 21219 detail::negation<std::is_same<ValueType, std::string_view>>, 21220 #endif 21221 #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI 21222 detail::negation<std::is_same<ValueType, std::any>>, 21223 #endif 21224 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType> 21225 >::value, int >::type = 0 > 21226 JSON_EXPLICIT operator ValueType() const 21227 { 21228 // delegate the call to get<>() const 21229 return get<ValueType>(); 21230 } 21231 21232 /// @brief get a binary value 21233 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 21234 binary_t& get_binary() 21235 { 21236 if (!is_binary()) 21237 { 21238 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); 21239 } 21240 21241 return *get_ptr<binary_t*>(); 21242 } 21243 21244 /// @brief get a binary value 21245 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 21246 const binary_t& get_binary() const 21247 { 21248 if (!is_binary()) 21249 { 21250 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); 21251 } 21252 21253 return *get_ptr<const binary_t*>(); 21254 } 21255 21256 /// @} 21257 21258 //////////////////// 21259 // element access // 21260 //////////////////// 21261 21262 /// @name element access 21263 /// Access to the JSON value. 21264 /// @{ 21265 21266 /// @brief access specified array element with bounds checking 21267 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21268 reference at(size_type idx) 21269 { 21270 // at only works for arrays 21271 if (JSON_HEDLEY_LIKELY(is_array())) 21272 { 21273 JSON_TRY 21274 { 21275 return set_parent(m_data.m_value.array->at(idx)); 21276 } 21277 JSON_CATCH (std::out_of_range&) 21278 { 21279 // create better exception explanation 21280 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 21281 } 21282 } 21283 else 21284 { 21285 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21286 } 21287 } 21288 21289 /// @brief access specified array element with bounds checking 21290 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21291 const_reference at(size_type idx) const 21292 { 21293 // at only works for arrays 21294 if (JSON_HEDLEY_LIKELY(is_array())) 21295 { 21296 JSON_TRY 21297 { 21298 return m_data.m_value.array->at(idx); 21299 } 21300 JSON_CATCH (std::out_of_range&) 21301 { 21302 // create better exception explanation 21303 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 21304 } 21305 } 21306 else 21307 { 21308 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21309 } 21310 } 21311 21312 /// @brief access specified object element with bounds checking 21313 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21314 reference at(const typename object_t::key_type& key) 21315 { 21316 // at only works for objects 21317 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21318 { 21319 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21320 } 21321 21322 auto it = m_data.m_value.object->find(key); 21323 if (it == m_data.m_value.object->end()) 21324 { 21325 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); 21326 } 21327 return set_parent(it->second); 21328 } 21329 21330 /// @brief access specified object element with bounds checking 21331 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21332 template<class KeyType, detail::enable_if_t< 21333 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21334 reference at(KeyType && key) 21335 { 21336 // at only works for objects 21337 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21338 { 21339 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21340 } 21341 21342 auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 21343 if (it == m_data.m_value.object->end()) 21344 { 21345 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); 21346 } 21347 return set_parent(it->second); 21348 } 21349 21350 /// @brief access specified object element with bounds checking 21351 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21352 const_reference at(const typename object_t::key_type& key) const 21353 { 21354 // at only works for objects 21355 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21356 { 21357 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21358 } 21359 21360 auto it = m_data.m_value.object->find(key); 21361 if (it == m_data.m_value.object->end()) 21362 { 21363 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); 21364 } 21365 return it->second; 21366 } 21367 21368 /// @brief access specified object element with bounds checking 21369 /// @sa https://json.nlohmann.me/api/basic_json/at/ 21370 template<class KeyType, detail::enable_if_t< 21371 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21372 const_reference at(KeyType && key) const 21373 { 21374 // at only works for objects 21375 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21376 { 21377 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 21378 } 21379 21380 auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 21381 if (it == m_data.m_value.object->end()) 21382 { 21383 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); 21384 } 21385 return it->second; 21386 } 21387 21388 /// @brief access specified array element 21389 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21390 reference operator[](size_type idx) 21391 { 21392 // implicitly convert null value to an empty array 21393 if (is_null()) 21394 { 21395 m_data.m_type = value_t::array; 21396 m_data.m_value.array = create<array_t>(); 21397 assert_invariant(); 21398 } 21399 21400 // operator[] only works for arrays 21401 if (JSON_HEDLEY_LIKELY(is_array())) 21402 { 21403 // fill up array with null values if given idx is outside range 21404 if (idx >= m_data.m_value.array->size()) 21405 { 21406 #if JSON_DIAGNOSTICS 21407 // remember array size & capacity before resizing 21408 const auto old_size = m_data.m_value.array->size(); 21409 const auto old_capacity = m_data.m_value.array->capacity(); 21410 #endif 21411 m_data.m_value.array->resize(idx + 1); 21412 21413 #if JSON_DIAGNOSTICS 21414 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) 21415 { 21416 // capacity has changed: update all parents 21417 set_parents(); 21418 } 21419 else 21420 { 21421 // set parent for values added above 21422 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size)); 21423 } 21424 #endif 21425 assert_invariant(); 21426 } 21427 21428 return m_data.m_value.array->operator[](idx); 21429 } 21430 21431 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); 21432 } 21433 21434 /// @brief access specified array element 21435 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21436 const_reference operator[](size_type idx) const 21437 { 21438 // const operator[] only works for arrays 21439 if (JSON_HEDLEY_LIKELY(is_array())) 21440 { 21441 return m_data.m_value.array->operator[](idx); 21442 } 21443 21444 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); 21445 } 21446 21447 /// @brief access specified object element 21448 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21449 reference operator[](typename object_t::key_type key) 21450 { 21451 // implicitly convert null value to an empty object 21452 if (is_null()) 21453 { 21454 m_data.m_type = value_t::object; 21455 m_data.m_value.object = create<object_t>(); 21456 assert_invariant(); 21457 } 21458 21459 // operator[] only works for objects 21460 if (JSON_HEDLEY_LIKELY(is_object())) 21461 { 21462 auto result = m_data.m_value.object->emplace(std::move(key), nullptr); 21463 return set_parent(result.first->second); 21464 } 21465 21466 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21467 } 21468 21469 /// @brief access specified object element 21470 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21471 const_reference operator[](const typename object_t::key_type& key) const 21472 { 21473 // const operator[] only works for objects 21474 if (JSON_HEDLEY_LIKELY(is_object())) 21475 { 21476 auto it = m_data.m_value.object->find(key); 21477 JSON_ASSERT(it != m_data.m_value.object->end()); 21478 return it->second; 21479 } 21480 21481 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21482 } 21483 21484 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC 21485 // (they seemingly cannot be constrained to resolve the ambiguity) 21486 template<typename T> 21487 reference operator[](T* key) 21488 { 21489 return operator[](typename object_t::key_type(key)); 21490 } 21491 21492 template<typename T> 21493 const_reference operator[](T* key) const 21494 { 21495 return operator[](typename object_t::key_type(key)); 21496 } 21497 21498 /// @brief access specified object element 21499 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21500 template<class KeyType, detail::enable_if_t< 21501 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > 21502 reference operator[](KeyType && key) 21503 { 21504 // implicitly convert null value to an empty object 21505 if (is_null()) 21506 { 21507 m_data.m_type = value_t::object; 21508 m_data.m_value.object = create<object_t>(); 21509 assert_invariant(); 21510 } 21511 21512 // operator[] only works for objects 21513 if (JSON_HEDLEY_LIKELY(is_object())) 21514 { 21515 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr); 21516 return set_parent(result.first->second); 21517 } 21518 21519 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21520 } 21521 21522 /// @brief access specified object element 21523 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 21524 template<class KeyType, detail::enable_if_t< 21525 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > 21526 const_reference operator[](KeyType && key) const 21527 { 21528 // const operator[] only works for objects 21529 if (JSON_HEDLEY_LIKELY(is_object())) 21530 { 21531 auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 21532 JSON_ASSERT(it != m_data.m_value.object->end()); 21533 return it->second; 21534 } 21535 21536 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 21537 } 21538 21539 private: 21540 template<typename KeyType> 21541 using is_comparable_with_object_key = detail::is_comparable < 21542 object_comparator_t, const typename object_t::key_type&, KeyType >; 21543 21544 template<typename ValueType> 21545 using value_return_type = std::conditional < 21546 detail::is_c_string_uncvref<ValueType>::value, 21547 string_t, typename std::decay<ValueType>::type >; 21548 21549 public: 21550 /// @brief access specified object element with default value 21551 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21552 template < class ValueType, detail::enable_if_t < 21553 !detail::is_transparent<object_comparator_t>::value 21554 && detail::is_getable<basic_json_t, ValueType>::value 21555 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21556 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const 21557 { 21558 // value only works for objects 21559 if (JSON_HEDLEY_LIKELY(is_object())) 21560 { 21561 // if key is found, return value and given default value otherwise 21562 const auto it = find(key); 21563 if (it != end()) 21564 { 21565 return it->template get<ValueType>(); 21566 } 21567 21568 return default_value; 21569 } 21570 21571 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21572 } 21573 21574 /// @brief access specified object element with default value 21575 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21576 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, 21577 detail::enable_if_t < 21578 !detail::is_transparent<object_comparator_t>::value 21579 && detail::is_getable<basic_json_t, ReturnType>::value 21580 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21581 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const 21582 { 21583 // value only works for objects 21584 if (JSON_HEDLEY_LIKELY(is_object())) 21585 { 21586 // if key is found, return value and given default value otherwise 21587 const auto it = find(key); 21588 if (it != end()) 21589 { 21590 return it->template get<ReturnType>(); 21591 } 21592 21593 return std::forward<ValueType>(default_value); 21594 } 21595 21596 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21597 } 21598 21599 /// @brief access specified object element with default value 21600 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21601 template < class ValueType, class KeyType, detail::enable_if_t < 21602 detail::is_transparent<object_comparator_t>::value 21603 && !detail::is_json_pointer<KeyType>::value 21604 && is_comparable_with_object_key<KeyType>::value 21605 && detail::is_getable<basic_json_t, ValueType>::value 21606 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21607 ValueType value(KeyType && key, const ValueType& default_value) const 21608 { 21609 // value only works for objects 21610 if (JSON_HEDLEY_LIKELY(is_object())) 21611 { 21612 // if key is found, return value and given default value otherwise 21613 const auto it = find(std::forward<KeyType>(key)); 21614 if (it != end()) 21615 { 21616 return it->template get<ValueType>(); 21617 } 21618 21619 return default_value; 21620 } 21621 21622 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21623 } 21624 21625 /// @brief access specified object element via JSON Pointer with default value 21626 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21627 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type, 21628 detail::enable_if_t < 21629 detail::is_transparent<object_comparator_t>::value 21630 && !detail::is_json_pointer<KeyType>::value 21631 && is_comparable_with_object_key<KeyType>::value 21632 && detail::is_getable<basic_json_t, ReturnType>::value 21633 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21634 ReturnType value(KeyType && key, ValueType && default_value) const 21635 { 21636 // value only works for objects 21637 if (JSON_HEDLEY_LIKELY(is_object())) 21638 { 21639 // if key is found, return value and given default value otherwise 21640 const auto it = find(std::forward<KeyType>(key)); 21641 if (it != end()) 21642 { 21643 return it->template get<ReturnType>(); 21644 } 21645 21646 return std::forward<ValueType>(default_value); 21647 } 21648 21649 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21650 } 21651 21652 /// @brief access specified object element via JSON Pointer with default value 21653 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21654 template < class ValueType, detail::enable_if_t < 21655 detail::is_getable<basic_json_t, ValueType>::value 21656 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21657 ValueType value(const json_pointer& ptr, const ValueType& default_value) const 21658 { 21659 // value only works for objects 21660 if (JSON_HEDLEY_LIKELY(is_object())) 21661 { 21662 // if pointer resolves a value, return it or use default value 21663 JSON_TRY 21664 { 21665 return ptr.get_checked(this).template get<ValueType>(); 21666 } 21667 JSON_INTERNAL_CATCH (out_of_range&) 21668 { 21669 return default_value; 21670 } 21671 } 21672 21673 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21674 } 21675 21676 /// @brief access specified object element via JSON Pointer with default value 21677 /// @sa https://json.nlohmann.me/api/basic_json/value/ 21678 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, 21679 detail::enable_if_t < 21680 detail::is_getable<basic_json_t, ReturnType>::value 21681 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21682 ReturnType value(const json_pointer& ptr, ValueType && default_value) const 21683 { 21684 // value only works for objects 21685 if (JSON_HEDLEY_LIKELY(is_object())) 21686 { 21687 // if pointer resolves a value, return it or use default value 21688 JSON_TRY 21689 { 21690 return ptr.get_checked(this).template get<ReturnType>(); 21691 } 21692 JSON_INTERNAL_CATCH (out_of_range&) 21693 { 21694 return std::forward<ValueType>(default_value); 21695 } 21696 } 21697 21698 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 21699 } 21700 21701 template < class ValueType, class BasicJsonType, detail::enable_if_t < 21702 detail::is_basic_json<BasicJsonType>::value 21703 && detail::is_getable<basic_json_t, ValueType>::value 21704 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21705 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 21706 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const 21707 { 21708 return value(ptr.convert(), default_value); 21709 } 21710 21711 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type, 21712 detail::enable_if_t < 21713 detail::is_basic_json<BasicJsonType>::value 21714 && detail::is_getable<basic_json_t, ReturnType>::value 21715 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 21716 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 21717 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const 21718 { 21719 return value(ptr.convert(), std::forward<ValueType>(default_value)); 21720 } 21721 21722 /// @brief access the first element 21723 /// @sa https://json.nlohmann.me/api/basic_json/front/ 21724 reference front() 21725 { 21726 return *begin(); 21727 } 21728 21729 /// @brief access the first element 21730 /// @sa https://json.nlohmann.me/api/basic_json/front/ 21731 const_reference front() const 21732 { 21733 return *cbegin(); 21734 } 21735 21736 /// @brief access the last element 21737 /// @sa https://json.nlohmann.me/api/basic_json/back/ 21738 reference back() 21739 { 21740 auto tmp = end(); 21741 --tmp; 21742 return *tmp; 21743 } 21744 21745 /// @brief access the last element 21746 /// @sa https://json.nlohmann.me/api/basic_json/back/ 21747 const_reference back() const 21748 { 21749 auto tmp = cend(); 21750 --tmp; 21751 return *tmp; 21752 } 21753 21754 /// @brief remove element given an iterator 21755 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21756 template < class IteratorType, detail::enable_if_t < 21757 std::is_same<IteratorType, typename basic_json_t::iterator>::value || 21758 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > 21759 IteratorType erase(IteratorType pos) 21760 { 21761 // make sure iterator fits the current value 21762 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) 21763 { 21764 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 21765 } 21766 21767 IteratorType result = end(); 21768 21769 switch (m_data.m_type) 21770 { 21771 case value_t::boolean: 21772 case value_t::number_float: 21773 case value_t::number_integer: 21774 case value_t::number_unsigned: 21775 case value_t::string: 21776 case value_t::binary: 21777 { 21778 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) 21779 { 21780 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this)); 21781 } 21782 21783 if (is_string()) 21784 { 21785 AllocatorType<string_t> alloc; 21786 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string); 21787 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1); 21788 m_data.m_value.string = nullptr; 21789 } 21790 else if (is_binary()) 21791 { 21792 AllocatorType<binary_t> alloc; 21793 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary); 21794 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1); 21795 m_data.m_value.binary = nullptr; 21796 } 21797 21798 m_data.m_type = value_t::null; 21799 assert_invariant(); 21800 break; 21801 } 21802 21803 case value_t::object: 21804 { 21805 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator); 21806 break; 21807 } 21808 21809 case value_t::array: 21810 { 21811 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator); 21812 break; 21813 } 21814 21815 case value_t::null: 21816 case value_t::discarded: 21817 default: 21818 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21819 } 21820 21821 return result; 21822 } 21823 21824 /// @brief remove elements given an iterator range 21825 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21826 template < class IteratorType, detail::enable_if_t < 21827 std::is_same<IteratorType, typename basic_json_t::iterator>::value || 21828 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > 21829 IteratorType erase(IteratorType first, IteratorType last) 21830 { 21831 // make sure iterator fits the current value 21832 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) 21833 { 21834 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this)); 21835 } 21836 21837 IteratorType result = end(); 21838 21839 switch (m_data.m_type) 21840 { 21841 case value_t::boolean: 21842 case value_t::number_float: 21843 case value_t::number_integer: 21844 case value_t::number_unsigned: 21845 case value_t::string: 21846 case value_t::binary: 21847 { 21848 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() 21849 || !last.m_it.primitive_iterator.is_end())) 21850 { 21851 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this)); 21852 } 21853 21854 if (is_string()) 21855 { 21856 AllocatorType<string_t> alloc; 21857 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string); 21858 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1); 21859 m_data.m_value.string = nullptr; 21860 } 21861 else if (is_binary()) 21862 { 21863 AllocatorType<binary_t> alloc; 21864 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary); 21865 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1); 21866 m_data.m_value.binary = nullptr; 21867 } 21868 21869 m_data.m_type = value_t::null; 21870 assert_invariant(); 21871 break; 21872 } 21873 21874 case value_t::object: 21875 { 21876 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator, 21877 last.m_it.object_iterator); 21878 break; 21879 } 21880 21881 case value_t::array: 21882 { 21883 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator, 21884 last.m_it.array_iterator); 21885 break; 21886 } 21887 21888 case value_t::null: 21889 case value_t::discarded: 21890 default: 21891 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21892 } 21893 21894 return result; 21895 } 21896 21897 private: 21898 template < typename KeyType, detail::enable_if_t < 21899 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > 21900 size_type erase_internal(KeyType && key) 21901 { 21902 // this erase only works for objects 21903 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21904 { 21905 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21906 } 21907 21908 return m_data.m_value.object->erase(std::forward<KeyType>(key)); 21909 } 21910 21911 template < typename KeyType, detail::enable_if_t < 21912 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > 21913 size_type erase_internal(KeyType && key) 21914 { 21915 // this erase only works for objects 21916 if (JSON_HEDLEY_UNLIKELY(!is_object())) 21917 { 21918 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21919 } 21920 21921 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 21922 if (it != m_data.m_value.object->end()) 21923 { 21924 m_data.m_value.object->erase(it); 21925 return 1; 21926 } 21927 return 0; 21928 } 21929 21930 public: 21931 21932 /// @brief remove element from a JSON object given a key 21933 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21934 size_type erase(const typename object_t::key_type& key) 21935 { 21936 // the indirection via erase_internal() is added to avoid making this 21937 // function a template and thus de-rank it during overload resolution 21938 return erase_internal(key); 21939 } 21940 21941 /// @brief remove element from a JSON object given a key 21942 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21943 template<class KeyType, detail::enable_if_t< 21944 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 21945 size_type erase(KeyType && key) 21946 { 21947 return erase_internal(std::forward<KeyType>(key)); 21948 } 21949 21950 /// @brief remove element from a JSON array given an index 21951 /// @sa https://json.nlohmann.me/api/basic_json/erase/ 21952 void erase(const size_type idx) 21953 { 21954 // this erase only works for arrays 21955 if (JSON_HEDLEY_LIKELY(is_array())) 21956 { 21957 if (JSON_HEDLEY_UNLIKELY(idx >= size())) 21958 { 21959 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 21960 } 21961 21962 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx)); 21963 } 21964 else 21965 { 21966 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 21967 } 21968 } 21969 21970 /// @} 21971 21972 //////////// 21973 // lookup // 21974 //////////// 21975 21976 /// @name lookup 21977 /// @{ 21978 21979 /// @brief find an element in a JSON object 21980 /// @sa https://json.nlohmann.me/api/basic_json/find/ 21981 iterator find(const typename object_t::key_type& key) 21982 { 21983 auto result = end(); 21984 21985 if (is_object()) 21986 { 21987 result.m_it.object_iterator = m_data.m_value.object->find(key); 21988 } 21989 21990 return result; 21991 } 21992 21993 /// @brief find an element in a JSON object 21994 /// @sa https://json.nlohmann.me/api/basic_json/find/ 21995 const_iterator find(const typename object_t::key_type& key) const 21996 { 21997 auto result = cend(); 21998 21999 if (is_object()) 22000 { 22001 result.m_it.object_iterator = m_data.m_value.object->find(key); 22002 } 22003 22004 return result; 22005 } 22006 22007 /// @brief find an element in a JSON object 22008 /// @sa https://json.nlohmann.me/api/basic_json/find/ 22009 template<class KeyType, detail::enable_if_t< 22010 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 22011 iterator find(KeyType && key) 22012 { 22013 auto result = end(); 22014 22015 if (is_object()) 22016 { 22017 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key)); 22018 } 22019 22020 return result; 22021 } 22022 22023 /// @brief find an element in a JSON object 22024 /// @sa https://json.nlohmann.me/api/basic_json/find/ 22025 template<class KeyType, detail::enable_if_t< 22026 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 22027 const_iterator find(KeyType && key) const 22028 { 22029 auto result = cend(); 22030 22031 if (is_object()) 22032 { 22033 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key)); 22034 } 22035 22036 return result; 22037 } 22038 22039 /// @brief returns the number of occurrences of a key in a JSON object 22040 /// @sa https://json.nlohmann.me/api/basic_json/count/ 22041 size_type count(const typename object_t::key_type& key) const 22042 { 22043 // return 0 for all nonobject types 22044 return is_object() ? m_data.m_value.object->count(key) : 0; 22045 } 22046 22047 /// @brief returns the number of occurrences of a key in a JSON object 22048 /// @sa https://json.nlohmann.me/api/basic_json/count/ 22049 template<class KeyType, detail::enable_if_t< 22050 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 22051 size_type count(KeyType && key) const 22052 { 22053 // return 0 for all nonobject types 22054 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0; 22055 } 22056 22057 /// @brief check the existence of an element in a JSON object 22058 /// @sa https://json.nlohmann.me/api/basic_json/contains/ 22059 bool contains(const typename object_t::key_type& key) const 22060 { 22061 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end(); 22062 } 22063 22064 /// @brief check the existence of an element in a JSON object 22065 /// @sa https://json.nlohmann.me/api/basic_json/contains/ 22066 template<class KeyType, detail::enable_if_t< 22067 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 22068 bool contains(KeyType && key) const 22069 { 22070 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end(); 22071 } 22072 22073 /// @brief check the existence of an element in a JSON object given a JSON pointer 22074 /// @sa https://json.nlohmann.me/api/basic_json/contains/ 22075 bool contains(const json_pointer& ptr) const 22076 { 22077 return ptr.contains(this); 22078 } 22079 22080 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 22081 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 22082 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const 22083 { 22084 return ptr.contains(this); 22085 } 22086 22087 /// @} 22088 22089 /////////////// 22090 // iterators // 22091 /////////////// 22092 22093 /// @name iterators 22094 /// @{ 22095 22096 /// @brief returns an iterator to the first element 22097 /// @sa https://json.nlohmann.me/api/basic_json/begin/ 22098 iterator begin() noexcept 22099 { 22100 iterator result(this); 22101 result.set_begin(); 22102 return result; 22103 } 22104 22105 /// @brief returns an iterator to the first element 22106 /// @sa https://json.nlohmann.me/api/basic_json/begin/ 22107 const_iterator begin() const noexcept 22108 { 22109 return cbegin(); 22110 } 22111 22112 /// @brief returns a const iterator to the first element 22113 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/ 22114 const_iterator cbegin() const noexcept 22115 { 22116 const_iterator result(this); 22117 result.set_begin(); 22118 return result; 22119 } 22120 22121 /// @brief returns an iterator to one past the last element 22122 /// @sa https://json.nlohmann.me/api/basic_json/end/ 22123 iterator end() noexcept 22124 { 22125 iterator result(this); 22126 result.set_end(); 22127 return result; 22128 } 22129 22130 /// @brief returns an iterator to one past the last element 22131 /// @sa https://json.nlohmann.me/api/basic_json/end/ 22132 const_iterator end() const noexcept 22133 { 22134 return cend(); 22135 } 22136 22137 /// @brief returns an iterator to one past the last element 22138 /// @sa https://json.nlohmann.me/api/basic_json/cend/ 22139 const_iterator cend() const noexcept 22140 { 22141 const_iterator result(this); 22142 result.set_end(); 22143 return result; 22144 } 22145 22146 /// @brief returns an iterator to the reverse-beginning 22147 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 22148 reverse_iterator rbegin() noexcept 22149 { 22150 return reverse_iterator(end()); 22151 } 22152 22153 /// @brief returns an iterator to the reverse-beginning 22154 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 22155 const_reverse_iterator rbegin() const noexcept 22156 { 22157 return crbegin(); 22158 } 22159 22160 /// @brief returns an iterator to the reverse-end 22161 /// @sa https://json.nlohmann.me/api/basic_json/rend/ 22162 reverse_iterator rend() noexcept 22163 { 22164 return reverse_iterator(begin()); 22165 } 22166 22167 /// @brief returns an iterator to the reverse-end 22168 /// @sa https://json.nlohmann.me/api/basic_json/rend/ 22169 const_reverse_iterator rend() const noexcept 22170 { 22171 return crend(); 22172 } 22173 22174 /// @brief returns a const reverse iterator to the last element 22175 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/ 22176 const_reverse_iterator crbegin() const noexcept 22177 { 22178 return const_reverse_iterator(cend()); 22179 } 22180 22181 /// @brief returns a const reverse iterator to one before the first 22182 /// @sa https://json.nlohmann.me/api/basic_json/crend/ 22183 const_reverse_iterator crend() const noexcept 22184 { 22185 return const_reverse_iterator(cbegin()); 22186 } 22187 22188 public: 22189 /// @brief wrapper to access iterator member functions in range-based for 22190 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22191 /// @deprecated This function is deprecated since 3.1.0 and will be removed in 22192 /// version 4.0.0 of the library. Please use @ref items() instead; 22193 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 22194 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) 22195 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept 22196 { 22197 return ref.items(); 22198 } 22199 22200 /// @brief wrapper to access iterator member functions in range-based for 22201 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22202 /// @deprecated This function is deprecated since 3.1.0 and will be removed in 22203 /// version 4.0.0 of the library. Please use @ref items() instead; 22204 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 22205 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) 22206 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept 22207 { 22208 return ref.items(); 22209 } 22210 22211 /// @brief helper to access iterator member functions in range-based for 22212 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22213 iteration_proxy<iterator> items() noexcept 22214 { 22215 return iteration_proxy<iterator>(*this); 22216 } 22217 22218 /// @brief helper to access iterator member functions in range-based for 22219 /// @sa https://json.nlohmann.me/api/basic_json/items/ 22220 iteration_proxy<const_iterator> items() const noexcept 22221 { 22222 return iteration_proxy<const_iterator>(*this); 22223 } 22224 22225 /// @} 22226 22227 ////////////// 22228 // capacity // 22229 ////////////// 22230 22231 /// @name capacity 22232 /// @{ 22233 22234 /// @brief checks whether the container is empty. 22235 /// @sa https://json.nlohmann.me/api/basic_json/empty/ 22236 bool empty() const noexcept 22237 { 22238 switch (m_data.m_type) 22239 { 22240 case value_t::null: 22241 { 22242 // null values are empty 22243 return true; 22244 } 22245 22246 case value_t::array: 22247 { 22248 // delegate call to array_t::empty() 22249 return m_data.m_value.array->empty(); 22250 } 22251 22252 case value_t::object: 22253 { 22254 // delegate call to object_t::empty() 22255 return m_data.m_value.object->empty(); 22256 } 22257 22258 case value_t::string: 22259 case value_t::boolean: 22260 case value_t::number_integer: 22261 case value_t::number_unsigned: 22262 case value_t::number_float: 22263 case value_t::binary: 22264 case value_t::discarded: 22265 default: 22266 { 22267 // all other types are nonempty 22268 return false; 22269 } 22270 } 22271 } 22272 22273 /// @brief returns the number of elements 22274 /// @sa https://json.nlohmann.me/api/basic_json/size/ 22275 size_type size() const noexcept 22276 { 22277 switch (m_data.m_type) 22278 { 22279 case value_t::null: 22280 { 22281 // null values are empty 22282 return 0; 22283 } 22284 22285 case value_t::array: 22286 { 22287 // delegate call to array_t::size() 22288 return m_data.m_value.array->size(); 22289 } 22290 22291 case value_t::object: 22292 { 22293 // delegate call to object_t::size() 22294 return m_data.m_value.object->size(); 22295 } 22296 22297 case value_t::string: 22298 case value_t::boolean: 22299 case value_t::number_integer: 22300 case value_t::number_unsigned: 22301 case value_t::number_float: 22302 case value_t::binary: 22303 case value_t::discarded: 22304 default: 22305 { 22306 // all other types have size 1 22307 return 1; 22308 } 22309 } 22310 } 22311 22312 /// @brief returns the maximum possible number of elements 22313 /// @sa https://json.nlohmann.me/api/basic_json/max_size/ 22314 size_type max_size() const noexcept 22315 { 22316 switch (m_data.m_type) 22317 { 22318 case value_t::array: 22319 { 22320 // delegate call to array_t::max_size() 22321 return m_data.m_value.array->max_size(); 22322 } 22323 22324 case value_t::object: 22325 { 22326 // delegate call to object_t::max_size() 22327 return m_data.m_value.object->max_size(); 22328 } 22329 22330 case value_t::null: 22331 case value_t::string: 22332 case value_t::boolean: 22333 case value_t::number_integer: 22334 case value_t::number_unsigned: 22335 case value_t::number_float: 22336 case value_t::binary: 22337 case value_t::discarded: 22338 default: 22339 { 22340 // all other types have max_size() == size() 22341 return size(); 22342 } 22343 } 22344 } 22345 22346 /// @} 22347 22348 /////////////// 22349 // modifiers // 22350 /////////////// 22351 22352 /// @name modifiers 22353 /// @{ 22354 22355 /// @brief clears the contents 22356 /// @sa https://json.nlohmann.me/api/basic_json/clear/ 22357 void clear() noexcept 22358 { 22359 switch (m_data.m_type) 22360 { 22361 case value_t::number_integer: 22362 { 22363 m_data.m_value.number_integer = 0; 22364 break; 22365 } 22366 22367 case value_t::number_unsigned: 22368 { 22369 m_data.m_value.number_unsigned = 0; 22370 break; 22371 } 22372 22373 case value_t::number_float: 22374 { 22375 m_data.m_value.number_float = 0.0; 22376 break; 22377 } 22378 22379 case value_t::boolean: 22380 { 22381 m_data.m_value.boolean = false; 22382 break; 22383 } 22384 22385 case value_t::string: 22386 { 22387 m_data.m_value.string->clear(); 22388 break; 22389 } 22390 22391 case value_t::binary: 22392 { 22393 m_data.m_value.binary->clear(); 22394 break; 22395 } 22396 22397 case value_t::array: 22398 { 22399 m_data.m_value.array->clear(); 22400 break; 22401 } 22402 22403 case value_t::object: 22404 { 22405 m_data.m_value.object->clear(); 22406 break; 22407 } 22408 22409 case value_t::null: 22410 case value_t::discarded: 22411 default: 22412 break; 22413 } 22414 } 22415 22416 /// @brief add an object to an array 22417 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22418 void push_back(basic_json&& val) 22419 { 22420 // push_back only works for null objects or arrays 22421 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 22422 { 22423 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 22424 } 22425 22426 // transform null object into an array 22427 if (is_null()) 22428 { 22429 m_data.m_type = value_t::array; 22430 m_data.m_value = value_t::array; 22431 assert_invariant(); 22432 } 22433 22434 // add element to array (move semantics) 22435 const auto old_capacity = m_data.m_value.array->capacity(); 22436 m_data.m_value.array->push_back(std::move(val)); 22437 set_parent(m_data.m_value.array->back(), old_capacity); 22438 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor 22439 } 22440 22441 /// @brief add an object to an array 22442 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22443 reference operator+=(basic_json&& val) 22444 { 22445 push_back(std::move(val)); 22446 return *this; 22447 } 22448 22449 /// @brief add an object to an array 22450 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22451 void push_back(const basic_json& val) 22452 { 22453 // push_back only works for null objects or arrays 22454 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 22455 { 22456 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 22457 } 22458 22459 // transform null object into an array 22460 if (is_null()) 22461 { 22462 m_data.m_type = value_t::array; 22463 m_data.m_value = value_t::array; 22464 assert_invariant(); 22465 } 22466 22467 // add element to array 22468 const auto old_capacity = m_data.m_value.array->capacity(); 22469 m_data.m_value.array->push_back(val); 22470 set_parent(m_data.m_value.array->back(), old_capacity); 22471 } 22472 22473 /// @brief add an object to an array 22474 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22475 reference operator+=(const basic_json& val) 22476 { 22477 push_back(val); 22478 return *this; 22479 } 22480 22481 /// @brief add an object to an object 22482 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22483 void push_back(const typename object_t::value_type& val) 22484 { 22485 // push_back only works for null objects or objects 22486 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) 22487 { 22488 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 22489 } 22490 22491 // transform null object into an object 22492 if (is_null()) 22493 { 22494 m_data.m_type = value_t::object; 22495 m_data.m_value = value_t::object; 22496 assert_invariant(); 22497 } 22498 22499 // add element to object 22500 auto res = m_data.m_value.object->insert(val); 22501 set_parent(res.first->second); 22502 } 22503 22504 /// @brief add an object to an object 22505 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22506 reference operator+=(const typename object_t::value_type& val) 22507 { 22508 push_back(val); 22509 return *this; 22510 } 22511 22512 /// @brief add an object to an object 22513 /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 22514 void push_back(initializer_list_t init) 22515 { 22516 if (is_object() && init.size() == 2 && (*init.begin())->is_string()) 22517 { 22518 basic_json&& key = init.begin()->moved_or_copied(); 22519 push_back(typename object_t::value_type( 22520 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied())); 22521 } 22522 else 22523 { 22524 push_back(basic_json(init)); 22525 } 22526 } 22527 22528 /// @brief add an object to an object 22529 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 22530 reference operator+=(initializer_list_t init) 22531 { 22532 push_back(init); 22533 return *this; 22534 } 22535 22536 /// @brief add an object to an array 22537 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/ 22538 template<class... Args> 22539 reference emplace_back(Args&& ... args) 22540 { 22541 // emplace_back only works for null objects or arrays 22542 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 22543 { 22544 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this)); 22545 } 22546 22547 // transform null object into an array 22548 if (is_null()) 22549 { 22550 m_data.m_type = value_t::array; 22551 m_data.m_value = value_t::array; 22552 assert_invariant(); 22553 } 22554 22555 // add element to array (perfect forwarding) 22556 const auto old_capacity = m_data.m_value.array->capacity(); 22557 m_data.m_value.array->emplace_back(std::forward<Args>(args)...); 22558 return set_parent(m_data.m_value.array->back(), old_capacity); 22559 } 22560 22561 /// @brief add an object to an object if key does not exist 22562 /// @sa https://json.nlohmann.me/api/basic_json/emplace/ 22563 template<class... Args> 22564 std::pair<iterator, bool> emplace(Args&& ... args) 22565 { 22566 // emplace only works for null objects or arrays 22567 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) 22568 { 22569 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this)); 22570 } 22571 22572 // transform null object into an object 22573 if (is_null()) 22574 { 22575 m_data.m_type = value_t::object; 22576 m_data.m_value = value_t::object; 22577 assert_invariant(); 22578 } 22579 22580 // add element to array (perfect forwarding) 22581 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...); 22582 set_parent(res.first->second); 22583 22584 // create result iterator and set iterator to the result of emplace 22585 auto it = begin(); 22586 it.m_it.object_iterator = res.first; 22587 22588 // return pair of iterator and boolean 22589 return {it, res.second}; 22590 } 22591 22592 /// Helper for insertion of an iterator 22593 /// @note: This uses std::distance to support GCC 4.8, 22594 /// see https://github.com/nlohmann/json/pull/1257 22595 template<typename... Args> 22596 iterator insert_iterator(const_iterator pos, Args&& ... args) 22597 { 22598 iterator result(this); 22599 JSON_ASSERT(m_data.m_value.array != nullptr); 22600 22601 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator); 22602 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...); 22603 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos; 22604 22605 // This could have been written as: 22606 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); 22607 // but the return value of insert is missing in GCC 4.8, so it is written this way instead. 22608 22609 set_parents(); 22610 return result; 22611 } 22612 22613 /// @brief inserts element into array 22614 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22615 iterator insert(const_iterator pos, const basic_json& val) 22616 { 22617 // insert only works for arrays 22618 if (JSON_HEDLEY_LIKELY(is_array())) 22619 { 22620 // check if iterator pos fits to this JSON value 22621 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22622 { 22623 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22624 } 22625 22626 // insert to array and return iterator 22627 return insert_iterator(pos, val); 22628 } 22629 22630 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22631 } 22632 22633 /// @brief inserts element into array 22634 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22635 iterator insert(const_iterator pos, basic_json&& val) 22636 { 22637 return insert(pos, val); 22638 } 22639 22640 /// @brief inserts copies of element into array 22641 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22642 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) 22643 { 22644 // insert only works for arrays 22645 if (JSON_HEDLEY_LIKELY(is_array())) 22646 { 22647 // check if iterator pos fits to this JSON value 22648 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22649 { 22650 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22651 } 22652 22653 // insert to array and return iterator 22654 return insert_iterator(pos, cnt, val); 22655 } 22656 22657 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22658 } 22659 22660 /// @brief inserts range of elements into array 22661 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22662 iterator insert(const_iterator pos, const_iterator first, const_iterator last) 22663 { 22664 // insert only works for arrays 22665 if (JSON_HEDLEY_UNLIKELY(!is_array())) 22666 { 22667 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22668 } 22669 22670 // check if iterator pos fits to this JSON value 22671 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22672 { 22673 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22674 } 22675 22676 // check if range iterators belong to the same JSON object 22677 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 22678 { 22679 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 22680 } 22681 22682 if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) 22683 { 22684 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this)); 22685 } 22686 22687 // insert to array and return iterator 22688 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); 22689 } 22690 22691 /// @brief inserts elements from initializer list into array 22692 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22693 iterator insert(const_iterator pos, initializer_list_t ilist) 22694 { 22695 // insert only works for arrays 22696 if (JSON_HEDLEY_UNLIKELY(!is_array())) 22697 { 22698 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22699 } 22700 22701 // check if iterator pos fits to this JSON value 22702 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 22703 { 22704 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 22705 } 22706 22707 // insert to array and return iterator 22708 return insert_iterator(pos, ilist.begin(), ilist.end()); 22709 } 22710 22711 /// @brief inserts range of elements into object 22712 /// @sa https://json.nlohmann.me/api/basic_json/insert/ 22713 void insert(const_iterator first, const_iterator last) 22714 { 22715 // insert only works for objects 22716 if (JSON_HEDLEY_UNLIKELY(!is_object())) 22717 { 22718 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 22719 } 22720 22721 // check if range iterators belong to the same JSON object 22722 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 22723 { 22724 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 22725 } 22726 22727 // passed iterators must belong to objects 22728 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) 22729 { 22730 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this)); 22731 } 22732 22733 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); 22734 } 22735 22736 /// @brief updates a JSON object from another object, overwriting existing keys 22737 /// @sa https://json.nlohmann.me/api/basic_json/update/ 22738 void update(const_reference j, bool merge_objects = false) 22739 { 22740 update(j.begin(), j.end(), merge_objects); 22741 } 22742 22743 /// @brief updates a JSON object from another object, overwriting existing keys 22744 /// @sa https://json.nlohmann.me/api/basic_json/update/ 22745 void update(const_iterator first, const_iterator last, bool merge_objects = false) 22746 { 22747 // implicitly convert null value to an empty object 22748 if (is_null()) 22749 { 22750 m_data.m_type = value_t::object; 22751 m_data.m_value.object = create<object_t>(); 22752 assert_invariant(); 22753 } 22754 22755 if (JSON_HEDLEY_UNLIKELY(!is_object())) 22756 { 22757 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this)); 22758 } 22759 22760 // check if range iterators belong to the same JSON object 22761 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 22762 { 22763 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 22764 } 22765 22766 // passed iterators must belong to objects 22767 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) 22768 { 22769 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object)); 22770 } 22771 22772 for (auto it = first; it != last; ++it) 22773 { 22774 if (merge_objects && it.value().is_object()) 22775 { 22776 auto it2 = m_data.m_value.object->find(it.key()); 22777 if (it2 != m_data.m_value.object->end()) 22778 { 22779 it2->second.update(it.value(), true); 22780 continue; 22781 } 22782 } 22783 m_data.m_value.object->operator[](it.key()) = it.value(); 22784 #if JSON_DIAGNOSTICS 22785 m_data.m_value.object->operator[](it.key()).m_parent = this; 22786 #endif 22787 } 22788 } 22789 22790 /// @brief exchanges the values 22791 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22792 void swap(reference other) noexcept ( 22793 std::is_nothrow_move_constructible<value_t>::value&& 22794 std::is_nothrow_move_assignable<value_t>::value&& 22795 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 22796 std::is_nothrow_move_assignable<json_value>::value 22797 ) 22798 { 22799 std::swap(m_data.m_type, other.m_data.m_type); 22800 std::swap(m_data.m_value, other.m_data.m_value); 22801 22802 set_parents(); 22803 other.set_parents(); 22804 assert_invariant(); 22805 } 22806 22807 /// @brief exchanges the values 22808 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22809 friend void swap(reference left, reference right) noexcept ( 22810 std::is_nothrow_move_constructible<value_t>::value&& 22811 std::is_nothrow_move_assignable<value_t>::value&& 22812 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 22813 std::is_nothrow_move_assignable<json_value>::value 22814 ) 22815 { 22816 left.swap(right); 22817 } 22818 22819 /// @brief exchanges the values 22820 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22821 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 22822 { 22823 // swap only works for arrays 22824 if (JSON_HEDLEY_LIKELY(is_array())) 22825 { 22826 using std::swap; 22827 swap(*(m_data.m_value.array), other); 22828 } 22829 else 22830 { 22831 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this)); 22832 } 22833 } 22834 22835 /// @brief exchanges the values 22836 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22837 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 22838 { 22839 // swap only works for objects 22840 if (JSON_HEDLEY_LIKELY(is_object())) 22841 { 22842 using std::swap; 22843 swap(*(m_data.m_value.object), other); 22844 } 22845 else 22846 { 22847 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this)); 22848 } 22849 } 22850 22851 /// @brief exchanges the values 22852 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22853 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 22854 { 22855 // swap only works for strings 22856 if (JSON_HEDLEY_LIKELY(is_string())) 22857 { 22858 using std::swap; 22859 swap(*(m_data.m_value.string), other); 22860 } 22861 else 22862 { 22863 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this)); 22864 } 22865 } 22866 22867 /// @brief exchanges the values 22868 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22869 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 22870 { 22871 // swap only works for strings 22872 if (JSON_HEDLEY_LIKELY(is_binary())) 22873 { 22874 using std::swap; 22875 swap(*(m_data.m_value.binary), other); 22876 } 22877 else 22878 { 22879 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this)); 22880 } 22881 } 22882 22883 /// @brief exchanges the values 22884 /// @sa https://json.nlohmann.me/api/basic_json/swap/ 22885 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape) 22886 { 22887 // swap only works for strings 22888 if (JSON_HEDLEY_LIKELY(is_binary())) 22889 { 22890 using std::swap; 22891 swap(*(m_data.m_value.binary), other); 22892 } 22893 else 22894 { 22895 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this)); 22896 } 22897 } 22898 22899 /// @} 22900 22901 ////////////////////////////////////////// 22902 // lexicographical comparison operators // 22903 ////////////////////////////////////////// 22904 22905 /// @name lexicographical comparison operators 22906 /// @{ 22907 22908 // note parentheses around operands are necessary; see 22909 // https://github.com/nlohmann/json/issues/1530 22910 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \ 22911 const auto lhs_type = lhs.type(); \ 22912 const auto rhs_type = rhs.type(); \ 22913 \ 22914 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \ 22915 { \ 22916 switch (lhs_type) \ 22917 { \ 22918 case value_t::array: \ 22919 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \ 22920 \ 22921 case value_t::object: \ 22922 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \ 22923 \ 22924 case value_t::null: \ 22925 return (null_result); \ 22926 \ 22927 case value_t::string: \ 22928 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \ 22929 \ 22930 case value_t::boolean: \ 22931 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \ 22932 \ 22933 case value_t::number_integer: \ 22934 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \ 22935 \ 22936 case value_t::number_unsigned: \ 22937 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \ 22938 \ 22939 case value_t::number_float: \ 22940 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \ 22941 \ 22942 case value_t::binary: \ 22943 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \ 22944 \ 22945 case value_t::discarded: \ 22946 default: \ 22947 return (unordered_result); \ 22948 } \ 22949 } \ 22950 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \ 22951 { \ 22952 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \ 22953 } \ 22954 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \ 22955 { \ 22956 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \ 22957 } \ 22958 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \ 22959 { \ 22960 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \ 22961 } \ 22962 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \ 22963 { \ 22964 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \ 22965 } \ 22966 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \ 22967 { \ 22968 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \ 22969 } \ 22970 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \ 22971 { \ 22972 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \ 22973 } \ 22974 else if(compares_unordered(lhs, rhs))\ 22975 {\ 22976 return (unordered_result);\ 22977 }\ 22978 \ 22979 return (default_result); 22980 22981 JSON_PRIVATE_UNLESS_TESTED: 22982 // returns true if: 22983 // - any operand is NaN and the other operand is of number type 22984 // - any operand is discarded 22985 // in legacy mode, discarded values are considered ordered if 22986 // an operation is computed as an odd number of inverses of others 22987 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept 22988 { 22989 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number()) 22990 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) 22991 { 22992 return true; 22993 } 22994 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 22995 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse; 22996 #else 22997 static_cast<void>(inverse); 22998 return lhs.is_discarded() || rhs.is_discarded(); 22999 #endif 23000 } 23001 23002 private: 23003 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept 23004 { 23005 return compares_unordered(*this, rhs, inverse); 23006 } 23007 23008 public: 23009 #if JSON_HAS_THREE_WAY_COMPARISON 23010 /// @brief comparison: equal 23011 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23012 bool operator==(const_reference rhs) const noexcept 23013 { 23014 #ifdef __GNUC__ 23015 #pragma GCC diagnostic push 23016 #pragma GCC diagnostic ignored "-Wfloat-equal" 23017 #endif 23018 const_reference lhs = *this; 23019 JSON_IMPLEMENT_OPERATOR( ==, true, false, false) 23020 #ifdef __GNUC__ 23021 #pragma GCC diagnostic pop 23022 #endif 23023 } 23024 23025 /// @brief comparison: equal 23026 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23027 template<typename ScalarType> 23028 requires std::is_scalar_v<ScalarType> 23029 bool operator==(ScalarType rhs) const noexcept 23030 { 23031 return *this == basic_json(rhs); 23032 } 23033 23034 /// @brief comparison: not equal 23035 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 23036 bool operator!=(const_reference rhs) const noexcept 23037 { 23038 if (compares_unordered(rhs, true)) 23039 { 23040 return false; 23041 } 23042 return !operator==(rhs); 23043 } 23044 23045 /// @brief comparison: 3-way 23046 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 23047 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD* 23048 { 23049 const_reference lhs = *this; 23050 // default_result is used if we cannot compare values. In that case, 23051 // we compare types. 23052 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD* 23053 std::partial_ordering::equivalent, 23054 std::partial_ordering::unordered, 23055 lhs_type <=> rhs_type) // *NOPAD* 23056 } 23057 23058 /// @brief comparison: 3-way 23059 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 23060 template<typename ScalarType> 23061 requires std::is_scalar_v<ScalarType> 23062 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD* 23063 { 23064 return *this <=> basic_json(rhs); // *NOPAD* 23065 } 23066 23067 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 23068 // all operators that are computed as an odd number of inverses of others 23069 // need to be overloaded to emulate the legacy comparison behavior 23070 23071 /// @brief comparison: less than or equal 23072 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23073 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) 23074 bool operator<=(const_reference rhs) const noexcept 23075 { 23076 if (compares_unordered(rhs, true)) 23077 { 23078 return false; 23079 } 23080 return !(rhs < *this); 23081 } 23082 23083 /// @brief comparison: less than or equal 23084 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23085 template<typename ScalarType> 23086 requires std::is_scalar_v<ScalarType> 23087 bool operator<=(ScalarType rhs) const noexcept 23088 { 23089 return *this <= basic_json(rhs); 23090 } 23091 23092 /// @brief comparison: greater than or equal 23093 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23094 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) 23095 bool operator>=(const_reference rhs) const noexcept 23096 { 23097 if (compares_unordered(rhs, true)) 23098 { 23099 return false; 23100 } 23101 return !(*this < rhs); 23102 } 23103 23104 /// @brief comparison: greater than or equal 23105 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23106 template<typename ScalarType> 23107 requires std::is_scalar_v<ScalarType> 23108 bool operator>=(ScalarType rhs) const noexcept 23109 { 23110 return *this >= basic_json(rhs); 23111 } 23112 #endif 23113 #else 23114 /// @brief comparison: equal 23115 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 23116 friend bool operator==(const_reference lhs, const_reference rhs) noexcept 23117 { 23118 #ifdef __GNUC__ 23119 #pragma GCC diagnostic push 23120 #pragma GCC diagnostic ignored "-Wfloat-equal" 23121 #endif 23122 JSON_IMPLEMENT_OPERATOR( ==, true, false, false) 23123 #ifdef __GNUC__ 23124 #pragma GCC diagnostic pop 23125 #endif 23126 } 23127 23128 /// @brief comparison: equal 23129 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 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: equal 23138 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 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: not equal 23147 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 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: not equal 23158 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 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: not equal 23167 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 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 23175 /// @brief comparison: less than 23176 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23177 friend bool operator<(const_reference lhs, const_reference rhs) noexcept 23178 { 23179 // default_result is used if we cannot compare values. In that case, 23180 // we compare types. Note we have to call the operator explicitly, 23181 // because MSVC has problems otherwise. 23182 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type)) 23183 } 23184 23185 /// @brief comparison: less than 23186 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23187 template<typename ScalarType, typename std::enable_if< 23188 std::is_scalar<ScalarType>::value, int>::type = 0> 23189 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept 23190 { 23191 return lhs < basic_json(rhs); 23192 } 23193 23194 /// @brief comparison: less than 23195 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 23196 template<typename ScalarType, typename std::enable_if< 23197 std::is_scalar<ScalarType>::value, int>::type = 0> 23198 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept 23199 { 23200 return basic_json(lhs) < rhs; 23201 } 23202 23203 /// @brief comparison: less than or equal 23204 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23205 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept 23206 { 23207 if (compares_unordered(lhs, rhs, true)) 23208 { 23209 return false; 23210 } 23211 return !(rhs < lhs); 23212 } 23213 23214 /// @brief comparison: less than or equal 23215 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23216 template<typename ScalarType, typename std::enable_if< 23217 std::is_scalar<ScalarType>::value, int>::type = 0> 23218 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept 23219 { 23220 return lhs <= basic_json(rhs); 23221 } 23222 23223 /// @brief comparison: less than or equal 23224 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 23225 template<typename ScalarType, typename std::enable_if< 23226 std::is_scalar<ScalarType>::value, int>::type = 0> 23227 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept 23228 { 23229 return basic_json(lhs) <= rhs; 23230 } 23231 23232 /// @brief comparison: greater than 23233 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23234 friend bool operator>(const_reference lhs, const_reference rhs) noexcept 23235 { 23236 // double inverse 23237 if (compares_unordered(lhs, rhs)) 23238 { 23239 return false; 23240 } 23241 return !(lhs <= rhs); 23242 } 23243 23244 /// @brief comparison: greater than 23245 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23246 template<typename ScalarType, typename std::enable_if< 23247 std::is_scalar<ScalarType>::value, int>::type = 0> 23248 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept 23249 { 23250 return lhs > basic_json(rhs); 23251 } 23252 23253 /// @brief comparison: greater than 23254 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 23255 template<typename ScalarType, typename std::enable_if< 23256 std::is_scalar<ScalarType>::value, int>::type = 0> 23257 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept 23258 { 23259 return basic_json(lhs) > rhs; 23260 } 23261 23262 /// @brief comparison: greater than or equal 23263 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23264 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept 23265 { 23266 if (compares_unordered(lhs, rhs, true)) 23267 { 23268 return false; 23269 } 23270 return !(lhs < rhs); 23271 } 23272 23273 /// @brief comparison: greater than or equal 23274 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23275 template<typename ScalarType, typename std::enable_if< 23276 std::is_scalar<ScalarType>::value, int>::type = 0> 23277 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept 23278 { 23279 return lhs >= basic_json(rhs); 23280 } 23281 23282 /// @brief comparison: greater than or equal 23283 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 23284 template<typename ScalarType, typename std::enable_if< 23285 std::is_scalar<ScalarType>::value, int>::type = 0> 23286 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept 23287 { 23288 return basic_json(lhs) >= rhs; 23289 } 23290 #endif 23291 23292 #undef JSON_IMPLEMENT_OPERATOR 23293 23294 /// @} 23295 23296 /////////////////// 23297 // serialization // 23298 /////////////////// 23299 23300 /// @name serialization 23301 /// @{ 23302 #ifndef JSON_NO_IO 23303 /// @brief serialize to stream 23304 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 23305 friend std::ostream& operator<<(std::ostream& o, const basic_json& j) 23306 { 23307 // read width member and use it as indentation parameter if nonzero 23308 const bool pretty_print = o.width() > 0; 23309 const auto indentation = pretty_print ? o.width() : 0; 23310 23311 // reset width to 0 for subsequent calls to this stream 23312 o.width(0); 23313 23314 // do the actual serialization 23315 serializer s(detail::output_adapter<char>(o), o.fill()); 23316 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation)); 23317 return o; 23318 } 23319 23320 /// @brief serialize to stream 23321 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 23322 /// @deprecated This function is deprecated since 3.0.0 and will be removed in 23323 /// version 4.0.0 of the library. Please use 23324 /// operator<<(std::ostream&, const basic_json&) instead; that is, 23325 /// replace calls like `j >> o;` with `o << j;`. 23326 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) 23327 friend std::ostream& operator>>(const basic_json& j, std::ostream& o) 23328 { 23329 return o << j; 23330 } 23331 #endif // JSON_NO_IO 23332 /// @} 23333 23334 ///////////////////// 23335 // deserialization // 23336 ///////////////////// 23337 23338 /// @name deserialization 23339 /// @{ 23340 23341 /// @brief deserialize from a compatible input 23342 /// @sa https://json.nlohmann.me/api/basic_json/parse/ 23343 template<typename InputType> 23344 JSON_HEDLEY_WARN_UNUSED_RESULT 23345 static basic_json parse(InputType&& i, 23346 const parser_callback_t cb = nullptr, 23347 const bool allow_exceptions = true, 23348 const bool ignore_comments = false) 23349 { 23350 basic_json result; 23351 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result); 23352 return result; 23353 } 23354 23355 /// @brief deserialize from a pair of character iterators 23356 /// @sa https://json.nlohmann.me/api/basic_json/parse/ 23357 template<typename IteratorType> 23358 JSON_HEDLEY_WARN_UNUSED_RESULT 23359 static basic_json parse(IteratorType first, 23360 IteratorType last, 23361 const parser_callback_t cb = nullptr, 23362 const bool allow_exceptions = true, 23363 const bool ignore_comments = false) 23364 { 23365 basic_json result; 23366 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); 23367 return result; 23368 } 23369 23370 JSON_HEDLEY_WARN_UNUSED_RESULT 23371 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) 23372 static basic_json parse(detail::span_input_adapter&& i, 23373 const parser_callback_t cb = nullptr, 23374 const bool allow_exceptions = true, 23375 const bool ignore_comments = false) 23376 { 23377 basic_json result; 23378 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); 23379 return result; 23380 } 23381 23382 /// @brief check if the input is valid JSON 23383 /// @sa https://json.nlohmann.me/api/basic_json/accept/ 23384 template<typename InputType> 23385 static bool accept(InputType&& i, 23386 const bool ignore_comments = false) 23387 { 23388 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true); 23389 } 23390 23391 /// @brief check if the input is valid JSON 23392 /// @sa https://json.nlohmann.me/api/basic_json/accept/ 23393 template<typename IteratorType> 23394 static bool accept(IteratorType first, IteratorType last, 23395 const bool ignore_comments = false) 23396 { 23397 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); 23398 } 23399 23400 JSON_HEDLEY_WARN_UNUSED_RESULT 23401 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) 23402 static bool accept(detail::span_input_adapter&& i, 23403 const bool ignore_comments = false) 23404 { 23405 return parser(i.get(), nullptr, false, ignore_comments).accept(true); 23406 } 23407 23408 /// @brief generate SAX events 23409 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 23410 template <typename InputType, typename SAX> 23411 JSON_HEDLEY_NON_NULL(2) 23412 static bool sax_parse(InputType&& i, SAX* sax, 23413 input_format_t format = input_format_t::json, 23414 const bool strict = true, 23415 const bool ignore_comments = false) 23416 { 23417 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23418 return format == input_format_t::json 23419 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 23420 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 23421 } 23422 23423 /// @brief generate SAX events 23424 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 23425 template<class IteratorType, class SAX> 23426 JSON_HEDLEY_NON_NULL(3) 23427 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, 23428 input_format_t format = input_format_t::json, 23429 const bool strict = true, 23430 const bool ignore_comments = false) 23431 { 23432 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23433 return format == input_format_t::json 23434 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 23435 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 23436 } 23437 23438 /// @brief generate SAX events 23439 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 23440 /// @deprecated This function is deprecated since 3.8.0 and will be removed in 23441 /// version 4.0.0 of the library. Please use 23442 /// sax_parse(ptr, ptr + len) instead. 23443 template <typename SAX> 23444 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) 23445 JSON_HEDLEY_NON_NULL(2) 23446 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, 23447 input_format_t format = input_format_t::json, 23448 const bool strict = true, 23449 const bool ignore_comments = false) 23450 { 23451 auto ia = i.get(); 23452 return format == input_format_t::json 23453 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23454 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 23455 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23456 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 23457 } 23458 #ifndef JSON_NO_IO 23459 /// @brief deserialize from stream 23460 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 23461 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in 23462 /// version 4.0.0 of the library. Please use 23463 /// operator>>(std::istream&, basic_json&) instead; that is, 23464 /// replace calls like `j << i;` with `i >> j;`. 23465 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) 23466 friend std::istream& operator<<(basic_json& j, std::istream& i) 23467 { 23468 return operator>>(i, j); 23469 } 23470 23471 /// @brief deserialize from stream 23472 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 23473 friend std::istream& operator>>(std::istream& i, basic_json& j) 23474 { 23475 parser(detail::input_adapter(i)).parse(false, j); 23476 return i; 23477 } 23478 #endif // JSON_NO_IO 23479 /// @} 23480 23481 /////////////////////////// 23482 // convenience functions // 23483 /////////////////////////// 23484 23485 /// @brief return the type as string 23486 /// @sa https://json.nlohmann.me/api/basic_json/type_name/ 23487 JSON_HEDLEY_RETURNS_NON_NULL 23488 const char* type_name() const noexcept 23489 { 23490 switch (m_data.m_type) 23491 { 23492 case value_t::null: 23493 return "null"; 23494 case value_t::object: 23495 return "object"; 23496 case value_t::array: 23497 return "array"; 23498 case value_t::string: 23499 return "string"; 23500 case value_t::boolean: 23501 return "boolean"; 23502 case value_t::binary: 23503 return "binary"; 23504 case value_t::discarded: 23505 return "discarded"; 23506 case value_t::number_integer: 23507 case value_t::number_unsigned: 23508 case value_t::number_float: 23509 default: 23510 return "number"; 23511 } 23512 } 23513 23514 JSON_PRIVATE_UNLESS_TESTED: 23515 ////////////////////// 23516 // member variables // 23517 ////////////////////// 23518 23519 struct data 23520 { 23521 /// the type of the current element 23522 value_t m_type = value_t::null; 23523 23524 /// the value of the current element 23525 json_value m_value = {}; 23526 23527 data(const value_t v) 23528 : m_type(v), m_value(v) 23529 { 23530 } 23531 23532 data(size_type cnt, const basic_json& val) 23533 : m_type(value_t::array) 23534 { 23535 m_value.array = create<array_t>(cnt, val); 23536 } 23537 23538 data() noexcept = default; 23539 data(data&&) noexcept = default; 23540 data(const data&) noexcept = delete; 23541 data& operator=(data&&) noexcept = delete; 23542 data& operator=(const data&) noexcept = delete; 23543 23544 ~data() noexcept 23545 { 23546 m_value.destroy(m_type); 23547 } 23548 }; 23549 23550 data m_data = {}; 23551 23552 #if JSON_DIAGNOSTICS 23553 /// a pointer to a parent value (for debugging purposes) 23554 basic_json* m_parent = nullptr; 23555 #endif 23556 23557 ////////////////////////////////////////// 23558 // binary serialization/deserialization // 23559 ////////////////////////////////////////// 23560 23561 /// @name binary serialization/deserialization support 23562 /// @{ 23563 23564 public: 23565 /// @brief create a CBOR serialization of a given JSON value 23566 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 23567 static std::vector<std::uint8_t> to_cbor(const basic_json& j) 23568 { 23569 std::vector<std::uint8_t> result; 23570 to_cbor(j, result); 23571 return result; 23572 } 23573 23574 /// @brief create a CBOR serialization of a given JSON value 23575 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 23576 static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o) 23577 { 23578 binary_writer<std::uint8_t>(o).write_cbor(j); 23579 } 23580 23581 /// @brief create a CBOR serialization of a given JSON value 23582 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 23583 static void to_cbor(const basic_json& j, detail::output_adapter<char> o) 23584 { 23585 binary_writer<char>(o).write_cbor(j); 23586 } 23587 23588 /// @brief create a MessagePack serialization of a given JSON value 23589 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 23590 static std::vector<std::uint8_t> to_msgpack(const basic_json& j) 23591 { 23592 std::vector<std::uint8_t> result; 23593 to_msgpack(j, result); 23594 return result; 23595 } 23596 23597 /// @brief create a MessagePack serialization of a given JSON value 23598 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 23599 static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o) 23600 { 23601 binary_writer<std::uint8_t>(o).write_msgpack(j); 23602 } 23603 23604 /// @brief create a MessagePack serialization of a given JSON value 23605 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 23606 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o) 23607 { 23608 binary_writer<char>(o).write_msgpack(j); 23609 } 23610 23611 /// @brief create a UBJSON serialization of a given JSON value 23612 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 23613 static std::vector<std::uint8_t> to_ubjson(const basic_json& j, 23614 const bool use_size = false, 23615 const bool use_type = false) 23616 { 23617 std::vector<std::uint8_t> result; 23618 to_ubjson(j, result, use_size, use_type); 23619 return result; 23620 } 23621 23622 /// @brief create a UBJSON serialization of a given JSON value 23623 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 23624 static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o, 23625 const bool use_size = false, const bool use_type = false) 23626 { 23627 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type); 23628 } 23629 23630 /// @brief create a UBJSON serialization of a given JSON value 23631 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 23632 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o, 23633 const bool use_size = false, const bool use_type = false) 23634 { 23635 binary_writer<char>(o).write_ubjson(j, use_size, use_type); 23636 } 23637 23638 /// @brief create a BJData serialization of a given JSON value 23639 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 23640 static std::vector<std::uint8_t> to_bjdata(const basic_json& j, 23641 const bool use_size = false, 23642 const bool use_type = false) 23643 { 23644 std::vector<std::uint8_t> result; 23645 to_bjdata(j, result, use_size, use_type); 23646 return result; 23647 } 23648 23649 /// @brief create a BJData serialization of a given JSON value 23650 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 23651 static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o, 23652 const bool use_size = false, const bool use_type = false) 23653 { 23654 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true); 23655 } 23656 23657 /// @brief create a BJData serialization of a given JSON value 23658 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 23659 static void to_bjdata(const basic_json& j, detail::output_adapter<char> o, 23660 const bool use_size = false, const bool use_type = false) 23661 { 23662 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true); 23663 } 23664 23665 /// @brief create a BSON serialization of a given JSON value 23666 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 23667 static std::vector<std::uint8_t> to_bson(const basic_json& j) 23668 { 23669 std::vector<std::uint8_t> result; 23670 to_bson(j, result); 23671 return result; 23672 } 23673 23674 /// @brief create a BSON serialization of a given JSON value 23675 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 23676 static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o) 23677 { 23678 binary_writer<std::uint8_t>(o).write_bson(j); 23679 } 23680 23681 /// @brief create a BSON serialization of a given JSON value 23682 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 23683 static void to_bson(const basic_json& j, detail::output_adapter<char> o) 23684 { 23685 binary_writer<char>(o).write_bson(j); 23686 } 23687 23688 /// @brief create a JSON value from an input in CBOR format 23689 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 23690 template<typename InputType> 23691 JSON_HEDLEY_WARN_UNUSED_RESULT 23692 static basic_json from_cbor(InputType&& i, 23693 const bool strict = true, 23694 const bool allow_exceptions = true, 23695 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23696 { 23697 basic_json result; 23698 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23699 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23700 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 23701 return res ? result : basic_json(value_t::discarded); 23702 } 23703 23704 /// @brief create a JSON value from an input in CBOR format 23705 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 23706 template<typename IteratorType> 23707 JSON_HEDLEY_WARN_UNUSED_RESULT 23708 static basic_json from_cbor(IteratorType first, IteratorType last, 23709 const bool strict = true, 23710 const bool allow_exceptions = true, 23711 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23712 { 23713 basic_json result; 23714 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23715 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23716 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 23717 return res ? result : basic_json(value_t::discarded); 23718 } 23719 23720 template<typename T> 23721 JSON_HEDLEY_WARN_UNUSED_RESULT 23722 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) 23723 static basic_json from_cbor(const T* ptr, std::size_t len, 23724 const bool strict = true, 23725 const bool allow_exceptions = true, 23726 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23727 { 23728 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); 23729 } 23730 23731 JSON_HEDLEY_WARN_UNUSED_RESULT 23732 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) 23733 static basic_json from_cbor(detail::span_input_adapter&& i, 23734 const bool strict = true, 23735 const bool allow_exceptions = true, 23736 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 23737 { 23738 basic_json result; 23739 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23740 auto ia = i.get(); 23741 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23742 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 23743 return res ? result : basic_json(value_t::discarded); 23744 } 23745 23746 /// @brief create a JSON value from an input in MessagePack format 23747 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 23748 template<typename InputType> 23749 JSON_HEDLEY_WARN_UNUSED_RESULT 23750 static basic_json from_msgpack(InputType&& i, 23751 const bool strict = true, 23752 const bool allow_exceptions = true) 23753 { 23754 basic_json result; 23755 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23756 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23757 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 23758 return res ? result : basic_json(value_t::discarded); 23759 } 23760 23761 /// @brief create a JSON value from an input in MessagePack format 23762 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 23763 template<typename IteratorType> 23764 JSON_HEDLEY_WARN_UNUSED_RESULT 23765 static basic_json from_msgpack(IteratorType first, IteratorType last, 23766 const bool strict = true, 23767 const bool allow_exceptions = true) 23768 { 23769 basic_json result; 23770 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23771 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23772 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 23773 return res ? result : basic_json(value_t::discarded); 23774 } 23775 23776 template<typename T> 23777 JSON_HEDLEY_WARN_UNUSED_RESULT 23778 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) 23779 static basic_json from_msgpack(const T* ptr, std::size_t len, 23780 const bool strict = true, 23781 const bool allow_exceptions = true) 23782 { 23783 return from_msgpack(ptr, ptr + len, strict, allow_exceptions); 23784 } 23785 23786 JSON_HEDLEY_WARN_UNUSED_RESULT 23787 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) 23788 static basic_json from_msgpack(detail::span_input_adapter&& i, 23789 const bool strict = true, 23790 const bool allow_exceptions = true) 23791 { 23792 basic_json result; 23793 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23794 auto ia = i.get(); 23795 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23796 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 23797 return res ? result : basic_json(value_t::discarded); 23798 } 23799 23800 /// @brief create a JSON value from an input in UBJSON format 23801 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 23802 template<typename InputType> 23803 JSON_HEDLEY_WARN_UNUSED_RESULT 23804 static basic_json from_ubjson(InputType&& i, 23805 const bool strict = true, 23806 const bool allow_exceptions = true) 23807 { 23808 basic_json result; 23809 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23810 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23811 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 23812 return res ? result : basic_json(value_t::discarded); 23813 } 23814 23815 /// @brief create a JSON value from an input in UBJSON format 23816 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 23817 template<typename IteratorType> 23818 JSON_HEDLEY_WARN_UNUSED_RESULT 23819 static basic_json from_ubjson(IteratorType first, IteratorType last, 23820 const bool strict = true, 23821 const bool allow_exceptions = true) 23822 { 23823 basic_json result; 23824 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23825 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23826 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 23827 return res ? result : basic_json(value_t::discarded); 23828 } 23829 23830 template<typename T> 23831 JSON_HEDLEY_WARN_UNUSED_RESULT 23832 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) 23833 static basic_json from_ubjson(const T* ptr, std::size_t len, 23834 const bool strict = true, 23835 const bool allow_exceptions = true) 23836 { 23837 return from_ubjson(ptr, ptr + len, strict, allow_exceptions); 23838 } 23839 23840 JSON_HEDLEY_WARN_UNUSED_RESULT 23841 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) 23842 static basic_json from_ubjson(detail::span_input_adapter&& i, 23843 const bool strict = true, 23844 const bool allow_exceptions = true) 23845 { 23846 basic_json result; 23847 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23848 auto ia = i.get(); 23849 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23850 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 23851 return res ? result : basic_json(value_t::discarded); 23852 } 23853 23854 /// @brief create a JSON value from an input in BJData format 23855 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 23856 template<typename InputType> 23857 JSON_HEDLEY_WARN_UNUSED_RESULT 23858 static basic_json from_bjdata(InputType&& i, 23859 const bool strict = true, 23860 const bool allow_exceptions = true) 23861 { 23862 basic_json result; 23863 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23864 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23865 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); 23866 return res ? result : basic_json(value_t::discarded); 23867 } 23868 23869 /// @brief create a JSON value from an input in BJData format 23870 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 23871 template<typename IteratorType> 23872 JSON_HEDLEY_WARN_UNUSED_RESULT 23873 static basic_json from_bjdata(IteratorType first, IteratorType last, 23874 const bool strict = true, 23875 const bool allow_exceptions = true) 23876 { 23877 basic_json result; 23878 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23879 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23880 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); 23881 return res ? result : basic_json(value_t::discarded); 23882 } 23883 23884 /// @brief create a JSON value from an input in BSON format 23885 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 23886 template<typename InputType> 23887 JSON_HEDLEY_WARN_UNUSED_RESULT 23888 static basic_json from_bson(InputType&& i, 23889 const bool strict = true, 23890 const bool allow_exceptions = true) 23891 { 23892 basic_json result; 23893 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23894 auto ia = detail::input_adapter(std::forward<InputType>(i)); 23895 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 23896 return res ? result : basic_json(value_t::discarded); 23897 } 23898 23899 /// @brief create a JSON value from an input in BSON format 23900 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 23901 template<typename IteratorType> 23902 JSON_HEDLEY_WARN_UNUSED_RESULT 23903 static basic_json from_bson(IteratorType first, IteratorType last, 23904 const bool strict = true, 23905 const bool allow_exceptions = true) 23906 { 23907 basic_json result; 23908 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23909 auto ia = detail::input_adapter(std::move(first), std::move(last)); 23910 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 23911 return res ? result : basic_json(value_t::discarded); 23912 } 23913 23914 template<typename T> 23915 JSON_HEDLEY_WARN_UNUSED_RESULT 23916 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) 23917 static basic_json from_bson(const T* ptr, std::size_t len, 23918 const bool strict = true, 23919 const bool allow_exceptions = true) 23920 { 23921 return from_bson(ptr, ptr + len, strict, allow_exceptions); 23922 } 23923 23924 JSON_HEDLEY_WARN_UNUSED_RESULT 23925 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) 23926 static basic_json from_bson(detail::span_input_adapter&& i, 23927 const bool strict = true, 23928 const bool allow_exceptions = true) 23929 { 23930 basic_json result; 23931 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 23932 auto ia = i.get(); 23933 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 23934 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 23935 return res ? result : basic_json(value_t::discarded); 23936 } 23937 /// @} 23938 23939 ////////////////////////// 23940 // JSON Pointer support // 23941 ////////////////////////// 23942 23943 /// @name JSON Pointer functions 23944 /// @{ 23945 23946 /// @brief access specified element via JSON Pointer 23947 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 23948 reference operator[](const json_pointer& ptr) 23949 { 23950 return ptr.get_unchecked(this); 23951 } 23952 23953 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 23954 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 23955 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) 23956 { 23957 return ptr.get_unchecked(this); 23958 } 23959 23960 /// @brief access specified element via JSON Pointer 23961 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 23962 const_reference operator[](const json_pointer& ptr) const 23963 { 23964 return ptr.get_unchecked(this); 23965 } 23966 23967 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 23968 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 23969 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const 23970 { 23971 return ptr.get_unchecked(this); 23972 } 23973 23974 /// @brief access specified element via JSON Pointer 23975 /// @sa https://json.nlohmann.me/api/basic_json/at/ 23976 reference at(const json_pointer& ptr) 23977 { 23978 return ptr.get_checked(this); 23979 } 23980 23981 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 23982 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 23983 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) 23984 { 23985 return ptr.get_checked(this); 23986 } 23987 23988 /// @brief access specified element via JSON Pointer 23989 /// @sa https://json.nlohmann.me/api/basic_json/at/ 23990 const_reference at(const json_pointer& ptr) const 23991 { 23992 return ptr.get_checked(this); 23993 } 23994 23995 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 23996 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 23997 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const 23998 { 23999 return ptr.get_checked(this); 24000 } 24001 24002 /// @brief return flattened JSON value 24003 /// @sa https://json.nlohmann.me/api/basic_json/flatten/ 24004 basic_json flatten() const 24005 { 24006 basic_json result(value_t::object); 24007 json_pointer::flatten("", *this, result); 24008 return result; 24009 } 24010 24011 /// @brief unflatten a previously flattened JSON value 24012 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/ 24013 basic_json unflatten() const 24014 { 24015 return json_pointer::unflatten(*this); 24016 } 24017 24018 /// @} 24019 24020 ////////////////////////// 24021 // JSON Patch functions // 24022 ////////////////////////// 24023 24024 /// @name JSON Patch functions 24025 /// @{ 24026 24027 /// @brief applies a JSON patch in-place without copying the object 24028 /// @sa https://json.nlohmann.me/api/basic_json/patch/ 24029 void patch_inplace(const basic_json& json_patch) 24030 { 24031 basic_json& result = *this; 24032 // the valid JSON Patch operations 24033 enum class patch_operations {add, remove, replace, move, copy, test, invalid}; 24034 24035 const auto get_op = [](const std::string & op) 24036 { 24037 if (op == "add") 24038 { 24039 return patch_operations::add; 24040 } 24041 if (op == "remove") 24042 { 24043 return patch_operations::remove; 24044 } 24045 if (op == "replace") 24046 { 24047 return patch_operations::replace; 24048 } 24049 if (op == "move") 24050 { 24051 return patch_operations::move; 24052 } 24053 if (op == "copy") 24054 { 24055 return patch_operations::copy; 24056 } 24057 if (op == "test") 24058 { 24059 return patch_operations::test; 24060 } 24061 24062 return patch_operations::invalid; 24063 }; 24064 24065 // wrapper for "add" operation; add value at ptr 24066 const auto operation_add = [&result](json_pointer & ptr, basic_json val) 24067 { 24068 // adding to the root of the target document means replacing it 24069 if (ptr.empty()) 24070 { 24071 result = val; 24072 return; 24073 } 24074 24075 // make sure the top element of the pointer exists 24076 json_pointer const top_pointer = ptr.top(); 24077 if (top_pointer != ptr) 24078 { 24079 result.at(top_pointer); 24080 } 24081 24082 // get reference to parent of JSON pointer ptr 24083 const auto last_path = ptr.back(); 24084 ptr.pop_back(); 24085 // parent must exist when performing patch add per RFC6902 specs 24086 basic_json& parent = result.at(ptr); 24087 24088 switch (parent.m_data.m_type) 24089 { 24090 case value_t::null: 24091 case value_t::object: 24092 { 24093 // use operator[] to add value 24094 parent[last_path] = val; 24095 break; 24096 } 24097 24098 case value_t::array: 24099 { 24100 if (last_path == "-") 24101 { 24102 // special case: append to back 24103 parent.push_back(val); 24104 } 24105 else 24106 { 24107 const auto idx = json_pointer::template array_index<basic_json_t>(last_path); 24108 if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) 24109 { 24110 // avoid undefined behavior 24111 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent)); 24112 } 24113 24114 // default case: insert add offset 24115 parent.insert(parent.begin() + static_cast<difference_type>(idx), val); 24116 } 24117 break; 24118 } 24119 24120 // if there exists a parent it cannot be primitive 24121 case value_t::string: // LCOV_EXCL_LINE 24122 case value_t::boolean: // LCOV_EXCL_LINE 24123 case value_t::number_integer: // LCOV_EXCL_LINE 24124 case value_t::number_unsigned: // LCOV_EXCL_LINE 24125 case value_t::number_float: // LCOV_EXCL_LINE 24126 case value_t::binary: // LCOV_EXCL_LINE 24127 case value_t::discarded: // LCOV_EXCL_LINE 24128 default: // LCOV_EXCL_LINE 24129 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 24130 } 24131 }; 24132 24133 // wrapper for "remove" operation; remove value at ptr 24134 const auto operation_remove = [this, & result](json_pointer & ptr) 24135 { 24136 // get reference to parent of JSON pointer ptr 24137 const auto last_path = ptr.back(); 24138 ptr.pop_back(); 24139 basic_json& parent = result.at(ptr); 24140 24141 // remove child 24142 if (parent.is_object()) 24143 { 24144 // perform range check 24145 auto it = parent.find(last_path); 24146 if (JSON_HEDLEY_LIKELY(it != parent.end())) 24147 { 24148 parent.erase(it); 24149 } 24150 else 24151 { 24152 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this)); 24153 } 24154 } 24155 else if (parent.is_array()) 24156 { 24157 // note erase performs range check 24158 parent.erase(json_pointer::template array_index<basic_json_t>(last_path)); 24159 } 24160 }; 24161 24162 // type check: top level value must be an array 24163 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) 24164 { 24165 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch)); 24166 } 24167 24168 // iterate and apply the operations 24169 for (const auto& val : json_patch) 24170 { 24171 // wrapper to get a value for an operation 24172 const auto get_value = [&val](const std::string & op, 24173 const std::string & member, 24174 bool string_type) -> basic_json & 24175 { 24176 // find value 24177 auto it = val.m_data.m_value.object->find(member); 24178 24179 // context-sensitive error message 24180 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); 24181 24182 // check if desired value is present 24183 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) 24184 { 24185 // NOLINTNEXTLINE(performance-inefficient-string-concatenation) 24186 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val)); 24187 } 24188 24189 // check if result is of type string 24190 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) 24191 { 24192 // NOLINTNEXTLINE(performance-inefficient-string-concatenation) 24193 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val)); 24194 } 24195 24196 // no error: return value 24197 return it->second; 24198 }; 24199 24200 // type check: every element of the array must be an object 24201 if (JSON_HEDLEY_UNLIKELY(!val.is_object())) 24202 { 24203 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val)); 24204 } 24205 24206 // collect mandatory members 24207 const auto op = get_value("op", "op", true).template get<std::string>(); 24208 const auto path = get_value(op, "path", true).template get<std::string>(); 24209 json_pointer ptr(path); 24210 24211 switch (get_op(op)) 24212 { 24213 case patch_operations::add: 24214 { 24215 operation_add(ptr, get_value("add", "value", false)); 24216 break; 24217 } 24218 24219 case patch_operations::remove: 24220 { 24221 operation_remove(ptr); 24222 break; 24223 } 24224 24225 case patch_operations::replace: 24226 { 24227 // the "path" location must exist - use at() 24228 result.at(ptr) = get_value("replace", "value", false); 24229 break; 24230 } 24231 24232 case patch_operations::move: 24233 { 24234 const auto from_path = get_value("move", "from", true).template get<std::string>(); 24235 json_pointer from_ptr(from_path); 24236 24237 // the "from" location must exist - use at() 24238 basic_json const v = result.at(from_ptr); 24239 24240 // The move operation is functionally identical to a 24241 // "remove" operation on the "from" location, followed 24242 // immediately by an "add" operation at the target 24243 // location with the value that was just removed. 24244 operation_remove(from_ptr); 24245 operation_add(ptr, v); 24246 break; 24247 } 24248 24249 case patch_operations::copy: 24250 { 24251 const auto from_path = get_value("copy", "from", true).template get<std::string>(); 24252 const json_pointer from_ptr(from_path); 24253 24254 // the "from" location must exist - use at() 24255 basic_json const v = result.at(from_ptr); 24256 24257 // The copy is functionally identical to an "add" 24258 // operation at the target location using the value 24259 // specified in the "from" member. 24260 operation_add(ptr, v); 24261 break; 24262 } 24263 24264 case patch_operations::test: 24265 { 24266 bool success = false; 24267 JSON_TRY 24268 { 24269 // check if "value" matches the one at "path" 24270 // the "path" location must exist - use at() 24271 success = (result.at(ptr) == get_value("test", "value", false)); 24272 } 24273 JSON_INTERNAL_CATCH (out_of_range&) 24274 { 24275 // ignore out of range errors: success remains false 24276 } 24277 24278 // throw an exception if test fails 24279 if (JSON_HEDLEY_UNLIKELY(!success)) 24280 { 24281 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val)); 24282 } 24283 24284 break; 24285 } 24286 24287 case patch_operations::invalid: 24288 default: 24289 { 24290 // op must be "add", "remove", "replace", "move", "copy", or 24291 // "test" 24292 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val)); 24293 } 24294 } 24295 } 24296 } 24297 24298 /// @brief applies a JSON patch to a copy of the current object 24299 /// @sa https://json.nlohmann.me/api/basic_json/patch/ 24300 basic_json patch(const basic_json& json_patch) const 24301 { 24302 basic_json result = *this; 24303 result.patch_inplace(json_patch); 24304 return result; 24305 } 24306 24307 /// @brief creates a diff as a JSON patch 24308 /// @sa https://json.nlohmann.me/api/basic_json/diff/ 24309 JSON_HEDLEY_WARN_UNUSED_RESULT 24310 static basic_json diff(const basic_json& source, const basic_json& target, 24311 const std::string& path = "") 24312 { 24313 // the patch 24314 basic_json result(value_t::array); 24315 24316 // if the values are the same, return empty patch 24317 if (source == target) 24318 { 24319 return result; 24320 } 24321 24322 if (source.type() != target.type()) 24323 { 24324 // different types: replace value 24325 result.push_back( 24326 { 24327 {"op", "replace"}, {"path", path}, {"value", target} 24328 }); 24329 return result; 24330 } 24331 24332 switch (source.type()) 24333 { 24334 case value_t::array: 24335 { 24336 // first pass: traverse common elements 24337 std::size_t i = 0; 24338 while (i < source.size() && i < target.size()) 24339 { 24340 // recursive call to compare array values at index i 24341 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i))); 24342 result.insert(result.end(), temp_diff.begin(), temp_diff.end()); 24343 ++i; 24344 } 24345 24346 // We now reached the end of at least one array 24347 // in a second pass, traverse the remaining elements 24348 24349 // remove my remaining elements 24350 const auto end_index = static_cast<difference_type>(result.size()); 24351 while (i < source.size()) 24352 { 24353 // add operations in reverse order to avoid invalid 24354 // indices 24355 result.insert(result.begin() + end_index, object( 24356 { 24357 {"op", "remove"}, 24358 {"path", detail::concat(path, '/', std::to_string(i))} 24359 })); 24360 ++i; 24361 } 24362 24363 // add other remaining elements 24364 while (i < target.size()) 24365 { 24366 result.push_back( 24367 { 24368 {"op", "add"}, 24369 {"path", detail::concat(path, "/-")}, 24370 {"value", target[i]} 24371 }); 24372 ++i; 24373 } 24374 24375 break; 24376 } 24377 24378 case value_t::object: 24379 { 24380 // first pass: traverse this object's elements 24381 for (auto it = source.cbegin(); it != source.cend(); ++it) 24382 { 24383 // escape the key name to be used in a JSON patch 24384 const auto path_key = detail::concat(path, '/', detail::escape(it.key())); 24385 24386 if (target.find(it.key()) != target.end()) 24387 { 24388 // recursive call to compare object values at key it 24389 auto temp_diff = diff(it.value(), target[it.key()], path_key); 24390 result.insert(result.end(), temp_diff.begin(), temp_diff.end()); 24391 } 24392 else 24393 { 24394 // found a key that is not in o -> remove it 24395 result.push_back(object( 24396 { 24397 {"op", "remove"}, {"path", path_key} 24398 })); 24399 } 24400 } 24401 24402 // second pass: traverse other object's elements 24403 for (auto it = target.cbegin(); it != target.cend(); ++it) 24404 { 24405 if (source.find(it.key()) == source.end()) 24406 { 24407 // found a key that is not in this -> add it 24408 const auto path_key = detail::concat(path, '/', detail::escape(it.key())); 24409 result.push_back( 24410 { 24411 {"op", "add"}, {"path", path_key}, 24412 {"value", it.value()} 24413 }); 24414 } 24415 } 24416 24417 break; 24418 } 24419 24420 case value_t::null: 24421 case value_t::string: 24422 case value_t::boolean: 24423 case value_t::number_integer: 24424 case value_t::number_unsigned: 24425 case value_t::number_float: 24426 case value_t::binary: 24427 case value_t::discarded: 24428 default: 24429 { 24430 // both primitive type: replace value 24431 result.push_back( 24432 { 24433 {"op", "replace"}, {"path", path}, {"value", target} 24434 }); 24435 break; 24436 } 24437 } 24438 24439 return result; 24440 } 24441 /// @} 24442 24443 //////////////////////////////// 24444 // JSON Merge Patch functions // 24445 //////////////////////////////// 24446 24447 /// @name JSON Merge Patch functions 24448 /// @{ 24449 24450 /// @brief applies a JSON Merge Patch 24451 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/ 24452 void merge_patch(const basic_json& apply_patch) 24453 { 24454 if (apply_patch.is_object()) 24455 { 24456 if (!is_object()) 24457 { 24458 *this = object(); 24459 } 24460 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) 24461 { 24462 if (it.value().is_null()) 24463 { 24464 erase(it.key()); 24465 } 24466 else 24467 { 24468 operator[](it.key()).merge_patch(it.value()); 24469 } 24470 } 24471 } 24472 else 24473 { 24474 *this = apply_patch; 24475 } 24476 } 24477 24478 /// @} 24479 }; 24480 24481 /// @brief user-defined to_string function for JSON values 24482 /// @sa https://json.nlohmann.me/api/basic_json/to_string/ 24483 NLOHMANN_BASIC_JSON_TPL_DECLARATION 24484 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) 24485 { 24486 return j.dump(); 24487 } 24488 24489 inline namespace literals 24490 { 24491 inline namespace json_literals 24492 { 24493 24494 /// @brief user-defined string literal for JSON values 24495 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ 24496 JSON_HEDLEY_NON_NULL(1) 24497 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) 24498 inline nlohmann::json operator ""_json(const char* s, std::size_t n) 24499 #else 24500 inline nlohmann::json operator "" _json(const char* s, std::size_t n) 24501 #endif 24502 { 24503 return nlohmann::json::parse(s, s + n); 24504 } 24505 24506 /// @brief user-defined string literal for JSON pointer 24507 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ 24508 JSON_HEDLEY_NON_NULL(1) 24509 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) 24510 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n) 24511 #else 24512 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) 24513 #endif 24514 { 24515 return nlohmann::json::json_pointer(std::string(s, n)); 24516 } 24517 24518 } // namespace json_literals 24519 } // namespace literals 24520 NLOHMANN_JSON_NAMESPACE_END 24521 24522 /////////////////////// 24523 // nonmember support // 24524 /////////////////////// 24525 24526 namespace std // NOLINT(cert-dcl58-cpp) 24527 { 24528 24529 /// @brief hash value for JSON objects 24530 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/ 24531 NLOHMANN_BASIC_JSON_TPL_DECLARATION 24532 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp) 24533 { 24534 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const 24535 { 24536 return nlohmann::detail::hash(j); 24537 } 24538 }; 24539 24540 // specialization for std::less<value_t> 24541 template<> 24542 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679 24543 { 24544 /*! 24545 @brief compare two value_t enum values 24546 @since version 3.0.0 24547 */ 24548 bool operator()(::nlohmann::detail::value_t lhs, 24549 ::nlohmann::detail::value_t rhs) const noexcept 24550 { 24551 #if JSON_HAS_THREE_WAY_COMPARISON 24552 return std::is_lt(lhs <=> rhs); // *NOPAD* 24553 #else 24554 return ::nlohmann::detail::operator<(lhs, rhs); 24555 #endif 24556 } 24557 }; 24558 24559 // C++20 prohibit function specialization in the std namespace. 24560 #ifndef JSON_HAS_CPP_20 24561 24562 /// @brief exchanges the values of two JSON objects 24563 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/ 24564 NLOHMANN_BASIC_JSON_TPL_DECLARATION 24565 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) 24566 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 24567 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value) 24568 { 24569 j1.swap(j2); 24570 } 24571 24572 #endif 24573 24574 } // namespace std 24575 24576 #if JSON_USE_GLOBAL_UDLS 24577 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) 24578 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24579 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24580 #else 24581 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24582 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) 24583 #endif 24584 #endif 24585 24586 // #include <nlohmann/detail/macro_unscope.hpp> 24587 // __ _____ _____ _____ 24588 // __| | __| | | | JSON for Modern C++ 24589 // | | |__ | | | | | | version 3.11.3 24590 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 24591 // 24592 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 24593 // SPDX-License-Identifier: MIT 24594 24595 24596 24597 // restore clang diagnostic settings 24598 #if defined(__clang__) 24599 #pragma clang diagnostic pop 24600 #endif 24601 24602 // clean up 24603 #undef JSON_ASSERT 24604 #undef JSON_INTERNAL_CATCH 24605 #undef JSON_THROW 24606 #undef JSON_PRIVATE_UNLESS_TESTED 24607 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION 24608 #undef NLOHMANN_BASIC_JSON_TPL 24609 #undef JSON_EXPLICIT 24610 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL 24611 #undef JSON_INLINE_VARIABLE 24612 #undef JSON_NO_UNIQUE_ADDRESS 24613 #undef JSON_DISABLE_ENUM_SERIALIZATION 24614 #undef JSON_USE_GLOBAL_UDLS 24615 24616 #ifndef JSON_TEST_KEEP_MACROS 24617 #undef JSON_CATCH 24618 #undef JSON_TRY 24619 #undef JSON_HAS_CPP_11 24620 #undef JSON_HAS_CPP_14 24621 #undef JSON_HAS_CPP_17 24622 #undef JSON_HAS_CPP_20 24623 #undef JSON_HAS_FILESYSTEM 24624 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM 24625 #undef JSON_HAS_THREE_WAY_COMPARISON 24626 #undef JSON_HAS_RANGES 24627 #undef JSON_HAS_STATIC_RTTI 24628 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 24629 #endif 24630 24631 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp> 24632 // __ _____ _____ _____ 24633 // __| | __| | | | JSON for Modern C++ 24634 // | | |__ | | | | | | version 3.11.3 24635 // |_____|_____|_____|_|___| https://github.com/nlohmann/json 24636 // 24637 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> 24638 // SPDX-License-Identifier: MIT 24639 24640 24641 24642 #undef JSON_HEDLEY_ALWAYS_INLINE 24643 #undef JSON_HEDLEY_ARM_VERSION 24644 #undef JSON_HEDLEY_ARM_VERSION_CHECK 24645 #undef JSON_HEDLEY_ARRAY_PARAM 24646 #undef JSON_HEDLEY_ASSUME 24647 #undef JSON_HEDLEY_BEGIN_C_DECLS 24648 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE 24649 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN 24650 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE 24651 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE 24652 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION 24653 #undef JSON_HEDLEY_CLANG_HAS_FEATURE 24654 #undef JSON_HEDLEY_CLANG_HAS_WARNING 24655 #undef JSON_HEDLEY_COMPCERT_VERSION 24656 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK 24657 #undef JSON_HEDLEY_CONCAT 24658 #undef JSON_HEDLEY_CONCAT3 24659 #undef JSON_HEDLEY_CONCAT3_EX 24660 #undef JSON_HEDLEY_CONCAT_EX 24661 #undef JSON_HEDLEY_CONST 24662 #undef JSON_HEDLEY_CONSTEXPR 24663 #undef JSON_HEDLEY_CONST_CAST 24664 #undef JSON_HEDLEY_CPP_CAST 24665 #undef JSON_HEDLEY_CRAY_VERSION 24666 #undef JSON_HEDLEY_CRAY_VERSION_CHECK 24667 #undef JSON_HEDLEY_C_DECL 24668 #undef JSON_HEDLEY_DEPRECATED 24669 #undef JSON_HEDLEY_DEPRECATED_FOR 24670 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL 24671 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ 24672 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED 24673 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES 24674 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS 24675 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION 24676 #undef JSON_HEDLEY_DIAGNOSTIC_POP 24677 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH 24678 #undef JSON_HEDLEY_DMC_VERSION 24679 #undef JSON_HEDLEY_DMC_VERSION_CHECK 24680 #undef JSON_HEDLEY_EMPTY_BASES 24681 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION 24682 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK 24683 #undef JSON_HEDLEY_END_C_DECLS 24684 #undef JSON_HEDLEY_FLAGS 24685 #undef JSON_HEDLEY_FLAGS_CAST 24686 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE 24687 #undef JSON_HEDLEY_GCC_HAS_BUILTIN 24688 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE 24689 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE 24690 #undef JSON_HEDLEY_GCC_HAS_EXTENSION 24691 #undef JSON_HEDLEY_GCC_HAS_FEATURE 24692 #undef JSON_HEDLEY_GCC_HAS_WARNING 24693 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK 24694 #undef JSON_HEDLEY_GCC_VERSION 24695 #undef JSON_HEDLEY_GCC_VERSION_CHECK 24696 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE 24697 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN 24698 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE 24699 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE 24700 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION 24701 #undef JSON_HEDLEY_GNUC_HAS_FEATURE 24702 #undef JSON_HEDLEY_GNUC_HAS_WARNING 24703 #undef JSON_HEDLEY_GNUC_VERSION 24704 #undef JSON_HEDLEY_GNUC_VERSION_CHECK 24705 #undef JSON_HEDLEY_HAS_ATTRIBUTE 24706 #undef JSON_HEDLEY_HAS_BUILTIN 24707 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE 24708 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS 24709 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE 24710 #undef JSON_HEDLEY_HAS_EXTENSION 24711 #undef JSON_HEDLEY_HAS_FEATURE 24712 #undef JSON_HEDLEY_HAS_WARNING 24713 #undef JSON_HEDLEY_IAR_VERSION 24714 #undef JSON_HEDLEY_IAR_VERSION_CHECK 24715 #undef JSON_HEDLEY_IBM_VERSION 24716 #undef JSON_HEDLEY_IBM_VERSION_CHECK 24717 #undef JSON_HEDLEY_IMPORT 24718 #undef JSON_HEDLEY_INLINE 24719 #undef JSON_HEDLEY_INTEL_CL_VERSION 24720 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK 24721 #undef JSON_HEDLEY_INTEL_VERSION 24722 #undef JSON_HEDLEY_INTEL_VERSION_CHECK 24723 #undef JSON_HEDLEY_IS_CONSTANT 24724 #undef JSON_HEDLEY_IS_CONSTEXPR_ 24725 #undef JSON_HEDLEY_LIKELY 24726 #undef JSON_HEDLEY_MALLOC 24727 #undef JSON_HEDLEY_MCST_LCC_VERSION 24728 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK 24729 #undef JSON_HEDLEY_MESSAGE 24730 #undef JSON_HEDLEY_MSVC_VERSION 24731 #undef JSON_HEDLEY_MSVC_VERSION_CHECK 24732 #undef JSON_HEDLEY_NEVER_INLINE 24733 #undef JSON_HEDLEY_NON_NULL 24734 #undef JSON_HEDLEY_NO_ESCAPE 24735 #undef JSON_HEDLEY_NO_RETURN 24736 #undef JSON_HEDLEY_NO_THROW 24737 #undef JSON_HEDLEY_NULL 24738 #undef JSON_HEDLEY_PELLES_VERSION 24739 #undef JSON_HEDLEY_PELLES_VERSION_CHECK 24740 #undef JSON_HEDLEY_PGI_VERSION 24741 #undef JSON_HEDLEY_PGI_VERSION_CHECK 24742 #undef JSON_HEDLEY_PREDICT 24743 #undef JSON_HEDLEY_PRINTF_FORMAT 24744 #undef JSON_HEDLEY_PRIVATE 24745 #undef JSON_HEDLEY_PUBLIC 24746 #undef JSON_HEDLEY_PURE 24747 #undef JSON_HEDLEY_REINTERPRET_CAST 24748 #undef JSON_HEDLEY_REQUIRE 24749 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR 24750 #undef JSON_HEDLEY_REQUIRE_MSG 24751 #undef JSON_HEDLEY_RESTRICT 24752 #undef JSON_HEDLEY_RETURNS_NON_NULL 24753 #undef JSON_HEDLEY_SENTINEL 24754 #undef JSON_HEDLEY_STATIC_ASSERT 24755 #undef JSON_HEDLEY_STATIC_CAST 24756 #undef JSON_HEDLEY_STRINGIFY 24757 #undef JSON_HEDLEY_STRINGIFY_EX 24758 #undef JSON_HEDLEY_SUNPRO_VERSION 24759 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK 24760 #undef JSON_HEDLEY_TINYC_VERSION 24761 #undef JSON_HEDLEY_TINYC_VERSION_CHECK 24762 #undef JSON_HEDLEY_TI_ARMCL_VERSION 24763 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK 24764 #undef JSON_HEDLEY_TI_CL2000_VERSION 24765 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK 24766 #undef JSON_HEDLEY_TI_CL430_VERSION 24767 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK 24768 #undef JSON_HEDLEY_TI_CL6X_VERSION 24769 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK 24770 #undef JSON_HEDLEY_TI_CL7X_VERSION 24771 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK 24772 #undef JSON_HEDLEY_TI_CLPRU_VERSION 24773 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK 24774 #undef JSON_HEDLEY_TI_VERSION 24775 #undef JSON_HEDLEY_TI_VERSION_CHECK 24776 #undef JSON_HEDLEY_UNAVAILABLE 24777 #undef JSON_HEDLEY_UNLIKELY 24778 #undef JSON_HEDLEY_UNPREDICTABLE 24779 #undef JSON_HEDLEY_UNREACHABLE 24780 #undef JSON_HEDLEY_UNREACHABLE_RETURN 24781 #undef JSON_HEDLEY_VERSION 24782 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR 24783 #undef JSON_HEDLEY_VERSION_DECODE_MINOR 24784 #undef JSON_HEDLEY_VERSION_DECODE_REVISION 24785 #undef JSON_HEDLEY_VERSION_ENCODE 24786 #undef JSON_HEDLEY_WARNING 24787 #undef JSON_HEDLEY_WARN_UNUSED_RESULT 24788 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG 24789 #undef JSON_HEDLEY_FALL_THROUGH 24790 24791 24792 24793 #endif // INCLUDE_NLOHMANN_JSON_HPP_