GameApi 28
Library used by GameApi Builder tool
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1/*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++
4| | |__ | | | | | | version 3.5.0
5|_____|_____|_____|_|___| https://github.com/nlohmann/json
6
7Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8SPDX-License-Identifier: MIT
9Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27SOFTWARE.
28*/
29
30#ifndef NLOHMANN_JSON_HPP
31#define NLOHMANN_JSON_HPP
32
33#define NLOHMANN_JSON_VERSION_MAJOR 3
34#define NLOHMANN_JSON_VERSION_MINOR 5
35#define NLOHMANN_JSON_VERSION_PATCH 0
36
37#include <algorithm> // all_of, find, for_each
38#include <cassert> // assert
39#include <ciso646> // and, not, or
40#include <cstddef> // nullptr_t, ptrdiff_t, size_t
41#include <functional> // hash, less
42#include <initializer_list> // initializer_list
43#include <iosfwd> // istream, ostream
44#include <iterator> // random_access_iterator_tag
45#include <numeric> // accumulate
46#include <string> // string, stoi, to_string
47#include <utility> // declval, forward, move, pair, swap
48#include <iostream>
49
50// #include <nlohmann/json_fwd.hpp>
51#ifndef NLOHMANN_JSON_FWD_HPP
52#define NLOHMANN_JSON_FWD_HPP
53
54#include <cstdint> // int64_t, uint64_t
55#include <map> // map
56#include <memory> // allocator
57#include <string> // string
58#include <vector> // vector
59
65namespace nlohmann
66{
74template<typename T = void, typename SFINAE = void>
75struct adl_serializer;
76
77template<template<typename U, typename V, typename... Args> class ObjectType =
78 std::map,
79 template<typename U, typename... Args> class ArrayType = std::vector,
80 class StringType = std::string, class BooleanType = bool,
81 class NumberIntegerType = std::int64_t,
82 class NumberUnsignedType = std::uint64_t,
83 class NumberFloatType = double,
84 template<typename U> class AllocatorType = std::allocator,
85 template<typename T, typename SFINAE = void> class JSONSerializer =
87class basic_json;
88
100template<typename BasicJsonType>
101class json_pointer;
102
112} // namespace nlohmann
113
114#endif
115
116// #include <nlohmann/detail/macro_scope.hpp>
117
118
119// This file contains all internal macro definitions
120// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
121
122// exclude unsupported compilers
123#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
124 #if defined(__clang__)
125 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
126 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
127 #endif
128 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
129 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
130 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
131 #endif
132 #endif
133#endif
134
135// disable float-equal warnings on GCC/clang
136#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
137 #pragma GCC diagnostic push
138 #pragma GCC diagnostic ignored "-Wfloat-equal"
139#endif
140
141// disable documentation warnings on clang
142#if defined(__clang__)
143 #pragma GCC diagnostic push
144 #pragma GCC diagnostic ignored "-Wdocumentation"
145#endif
146
147// allow for portable deprecation warnings
148#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
149 #define JSON_DEPRECATED __attribute__((deprecated))
150#elif defined(_MSC_VER)
151 #define JSON_DEPRECATED __declspec(deprecated)
152#else
153 #define JSON_DEPRECATED
154#endif
155
156// allow to disable exceptions
157#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
158 #define JSON_THROW(exception) throw exception
159 #define JSON_TRY try
160 #define JSON_CATCH(exception) catch(exception)
161 #define JSON_INTERNAL_CATCH(exception) catch(exception)
162#else
163 #define JSON_THROW(exception) std::abort()
164 #define JSON_TRY if(true)
165 #define JSON_CATCH(exception) if(false)
166 #define JSON_INTERNAL_CATCH(exception) if(false)
167#endif
168
169// override exception macros
170#if defined(JSON_THROW_USER)
171 #undef JSON_THROW
172 #define JSON_THROW JSON_THROW_USER
173#endif
174#if defined(JSON_TRY_USER)
175 #undef JSON_TRY
176 #define JSON_TRY JSON_TRY_USER
177#endif
178#if defined(JSON_CATCH_USER)
179 #undef JSON_CATCH
180 #define JSON_CATCH JSON_CATCH_USER
181 #undef JSON_INTERNAL_CATCH
182 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
183#endif
184#if defined(JSON_INTERNAL_CATCH_USER)
185 #undef JSON_INTERNAL_CATCH
186 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
187#endif
188
189// manual branch prediction
190#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
191 #define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
192 #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
193#else
194 #define JSON_LIKELY(x) x
195 #define JSON_UNLIKELY(x) x
196#endif
197
198// C++ language standard detection
199#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
200 #define JSON_HAS_CPP_17
201 #define JSON_HAS_CPP_14
202#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
203 #define JSON_HAS_CPP_14
204#endif
205
211#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
212 template<typename BasicJsonType> \
213 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
214 { \
215 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
216 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
217 auto it = std::find_if(std::begin(m), std::end(m), \
218 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
219 { \
220 return ej_pair.first == e; \
221 }); \
222 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
223 } \
224 template<typename BasicJsonType> \
225 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
226 { \
227 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
228 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
229 auto it = std::find_if(std::begin(m), std::end(m), \
230 [j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
231 { \
232 return ej_pair.second == j; \
233 }); \
234 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
235 }
236
237// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
238// may be removed in the future once the class is split.
239
240#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
241 template<template<typename, typename, typename...> class ObjectType, \
242 template<typename, typename...> class ArrayType, \
243 class StringType, class BooleanType, class NumberIntegerType, \
244 class NumberUnsignedType, class NumberFloatType, \
245 template<typename> class AllocatorType, \
246 template<typename, typename = void> class JSONSerializer>
247
248#define NLOHMANN_BASIC_JSON_TPL \
249 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
250 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
251 AllocatorType, JSONSerializer>
252
253// #include <nlohmann/detail/meta/cpp_future.hpp>
254
255
256#include <ciso646> // not
257#include <cstddef> // size_t
258#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
259
260namespace nlohmann
261{
262namespace detail
263{
264// alias templates to reduce boilerplate
265template<bool B, typename T = void>
266using enable_if_t = typename std::enable_if<B, T>::type;
267
268template<typename T>
269using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
270
271// implementation of C++14 index_sequence and affiliates
272// source: https://stackoverflow.com/a/32223343
273template<std::size_t... Ints>
275{
277 using value_type = std::size_t;
278 static constexpr std::size_t size() noexcept
279 {
280 return sizeof...(Ints);
281 }
282};
283
284template<class Sequence1, class Sequence2>
286
287template<std::size_t... I1, std::size_t... I2>
289 : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
290
291template<std::size_t N>
293 : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
294 typename make_index_sequence < N - N / 2 >::type > {};
295
296template<> struct make_index_sequence<0> : index_sequence<> {};
297template<> struct make_index_sequence<1> : index_sequence<0> {};
298
299template<typename... Ts>
301
302// dispatch utility (taken from ranges-v3)
303template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
304template<> struct priority_tag<0> {};
305
306// taken from ranges-v3
307template<typename T>
309{
310 static constexpr T value{};
311};
312
313template<typename T>
315} // namespace detail
316} // namespace nlohmann
317
318// #include <nlohmann/detail/meta/type_traits.hpp>
319
320
321#include <ciso646> // not
322#include <limits> // numeric_limits
323#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
324#include <utility> // declval
325
326// #include <nlohmann/json_fwd.hpp>
327
328// #include <nlohmann/detail/iterators/iterator_traits.hpp>
329
330
331#include <iterator> // random_access_iterator_tag
332
333// #include <nlohmann/detail/meta/void_t.hpp>
334
335
336namespace nlohmann
337{
338namespace detail
339{
340template <typename ...Ts> struct make_void
341{
342 using type = void;
343};
344template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
345} // namespace detail
346} // namespace nlohmann
347
348// #include <nlohmann/detail/meta/cpp_future.hpp>
349
350
351namespace nlohmann
352{
353namespace detail
354{
355template <typename It, typename = void>
357
358template <typename It>
360 It,
361 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
362 typename It::reference, typename It::iterator_category >>
363{
364 using difference_type = typename It::difference_type;
365 using value_type = typename It::value_type;
366 using pointer = typename It::pointer;
367 using reference = typename It::reference;
368 using iterator_category = typename It::iterator_category;
369};
370
371// This is required as some compilers implement std::iterator_traits in a way that
372// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
373template <typename T, typename = void>
375{
376};
377
378template <typename T>
379struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
380 : iterator_types<T>
381{
382};
383
384template <typename T>
386{
387 using iterator_category = std::random_access_iterator_tag;
388 using value_type = T;
389 using difference_type = ptrdiff_t;
390 using pointer = T*;
391 using reference = T&;
392};
393}
394}
395
396// #include <nlohmann/detail/meta/cpp_future.hpp>
397
398// #include <nlohmann/detail/meta/detected.hpp>
399
400
401#include <type_traits>
402
403// #include <nlohmann/detail/meta/void_t.hpp>
404
405
406// http://en.cppreference.com/w/cpp/experimental/is_detected
407namespace nlohmann
408{
409namespace detail
410{
412{
413 nonesuch() = delete;
414 ~nonesuch() = delete;
415 nonesuch(nonesuch const&) = delete;
416 void operator=(nonesuch const&) = delete;
417};
418
419template <class Default,
420 class AlwaysVoid,
421 template <class...> class Op,
422 class... Args>
424{
425 using value_t = std::false_type;
426 using type = Default;
427};
428
429template <class Default, template <class...> class Op, class... Args>
430struct detector<Default, void_t<Op<Args...>>, Op, Args...>
431{
432 using value_t = std::true_type;
433 using type = Op<Args...>;
434};
435
436template <template <class...> class Op, class... Args>
437using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
438
439template <template <class...> class Op, class... Args>
440using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
441
442template <class Default, template <class...> class Op, class... Args>
443using detected_or = detector<Default, void, Op, Args...>;
444
445template <class Default, template <class...> class Op, class... Args>
446using detected_or_t = typename detected_or<Default, Op, Args...>::type;
447
448template <class Expected, template <class...> class Op, class... Args>
449using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
450
451template <class To, template <class...> class Op, class... Args>
453 std::is_convertible<detected_t<Op, Args...>, To>;
454} // namespace detail
455} // namespace nlohmann
456
457// #include <nlohmann/detail/macro_scope.hpp>
458
459
460namespace nlohmann
461{
470namespace detail
471{
473// helpers //
475
476// Note to maintainers:
477//
478// Every trait in this file expects a non CV-qualified type.
479// The only exceptions are in the 'aliases for detected' section
480// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
481//
482// In this case, T has to be properly CV-qualified to constraint the function arguments
483// (e.g. to_json(BasicJsonType&, const T&))
484
485template<typename> struct is_basic_json : std::false_type {};
486
488struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
489
491// aliases for detected //
493
494template <typename T>
495using mapped_type_t = typename T::mapped_type;
496
497template <typename T>
498using key_type_t = typename T::key_type;
499
500template <typename T>
501using value_type_t = typename T::value_type;
502
503template <typename T>
504using difference_type_t = typename T::difference_type;
505
506template <typename T>
507using pointer_t = typename T::pointer;
508
509template <typename T>
510using reference_t = typename T::reference;
511
512template <typename T>
513using iterator_category_t = typename T::iterator_category;
514
515template <typename T>
516using iterator_t = typename T::iterator;
517
518template <typename T, typename... Args>
519using to_json_function = decltype(T::to_json(std::declval<Args>()...));
520
521template <typename T, typename... Args>
522using from_json_function = decltype(T::from_json(std::declval<Args>()...));
523
524template <typename T, typename U>
525using get_template_function = decltype(std::declval<T>().template get<U>());
526
527// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
528template <typename BasicJsonType, typename T, typename = void>
529struct has_from_json : std::false_type {};
530
531template <typename BasicJsonType, typename T>
532struct has_from_json<BasicJsonType, T,
534{
535 using serializer = typename BasicJsonType::template json_serializer<T, void>;
536
537 static constexpr bool value =
539 const BasicJsonType&, T&>::value;
540};
541
542// This trait checks if JSONSerializer<T>::from_json(json const&) exists
543// this overload is used for non-default-constructible user-defined-types
544template <typename BasicJsonType, typename T, typename = void>
545struct has_non_default_from_json : std::false_type {};
546
547template<typename BasicJsonType, typename T>
549{
550 using serializer = typename BasicJsonType::template json_serializer<T, void>;
551
552 static constexpr bool value =
554 const BasicJsonType&>::value;
555};
556
557// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
558// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
559template <typename BasicJsonType, typename T, typename = void>
560struct has_to_json : std::false_type {};
561
562template <typename BasicJsonType, typename T>
563struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
564{
565 using serializer = typename BasicJsonType::template json_serializer<T, void>;
566
567 static constexpr bool value =
568 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
569 T>::value;
570};
571
572
574// is_ functions //
576
577template <typename T, typename = void>
578struct is_iterator_traits : std::false_type {};
579
580template <typename T>
594
595// source: https://stackoverflow.com/a/37193089/4116453
596
597template <typename T, typename = void>
598struct is_complete_type : std::false_type {};
599
600template <typename T>
601struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
602
603template <typename BasicJsonType, typename CompatibleObjectType,
604 typename = void>
605struct is_compatible_object_type_impl : std::false_type {};
606
607template <typename BasicJsonType, typename CompatibleObjectType>
609 BasicJsonType, CompatibleObjectType,
610 enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
611 is_detected<key_type_t, CompatibleObjectType>::value >>
612{
613
614 using object_t = typename BasicJsonType::object_t;
615
616 // macOS's is_constructible does not play well with nonesuch...
617 static constexpr bool value =
618 std::is_constructible<typename object_t::key_type,
619 typename CompatibleObjectType::key_type>::value and
620 std::is_constructible<typename object_t::mapped_type,
621 typename CompatibleObjectType::mapped_type>::value;
622};
623
624template <typename BasicJsonType, typename CompatibleObjectType>
626 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
627
628template <typename BasicJsonType, typename ConstructibleObjectType,
629 typename = void>
630struct is_constructible_object_type_impl : std::false_type {};
631
632template <typename BasicJsonType, typename ConstructibleObjectType>
634 BasicJsonType, ConstructibleObjectType,
635 enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and
636 is_detected<key_type_t, ConstructibleObjectType>::value >>
637{
638 using object_t = typename BasicJsonType::object_t;
639
640 static constexpr bool value =
641 (std::is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value and
642 std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value) or
645};
646
647template <typename BasicJsonType, typename ConstructibleObjectType>
649 : is_constructible_object_type_impl<BasicJsonType,
650 ConstructibleObjectType> {};
651
652template <typename BasicJsonType, typename CompatibleStringType,
653 typename = void>
654struct is_compatible_string_type_impl : std::false_type {};
655
656template <typename BasicJsonType, typename CompatibleStringType>
658 BasicJsonType, CompatibleStringType,
659 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
660 value_type_t, CompatibleStringType>::value >>
661{
662 static constexpr auto value =
663 std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
664};
665
666template <typename BasicJsonType, typename ConstructibleStringType>
668 : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
669
670template <typename BasicJsonType, typename ConstructibleStringType,
671 typename = void>
672struct is_constructible_string_type_impl : std::false_type {};
673
674template <typename BasicJsonType, typename ConstructibleStringType>
676 BasicJsonType, ConstructibleStringType,
677 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
678 value_type_t, ConstructibleStringType>::value >>
679{
680 static constexpr auto value =
681 std::is_constructible<ConstructibleStringType,
682 typename BasicJsonType::string_t>::value;
683};
684
685template <typename BasicJsonType, typename ConstructibleStringType>
687 : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
688
689template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
690struct is_compatible_array_type_impl : std::false_type {};
691
692template <typename BasicJsonType, typename CompatibleArrayType>
694 BasicJsonType, CompatibleArrayType,
695 enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
696 is_detected<iterator_t, CompatibleArrayType>::value and
697// This is needed because json_reverse_iterator has a ::iterator type...
698// Therefore it is detected as a CompatibleArrayType.
699// The real fix would be to have an Iterable concept.
701 iterator_traits<CompatibleArrayType>>::value >>
702{
703 static constexpr bool value =
704 std::is_constructible<BasicJsonType,
705 typename CompatibleArrayType::value_type>::value;
706};
707
708template <typename BasicJsonType, typename CompatibleArrayType>
710 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
711
712template <typename BasicJsonType, typename ConstructibleArrayType, typename = void>
713struct is_constructible_array_type_impl : std::false_type {};
714
715template <typename BasicJsonType, typename ConstructibleArrayType>
717 BasicJsonType, ConstructibleArrayType,
718 enable_if_t<std::is_same<ConstructibleArrayType,
719 typename BasicJsonType::value_type>::value >>
720 : std::true_type {};
721
722template <typename BasicJsonType, typename ConstructibleArrayType>
724 BasicJsonType, ConstructibleArrayType,
725 enable_if_t<not std::is_same<ConstructibleArrayType,
726 typename BasicJsonType::value_type>::value and
727 is_detected<value_type_t, ConstructibleArrayType>::value and
728 is_detected<iterator_t, ConstructibleArrayType>::value and
730 detected_t<value_type_t, ConstructibleArrayType>>::value >>
731{
732 static constexpr bool value =
733 // This is needed because json_reverse_iterator has a ::iterator type,
734 // furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...
735 // Therefore it is detected as a ConstructibleArrayType.
736 // The real fix would be to have an Iterable concept.
739
740 (std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
741 has_from_json<BasicJsonType,
742 typename ConstructibleArrayType::value_type>::value or
744 BasicJsonType, typename ConstructibleArrayType::value_type >::value);
745};
746
747template <typename BasicJsonType, typename ConstructibleArrayType>
749 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
750
751template <typename RealIntegerType, typename CompatibleNumberIntegerType,
752 typename = void>
753struct is_compatible_integer_type_impl : std::false_type {};
754
755template <typename RealIntegerType, typename CompatibleNumberIntegerType>
757 RealIntegerType, CompatibleNumberIntegerType,
758 enable_if_t<std::is_integral<RealIntegerType>::value and
759 std::is_integral<CompatibleNumberIntegerType>::value and
760 not std::is_same<bool, CompatibleNumberIntegerType>::value >>
761{
762 // is there an assert somewhere on overflows?
763 using RealLimits = std::numeric_limits<RealIntegerType>;
764 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
765
766 static constexpr auto value =
767 std::is_constructible<RealIntegerType,
768 CompatibleNumberIntegerType>::value and
769 CompatibleLimits::is_integer and
770 RealLimits::is_signed == CompatibleLimits::is_signed;
771};
772
773template <typename RealIntegerType, typename CompatibleNumberIntegerType>
775 : is_compatible_integer_type_impl<RealIntegerType,
776 CompatibleNumberIntegerType> {};
777
778template <typename BasicJsonType, typename CompatibleType, typename = void>
779struct is_compatible_type_impl: std::false_type {};
780
781template <typename BasicJsonType, typename CompatibleType>
783 BasicJsonType, CompatibleType,
784 enable_if_t<is_complete_type<CompatibleType>::value >>
785{
786 static constexpr bool value =
788};
789
790template <typename BasicJsonType, typename CompatibleType>
792 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
793} // namespace detail
794} // namespace nlohmann
795
796// #include <nlohmann/detail/exceptions.hpp>
797
798
799#include <exception> // exception
800#include <stdexcept> // runtime_error
801#include <string> // to_string
802
803// #include <nlohmann/detail/input/position_t.hpp>
804
805
806#include <cstddef> // size_t
807
808namespace nlohmann
809{
810namespace detail
811{
814{
816 std::size_t chars_read_total = 0;
818 std::size_t chars_read_current_line = 0;
820 std::size_t lines_read = 0;
821
823 constexpr operator size_t() const
824 {
825 return chars_read_total;
826 }
827};
828
829}
830}
831
832
833namespace nlohmann
834{
835namespace detail
836{
838// exceptions //
840
869class exception : public std::exception
870{
871 public:
873 const char* what() const noexcept override
874 {
875 return m.what();
876 }
877
879 const int id;
880
881 protected:
882 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
883
884 static std::string name(const std::string& ename, int id_)
885 {
886 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
887 }
888
889 private:
891 std::runtime_error m;
892};
893
938class parse_error : public exception
939{
940 public:
950 static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
951 {
952 std::string w = exception::name("parse_error", id_) + "parse error" +
953 position_string(pos) + ": " + what_arg;
954 return parse_error(id_, pos.chars_read_total, w.c_str());
955 }
956
957 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
958 {
959 std::string w = exception::name("parse_error", id_) + "parse error" +
960 (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
961 ": " + what_arg;
962 return parse_error(id_, byte_, w.c_str());
963 }
964
974 const std::size_t byte;
975
976 private:
977 parse_error(int id_, std::size_t byte_, const char* what_arg)
978 : exception(id_, what_arg), byte(byte_) {
979
980 std::cout << "PARSE ERROR:" << id_ << std::endl;
981 }
982
983 static std::string position_string(const position_t& pos)
984 {
985 return " at line " + std::to_string(pos.lines_read + 1) +
986 ", column " + std::to_string(pos.chars_read_current_line);
987 }
988};
989
1027class invalid_iterator : public exception
1028{
1029 public:
1030 static invalid_iterator create(int id_, const std::string& what_arg)
1031 {
1032 std::string w = exception::name("invalid_iterator", id_) + what_arg;
1033 return invalid_iterator(id_, w.c_str());
1034 }
1035
1036 private:
1037 invalid_iterator(int id_, const char* what_arg)
1038 : exception(id_, what_arg) {}
1039};
1040
1080class type_error : public exception
1081{
1082 public:
1083 static type_error create(int id_, const std::string& what_arg)
1084 {
1085 std::string w = exception::name("type_error", id_) + what_arg;
1086 return type_error(id_, w.c_str());
1087 }
1088
1089 private:
1090 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
1091};
1092
1126class out_of_range : public exception
1127{
1128 public:
1129 static out_of_range create(int id_, const std::string& what_arg)
1130 {
1131 std::string w = exception::name("out_of_range", id_) + what_arg;
1132 return out_of_range(id_, w.c_str());
1133 }
1134
1135 private:
1136 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
1137};
1138
1163class other_error : public exception
1164{
1165 public:
1166 static other_error create(int id_, const std::string& what_arg)
1167 {
1168 std::string w = exception::name("other_error", id_) + what_arg;
1169 return other_error(id_, w.c_str());
1170 }
1171
1172 private:
1173 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
1174};
1175} // namespace detail
1176} // namespace nlohmann
1177
1178// #include <nlohmann/detail/value_t.hpp>
1179
1180
1181#include <array> // array
1182#include <ciso646> // and
1183#include <cstddef> // size_t
1184#include <cstdint> // uint8_t
1185
1186namespace nlohmann
1187{
1188namespace detail
1189{
1191// JSON type enumeration //
1193
1230
1241inline bool operator<(const value_t lhs, const value_t rhs) noexcept
1242{
1243 static constexpr std::array<std::uint8_t, 8> order = {{
1244 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
1245 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
1246 }
1247 };
1248
1249 const auto l_index = static_cast<std::size_t>(lhs);
1250 const auto r_index = static_cast<std::size_t>(rhs);
1251 return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
1252}
1253} // namespace detail
1254} // namespace nlohmann
1255
1256// #include <nlohmann/detail/conversions/from_json.hpp>
1257
1258
1259#include <algorithm> // transform
1260#include <array> // array
1261#include <ciso646> // and, not
1262#include <forward_list> // forward_list
1263#include <iterator> // inserter, front_inserter, end
1264#include <map> // map
1265#include <string> // string
1266#include <tuple> // tuple, make_tuple
1267#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
1268#include <unordered_map> // unordered_map
1269#include <utility> // pair, declval
1270#include <valarray> // valarray
1271
1272// #include <nlohmann/detail/exceptions.hpp>
1273
1274// #include <nlohmann/detail/macro_scope.hpp>
1275
1276// #include <nlohmann/detail/meta/cpp_future.hpp>
1277
1278// #include <nlohmann/detail/meta/type_traits.hpp>
1279
1280// #include <nlohmann/detail/value_t.hpp>
1281
1282
1283namespace nlohmann
1284{
1285namespace detail
1286{
1287template<typename BasicJsonType>
1288void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
1289{
1290 if (JSON_UNLIKELY(not j.is_null()))
1291 {
1292 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
1293 }
1294 n = nullptr;
1295}
1296
1297// overloads for basic_json template parameters
1298template<typename BasicJsonType, typename ArithmeticType,
1299 enable_if_t<std::is_arithmetic<ArithmeticType>::value and
1300 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1301 int> = 0>
1302void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
1303{
1304 switch (static_cast<value_t>(j))
1305 {
1307 {
1308 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1309 break;
1310 }
1312 {
1313 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1314 break;
1315 }
1317 {
1318 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1319 break;
1320 }
1321
1322 default:
1323 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1324 }
1325}
1326
1327template<typename BasicJsonType>
1328void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
1329{
1330 if (JSON_UNLIKELY(not j.is_boolean()))
1331 {
1332 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
1333 }
1334 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
1335}
1336
1337template<typename BasicJsonType>
1338void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
1339{
1340 if (JSON_UNLIKELY(not j.is_string()))
1341 {
1342 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1343 }
1344 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1345}
1346
1347template <
1348 typename BasicJsonType, typename ConstructibleStringType,
1349 enable_if_t <
1350 is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and
1351 not std::is_same<typename BasicJsonType::string_t,
1352 ConstructibleStringType>::value,
1353 int > = 0 >
1354void from_json(const BasicJsonType& j, ConstructibleStringType& s)
1355{
1356 if (JSON_UNLIKELY(not j.is_string()))
1357 {
1358 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1359 }
1360
1361 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1362}
1363
1364template<typename BasicJsonType>
1365void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
1366{
1367 get_arithmetic_value(j, val);
1368}
1369
1370template<typename BasicJsonType>
1371void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
1372{
1373 get_arithmetic_value(j, val);
1374}
1375
1376template<typename BasicJsonType>
1377void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
1378{
1379 get_arithmetic_value(j, val);
1380}
1381
1382template<typename BasicJsonType, typename EnumType,
1383 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1384void from_json(const BasicJsonType& j, EnumType& e)
1385{
1386 typename std::underlying_type<EnumType>::type val;
1387 get_arithmetic_value(j, val);
1388 e = static_cast<EnumType>(val);
1389}
1390
1391// forward_list doesn't have an insert method
1392template<typename BasicJsonType, typename T, typename Allocator,
1393 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1394void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
1395{
1396 if (JSON_UNLIKELY(not j.is_array()))
1397 {
1398 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1399 }
1400 std::transform(j.rbegin(), j.rend(),
1401 std::front_inserter(l), [](const BasicJsonType & i)
1402 {
1403 return i.template get<T>();
1404 });
1405}
1406
1407// valarray doesn't have an insert method
1408template<typename BasicJsonType, typename T,
1409 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1410void from_json(const BasicJsonType& j, std::valarray<T>& l)
1411{
1412 if (JSON_UNLIKELY(not j.is_array()))
1413 {
1414 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1415 }
1416 l.resize(j.size());
1417 std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
1418}
1419
1420template<typename BasicJsonType>
1421void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
1422{
1423 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
1424}
1425
1426template <typename BasicJsonType, typename T, std::size_t N>
1427auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
1428 priority_tag<2> /*unused*/)
1429-> decltype(j.template get<T>(), void())
1430{
1431 for (std::size_t i = 0; i < N; ++i)
1432 {
1433 arr[i] = j.at(i).template get<T>();
1434 }
1435}
1436
1437template<typename BasicJsonType, typename ConstructibleArrayType>
1438auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
1439-> decltype(
1440 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
1442 void())
1443{
1444 using std::end;
1445
1446 arr.reserve(j.size());
1447 std::transform(j.begin(), j.end(),
1448 std::inserter(arr, end(arr)), [](const BasicJsonType & i)
1449 {
1450 // get<BasicJsonType>() returns *this, this won't call a from_json
1451 // method when value_type is BasicJsonType
1453 });
1454}
1455
1456template <typename BasicJsonType, typename ConstructibleArrayType>
1457void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
1458 priority_tag<0> /*unused*/)
1459{
1460 using std::end;
1461
1462 std::transform(
1463 j.begin(), j.end(), std::inserter(arr, end(arr)),
1464 [](const BasicJsonType & i)
1465 {
1466 // get<BasicJsonType>() returns *this, this won't call a from_json
1467 // method when value_type is BasicJsonType
1469 });
1470}
1471
1472template <typename BasicJsonType, typename ConstructibleArrayType,
1473 enable_if_t <
1474 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and
1475 not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and
1476 not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and
1477 not is_basic_json<ConstructibleArrayType>::value,
1478 int > = 0 >
1479
1480auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
1481-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
1483void())
1484{
1485 if (JSON_UNLIKELY(not j.is_array()))
1486 {
1487 JSON_THROW(type_error::create(302, "type must be array, but is " +
1488 std::string(j.type_name())));
1489 }
1490
1491 from_json_array_impl(j, arr, priority_tag<3> {});
1492}
1493
1494template<typename BasicJsonType, typename ConstructibleObjectType,
1496void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
1497{
1498 if (JSON_UNLIKELY(not j.is_object()))
1499 {
1500 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
1501 }
1502
1503 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1504 using value_type = typename ConstructibleObjectType::value_type;
1505 std::transform(
1506 inner_object->begin(), inner_object->end(),
1507 std::inserter(obj, obj.begin()),
1508 [](typename BasicJsonType::object_t::value_type const & p)
1509 {
1510 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
1511 });
1512}
1513
1514// overload for arithmetic types, not chosen for basic_json template arguments
1515// (BooleanType, etc..); note: Is it really necessary to provide explicit
1516// overloads for boolean_t etc. in case of a custom BooleanType which is not
1517// an arithmetic type?
1518template<typename BasicJsonType, typename ArithmeticType,
1519 enable_if_t <
1520 std::is_arithmetic<ArithmeticType>::value and
1521 not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1522 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1523 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1524 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1525 int> = 0>
1526void from_json(const BasicJsonType& j, ArithmeticType& val)
1527{
1528 switch (static_cast<value_t>(j))
1529 {
1531 {
1532 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1533 break;
1534 }
1536 {
1537 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1538 break;
1539 }
1541 {
1542 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1543 break;
1544 }
1545 case value_t::boolean:
1546 {
1547 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
1548 break;
1549 }
1550
1551 default:
1552 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1553 }
1554}
1555
1556template<typename BasicJsonType, typename A1, typename A2>
1557void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
1558{
1559 p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
1560}
1561
1562template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1563void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
1564{
1565 t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
1566}
1567
1568template<typename BasicJsonType, typename... Args>
1569void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
1570{
1572}
1573
1574template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
1575 typename = enable_if_t<not std::is_constructible<
1576 typename BasicJsonType::string_t, Key>::value>>
1577void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
1578{
1579 if (JSON_UNLIKELY(not j.is_array()))
1580 {
1581 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1582 }
1583 for (const auto& p : j)
1584 {
1585 if (JSON_UNLIKELY(not p.is_array()))
1586 {
1587 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1588 }
1589 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1590 }
1591}
1592
1593template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
1594 typename = enable_if_t<not std::is_constructible<
1595 typename BasicJsonType::string_t, Key>::value>>
1596void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
1597{
1598 if (JSON_UNLIKELY(not j.is_array()))
1599 {
1600 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1601 }
1602 for (const auto& p : j)
1603 {
1604 if (JSON_UNLIKELY(not p.is_array()))
1605 {
1606 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1607 }
1608 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1609 }
1610}
1611
1613{
1614 template<typename BasicJsonType, typename T>
1615 auto operator()(const BasicJsonType& j, T& val) const
1616 noexcept(noexcept(from_json(j, val)))
1617 -> decltype(from_json(j, val), void())
1618 {
1619 return from_json(j, val);
1620 }
1621};
1622} // namespace detail
1623
1627namespace
1628{
1629constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1630} // namespace
1631} // namespace nlohmann
1632
1633// #include <nlohmann/detail/conversions/to_json.hpp>
1634
1635
1636#include <ciso646> // or, and, not
1637#include <iterator> // begin, end
1638#include <tuple> // tuple, get
1639#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
1640#include <utility> // move, forward, declval, pair
1641#include <valarray> // valarray
1642#include <vector> // vector
1643
1644// #include <nlohmann/detail/meta/cpp_future.hpp>
1645
1646// #include <nlohmann/detail/meta/type_traits.hpp>
1647
1648// #include <nlohmann/detail/value_t.hpp>
1649
1650// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
1651
1652
1653#include <cstddef> // size_t
1654#include <string> // string, to_string
1655#include <iterator> // input_iterator_tag
1656#include <tuple> // tuple_size, get, tuple_element
1657
1658// #include <nlohmann/detail/value_t.hpp>
1659
1660// #include <nlohmann/detail/meta/type_traits.hpp>
1661
1662
1663namespace nlohmann
1664{
1665namespace detail
1666{
1667template <typename IteratorType> class iteration_proxy_value
1668{
1669 public:
1670 using difference_type = std::ptrdiff_t;
1674 using iterator_category = std::input_iterator_tag;
1675
1676 private:
1678 IteratorType anchor;
1680 std::size_t array_index = 0;
1682 mutable std::size_t array_index_last = 0;
1684 mutable std::string array_index_str = "0";
1686 const std::string empty_str = "";
1687
1688 public:
1689 explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
1690
1693 {
1694 return *this;
1695 }
1696
1699 {
1700 ++anchor;
1701 ++array_index;
1702
1703 return *this;
1704 }
1705
1707 bool operator==(const iteration_proxy_value& o) const noexcept
1708 {
1709 return anchor == o.anchor;
1710 }
1711
1713 bool operator!=(const iteration_proxy_value& o) const noexcept
1714 {
1715 return anchor != o.anchor;
1716 }
1717
1719 const std::string& key() const
1720 {
1721 assert(anchor.m_object != nullptr);
1722
1723 switch (anchor.m_object->type())
1724 {
1725 // use integer array index as key
1726 case value_t::array:
1727 {
1728 if (array_index != array_index_last)
1729 {
1730 array_index_str = std::to_string(array_index);
1731 array_index_last = array_index;
1732 }
1733 return array_index_str;
1734 }
1735
1736 // use key from the object
1737 case value_t::object:
1738 return anchor.key();
1739
1740 // use an empty key for all primitive types
1741 default:
1742 return empty_str;
1743 }
1744 }
1745
1747 typename IteratorType::reference value() const
1748 {
1749 return anchor.value();
1750 }
1751};
1752
1754template<typename IteratorType> class iteration_proxy
1755{
1756 private:
1758 typename IteratorType::reference container;
1759
1760 public:
1762 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
1763 : container(cont) {}
1764
1767 {
1768 return iteration_proxy_value<IteratorType>(container.begin());
1769 }
1770
1773 {
1774 return iteration_proxy_value<IteratorType>(container.end());
1775 }
1776};
1777// Structured Bindings Support
1778// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1779// And see https://github.com/nlohmann/json/pull/1391
1780template <std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
1782{
1783 return i.key();
1784}
1785// Structured Bindings Support
1786// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1787// And see https://github.com/nlohmann/json/pull/1391
1788template <std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
1790{
1791 return i.value();
1792}
1793} // namespace detail
1794} // namespace nlohmann
1795
1796// The Addition to the STD Namespace is required to add
1797// Structured Bindings Support to the iteration_proxy_value class
1798// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1799// And see https://github.com/nlohmann/json/pull/1391
1800namespace std
1801{
1802template <typename IteratorType>
1803class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
1804 : public std::integral_constant<std::size_t, 2> {};
1805
1806template <std::size_t N, typename IteratorType>
1807class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
1808{
1809 public:
1810 using type = decltype(
1811 get<N>(std::declval <
1813};
1814}
1815
1816namespace nlohmann
1817{
1818namespace detail
1819{
1821// constructors //
1823
1824template<value_t> struct external_constructor;
1825
1826template<>
1828{
1829 template<typename BasicJsonType>
1830 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
1831 {
1832 j.m_type = value_t::boolean;
1833 j.m_value = b;
1834 j.assert_invariant();
1835 }
1836};
1837
1838template<>
1840{
1841 template<typename BasicJsonType>
1842 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
1843 {
1844 j.m_type = value_t::string;
1845 j.m_value = s;
1846 j.assert_invariant();
1847 }
1848
1849 template<typename BasicJsonType>
1850 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1851 {
1852 j.m_type = value_t::string;
1853 j.m_value = std::move(s);
1854 j.assert_invariant();
1855 }
1856
1857 template<typename BasicJsonType, typename CompatibleStringType,
1859 int> = 0>
1860 static void construct(BasicJsonType& j, const CompatibleStringType& str)
1861 {
1862 j.m_type = value_t::string;
1863 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1864 j.assert_invariant();
1865 }
1866};
1867
1868template<>
1870{
1871 template<typename BasicJsonType>
1872 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
1873 {
1874 j.m_type = value_t::number_float;
1875 j.m_value = val;
1876 j.assert_invariant();
1877 }
1878};
1879
1880template<>
1882{
1883 template<typename BasicJsonType>
1884 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
1885 {
1886 j.m_type = value_t::number_unsigned;
1887 j.m_value = val;
1888 j.assert_invariant();
1889 }
1890};
1891
1892template<>
1894{
1895 template<typename BasicJsonType>
1896 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
1897 {
1898 j.m_type = value_t::number_integer;
1899 j.m_value = val;
1900 j.assert_invariant();
1901 }
1902};
1903
1904template<>
1906{
1907 template<typename BasicJsonType>
1908 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1909 {
1910 j.m_type = value_t::array;
1911 j.m_value = arr;
1912 j.assert_invariant();
1913 }
1914
1915 template<typename BasicJsonType>
1916 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1917 {
1918 j.m_type = value_t::array;
1919 j.m_value = std::move(arr);
1920 j.assert_invariant();
1921 }
1922
1923 template<typename BasicJsonType, typename CompatibleArrayType,
1925 int> = 0>
1926 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1927 {
1928 using std::begin;
1929 using std::end;
1930 j.m_type = value_t::array;
1931 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1932 j.assert_invariant();
1933 }
1934
1935 template<typename BasicJsonType>
1936 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1937 {
1938 j.m_type = value_t::array;
1939 j.m_value = value_t::array;
1940 j.m_value.array->reserve(arr.size());
1941 for (const bool x : arr)
1942 {
1943 j.m_value.array->push_back(x);
1944 }
1945 j.assert_invariant();
1946 }
1947
1948 template<typename BasicJsonType, typename T,
1950 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
1951 {
1952 j.m_type = value_t::array;
1953 j.m_value = value_t::array;
1954 j.m_value.array->resize(arr.size());
1955 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
1956 j.assert_invariant();
1957 }
1958};
1959
1960template<>
1962{
1963 template<typename BasicJsonType>
1964 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1965 {
1966 j.m_type = value_t::object;
1967 j.m_value = obj;
1968 j.assert_invariant();
1969 }
1970
1971 template<typename BasicJsonType>
1972 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1973 {
1974 j.m_type = value_t::object;
1975 j.m_value = std::move(obj);
1976 j.assert_invariant();
1977 }
1978
1979 template<typename BasicJsonType, typename CompatibleObjectType,
1981 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
1982 {
1983 using std::begin;
1984 using std::end;
1985
1986 j.m_type = value_t::object;
1987 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
1988 j.assert_invariant();
1989 }
1990};
1991
1993// to_json //
1995
1996template<typename BasicJsonType, typename T,
1997 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
1998void to_json(BasicJsonType& j, T b) noexcept
1999{
2001}
2002
2003template<typename BasicJsonType, typename CompatibleString,
2004 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
2005void to_json(BasicJsonType& j, const CompatibleString& s)
2006{
2008}
2009
2010template<typename BasicJsonType>
2011void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
2012{
2014}
2015
2016template<typename BasicJsonType, typename FloatType,
2017 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
2018void to_json(BasicJsonType& j, FloatType val) noexcept
2019{
2020 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
2021}
2022
2023template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
2024 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
2025void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
2026{
2027 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
2028}
2029
2030template<typename BasicJsonType, typename CompatibleNumberIntegerType,
2031 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
2032void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
2033{
2034 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
2035}
2036
2037template<typename BasicJsonType, typename EnumType,
2038 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
2039void to_json(BasicJsonType& j, EnumType e) noexcept
2040{
2041 using underlying_type = typename std::underlying_type<EnumType>::type;
2042 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
2043}
2044
2045template<typename BasicJsonType>
2046void to_json(BasicJsonType& j, const std::vector<bool>& e)
2047{
2049}
2050
2051template <typename BasicJsonType, typename CompatibleArrayType,
2052 enable_if_t<is_compatible_array_type<BasicJsonType,
2053 CompatibleArrayType>::value and
2054 not is_compatible_object_type<
2055 BasicJsonType, CompatibleArrayType>::value and
2056 not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
2057 not is_basic_json<CompatibleArrayType>::value,
2058 int> = 0>
2059void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
2060{
2062}
2063
2064template<typename BasicJsonType, typename T,
2065 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
2066void to_json(BasicJsonType& j, const std::valarray<T>& arr)
2067{
2069}
2070
2071template<typename BasicJsonType>
2072void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
2073{
2075}
2076
2077template<typename BasicJsonType, typename CompatibleObjectType,
2078 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
2079void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
2080{
2082}
2083
2084template<typename BasicJsonType>
2085void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
2086{
2088}
2089
2090template <
2091 typename BasicJsonType, typename T, std::size_t N,
2092 enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
2093 const T(&)[N]>::value,
2094 int> = 0 >
2095void to_json(BasicJsonType& j, const T(&arr)[N])
2096{
2098}
2099
2100template<typename BasicJsonType, typename... Args>
2101void to_json(BasicJsonType& j, const std::pair<Args...>& p)
2102{
2103 j = { p.first, p.second };
2104}
2105
2106// for https://github.com/nlohmann/json/pull/1134
2107template < typename BasicJsonType, typename T,
2109void to_json(BasicJsonType& j, const T& b)
2110{
2111 j = { {b.key(), b.value()} };
2112}
2113
2114template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
2115void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
2116{
2117 j = { std::get<Idx>(t)... };
2118}
2119
2120template<typename BasicJsonType, typename... Args>
2121void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
2122{
2124}
2125
2127{
2128 template<typename BasicJsonType, typename T>
2129 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
2130 -> decltype(to_json(j, std::forward<T>(val)), void())
2131 {
2132 return to_json(j, std::forward<T>(val));
2133 }
2134};
2135} // namespace detail
2136
2138namespace
2139{
2140constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
2141} // namespace
2142} // namespace nlohmann
2143
2144// #include <nlohmann/detail/input/input_adapters.hpp>
2145
2146
2147#include <cassert> // assert
2148#include <cstddef> // size_t
2149#include <cstring> // strlen
2150#include <istream> // istream
2151#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
2152#include <memory> // shared_ptr, make_shared, addressof
2153#include <numeric> // accumulate
2154#include <string> // string, char_traits
2155#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
2156#include <utility> // pair, declval
2157#include <cstdio> //FILE *
2158
2159// #include <nlohmann/detail/macro_scope.hpp>
2160
2161
2162namespace nlohmann
2163{
2164namespace detail
2165{
2168
2170// input adapters //
2172
2185{
2187 virtual std::char_traits<char>::int_type get_character() = 0;
2188 virtual ~input_adapter_protocol() = default;
2189};
2190
2192using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
2193
2199{
2200 public:
2201 explicit file_input_adapter(std::FILE* f) noexcept
2202 : m_file(f)
2203 {}
2204
2205 std::char_traits<char>::int_type get_character() noexcept override
2206 {
2207 return std::fgetc(m_file);
2208 }
2209 private:
2211 std::FILE* m_file;
2212};
2213
2214
2225{
2226 public:
2228 {
2229 // clear stream flags; we use underlying streambuf I/O, do not
2230 // maintain ifstream flags, except eof
2231 is.clear(is.rdstate() & std::ios::eofbit);
2232 }
2233
2234 explicit input_stream_adapter(std::istream& i)
2235 : is(i), sb(*i.rdbuf())
2236 {}
2237
2238 // delete because of pointer members
2243
2244 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
2245 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
2246 // end up as the same value, eg. 0xFFFFFFFF.
2247 std::char_traits<char>::int_type get_character() override
2248 {
2249 auto res = sb.sbumpc();
2250 // set eof manually, as we don't use the istream interface.
2251 if (res == EOF)
2252 {
2253 is.clear(is.rdstate() | std::ios::eofbit);
2254 }
2255 return res;
2256 }
2257
2258 private:
2260 std::istream& is;
2261 std::streambuf& sb;
2262};
2263
2266{
2267 public:
2268 input_buffer_adapter(const char* b, const std::size_t l) noexcept
2269 : cursor(b), limit(b + l)
2270 {}
2271
2272 // delete because of pointer members
2277 ~input_buffer_adapter() override = default;
2278
2279 std::char_traits<char>::int_type get_character() noexcept override
2280 {
2281 if (JSON_LIKELY(cursor < limit))
2282 {
2283 return std::char_traits<char>::to_int_type(*(cursor++));
2284 }
2285
2286 return std::char_traits<char>::eof();
2287 }
2288
2289 private:
2291 const char* cursor;
2293 const char* const limit;
2294};
2295
2296template<typename WideStringType, size_t T>
2298{
2299 // UTF-32
2300 static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
2301 {
2302 utf8_bytes_index = 0;
2303
2304 if (current_wchar == str.size())
2305 {
2306 utf8_bytes[0] = std::char_traits<char>::eof();
2307 utf8_bytes_filled = 1;
2308 }
2309 else
2310 {
2311 // get the current character
2312 const auto wc = static_cast<int>(str[current_wchar++]);
2313
2314 // UTF-32 to UTF-8 encoding
2315 if (wc < 0x80)
2316 {
2317 utf8_bytes[0] = wc;
2318 utf8_bytes_filled = 1;
2319 }
2320 else if (wc <= 0x7FF)
2321 {
2322 utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
2323 utf8_bytes[1] = 0x80 | (wc & 0x3F);
2324 utf8_bytes_filled = 2;
2325 }
2326 else if (wc <= 0xFFFF)
2327 {
2328 utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
2329 utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2330 utf8_bytes[2] = 0x80 | (wc & 0x3F);
2331 utf8_bytes_filled = 3;
2332 }
2333 else if (wc <= 0x10FFFF)
2334 {
2335 utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);
2336 utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
2337 utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
2338 utf8_bytes[3] = 0x80 | (wc & 0x3F);
2339 utf8_bytes_filled = 4;
2340 }
2341 else
2342 {
2343 // unknown character
2344 utf8_bytes[0] = wc;
2345 utf8_bytes_filled = 1;
2346 }
2347 }
2348 }
2349};
2350
2351template<typename WideStringType>
2352struct wide_string_input_helper<WideStringType, 2>
2353{
2354 // UTF-16
2355 static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
2356 {
2357 utf8_bytes_index = 0;
2358
2359 if (current_wchar == str.size())
2360 {
2361 utf8_bytes[0] = std::char_traits<char>::eof();
2362 utf8_bytes_filled = 1;
2363 }
2364 else
2365 {
2366 // get the current character
2367 const auto wc = static_cast<int>(str[current_wchar++]);
2368
2369 // UTF-16 to UTF-8 encoding
2370 if (wc < 0x80)
2371 {
2372 utf8_bytes[0] = wc;
2373 utf8_bytes_filled = 1;
2374 }
2375 else if (wc <= 0x7FF)
2376 {
2377 utf8_bytes[0] = 0xC0 | ((wc >> 6));
2378 utf8_bytes[1] = 0x80 | (wc & 0x3F);
2379 utf8_bytes_filled = 2;
2380 }
2381 else if (0xD800 > wc or wc >= 0xE000)
2382 {
2383 utf8_bytes[0] = 0xE0 | ((wc >> 12));
2384 utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2385 utf8_bytes[2] = 0x80 | (wc & 0x3F);
2386 utf8_bytes_filled = 3;
2387 }
2388 else
2389 {
2390 if (current_wchar < str.size())
2391 {
2392 const auto wc2 = static_cast<int>(str[current_wchar++]);
2393 const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
2394 utf8_bytes[0] = 0xf0 | (charcode >> 18);
2395 utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
2396 utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
2397 utf8_bytes[3] = 0x80 | (charcode & 0x3F);
2398 utf8_bytes_filled = 4;
2399 }
2400 else
2401 {
2402 // unknown character
2403 ++current_wchar;
2404 utf8_bytes[0] = wc;
2405 utf8_bytes_filled = 1;
2406 }
2407 }
2408 }
2409 }
2410};
2411
2412template<typename WideStringType>
2414{
2415 public:
2416 explicit wide_string_input_adapter(const WideStringType& w) noexcept
2417 : str(w)
2418 {}
2419
2420 std::char_traits<char>::int_type get_character() noexcept override
2421 {
2422 // check if buffer needs to be filled
2423 if (utf8_bytes_index == utf8_bytes_filled)
2424 {
2425 fill_buffer<sizeof(typename WideStringType::value_type)>();
2426
2427 assert(utf8_bytes_filled > 0);
2428 assert(utf8_bytes_index == 0);
2429 }
2430
2431 // use buffer
2432 assert(utf8_bytes_filled > 0);
2433 assert(utf8_bytes_index < utf8_bytes_filled);
2434 return utf8_bytes[utf8_bytes_index++];
2435 }
2436
2437 private:
2438 template<size_t T>
2439 void fill_buffer()
2440 {
2441 wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
2442 }
2443
2445 const WideStringType& str;
2446
2448 std::size_t current_wchar = 0;
2449
2451 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
2452
2454 std::size_t utf8_bytes_index = 0;
2456 std::size_t utf8_bytes_filled = 0;
2457};
2458
2460{
2461 public:
2462 // native support
2463 input_adapter(std::FILE* file)
2464 : ia(std::make_shared<file_input_adapter>(file)) {}
2465
2466 input_adapter(std::istream& i)
2467 : ia(std::make_shared<input_stream_adapter>(i)) {}
2468
2470 input_adapter(std::istream&& i)
2471 : ia(std::make_shared<input_stream_adapter>(i)) {}
2472
2473 input_adapter(const std::wstring& ws)
2474 : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
2475
2476 input_adapter(const std::u16string& ws)
2477 : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
2478
2479 input_adapter(const std::u32string& ws)
2480 : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
2481
2483 template<typename CharT,
2484 typename std::enable_if<
2485 std::is_pointer<CharT>::value and
2486 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2487 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2488 int>::type = 0>
2489 input_adapter(CharT b, std::size_t l)
2490 : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
2491
2492 // derived support
2493
2495 template<typename CharT,
2496 typename std::enable_if<
2497 std::is_pointer<CharT>::value and
2498 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2499 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2500 int>::type = 0>
2502 : input_adapter(reinterpret_cast<const char*>(b),
2503 std::strlen(reinterpret_cast<const char*>(b))) {}
2504
2506 template<class IteratorType,
2507 typename std::enable_if<
2508 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
2509 int>::type = 0>
2510 input_adapter(IteratorType first, IteratorType last)
2511 {
2512#ifndef NDEBUG
2513 // assertion to check that the iterator range is indeed contiguous,
2514 // see http://stackoverflow.com/a/35008842/266378 for more discussion
2515 const auto is_contiguous = std::accumulate(
2516 first, last, std::pair<bool, int>(true, 0),
2517 [&first](std::pair<bool, int> res, decltype(*first) val)
2518 {
2519 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2520 return res;
2521 }).first;
2522 assert(is_contiguous);
2523#endif
2524
2525 // assertion to check that each element is 1 byte long
2526 static_assert(
2527 sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
2528 "each element in the iterator range must have the size of 1 byte");
2529
2530 const auto len = static_cast<size_t>(std::distance(first, last));
2531 if (JSON_LIKELY(len > 0))
2532 {
2533 // there is at least one element: use the address of first
2534 ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2535 }
2536 else
2537 {
2538 // the address of first cannot be used: use nullptr
2539 ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2540 }
2541 }
2542
2544 template<class T, std::size_t N>
2546 : input_adapter(std::begin(array), std::end(array)) {}
2547
2549 template<class ContiguousContainer, typename
2550 std::enable_if<not std::is_pointer<ContiguousContainer>::value and
2551 std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
2552 int>::type = 0>
2553 input_adapter(const ContiguousContainer& c)
2554 : input_adapter(std::begin(c), std::end(c)) {}
2555
2557 {
2558 return ia;
2559 }
2560
2561 private:
2563 input_adapter_t ia = nullptr;
2564};
2565} // namespace detail
2566} // namespace nlohmann
2567
2568// #include <nlohmann/detail/input/lexer.hpp>
2569
2570
2571#include <clocale> // localeconv
2572#include <cstddef> // size_t
2573#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
2574#include <cstdio> // snprintf
2575#include <initializer_list> // initializer_list
2576#include <string> // char_traits, string
2577#include <vector> // vector
2578
2579// #include <nlohmann/detail/macro_scope.hpp>
2580
2581// #include <nlohmann/detail/input/input_adapters.hpp>
2582
2583// #include <nlohmann/detail/input/position_t.hpp>
2584
2585
2586namespace nlohmann
2587{
2588namespace detail
2589{
2591// lexer //
2593
2599template<typename BasicJsonType>
2601{
2602 using number_integer_t = typename BasicJsonType::number_integer_t;
2603 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2604 using number_float_t = typename BasicJsonType::number_float_t;
2605 using string_t = typename BasicJsonType::string_t;
2606
2607 public:
2629
2631 static const char* token_type_name(const token_type t) noexcept
2632 {
2633 switch (t)
2634 {
2636 return "<uninitialized>";
2638 return "true literal";
2640 return "false literal";
2642 return "null literal";
2644 return "string literal";
2648 return "number literal";
2650 return "'['";
2652 return "'{'";
2654 return "']'";
2656 return "'}'";
2658 return "':'";
2660 return "','";
2662 return "<parse error>";
2664 return "end of input";
2666 return "'[', '{', or a literal";
2667 // LCOV_EXCL_START
2668 default: // catch non-enum values
2669 return "unknown token";
2670 // LCOV_EXCL_STOP
2671 }
2672 }
2673
2674 explicit lexer(detail::input_adapter_t&& adapter)
2675 : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
2676
2677 // delete because of pointer members
2678 lexer(const lexer&) = delete;
2679 lexer(lexer&&) = delete;
2680 lexer& operator=(lexer&) = delete;
2681 lexer& operator=(lexer&&) = delete;
2682 ~lexer() = default;
2683
2684 private:
2686 // locales
2688
2690 static char get_decimal_point() noexcept
2691 {
2692 const auto loc = localeconv();
2693 assert(loc != nullptr);
2694 return '.';
2695 }
2696
2698 // scan functions
2700
2716 int get_codepoint()
2717 {
2718 // this function only makes sense after reading `\u`
2719 assert(current == 'u');
2720 int codepoint = 0;
2721
2722 const auto factors = { 12, 8, 4, 0 };
2723 for (const auto factor : factors)
2724 {
2725 get();
2726
2727 if (current >= '0' and current <= '9')
2728 {
2729 codepoint += ((current - 0x30) << factor);
2730 }
2731 else if (current >= 'A' and current <= 'F')
2732 {
2733 codepoint += ((current - 0x37) << factor);
2734 }
2735 else if (current >= 'a' and current <= 'f')
2736 {
2737 codepoint += ((current - 0x57) << factor);
2738 }
2739 else
2740 {
2741 return -1;
2742 }
2743 }
2744
2745 assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
2746 return codepoint;
2747 }
2748
2764 bool next_byte_in_range(std::initializer_list<int> ranges)
2765 {
2766 assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
2767 add(current);
2768
2769 for (auto range = ranges.begin(); range != ranges.end(); ++range)
2770 {
2771 get();
2772 if (JSON_LIKELY(*range <= current and current <= *(++range)))
2773 {
2774 add(current);
2775 }
2776 else
2777 {
2778 error_message = "invalid string: ill-formed UTF-8 byte";
2779 return false;
2780 }
2781 }
2782
2783 return true;
2784 }
2785
2801 token_type scan_string()
2802 {
2803 // reset token_buffer (ignore opening quote)
2804 reset();
2805
2806 // we entered the function by reading an open quote
2807 assert(current == '\"');
2808
2809 while (true)
2810 {
2811 // get next character
2812 switch (get())
2813 {
2814 // end of file while parsing string
2815 case std::char_traits<char>::eof():
2816 {
2817 error_message = "invalid string: missing closing quote";
2819 }
2820
2821 // closing quote
2822 case '\"':
2823 {
2824 return token_type::value_string;
2825 }
2826
2827 // escapes
2828 case '\\':
2829 {
2830 switch (get())
2831 {
2832 // quotation mark
2833 case '\"':
2834 add('\"');
2835 break;
2836 // reverse solidus
2837 case '\\':
2838 add('\\');
2839 break;
2840 // solidus
2841 case '/':
2842 add('/');
2843 break;
2844 // backspace
2845 case 'b':
2846 add('\b');
2847 break;
2848 // form feed
2849 case 'f':
2850 add('\f');
2851 break;
2852 // line feed
2853 case 'n':
2854 add('\n');
2855 break;
2856 // carriage return
2857 case 'r':
2858 add('\r');
2859 break;
2860 // tab
2861 case 't':
2862 add('\t');
2863 break;
2864
2865 // unicode escapes
2866 case 'u':
2867 {
2868 const int codepoint1 = get_codepoint();
2869 int codepoint = codepoint1; // start with codepoint1
2870
2871 if (JSON_UNLIKELY(codepoint1 == -1))
2872 {
2873 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2874 return token_type::parse_error;
2875 }
2876
2877 // check if code point is a high surrogate
2878 if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
2879 {
2880 // expect next \uxxxx entry
2881 if (JSON_LIKELY(get() == '\\' and get() == 'u'))
2882 {
2883 const int codepoint2 = get_codepoint();
2884
2885 if (JSON_UNLIKELY(codepoint2 == -1))
2886 {
2887 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2888 return token_type::parse_error;
2889 }
2890
2891 // check if codepoint2 is a low surrogate
2892 if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
2893 {
2894 // overwrite codepoint
2895 codepoint =
2896 // high surrogate occupies the most significant 22 bits
2897 (codepoint1 << 10)
2898 // low surrogate occupies the least significant 15 bits
2899 + codepoint2
2900 // there is still the 0xD800, 0xDC00 and 0x10000 noise
2901 // in the result so we have to subtract with:
2902 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
2903 - 0x35FDC00;
2904 }
2905 else
2906 {
2907 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2908 return token_type::parse_error;
2909 }
2910 }
2911 else
2912 {
2913 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2914 return token_type::parse_error;
2915 }
2916 }
2917 else
2918 {
2919 if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
2920 {
2921 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
2922 return token_type::parse_error;
2923 }
2924 }
2925
2926 // result of the above calculation yields a proper codepoint
2927 assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
2928
2929 // translate codepoint into bytes
2930 if (codepoint < 0x80)
2931 {
2932 // 1-byte characters: 0xxxxxxx (ASCII)
2933 add(codepoint);
2934 }
2935 else if (codepoint <= 0x7FF)
2936 {
2937 // 2-byte characters: 110xxxxx 10xxxxxx
2938 add(0xC0 | (codepoint >> 6));
2939 add(0x80 | (codepoint & 0x3F));
2940 }
2941 else if (codepoint <= 0xFFFF)
2942 {
2943 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
2944 add(0xE0 | (codepoint >> 12));
2945 add(0x80 | ((codepoint >> 6) & 0x3F));
2946 add(0x80 | (codepoint & 0x3F));
2947 }
2948 else
2949 {
2950 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2951 add(0xF0 | (codepoint >> 18));
2952 add(0x80 | ((codepoint >> 12) & 0x3F));
2953 add(0x80 | ((codepoint >> 6) & 0x3F));
2954 add(0x80 | (codepoint & 0x3F));
2955 }
2956
2957 break;
2958 }
2959
2960 // other characters after escape
2961 default:
2962 error_message = "invalid string: forbidden character after backslash";
2963 return token_type::parse_error;
2964 }
2965
2966 break;
2967 }
2968
2969 // invalid control characters
2970 case 0x00:
2971 {
2972 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
2973 return token_type::parse_error;
2974 }
2975
2976 case 0x01:
2977 {
2978 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
2979 return token_type::parse_error;
2980 }
2981
2982 case 0x02:
2983 {
2984 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
2985 return token_type::parse_error;
2986 }
2987
2988 case 0x03:
2989 {
2990 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
2991 return token_type::parse_error;
2992 }
2993
2994 case 0x04:
2995 {
2996 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
2997 return token_type::parse_error;
2998 }
2999
3000 case 0x05:
3001 {
3002 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
3003 return token_type::parse_error;
3004 }
3005
3006 case 0x06:
3007 {
3008 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
3009 return token_type::parse_error;
3010 }
3011
3012 case 0x07:
3013 {
3014 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
3015 return token_type::parse_error;
3016 }
3017
3018 case 0x08:
3019 {
3020 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
3021 return token_type::parse_error;
3022 }
3023
3024 case 0x09:
3025 {
3026 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
3027 return token_type::parse_error;
3028 }
3029
3030 case 0x0A:
3031 {
3032 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
3033 return token_type::parse_error;
3034 }
3035
3036 case 0x0B:
3037 {
3038 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
3039 return token_type::parse_error;
3040 }
3041
3042 case 0x0C:
3043 {
3044 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
3045 return token_type::parse_error;
3046 }
3047
3048 case 0x0D:
3049 {
3050 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
3051 return token_type::parse_error;
3052 }
3053
3054 case 0x0E:
3055 {
3056 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
3057 return token_type::parse_error;
3058 }
3059
3060 case 0x0F:
3061 {
3062 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
3063 return token_type::parse_error;
3064 }
3065
3066 case 0x10:
3067 {
3068 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
3069 return token_type::parse_error;
3070 }
3071
3072 case 0x11:
3073 {
3074 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
3075 return token_type::parse_error;
3076 }
3077
3078 case 0x12:
3079 {
3080 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
3081 return token_type::parse_error;
3082 }
3083
3084 case 0x13:
3085 {
3086 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
3087 return token_type::parse_error;
3088 }
3089
3090 case 0x14:
3091 {
3092 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
3093 return token_type::parse_error;
3094 }
3095
3096 case 0x15:
3097 {
3098 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
3099 return token_type::parse_error;
3100 }
3101
3102 case 0x16:
3103 {
3104 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
3105 return token_type::parse_error;
3106 }
3107
3108 case 0x17:
3109 {
3110 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
3111 return token_type::parse_error;
3112 }
3113
3114 case 0x18:
3115 {
3116 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
3117 return token_type::parse_error;
3118 }
3119
3120 case 0x19:
3121 {
3122 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
3123 return token_type::parse_error;
3124 }
3125
3126 case 0x1A:
3127 {
3128 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
3129 return token_type::parse_error;
3130 }
3131
3132 case 0x1B:
3133 {
3134 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
3135 return token_type::parse_error;
3136 }
3137
3138 case 0x1C:
3139 {
3140 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
3141 return token_type::parse_error;
3142 }
3143
3144 case 0x1D:
3145 {
3146 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
3147 return token_type::parse_error;
3148 }
3149
3150 case 0x1E:
3151 {
3152 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
3153 return token_type::parse_error;
3154 }
3155
3156 case 0x1F:
3157 {
3158 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
3159 return token_type::parse_error;
3160 }
3161
3162 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
3163 case 0x20:
3164 case 0x21:
3165 case 0x23:
3166 case 0x24:
3167 case 0x25:
3168 case 0x26:
3169 case 0x27:
3170 case 0x28:
3171 case 0x29:
3172 case 0x2A:
3173 case 0x2B:
3174 case 0x2C:
3175 case 0x2D:
3176 case 0x2E:
3177 case 0x2F:
3178 case 0x30:
3179 case 0x31:
3180 case 0x32:
3181 case 0x33:
3182 case 0x34:
3183 case 0x35:
3184 case 0x36:
3185 case 0x37:
3186 case 0x38:
3187 case 0x39:
3188 case 0x3A:
3189 case 0x3B:
3190 case 0x3C:
3191 case 0x3D:
3192 case 0x3E:
3193 case 0x3F:
3194 case 0x40:
3195 case 0x41:
3196 case 0x42:
3197 case 0x43:
3198 case 0x44:
3199 case 0x45:
3200 case 0x46:
3201 case 0x47:
3202 case 0x48:
3203 case 0x49:
3204 case 0x4A:
3205 case 0x4B:
3206 case 0x4C:
3207 case 0x4D:
3208 case 0x4E:
3209 case 0x4F:
3210 case 0x50:
3211 case 0x51:
3212 case 0x52:
3213 case 0x53:
3214 case 0x54:
3215 case 0x55:
3216 case 0x56:
3217 case 0x57:
3218 case 0x58:
3219 case 0x59:
3220 case 0x5A:
3221 case 0x5B:
3222 case 0x5D:
3223 case 0x5E:
3224 case 0x5F:
3225 case 0x60:
3226 case 0x61:
3227 case 0x62:
3228 case 0x63:
3229 case 0x64:
3230 case 0x65:
3231 case 0x66:
3232 case 0x67:
3233 case 0x68:
3234 case 0x69:
3235 case 0x6A:
3236 case 0x6B:
3237 case 0x6C:
3238 case 0x6D:
3239 case 0x6E:
3240 case 0x6F:
3241 case 0x70:
3242 case 0x71:
3243 case 0x72:
3244 case 0x73:
3245 case 0x74:
3246 case 0x75:
3247 case 0x76:
3248 case 0x77:
3249 case 0x78:
3250 case 0x79:
3251 case 0x7A:
3252 case 0x7B:
3253 case 0x7C:
3254 case 0x7D:
3255 case 0x7E:
3256 case 0x7F:
3257 {
3258 add(current);
3259 break;
3260 }
3261
3262 // U+0080..U+07FF: bytes C2..DF 80..BF
3263 case 0xC2:
3264 case 0xC3:
3265 case 0xC4:
3266 case 0xC5:
3267 case 0xC6:
3268 case 0xC7:
3269 case 0xC8:
3270 case 0xC9:
3271 case 0xCA:
3272 case 0xCB:
3273 case 0xCC:
3274 case 0xCD:
3275 case 0xCE:
3276 case 0xCF:
3277 case 0xD0:
3278 case 0xD1:
3279 case 0xD2:
3280 case 0xD3:
3281 case 0xD4:
3282 case 0xD5:
3283 case 0xD6:
3284 case 0xD7:
3285 case 0xD8:
3286 case 0xD9:
3287 case 0xDA:
3288 case 0xDB:
3289 case 0xDC:
3290 case 0xDD:
3291 case 0xDE:
3292 case 0xDF:
3293 {
3294 if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
3295 {
3296 return token_type::parse_error;
3297 }
3298 break;
3299 }
3300
3301 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
3302 case 0xE0:
3303 {
3304 if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
3305 {
3306 return token_type::parse_error;
3307 }
3308 break;
3309 }
3310
3311 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
3312 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
3313 case 0xE1:
3314 case 0xE2:
3315 case 0xE3:
3316 case 0xE4:
3317 case 0xE5:
3318 case 0xE6:
3319 case 0xE7:
3320 case 0xE8:
3321 case 0xE9:
3322 case 0xEA:
3323 case 0xEB:
3324 case 0xEC:
3325 case 0xEE:
3326 case 0xEF:
3327 {
3328 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
3329 {
3330 return token_type::parse_error;
3331 }
3332 break;
3333 }
3334
3335 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
3336 case 0xED:
3337 {
3338 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
3339 {
3340 return token_type::parse_error;
3341 }
3342 break;
3343 }
3344
3345 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
3346 case 0xF0:
3347 {
3348 if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
3349 {
3350 return token_type::parse_error;
3351 }
3352 break;
3353 }
3354
3355 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
3356 case 0xF1:
3357 case 0xF2:
3358 case 0xF3:
3359 {
3360 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
3361 {
3362 return token_type::parse_error;
3363 }
3364 break;
3365 }
3366
3367 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
3368 case 0xF4:
3369 {
3370 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
3371 {
3372 return token_type::parse_error;
3373 }
3374 break;
3375 }
3376
3377 // remaining bytes (80..C1 and F5..FF) are ill-formed
3378 default:
3379 {
3380 error_message = "invalid string: ill-formed UTF-8 byte";
3381 return token_type::parse_error;
3382 }
3383 }
3384 }
3385 }
3386
3387 static void strtof(float& f, const char* str, char** endptr) noexcept
3388 {
3389 f = std::strtof(str, endptr);
3390 }
3391
3392 static void strtof(double& f, const char* str, char** endptr) noexcept
3393 {
3394 f = std::strtod(str, endptr);
3395 }
3396
3397 static void strtof(long double& f, const char* str, char** endptr) noexcept
3398 {
3399 f = std::strtold(str, endptr);
3400 }
3401
3442 token_type scan_number() // lgtm [cpp/use-of-goto]
3443 {
3444 // reset token_buffer to store the number's bytes
3445 reset();
3446
3447 // the type of the parsed number; initially set to unsigned; will be
3448 // changed if minus sign, decimal point or exponent is read
3449 token_type number_type = token_type::value_unsigned;
3450
3451 // state (init): we just found out we need to scan a number
3452 switch (current)
3453 {
3454 case '-':
3455 {
3456 add(current);
3457 goto scan_number_minus;
3458 }
3459
3460 case '0':
3461 {
3462 add(current);
3463 goto scan_number_zero;
3464 }
3465
3466 case '1':
3467 case '2':
3468 case '3':
3469 case '4':
3470 case '5':
3471 case '6':
3472 case '7':
3473 case '8':
3474 case '9':
3475 {
3476 add(current);
3477 goto scan_number_any1;
3478 }
3479
3480 // LCOV_EXCL_START
3481 default:
3482 {
3483 // all other characters are rejected outside scan_number()
3484 assert(false);
3485 }
3486 // LCOV_EXCL_STOP
3487 }
3488
3489scan_number_minus:
3490 // state: we just parsed a leading minus sign
3491 number_type = token_type::value_integer;
3492 switch (get())
3493 {
3494 case '0':
3495 {
3496 add(current);
3497 goto scan_number_zero;
3498 }
3499
3500 case '1':
3501 case '2':
3502 case '3':
3503 case '4':
3504 case '5':
3505 case '6':
3506 case '7':
3507 case '8':
3508 case '9':
3509 {
3510 add(current);
3511 goto scan_number_any1;
3512 }
3513
3514 default:
3515 {
3516 error_message = "invalid number; expected digit after '-'";
3517 return token_type::parse_error;
3518 }
3519 }
3520
3521scan_number_zero:
3522 // state: we just parse a zero (maybe with a leading minus sign)
3523 switch (get())
3524 {
3525 case '.':
3526 {
3527 add(decimal_point_char);
3528 goto scan_number_decimal1;
3529 }
3530
3531 case 'e':
3532 case 'E':
3533 {
3534 add(current);
3535 goto scan_number_exponent;
3536 }
3537
3538 default:
3539 goto scan_number_done;
3540 }
3541
3542scan_number_any1:
3543 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
3544 switch (get())
3545 {
3546 case '0':
3547 case '1':
3548 case '2':
3549 case '3':
3550 case '4':
3551 case '5':
3552 case '6':
3553 case '7':
3554 case '8':
3555 case '9':
3556 {
3557 add(current);
3558 goto scan_number_any1;
3559 }
3560
3561 case '.':
3562 {
3563 add(decimal_point_char);
3564 goto scan_number_decimal1;
3565 }
3566
3567 case 'e':
3568 case 'E':
3569 {
3570 add(current);
3571 goto scan_number_exponent;
3572 }
3573
3574 default:
3575 goto scan_number_done;
3576 }
3577
3578scan_number_decimal1:
3579 // state: we just parsed a decimal point
3580 number_type = token_type::value_float;
3581 switch (get())
3582 {
3583 case '0':
3584 case '1':
3585 case '2':
3586 case '3':
3587 case '4':
3588 case '5':
3589 case '6':
3590 case '7':
3591 case '8':
3592 case '9':
3593 {
3594 add(current);
3595 goto scan_number_decimal2;
3596 }
3597
3598 default:
3599 {
3600 error_message = "invalid number; expected digit after '.'";
3601 return token_type::parse_error;
3602 }
3603 }
3604
3605scan_number_decimal2:
3606 // we just parsed at least one number after a decimal point
3607 switch (get())
3608 {
3609 case '0':
3610 case '1':
3611 case '2':
3612 case '3':
3613 case '4':
3614 case '5':
3615 case '6':
3616 case '7':
3617 case '8':
3618 case '9':
3619 {
3620 add(current);
3621 goto scan_number_decimal2;
3622 }
3623
3624 case 'e':
3625 case 'E':
3626 {
3627 add(current);
3628 goto scan_number_exponent;
3629 }
3630
3631 default:
3632 goto scan_number_done;
3633 }
3634
3635scan_number_exponent:
3636 // we just parsed an exponent
3637 number_type = token_type::value_float;
3638 switch (get())
3639 {
3640 case '+':
3641 case '-':
3642 {
3643 add(current);
3644 goto scan_number_sign;
3645 }
3646
3647 case '0':
3648 case '1':
3649 case '2':
3650 case '3':
3651 case '4':
3652 case '5':
3653 case '6':
3654 case '7':
3655 case '8':
3656 case '9':
3657 {
3658 add(current);
3659 goto scan_number_any2;
3660 }
3661
3662 default:
3663 {
3664 error_message =
3665 "invalid number; expected '+', '-', or digit after exponent";
3666 return token_type::parse_error;
3667 }
3668 }
3669
3670scan_number_sign:
3671 // we just parsed an exponent sign
3672 switch (get())
3673 {
3674 case '0':
3675 case '1':
3676 case '2':
3677 case '3':
3678 case '4':
3679 case '5':
3680 case '6':
3681 case '7':
3682 case '8':
3683 case '9':
3684 {
3685 add(current);
3686 goto scan_number_any2;
3687 }
3688
3689 default:
3690 {
3691 error_message = "invalid number; expected digit after exponent sign";
3692 return token_type::parse_error;
3693 }
3694 }
3695
3696scan_number_any2:
3697 // we just parsed a number after the exponent or exponent sign
3698 switch (get())
3699 {
3700 case '0':
3701 case '1':
3702 case '2':
3703 case '3':
3704 case '4':
3705 case '5':
3706 case '6':
3707 case '7':
3708 case '8':
3709 case '9':
3710 {
3711 add(current);
3712 goto scan_number_any2;
3713 }
3714
3715 default:
3716 goto scan_number_done;
3717 }
3718
3719scan_number_done:
3720 // unget the character after the number (we only read it to know that
3721 // we are done scanning a number)
3722 unget();
3723
3724 char* endptr = nullptr;
3725 errno = 0;
3726
3727 // try to parse integers first and fall back to floats
3728 if (number_type == token_type::value_unsigned)
3729 {
3730 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
3731
3732 // we checked the number format before
3733 assert(endptr == token_buffer.data() + token_buffer.size());
3734
3735 if (errno == 0)
3736 {
3737 value_unsigned = static_cast<number_unsigned_t>(x);
3738 if (value_unsigned == x)
3739 {
3740 return token_type::value_unsigned;
3741 }
3742 }
3743 }
3744 else if (number_type == token_type::value_integer)
3745 {
3746 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
3747
3748 // we checked the number format before
3749 assert(endptr == token_buffer.data() + token_buffer.size());
3750
3751 if (errno == 0)
3752 {
3753 value_integer = static_cast<number_integer_t>(x);
3754 if (value_integer == x)
3755 {
3756 return token_type::value_integer;
3757 }
3758 }
3759 }
3760
3761 // this code is reached if we parse a floating-point number or if an
3762 // integer conversion above failed
3763 strtof(value_float, token_buffer.data(), &endptr);
3764
3765 // we checked the number format before
3766 assert(endptr == token_buffer.data() + token_buffer.size());
3767
3768 return token_type::value_float;
3769 }
3770
3776 token_type scan_literal(const char* literal_text, const std::size_t length,
3777 token_type return_type)
3778 {
3779 assert(current == literal_text[0]);
3780 for (std::size_t i = 1; i < length; ++i)
3781 {
3782 if (JSON_UNLIKELY(get() != literal_text[i]))
3783 {
3784 error_message = "invalid literal";
3785 return token_type::parse_error;
3786 }
3787 }
3788 return return_type;
3789 }
3790
3792 // input management
3794
3796 void reset() noexcept
3797 {
3798 token_buffer.clear();
3799 token_string.clear();
3800 token_string.push_back(std::char_traits<char>::to_char_type(current));
3801 }
3802
3803 /*
3804 @brief get next character from the input
3805
3806 This function provides the interface to the used input adapter. It does
3807 not throw in case the input reached EOF, but returns a
3808 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
3809 for use in error messages.
3810
3811 @return character read from the input
3812 */
3813 std::char_traits<char>::int_type get()
3814 {
3815 ++position.chars_read_total;
3816 ++position.chars_read_current_line;
3817
3818 if (next_unget)
3819 {
3820 // just reset the next_unget variable and work with current
3821 next_unget = false;
3822 }
3823 else
3824 {
3825 current = ia->get_character();
3826 }
3827
3828 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3829 {
3830 token_string.push_back(std::char_traits<char>::to_char_type(current));
3831 }
3832
3833 if (current == '\n')
3834 {
3835 ++position.lines_read;
3836 ++position.chars_read_current_line = 0;
3837 }
3838
3839 return current;
3840 }
3841
3850 void unget()
3851 {
3852 next_unget = true;
3853
3854 --position.chars_read_total;
3855
3856 // in case we "unget" a newline, we have to also decrement the lines_read
3857 if (position.chars_read_current_line == 0)
3858 {
3859 if (position.lines_read > 0)
3860 {
3861 --position.lines_read;
3862 }
3863 }
3864 else
3865 {
3866 --position.chars_read_current_line;
3867 }
3868
3869 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3870 {
3871 assert(token_string.size() != 0);
3872 token_string.pop_back();
3873 }
3874 }
3875
3877 void add(int c)
3878 {
3879 token_buffer.push_back(std::char_traits<char>::to_char_type(c));
3880 }
3881
3882 public:
3884 // value getters
3886
3888 constexpr number_integer_t get_number_integer() const noexcept
3889 {
3890 return value_integer;
3891 }
3892
3894 constexpr number_unsigned_t get_number_unsigned() const noexcept
3895 {
3896 return value_unsigned;
3897 }
3898
3900 constexpr number_float_t get_number_float() const noexcept
3901 {
3902 return value_float;
3903 }
3904
3906 string_t& get_string()
3907 {
3908 return token_buffer;
3909 }
3910
3912 // diagnostics
3914
3916 constexpr position_t get_position() const noexcept
3917 {
3918 return position;
3919 }
3920
3924 std::string get_token_string() const
3925 {
3926 // escape control characters
3927 std::string result;
3928 for (const auto c : token_string)
3929 {
3930 if ('\x00' <= c and c <= '\x1F')
3931 {
3932 // escape control characters
3933 char cs[9];
3934 (std::snprintf)(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
3935 result += cs;
3936 }
3937 else
3938 {
3939 // add character as is
3940 result.push_back(c);
3941 }
3942 }
3943
3944 return result;
3945 }
3946
3948 constexpr const char* get_error_message() const noexcept
3949 {
3950 return error_message;
3951 }
3952
3954 // actual scanner
3956
3962 {
3963 if (get() == 0xEF)
3964 {
3965 // check if we completely parse the BOM
3966 return get() == 0xBB and get() == 0xBF;
3967 }
3968
3969 // the first character is not the beginning of the BOM; unget it to
3970 // process is later
3971 unget();
3972 return true;
3973 }
3974
3976 {
3977 // initially, skip the BOM
3978 if (position.chars_read_total == 0 and not skip_bom())
3979 {
3980 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
3981 return token_type::parse_error;
3982 }
3983
3984 // read next character and ignore whitespace
3985 do
3986 {
3987 get();
3988 }
3989 while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
3990
3991 switch (current)
3992 {
3993 // structural characters
3994 case '[':
3995 return token_type::begin_array;
3996 case ']':
3997 return token_type::end_array;
3998 case '{':
3999 return token_type::begin_object;
4000 case '}':
4001 return token_type::end_object;
4002 case ':':
4003 return token_type::name_separator;
4004 case ',':
4005 return token_type::value_separator;
4006
4007 // literals
4008 case 't':
4009 return scan_literal("true", 4, token_type::literal_true);
4010 case 'f':
4011 return scan_literal("false", 5, token_type::literal_false);
4012 case 'n':
4013 return scan_literal("null", 4, token_type::literal_null);
4014
4015 // string
4016 case '\"':
4017 return scan_string();
4018
4019 // number
4020 case '-':
4021 case '0':
4022 case '1':
4023 case '2':
4024 case '3':
4025 case '4':
4026 case '5':
4027 case '6':
4028 case '7':
4029 case '8':
4030 case '9':
4031 return scan_number();
4032
4033 // end of input (the null byte is needed when parsing from
4034 // string literals)
4035 case '\0':
4036 case std::char_traits<char>::eof():
4037 return token_type::end_of_input;
4038
4039 // error
4040 default:
4041 error_message = "invalid literal";
4042 return token_type::parse_error;
4043 }
4044 }
4045
4046 private:
4048 detail::input_adapter_t ia = nullptr;
4049
4051 std::char_traits<char>::int_type current = std::char_traits<char>::eof();
4052
4054 bool next_unget = false;
4055
4057 position_t position;
4058
4060 std::vector<char> token_string {};
4061
4063 string_t token_buffer {};
4064
4066 const char* error_message = "";
4067
4068 // number values
4069 number_integer_t value_integer = 0;
4070 number_unsigned_t value_unsigned = 0;
4071 number_float_t value_float = 0;
4072
4074 const char decimal_point_char = '.';
4075};
4076} // namespace detail
4077} // namespace nlohmann
4078
4079// #include <nlohmann/detail/input/parser.hpp>
4080
4081
4082#include <cassert> // assert
4083#include <cmath> // isfinite
4084#include <cstdint> // uint8_t
4085#include <functional> // function
4086#include <string> // string
4087#include <utility> // move
4088
4089// #include <nlohmann/detail/exceptions.hpp>
4090
4091// #include <nlohmann/detail/macro_scope.hpp>
4092
4093// #include <nlohmann/detail/meta/is_sax.hpp>
4094
4095
4096#include <cstdint> // size_t
4097#include <utility> // declval
4098
4099// #include <nlohmann/detail/meta/detected.hpp>
4100
4101// #include <nlohmann/detail/meta/type_traits.hpp>
4102
4103
4104namespace nlohmann
4105{
4106namespace detail
4107{
4108template <typename T>
4109using null_function_t = decltype(std::declval<T&>().null());
4110
4111template <typename T>
4113 decltype(std::declval<T&>().boolean(std::declval<bool>()));
4114
4115template <typename T, typename Integer>
4117 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
4118
4119template <typename T, typename Unsigned>
4121 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
4122
4123template <typename T, typename Float, typename String>
4124using number_float_function_t = decltype(std::declval<T&>().number_float(
4125 std::declval<Float>(), std::declval<const String&>()));
4126
4127template <typename T, typename String>
4129 decltype(std::declval<T&>().string(std::declval<String&>()));
4130
4131template <typename T>
4133 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
4134
4135template <typename T, typename String>
4137 decltype(std::declval<T&>().key(std::declval<String&>()));
4138
4139template <typename T>
4140using end_object_function_t = decltype(std::declval<T&>().end_object());
4141
4142template <typename T>
4144 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
4145
4146template <typename T>
4147using end_array_function_t = decltype(std::declval<T&>().end_array());
4148
4149template <typename T, typename Exception>
4150using parse_error_function_t = decltype(std::declval<T&>().parse_error(
4151 std::declval<std::size_t>(), std::declval<const std::string&>(),
4152 std::declval<const Exception&>()));
4153
4154template <typename SAX, typename BasicJsonType>
4156{
4157 private:
4159 "BasicJsonType must be of type basic_json<...>");
4160
4161 using number_integer_t = typename BasicJsonType::number_integer_t;
4162 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4163 using number_float_t = typename BasicJsonType::number_float_t;
4164 using string_t = typename BasicJsonType::string_t;
4165 using exception_t = typename BasicJsonType::exception;
4166
4167 public:
4168 static constexpr bool value =
4172 number_integer_t>::value &&
4174 number_unsigned_t>::value &&
4175 is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
4176 string_t>::value &&
4184};
4185
4186template <typename SAX, typename BasicJsonType>
4188{
4189 private:
4191 "BasicJsonType must be of type basic_json<...>");
4192
4193 using number_integer_t = typename BasicJsonType::number_integer_t;
4194 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4195 using number_float_t = typename BasicJsonType::number_float_t;
4196 using string_t = typename BasicJsonType::string_t;
4197 using exception_t = typename BasicJsonType::exception;
4198
4199 public:
4201 "Missing/invalid function: bool null()");
4203 "Missing/invalid function: bool boolean(bool)");
4205 "Missing/invalid function: bool boolean(bool)");
4206 static_assert(
4208 number_integer_t>::value,
4209 "Missing/invalid function: bool number_integer(number_integer_t)");
4210 static_assert(
4212 number_unsigned_t>::value,
4213 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
4214 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
4215 number_float_t, string_t>::value,
4216 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
4217 static_assert(
4219 "Missing/invalid function: bool string(string_t&)");
4221 "Missing/invalid function: bool start_object(std::size_t)");
4223 "Missing/invalid function: bool key(string_t&)");
4225 "Missing/invalid function: bool end_object()");
4227 "Missing/invalid function: bool start_array(std::size_t)");
4229 "Missing/invalid function: bool end_array()");
4230 static_assert(
4232 "Missing/invalid function: bool parse_error(std::size_t, const "
4233 "std::string&, const exception&)");
4234};
4235} // namespace detail
4236} // namespace nlohmann
4237
4238// #include <nlohmann/detail/input/input_adapters.hpp>
4239
4240// #include <nlohmann/detail/input/json_sax.hpp>
4241
4242
4243#include <cstddef>
4244#include <string>
4245#include <vector>
4246
4247// #include <nlohmann/detail/input/parser.hpp>
4248
4249// #include <nlohmann/detail/exceptions.hpp>
4250
4251
4252namespace nlohmann
4253{
4254
4263template<typename BasicJsonType>
4265{
4267 using number_integer_t = typename BasicJsonType::number_integer_t;
4269 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4271 using number_float_t = typename BasicJsonType::number_float_t;
4273 using string_t = typename BasicJsonType::string_t;
4274
4279 virtual bool null() = 0;
4280
4286 virtual bool boolean(bool val) = 0;
4287
4293 virtual bool number_integer(number_integer_t val) = 0;
4294
4300 virtual bool number_unsigned(number_unsigned_t val) = 0;
4301
4308 virtual bool number_float(number_float_t val, const string_t& s) = 0;
4309
4316 virtual bool string(string_t& val) = 0;
4317
4324 virtual bool start_object(std::size_t elements) = 0;
4325
4332 virtual bool key(string_t& val) = 0;
4333
4338 virtual bool end_object() = 0;
4339
4346 virtual bool start_array(std::size_t elements) = 0;
4347
4352 virtual bool end_array() = 0;
4353
4361 virtual bool parse_error(std::size_t position,
4362 const std::string& last_token,
4363 const detail::exception& ex) = 0;
4364
4365 virtual ~json_sax() = default;
4366};
4367
4368
4369namespace detail
4370{
4384template<typename BasicJsonType>
4386{
4387 public:
4388 using number_integer_t = typename BasicJsonType::number_integer_t;
4389 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4390 using number_float_t = typename BasicJsonType::number_float_t;
4391 using string_t = typename BasicJsonType::string_t;
4392
4398 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
4399 : root(r), allow_exceptions(allow_exceptions_)
4400 {}
4401
4402 bool null()
4403 {
4404 handle_value(nullptr);
4405 return true;
4406 }
4407
4408 bool boolean(bool val)
4409 {
4410 handle_value(val);
4411 return true;
4412 }
4413
4415 {
4416 handle_value(val);
4417 return true;
4418 }
4419
4421 {
4422 handle_value(val);
4423 return true;
4424 }
4425
4426 bool number_float(number_float_t val, const string_t& /*unused*/)
4427 {
4428 handle_value(val);
4429 return true;
4430 }
4431
4432 bool string(string_t& val)
4433 {
4434 handle_value(val);
4435 return true;
4436 }
4437
4438 bool start_object(std::size_t len)
4439 {
4440 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
4441
4442 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4443 {
4445 "excessive object size: " + std::to_string(len)));
4446 }
4447
4448 return true;
4449 }
4450
4451 bool key(string_t& val)
4452 {
4453 // add null at given key and store the reference for later
4454 object_element = &(ref_stack.back()->m_value.object->operator[](val));
4455 return true;
4456 }
4457
4459 {
4460 ref_stack.pop_back();
4461 return true;
4462 }
4463
4464 bool start_array(std::size_t len)
4465 {
4466 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
4467
4468 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4469 {
4471 "excessive array size: " + std::to_string(len)));
4472 }
4473
4474 return true;
4475 }
4476
4478 {
4479 ref_stack.pop_back();
4480 return true;
4481 }
4482
4483 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
4484 const detail::exception& ex)
4485 {
4486 errored = true;
4487 if (allow_exceptions)
4488 {
4489 // determine the proper exception type from the id
4490 switch ((ex.id / 100) % 100)
4491 {
4492 case 1:
4493 JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
4494 case 4:
4495 JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
4496 // LCOV_EXCL_START
4497 case 2:
4498 JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4499 case 3:
4500 JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4501 case 5:
4502 JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4503 default:
4504 assert(false);
4505 // LCOV_EXCL_STOP
4506 }
4507 }
4508 return false;
4509 }
4510
4511 constexpr bool is_errored() const
4512 {
4513 return errored;
4514 }
4515
4516 private:
4523 template<typename Value>
4524 BasicJsonType* handle_value(Value&& v)
4525 {
4526 if (ref_stack.empty())
4527 {
4528 root = BasicJsonType(std::forward<Value>(v));
4529 return &root;
4530 }
4531
4532 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4533
4534 if (ref_stack.back()->is_array())
4535 {
4536 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4537 return &(ref_stack.back()->m_value.array->back());
4538 }
4539 else
4540 {
4541 assert(object_element);
4542 *object_element = BasicJsonType(std::forward<Value>(v));
4543 return object_element;
4544 }
4545 }
4546
4548 BasicJsonType& root;
4550 std::vector<BasicJsonType*> ref_stack;
4552 BasicJsonType* object_element = nullptr;
4554 bool errored = false;
4556 const bool allow_exceptions = true;
4557};
4558
4559template<typename BasicJsonType>
4561{
4562 public:
4563 using number_integer_t = typename BasicJsonType::number_integer_t;
4564 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4565 using number_float_t = typename BasicJsonType::number_float_t;
4566 using string_t = typename BasicJsonType::string_t;
4567 using parser_callback_t = typename BasicJsonType::parser_callback_t;
4568 using parse_event_t = typename BasicJsonType::parse_event_t;
4569
4571 const parser_callback_t cb,
4572 const bool allow_exceptions_ = true)
4573 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
4574 {
4575 keep_stack.push_back(true);
4576 }
4577
4578 bool null()
4579 {
4580 handle_value(nullptr);
4581 return true;
4582 }
4583
4584 bool boolean(bool val)
4585 {
4586 handle_value(val);
4587 return true;
4588 }
4589
4591 {
4592 handle_value(val);
4593 return true;
4594 }
4595
4597 {
4598 handle_value(val);
4599 return true;
4600 }
4601
4602 bool number_float(number_float_t val, const string_t& /*unused*/)
4603 {
4604 handle_value(val);
4605 return true;
4606 }
4607
4608 bool string(string_t& val)
4609 {
4610 handle_value(val);
4611 return true;
4612 }
4613
4614 bool start_object(std::size_t len)
4615 {
4616 // check callback for object start
4617 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
4618 keep_stack.push_back(keep);
4619
4620 auto val = handle_value(BasicJsonType::value_t::object, true);
4621 ref_stack.push_back(val.second);
4622
4623 // check object limit
4624 if (ref_stack.back())
4625 {
4626 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4627 {
4629 "excessive object size: " + std::to_string(len)));
4630 }
4631 }
4632
4633 return true;
4634 }
4635
4636 bool key(string_t& val)
4637 {
4638 BasicJsonType k = BasicJsonType(val);
4639
4640 // check callback for key
4641 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
4642 key_keep_stack.push_back(keep);
4643
4644 // add discarded value at given key and store the reference for later
4645 if (keep and ref_stack.back())
4646 {
4647 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
4648 }
4649
4650 return true;
4651 }
4652
4654 {
4655 if (ref_stack.back())
4656 {
4657 if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
4658 {
4659 // discard object
4660 *ref_stack.back() = discarded;
4661 }
4662 }
4663
4664 assert(not ref_stack.empty());
4665 assert(not keep_stack.empty());
4666 ref_stack.pop_back();
4667 keep_stack.pop_back();
4668
4669 if (not ref_stack.empty() and ref_stack.back())
4670 {
4671 // remove discarded value
4672 if (ref_stack.back()->is_object())
4673 {
4674 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
4675 {
4676 if (it->is_discarded())
4677 {
4678 ref_stack.back()->erase(it);
4679 break;
4680 }
4681 }
4682 }
4683 }
4684
4685 return true;
4686 }
4687
4688 bool start_array(std::size_t len)
4689 {
4690 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
4691 keep_stack.push_back(keep);
4692
4693 auto val = handle_value(BasicJsonType::value_t::array, true);
4694 ref_stack.push_back(val.second);
4695
4696 // check array limit
4697 if (ref_stack.back())
4698 {
4699 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4700 {
4702 "excessive array size: " + std::to_string(len)));
4703 }
4704 }
4705
4706 return true;
4707 }
4708
4710 {
4711 bool keep = true;
4712
4713 if (ref_stack.back())
4714 {
4715 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
4716 if (not keep)
4717 {
4718 // discard array
4719 *ref_stack.back() = discarded;
4720 }
4721 }
4722
4723 assert(not ref_stack.empty());
4724 assert(not keep_stack.empty());
4725 ref_stack.pop_back();
4726 keep_stack.pop_back();
4727
4728 // remove discarded value
4729 if (not keep and not ref_stack.empty())
4730 {
4731 if (ref_stack.back()->is_array())
4732 {
4733 ref_stack.back()->m_value.array->pop_back();
4734 }
4735 }
4736
4737 return true;
4738 }
4739
4740 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
4741 const detail::exception& ex)
4742 {
4743 errored = true;
4744 if (allow_exceptions)
4745 {
4746 // determine the proper exception type from the id
4747 switch ((ex.id / 100) % 100)
4748 {
4749 case 1:
4750 JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
4751 case 4:
4752 JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
4753 // LCOV_EXCL_START
4754 case 2:
4755 JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4756 case 3:
4757 JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4758 case 5:
4759 JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4760 default:
4761 assert(false);
4762 // LCOV_EXCL_STOP
4763 }
4764 }
4765 return false;
4766 }
4767
4768 constexpr bool is_errored() const
4769 {
4770 return errored;
4771 }
4772
4773 private:
4789 template<typename Value>
4790 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
4791 {
4792 assert(not keep_stack.empty());
4793
4794 // do not handle this value if we know it would be added to a discarded
4795 // container
4796 if (not keep_stack.back())
4797 {
4798 return {false, nullptr};
4799 }
4800
4801 // create value
4802 auto value = BasicJsonType(std::forward<Value>(v));
4803
4804 // check callback
4805 const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
4806
4807 // do not handle this value if we just learnt it shall be discarded
4808 if (not keep)
4809 {
4810 return {false, nullptr};
4811 }
4812
4813 if (ref_stack.empty())
4814 {
4815 root = std::move(value);
4816 return {true, &root};
4817 }
4818
4819 // skip this value if we already decided to skip the parent
4820 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
4821 if (not ref_stack.back())
4822 {
4823 return {false, nullptr};
4824 }
4825
4826 // we now only expect arrays and objects
4827 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4828
4829 if (ref_stack.back()->is_array())
4830 {
4831 ref_stack.back()->m_value.array->push_back(std::move(value));
4832 return {true, &(ref_stack.back()->m_value.array->back())};
4833 }
4834 else
4835 {
4836 // check if we should store an element for the current key
4837 assert(not key_keep_stack.empty());
4838 const bool store_element = key_keep_stack.back();
4839 key_keep_stack.pop_back();
4840
4841 if (not store_element)
4842 {
4843 return {false, nullptr};
4844 }
4845
4846 assert(object_element);
4847 *object_element = std::move(value);
4848 return {true, object_element};
4849 }
4850 }
4851
4853 BasicJsonType& root;
4855 std::vector<BasicJsonType*> ref_stack;
4857 std::vector<bool> keep_stack;
4859 std::vector<bool> key_keep_stack;
4861 BasicJsonType* object_element = nullptr;
4863 bool errored = false;
4865 const parser_callback_t callback = nullptr;
4867 const bool allow_exceptions = true;
4869 BasicJsonType discarded = BasicJsonType::value_t::discarded;
4870};
4871
4872template<typename BasicJsonType>
4874{
4875 public:
4876 using number_integer_t = typename BasicJsonType::number_integer_t;
4877 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4878 using number_float_t = typename BasicJsonType::number_float_t;
4879 using string_t = typename BasicJsonType::string_t;
4880
4881 bool null()
4882 {
4883 return true;
4884 }
4885
4886 bool boolean(bool /*unused*/)
4887 {
4888 return true;
4889 }
4890
4892 {
4893 return true;
4894 }
4895
4897 {
4898 return true;
4899 }
4900
4901 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
4902 {
4903 return true;
4904 }
4905
4906 bool string(string_t& /*unused*/)
4907 {
4908 return true;
4909 }
4910
4911 bool start_object(std::size_t /*unused*/ = std::size_t(-1))
4912 {
4913 return true;
4914 }
4915
4916 bool key(string_t& /*unused*/)
4917 {
4918 return true;
4919 }
4920
4922 {
4923 return true;
4924 }
4925
4926 bool start_array(std::size_t /*unused*/ = std::size_t(-1))
4927 {
4928 return true;
4929 }
4930
4932 {
4933 return true;
4934 }
4935
4936 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
4937 {
4938 return false;
4939 }
4940};
4941} // namespace detail
4942
4943} // namespace nlohmann
4944
4945// #include <nlohmann/detail/input/lexer.hpp>
4946
4947// #include <nlohmann/detail/value_t.hpp>
4948
4949
4950namespace nlohmann
4951{
4952namespace detail
4953{
4955// parser //
4957
4963template<typename BasicJsonType>
4965{
4966 using number_integer_t = typename BasicJsonType::number_integer_t;
4967 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4968 using number_float_t = typename BasicJsonType::number_float_t;
4969 using string_t = typename BasicJsonType::string_t;
4970 using lexer_t = lexer<BasicJsonType>;
4971 using token_type = typename lexer_t::token_type;
4972
4973 public:
4989
4991 std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
4992
4995 const parser_callback_t cb = nullptr,
4996 const bool allow_exceptions_ = true)
4997 : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
4998 {
4999 // read first token
5000 get_token();
5001 }
5002
5013 void parse(const bool strict, BasicJsonType& result)
5014 {
5015 if (callback)
5016 {
5017 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
5018 sax_parse_internal(&sdp);
5019 result.assert_invariant();
5020
5021 // in strict mode, input must be completely read
5022 if (strict and (get_token() != token_type::end_of_input))
5023 {
5024 sdp.parse_error(m_lexer.get_position(),
5025 m_lexer.get_token_string(),
5026 parse_error::create(101, m_lexer.get_position(),
5027 exception_message(token_type::end_of_input, "value")));
5028 }
5029
5030 // in case of an error, return discarded value
5031 if (sdp.is_errored())
5032 {
5033 result = value_t::discarded;
5034 return;
5035 }
5036
5037 // set top-level value to null if it was discarded by the callback
5038 // function
5039 if (result.is_discarded())
5040 {
5041 result = nullptr;
5042 }
5043 }
5044 else
5045 {
5046 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
5047 sax_parse_internal(&sdp);
5048 result.assert_invariant();
5049
5050 // in strict mode, input must be completely read
5051 if (strict and (get_token() != token_type::end_of_input))
5052 {
5053 sdp.parse_error(m_lexer.get_position(),
5054 m_lexer.get_token_string(),
5055 parse_error::create(101, m_lexer.get_position(),
5056 exception_message(token_type::end_of_input, "value")));
5057 }
5058
5059 // in case of an error, return discarded value
5060 if (sdp.is_errored())
5061 {
5062 result = value_t::discarded;
5063 return;
5064 }
5065 }
5066 }
5067
5074 bool accept(const bool strict = true)
5075 {
5077 return sax_parse(&sax_acceptor, strict);
5078 }
5079
5080 template <typename SAX>
5081 bool sax_parse(SAX* sax, const bool strict = true)
5082 {
5084 const bool result = sax_parse_internal(sax);
5085
5086 // strict mode: next byte must be EOF
5087 if (result and strict and (get_token() != token_type::end_of_input))
5088 {
5089 return sax->parse_error(m_lexer.get_position(),
5090 m_lexer.get_token_string(),
5091 parse_error::create(101, m_lexer.get_position(),
5092 exception_message(token_type::end_of_input, "value")));
5093 }
5094
5095 return result;
5096 }
5097
5098 private:
5099 template <typename SAX>
5100 bool sax_parse_internal(SAX* sax)
5101 {
5102 // stack to remember the hierarchy of structured values we are parsing
5103 // true = array; false = object
5104 std::vector<bool> states;
5105 // value to avoid a goto (see comment where set to true)
5106 bool skip_to_state_evaluation = false;
5107
5108 while (true)
5109 {
5110 if (not skip_to_state_evaluation)
5111 {
5112 // invariant: get_token() was called before each iteration
5113 switch (last_token)
5114 {
5115 case token_type::begin_object:
5116 {
5117 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
5118 {
5119 return false;
5120 }
5121
5122 // closing } -> we are done
5123 if (get_token() == token_type::end_object)
5124 {
5125 if (JSON_UNLIKELY(not sax->end_object()))
5126 {
5127 return false;
5128 }
5129 break;
5130 }
5131
5132 // parse key
5133 if (JSON_UNLIKELY(last_token != token_type::value_string))
5134 {
5135 return sax->parse_error(m_lexer.get_position(),
5136 m_lexer.get_token_string(),
5137 parse_error::create(101, m_lexer.get_position(),
5138 exception_message(token_type::value_string, "object key")));
5139 }
5140 if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
5141 {
5142 return false;
5143 }
5144
5145 // parse separator (:)
5146 if (JSON_UNLIKELY(get_token() != token_type::name_separator))
5147 {
5148 return sax->parse_error(m_lexer.get_position(),
5149 m_lexer.get_token_string(),
5150 parse_error::create(101, m_lexer.get_position(),
5151 exception_message(token_type::name_separator, "object separator")));
5152 }
5153
5154 // remember we are now inside an object
5155 states.push_back(false);
5156
5157 // parse values
5158 get_token();
5159 continue;
5160 }
5161
5162 case token_type::begin_array:
5163 {
5164 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
5165 {
5166 return false;
5167 }
5168
5169 // closing ] -> we are done
5170 if (get_token() == token_type::end_array)
5171 {
5172 if (JSON_UNLIKELY(not sax->end_array()))
5173 {
5174 return false;
5175 }
5176 break;
5177 }
5178
5179 // remember we are now inside an array
5180 states.push_back(true);
5181
5182 // parse values (no need to call get_token)
5183 continue;
5184 }
5185
5186 case token_type::value_float:
5187 {
5188 const auto res = m_lexer.get_number_float();
5189
5190 if (JSON_UNLIKELY(not std::isfinite(res)))
5191 {
5192 return sax->parse_error(m_lexer.get_position(),
5193 m_lexer.get_token_string(),
5194 out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
5195 }
5196 else
5197 {
5198 if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
5199 {
5200 return false;
5201 }
5202 break;
5203 }
5204 }
5205
5206 case token_type::literal_false:
5207 {
5208 if (JSON_UNLIKELY(not sax->boolean(false)))
5209 {
5210 return false;
5211 }
5212 break;
5213 }
5214
5215 case token_type::literal_null:
5216 {
5217 if (JSON_UNLIKELY(not sax->null()))
5218 {
5219 return false;
5220 }
5221 break;
5222 }
5223
5224 case token_type::literal_true:
5225 {
5226 if (JSON_UNLIKELY(not sax->boolean(true)))
5227 {
5228 return false;
5229 }
5230 break;
5231 }
5232
5233 case token_type::value_integer:
5234 {
5235 if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
5236 {
5237 return false;
5238 }
5239 break;
5240 }
5241
5242 case token_type::value_string:
5243 {
5244 if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
5245 {
5246 return false;
5247 }
5248 break;
5249 }
5250
5251 case token_type::value_unsigned:
5252 {
5253 if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
5254 {
5255 return false;
5256 }
5257 break;
5258 }
5259
5260 case token_type::parse_error:
5261 {
5262 // using "uninitialized" to avoid "expected" message
5263 return sax->parse_error(m_lexer.get_position(),
5264 m_lexer.get_token_string(),
5265 parse_error::create(101, m_lexer.get_position(),
5266 exception_message(token_type::uninitialized, "value")));
5267 }
5268
5269 default: // the last token was unexpected
5270 {
5271 return sax->parse_error(m_lexer.get_position(),
5272 m_lexer.get_token_string(),
5273 parse_error::create(101, m_lexer.get_position(),
5274 exception_message(token_type::literal_or_value, "value")));
5275 }
5276 }
5277 }
5278 else
5279 {
5280 skip_to_state_evaluation = false;
5281 }
5282
5283 // we reached this line after we successfully parsed a value
5284 if (states.empty())
5285 {
5286 // empty stack: we reached the end of the hierarchy: done
5287 return true;
5288 }
5289 else
5290 {
5291 if (states.back()) // array
5292 {
5293 // comma -> next value
5294 if (get_token() == token_type::value_separator)
5295 {
5296 // parse a new value
5297 get_token();
5298 continue;
5299 }
5300
5301 // closing ]
5302 if (JSON_LIKELY(last_token == token_type::end_array))
5303 {
5304 if (JSON_UNLIKELY(not sax->end_array()))
5305 {
5306 return false;
5307 }
5308
5309 // We are done with this array. Before we can parse a
5310 // new value, we need to evaluate the new state first.
5311 // By setting skip_to_state_evaluation to false, we
5312 // are effectively jumping to the beginning of this if.
5313 assert(not states.empty());
5314 states.pop_back();
5315 skip_to_state_evaluation = true;
5316 continue;
5317 }
5318 else
5319 {
5320 return sax->parse_error(m_lexer.get_position(),
5321 m_lexer.get_token_string(),
5322 parse_error::create(101, m_lexer.get_position(),
5323 exception_message(token_type::end_array, "array")));
5324 }
5325 }
5326 else // object
5327 {
5328 // comma -> next value
5329 if (get_token() == token_type::value_separator)
5330 {
5331 // parse key
5332 if (JSON_UNLIKELY(get_token() != token_type::value_string))
5333 {
5334 return sax->parse_error(m_lexer.get_position(),
5335 m_lexer.get_token_string(),
5336 parse_error::create(101, m_lexer.get_position(),
5337 exception_message(token_type::value_string, "object key")));
5338 }
5339 else
5340 {
5341 if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
5342 {
5343 return false;
5344 }
5345 }
5346
5347 // parse separator (:)
5348 if (JSON_UNLIKELY(get_token() != token_type::name_separator))
5349 {
5350 return sax->parse_error(m_lexer.get_position(),
5351 m_lexer.get_token_string(),
5352 parse_error::create(101, m_lexer.get_position(),
5353 exception_message(token_type::name_separator, "object separator")));
5354 }
5355
5356 // parse values
5357 get_token();
5358 continue;
5359 }
5360
5361 // closing }
5362 if (JSON_LIKELY(last_token == token_type::end_object))
5363 {
5364 if (JSON_UNLIKELY(not sax->end_object()))
5365 {
5366 return false;
5367 }
5368
5369 // We are done with this object. Before we can parse a
5370 // new value, we need to evaluate the new state first.
5371 // By setting skip_to_state_evaluation to false, we
5372 // are effectively jumping to the beginning of this if.
5373 assert(not states.empty());
5374 states.pop_back();
5375 skip_to_state_evaluation = true;
5376 continue;
5377 }
5378 else
5379 {
5380 return sax->parse_error(m_lexer.get_position(),
5381 m_lexer.get_token_string(),
5382 parse_error::create(101, m_lexer.get_position(),
5383 exception_message(token_type::end_object, "object")));
5384 }
5385 }
5386 }
5387 }
5388 }
5389
5391 token_type get_token()
5392 {
5393 return (last_token = m_lexer.scan());
5394 }
5395
5396 std::string exception_message(const token_type expected, const std::string& context)
5397 {
5398 std::string error_msg = "syntax error ";
5399
5400 if (not context.empty())
5401 {
5402 error_msg += "while parsing " + context + " ";
5403 }
5404
5405 error_msg += "- ";
5406
5407 if (last_token == token_type::parse_error)
5408 {
5409 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
5410 m_lexer.get_token_string() + "'";
5411 }
5412 else
5413 {
5414 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
5415 }
5416
5417 if (expected != token_type::uninitialized)
5418 {
5419 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
5420 }
5421
5422 return error_msg;
5423 }
5424
5425 private:
5427 const parser_callback_t callback = nullptr;
5429 token_type last_token = token_type::uninitialized;
5431 lexer_t m_lexer;
5433 const bool allow_exceptions = true;
5434};
5435} // namespace detail
5436} // namespace nlohmann
5437
5438// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5439
5440
5441#include <cstddef> // ptrdiff_t
5442#include <limits> // numeric_limits
5443
5444namespace nlohmann
5445{
5446namespace detail
5447{
5448/*
5449@brief an iterator for primitive JSON types
5450
5451This class models an iterator for primitive JSON types (boolean, number,
5452string). It's only purpose is to allow the iterator/const_iterator classes
5453to "iterate" over primitive values. Internally, the iterator is modeled by
5454a `difference_type` variable. Value begin_value (`0`) models the begin,
5455end_value (`1`) models past the end.
5456*/
5458{
5459 private:
5460 using difference_type = std::ptrdiff_t;
5461 static constexpr difference_type begin_value = 0;
5462 static constexpr difference_type end_value = begin_value + 1;
5463
5465 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
5466
5467 public:
5468 constexpr difference_type get_value() const noexcept
5469 {
5470 return m_it;
5471 }
5472
5474 void set_begin() noexcept
5475 {
5476 m_it = begin_value;
5477 }
5478
5480 void set_end() noexcept
5481 {
5482 m_it = end_value;
5483 }
5484
5486 constexpr bool is_begin() const noexcept
5487 {
5488 return m_it == begin_value;
5489 }
5490
5492 constexpr bool is_end() const noexcept
5493 {
5494 return m_it == end_value;
5495 }
5496
5497 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5498 {
5499 return lhs.m_it == rhs.m_it;
5500 }
5501
5502 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5503 {
5504 return lhs.m_it < rhs.m_it;
5505 }
5506
5507 primitive_iterator_t operator+(difference_type n) noexcept
5508 {
5509 auto result = *this;
5510 result += n;
5511 return result;
5512 }
5513
5514 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5515 {
5516 return lhs.m_it - rhs.m_it;
5517 }
5518
5520 {
5521 ++m_it;
5522 return *this;
5523 }
5524
5526 {
5527 auto result = *this;
5528 ++m_it;
5529 return result;
5530 }
5531
5533 {
5534 --m_it;
5535 return *this;
5536 }
5537
5539 {
5540 auto result = *this;
5541 --m_it;
5542 return result;
5543 }
5544
5545 primitive_iterator_t& operator+=(difference_type n) noexcept
5546 {
5547 m_it += n;
5548 return *this;
5549 }
5550
5551 primitive_iterator_t& operator-=(difference_type n) noexcept
5552 {
5553 m_it -= n;
5554 return *this;
5555 }
5556};
5557} // namespace detail
5558} // namespace nlohmann
5559
5560// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5561
5562
5563// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5564
5565
5566namespace nlohmann
5567{
5568namespace detail
5569{
5576template<typename BasicJsonType> struct internal_iterator
5577{
5579 typename BasicJsonType::object_t::iterator object_iterator {};
5581 typename BasicJsonType::array_t::iterator array_iterator {};
5584};
5585} // namespace detail
5586} // namespace nlohmann
5587
5588// #include <nlohmann/detail/iterators/iter_impl.hpp>
5589
5590
5591#include <ciso646> // not
5592#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
5593#include <type_traits> // conditional, is_const, remove_const
5594
5595// #include <nlohmann/detail/exceptions.hpp>
5596
5597// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5598
5599// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5600
5601// #include <nlohmann/detail/macro_scope.hpp>
5602
5603// #include <nlohmann/detail/meta/cpp_future.hpp>
5604
5605// #include <nlohmann/detail/value_t.hpp>
5606
5607
5608namespace nlohmann
5609{
5610namespace detail
5611{
5612// forward declare, to be able to friend it later on
5613template<typename IteratorType> class iteration_proxy;
5614template<typename IteratorType> class iteration_proxy_value;
5615
5632template<typename BasicJsonType>
5634{
5636 friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
5637 friend BasicJsonType;
5640
5641 using object_t = typename BasicJsonType::object_t;
5642 using array_t = typename BasicJsonType::array_t;
5643 // make sure BasicJsonType is basic_json or const basic_json
5645 "iter_impl only accepts (const) basic_json");
5646
5647 public:
5648
5654 using iterator_category = std::bidirectional_iterator_tag;
5655
5657 using value_type = typename BasicJsonType::value_type;
5659 using difference_type = typename BasicJsonType::difference_type;
5661 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
5662 typename BasicJsonType::const_pointer,
5663 typename BasicJsonType::pointer>::type;
5666 typename std::conditional<std::is_const<BasicJsonType>::value,
5667 typename BasicJsonType::const_reference,
5668 typename BasicJsonType::reference>::type;
5669
5671 iter_impl() = default;
5672
5679 explicit iter_impl(pointer object) noexcept : m_object(object)
5680 {
5681 assert(m_object != nullptr);
5682
5683 switch (m_object->m_type)
5684 {
5685 case value_t::object:
5686 {
5687 m_it.object_iterator = typename object_t::iterator();
5688 break;
5689 }
5690
5691 case value_t::array:
5692 {
5693 m_it.array_iterator = typename array_t::iterator();
5694 break;
5695 }
5696
5697 default:
5698 {
5699 m_it.primitive_iterator = primitive_iterator_t();
5700 break;
5701 }
5702 }
5703 }
5704
5713
5719 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5720 : m_object(other.m_object), m_it(other.m_it) {}
5721
5728 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5729 {
5730 m_object = other.m_object;
5731 m_it = other.m_it;
5732 return *this;
5733 }
5734
5735 private:
5740 void set_begin() noexcept
5741 {
5742 assert(m_object != nullptr);
5743
5744 switch (m_object->m_type)
5745 {
5746 case value_t::object:
5747 {
5748 m_it.object_iterator = m_object->m_value.object->begin();
5749 break;
5750 }
5751
5752 case value_t::array:
5753 {
5754 m_it.array_iterator = m_object->m_value.array->begin();
5755 break;
5756 }
5757
5758 case value_t::null:
5759 {
5760 // set to end so begin()==end() is true: null is empty
5761 m_it.primitive_iterator.set_end();
5762 break;
5763 }
5764
5765 default:
5766 {
5767 m_it.primitive_iterator.set_begin();
5768 break;
5769 }
5770 }
5771 }
5772
5777 void set_end() noexcept
5778 {
5779 assert(m_object != nullptr);
5780
5781 switch (m_object->m_type)
5782 {
5783 case value_t::object:
5784 {
5785 m_it.object_iterator = m_object->m_value.object->end();
5786 break;
5787 }
5788
5789 case value_t::array:
5790 {
5791 m_it.array_iterator = m_object->m_value.array->end();
5792 break;
5793 }
5794
5795 default:
5796 {
5797 m_it.primitive_iterator.set_end();
5798 break;
5799 }
5800 }
5801 }
5802
5803 public:
5809 {
5810 assert(m_object != nullptr);
5811
5812 switch (m_object->m_type)
5813 {
5814 case value_t::object:
5815 {
5816 assert(m_it.object_iterator != m_object->m_value.object->end());
5817 return m_it.object_iterator->second;
5818 }
5819
5820 case value_t::array:
5821 {
5822 assert(m_it.array_iterator != m_object->m_value.array->end());
5823 return *m_it.array_iterator;
5824 }
5825
5826 case value_t::null:
5827 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5828
5829 default:
5830 {
5831 if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5832 {
5833 return *m_object;
5834 }
5835
5836 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5837 }
5838 }
5839 }
5840
5846 {
5847 assert(m_object != nullptr);
5848
5849 switch (m_object->m_type)
5850 {
5851 case value_t::object:
5852 {
5853 assert(m_it.object_iterator != m_object->m_value.object->end());
5854 return &(m_it.object_iterator->second);
5855 }
5856
5857 case value_t::array:
5858 {
5859 assert(m_it.array_iterator != m_object->m_value.array->end());
5860 return &*m_it.array_iterator;
5861 }
5862
5863 default:
5864 {
5865 if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5866 {
5867 return m_object;
5868 }
5869
5870 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5871 }
5872 }
5873 }
5874
5880 {
5881 auto result = *this;
5882 ++(*this);
5883 return result;
5884 }
5885
5891 {
5892 assert(m_object != nullptr);
5893
5894 switch (m_object->m_type)
5895 {
5896 case value_t::object:
5897 {
5898 std::advance(m_it.object_iterator, 1);
5899 break;
5900 }
5901
5902 case value_t::array:
5903 {
5904 std::advance(m_it.array_iterator, 1);
5905 break;
5906 }
5907
5908 default:
5909 {
5910 ++m_it.primitive_iterator;
5911 break;
5912 }
5913 }
5914
5915 return *this;
5916 }
5917
5923 {
5924 auto result = *this;
5925 --(*this);
5926 return result;
5927 }
5928
5934 {
5935 assert(m_object != nullptr);
5936
5937 switch (m_object->m_type)
5938 {
5939 case value_t::object:
5940 {
5941 std::advance(m_it.object_iterator, -1);
5942 break;
5943 }
5944
5945 case value_t::array:
5946 {
5947 std::advance(m_it.array_iterator, -1);
5948 break;
5949 }
5950
5951 default:
5952 {
5953 --m_it.primitive_iterator;
5954 break;
5955 }
5956 }
5957
5958 return *this;
5959 }
5960
5965 bool operator==(const iter_impl& other) const
5966 {
5967 // if objects are not the same, the comparison is undefined
5968 if (JSON_UNLIKELY(m_object != other.m_object))
5969 {
5970 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
5971 }
5972
5973 assert(m_object != nullptr);
5974
5975 switch (m_object->m_type)
5976 {
5977 case value_t::object:
5978 return (m_it.object_iterator == other.m_it.object_iterator);
5979
5980 case value_t::array:
5981 return (m_it.array_iterator == other.m_it.array_iterator);
5982
5983 default:
5984 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5985 }
5986 }
5987
5992 bool operator!=(const iter_impl& other) const
5993 {
5994 return not operator==(other);
5995 }
5996
6001 bool operator<(const iter_impl& other) const
6002 {
6003 // if objects are not the same, the comparison is undefined
6004 if (JSON_UNLIKELY(m_object != other.m_object))
6005 {
6006 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
6007 }
6008
6009 assert(m_object != nullptr);
6010
6011 switch (m_object->m_type)
6012 {
6013 case value_t::object:
6014 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
6015
6016 case value_t::array:
6017 return (m_it.array_iterator < other.m_it.array_iterator);
6018
6019 default:
6020 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6021 }
6022 }
6023
6028 bool operator<=(const iter_impl& other) const
6029 {
6030 return not other.operator < (*this);
6031 }
6032
6037 bool operator>(const iter_impl& other) const
6038 {
6039 return not operator<=(other);
6040 }
6041
6046 bool operator>=(const iter_impl& other) const
6047 {
6048 return not operator<(other);
6049 }
6050
6056 {
6057 assert(m_object != nullptr);
6058
6059 switch (m_object->m_type)
6060 {
6061 case value_t::object:
6062 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
6063
6064 case value_t::array:
6065 {
6066 std::advance(m_it.array_iterator, i);
6067 break;
6068 }
6069
6070 default:
6071 {
6072 m_it.primitive_iterator += i;
6073 break;
6074 }
6075 }
6076
6077 return *this;
6078 }
6079
6085 {
6086 return operator+=(-i);
6087 }
6088
6094 {
6095 auto result = *this;
6096 result += i;
6097 return result;
6098 }
6099
6105 {
6106 auto result = it;
6107 result += i;
6108 return result;
6109 }
6110
6116 {
6117 auto result = *this;
6118 result -= i;
6119 return result;
6120 }
6121
6127 {
6128 assert(m_object != nullptr);
6129
6130 switch (m_object->m_type)
6131 {
6132 case value_t::object:
6133 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
6134
6135 case value_t::array:
6136 return m_it.array_iterator - other.m_it.array_iterator;
6137
6138 default:
6139 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6140 }
6141 }
6142
6148 {
6149 assert(m_object != nullptr);
6150
6151 switch (m_object->m_type)
6152 {
6153 case value_t::object:
6154 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
6155
6156 case value_t::array:
6157 return *std::next(m_it.array_iterator, n);
6158
6159 case value_t::null:
6160 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
6161
6162 default:
6163 {
6164 if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
6165 {
6166 return *m_object;
6167 }
6168
6169 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
6170 }
6171 }
6172 }
6173
6178 const typename object_t::key_type& key() const
6179 {
6180 assert(m_object != nullptr);
6181
6182 if (JSON_LIKELY(m_object->is_object()))
6183 {
6184 return m_it.object_iterator->first;
6185 }
6186
6187 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
6188 }
6189
6195 {
6196 return operator*();
6197 }
6198
6199 private:
6201 pointer m_object = nullptr;
6204};
6205} // namespace detail
6206} // namespace nlohmann
6207// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
6208
6209// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
6210
6211
6212#include <cstddef> // ptrdiff_t
6213#include <iterator> // reverse_iterator
6214#include <utility> // declval
6215
6216namespace nlohmann
6217{
6218namespace detail
6219{
6221// reverse_iterator //
6223
6242template<typename Base>
6243class json_reverse_iterator : public std::reverse_iterator<Base>
6244{
6245 public:
6246 using difference_type = std::ptrdiff_t;
6248 using base_iterator = std::reverse_iterator<Base>;
6250 using reference = typename Base::reference;
6251
6253 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
6254 : base_iterator(it) {}
6255
6257 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
6258
6261 {
6262 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
6263 }
6264
6267 {
6268 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
6269 }
6270
6273 {
6274 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
6275 }
6276
6279 {
6280 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
6281 }
6282
6285 {
6286 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
6287 }
6288
6291 {
6292 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
6293 }
6294
6297 {
6298 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
6299 }
6300
6303 {
6304 return base_iterator(*this) - base_iterator(other);
6305 }
6306
6309 {
6310 return *(this->operator+(n));
6311 }
6312
6314 auto key() const -> decltype(std::declval<Base>().key())
6315 {
6316 auto it = --this->base();
6317 return it.key();
6318 }
6319
6322 {
6323 auto it = --this->base();
6324 return it.operator * ();
6325 }
6326};
6327} // namespace detail
6328} // namespace nlohmann
6329
6330// #include <nlohmann/detail/output/output_adapters.hpp>
6331
6332
6333#include <algorithm> // copy
6334#include <cstddef> // size_t
6335#include <ios> // streamsize
6336#include <iterator> // back_inserter
6337#include <memory> // shared_ptr, make_shared
6338#include <ostream> // basic_ostream
6339#include <string> // basic_string
6340#include <vector> // vector
6341
6342namespace nlohmann
6343{
6344namespace detail
6345{
6347template<typename CharType> struct output_adapter_protocol
6348{
6349 virtual void write_character(CharType c) = 0;
6350 virtual void write_characters(const CharType* s, std::size_t length) = 0;
6351 virtual ~output_adapter_protocol() = default;
6352};
6353
6355template<typename CharType>
6356using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
6357
6359template<typename CharType>
6361{
6362 public:
6363 explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
6364 : v(vec)
6365 {}
6366
6367 void write_character(CharType c) override
6368 {
6369 v.push_back(c);
6370 }
6371
6372 void write_characters(const CharType* s, std::size_t length) override
6373 {
6374 std::copy(s, s + length, std::back_inserter(v));
6375 }
6376
6377 private:
6378 std::vector<CharType>& v;
6379};
6380
6382template<typename CharType>
6384{
6385 public:
6386 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
6387 : stream(s)
6388 {}
6389
6390 void write_character(CharType c) override
6391 {
6392 stream.put(c);
6393 }
6394
6395 void write_characters(const CharType* s, std::size_t length) override
6396 {
6397 stream.write(s, static_cast<std::streamsize>(length));
6398 }
6399
6400 private:
6401 std::basic_ostream<CharType>& stream;
6402};
6403
6405template<typename CharType, typename StringType = std::basic_string<CharType>>
6407{
6408 public:
6409 explicit output_string_adapter(StringType& s) noexcept
6410 : str(s)
6411 {}
6412
6413 void write_character(CharType c) override
6414 {
6415 str.push_back(c);
6416 }
6417
6418 void write_characters(const CharType* s, std::size_t length) override
6419 {
6420 str.append(s, length);
6421 }
6422
6423 private:
6424 StringType& str;
6425};
6426
6427template<typename CharType, typename StringType = std::basic_string<CharType>>
6429{
6430 public:
6431 output_adapter(std::vector<CharType>& vec)
6432 : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
6433
6434 output_adapter(std::basic_ostream<CharType>& s)
6435 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
6436
6437 output_adapter(StringType& s)
6438 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
6439
6441 {
6442 return oa;
6443 }
6444
6445 private:
6446 output_adapter_t<CharType> oa = nullptr;
6447};
6448} // namespace detail
6449} // namespace nlohmann
6450
6451// #include <nlohmann/detail/input/binary_reader.hpp>
6452
6453
6454#include <algorithm> // generate_n
6455#include <array> // array
6456#include <cassert> // assert
6457#include <cmath> // ldexp
6458#include <cstddef> // size_t
6459#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6460#include <cstdio> // snprintf
6461#include <cstring> // memcpy
6462#include <iterator> // back_inserter
6463#include <limits> // numeric_limits
6464#include <string> // char_traits, string
6465#include <utility> // make_pair, move
6466
6467// #include <nlohmann/detail/input/input_adapters.hpp>
6468
6469// #include <nlohmann/detail/input/json_sax.hpp>
6470
6471// #include <nlohmann/detail/exceptions.hpp>
6472
6473// #include <nlohmann/detail/macro_scope.hpp>
6474
6475// #include <nlohmann/detail/meta/is_sax.hpp>
6476
6477// #include <nlohmann/detail/value_t.hpp>
6478
6479
6480namespace nlohmann
6481{
6482namespace detail
6483{
6485// binary reader //
6487
6491template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
6493{
6494 using number_integer_t = typename BasicJsonType::number_integer_t;
6495 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6496 using number_float_t = typename BasicJsonType::number_float_t;
6497 using string_t = typename BasicJsonType::string_t;
6498 using json_sax_t = SAX;
6499
6500 public:
6506 explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
6507 {
6509 assert(ia);
6510 }
6511
6520 json_sax_t* sax_,
6521 const bool strict = true)
6522 {
6523 sax = sax_;
6524 bool result = false;
6525
6526 switch (format)
6527 {
6529 result = parse_bson_internal();
6530 break;
6531
6533 result = parse_cbor_internal();
6534 break;
6535
6537 result = parse_msgpack_internal();
6538 break;
6539
6541 result = parse_ubjson_internal();
6542 break;
6543
6544 // LCOV_EXCL_START
6545 default:
6546 assert(false);
6547 // LCOV_EXCL_STOP
6548 }
6549
6550 // strict mode: next byte must be EOF
6551 if (result and strict)
6552 {
6554 {
6555 get_ignore_noop();
6556 }
6557 else
6558 {
6559 get();
6560 }
6561
6562 if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
6563 {
6564 return sax->parse_error(chars_read, get_token_string(),
6565 parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
6566 }
6567 }
6568
6569 return result;
6570 }
6571
6579 static constexpr bool little_endianess(int num = 1) noexcept
6580 {
6581 return (*reinterpret_cast<char*>(&num) == 1);
6582 }
6583
6584 private:
6586 // BSON //
6588
6593 bool parse_bson_internal()
6594 {
6595 std::int32_t document_size;
6596 get_number<std::int32_t, true>(input_format_t::bson, document_size);
6597
6598 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
6599 {
6600 return false;
6601 }
6602
6603 if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))
6604 {
6605 return false;
6606 }
6607
6608 return sax->end_object();
6609 }
6610
6618 bool get_bson_cstr(string_t& result)
6619 {
6620 auto out = std::back_inserter(result);
6621 while (true)
6622 {
6623 get();
6624 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring")))
6625 {
6626 return false;
6627 }
6628 if (current == 0x00)
6629 {
6630 return true;
6631 }
6632 *out++ = static_cast<char>(current);
6633 }
6634
6635 return true;
6636 }
6637
6649 template<typename NumberType>
6650 bool get_bson_string(const NumberType len, string_t& result)
6651 {
6652 if (JSON_UNLIKELY(len < 1))
6653 {
6654 auto last_token = get_token_string();
6655 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
6656 }
6657
6658 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) and get() != std::char_traits<char>::eof();
6659 }
6660
6671 bool parse_bson_element_internal(const int element_type,
6672 const std::size_t element_type_parse_position)
6673 {
6674 switch (element_type)
6675 {
6676 case 0x01: // double
6677 {
6678 double number;
6679 return get_number<double, true>(input_format_t::bson, number) and sax->number_float(static_cast<number_float_t>(number), "");
6680 }
6681
6682 case 0x02: // string
6683 {
6684 std::int32_t len;
6685 string_t value;
6686 return get_number<std::int32_t, true>(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value);
6687 }
6688
6689 case 0x03: // object
6690 {
6691 return parse_bson_internal();
6692 }
6693
6694 case 0x04: // array
6695 {
6696 return parse_bson_array();
6697 }
6698
6699 case 0x08: // boolean
6700 {
6701 return sax->boolean(get() != 0);
6702 }
6703
6704 case 0x0A: // null
6705 {
6706 return sax->null();
6707 }
6708
6709 case 0x10: // int32
6710 {
6711 std::int32_t value;
6712 return get_number<std::int32_t, true>(input_format_t::bson, value) and sax->number_integer(value);
6713 }
6714
6715 case 0x12: // int64
6716 {
6717 std::int64_t value;
6718 return get_number<std::int64_t, true>(input_format_t::bson, value) and sax->number_integer(value);
6719 }
6720
6721 default: // anything else not supported (yet)
6722 {
6723 char cr[3];
6724 (std::snprintf)(cr, sizeof(cr), "%.2hhX", static_cast<unsigned char>(element_type));
6725 return sax->parse_error(element_type_parse_position, std::string(cr), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr)));
6726 }
6727 }
6728 }
6729
6742 bool parse_bson_element_list(const bool is_array)
6743 {
6744 string_t key;
6745 while (int element_type = get())
6746 {
6747 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list")))
6748 {
6749 return false;
6750 }
6751
6752 const std::size_t element_type_parse_position = chars_read;
6753 if (JSON_UNLIKELY(not get_bson_cstr(key)))
6754 {
6755 return false;
6756 }
6757
6758 if (not is_array)
6759 {
6760 if (not sax->key(key))
6761 {
6762 return false;
6763 }
6764 }
6765
6766 if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
6767 {
6768 return false;
6769 }
6770
6771 // get_bson_cstr only appends
6772 key.clear();
6773 }
6774
6775 return true;
6776 }
6777
6782 bool parse_bson_array()
6783 {
6784 std::int32_t document_size;
6785 get_number<std::int32_t, true>(input_format_t::bson, document_size);
6786
6787 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
6788 {
6789 return false;
6790 }
6791
6792 if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))
6793 {
6794 return false;
6795 }
6796
6797 return sax->end_array();
6798 }
6799
6801 // CBOR //
6803
6811 bool parse_cbor_internal(const bool get_char = true)
6812 {
6813 switch (get_char ? get() : current)
6814 {
6815 // EOF
6816 case std::char_traits<char>::eof():
6817 return unexpect_eof(input_format_t::cbor, "value");
6818
6819 // Integer 0x00..0x17 (0..23)
6820 case 0x00:
6821 case 0x01:
6822 case 0x02:
6823 case 0x03:
6824 case 0x04:
6825 case 0x05:
6826 case 0x06:
6827 case 0x07:
6828 case 0x08:
6829 case 0x09:
6830 case 0x0A:
6831 case 0x0B:
6832 case 0x0C:
6833 case 0x0D:
6834 case 0x0E:
6835 case 0x0F:
6836 case 0x10:
6837 case 0x11:
6838 case 0x12:
6839 case 0x13:
6840 case 0x14:
6841 case 0x15:
6842 case 0x16:
6843 case 0x17:
6844 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6845
6846 case 0x18: // Unsigned integer (one-byte uint8_t follows)
6847 {
6848 uint8_t number;
6849 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6850 }
6851
6852 case 0x19: // Unsigned integer (two-byte uint16_t follows)
6853 {
6854 uint16_t number;
6855 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6856 }
6857
6858 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
6859 {
6860 uint32_t number;
6861 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6862 }
6863
6864 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
6865 {
6866 uint64_t number;
6867 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6868 }
6869
6870 // Negative integer -1-0x00..-1-0x17 (-1..-24)
6871 case 0x20:
6872 case 0x21:
6873 case 0x22:
6874 case 0x23:
6875 case 0x24:
6876 case 0x25:
6877 case 0x26:
6878 case 0x27:
6879 case 0x28:
6880 case 0x29:
6881 case 0x2A:
6882 case 0x2B:
6883 case 0x2C:
6884 case 0x2D:
6885 case 0x2E:
6886 case 0x2F:
6887 case 0x30:
6888 case 0x31:
6889 case 0x32:
6890 case 0x33:
6891 case 0x34:
6892 case 0x35:
6893 case 0x36:
6894 case 0x37:
6895 return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
6896
6897 case 0x38: // Negative integer (one-byte uint8_t follows)
6898 {
6899 uint8_t number;
6900 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6901 }
6902
6903 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
6904 {
6905 uint16_t number;
6906 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6907 }
6908
6909 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
6910 {
6911 uint32_t number;
6912 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6913 }
6914
6915 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
6916 {
6917 uint64_t number;
6918 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
6919 - static_cast<number_integer_t>(number));
6920 }
6921
6922 // UTF-8 string (0x00..0x17 bytes follow)
6923 case 0x60:
6924 case 0x61:
6925 case 0x62:
6926 case 0x63:
6927 case 0x64:
6928 case 0x65:
6929 case 0x66:
6930 case 0x67:
6931 case 0x68:
6932 case 0x69:
6933 case 0x6A:
6934 case 0x6B:
6935 case 0x6C:
6936 case 0x6D:
6937 case 0x6E:
6938 case 0x6F:
6939 case 0x70:
6940 case 0x71:
6941 case 0x72:
6942 case 0x73:
6943 case 0x74:
6944 case 0x75:
6945 case 0x76:
6946 case 0x77:
6947 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
6948 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
6949 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
6950 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
6951 case 0x7F: // UTF-8 string (indefinite length)
6952 {
6953 string_t s;
6954 return get_cbor_string(s) and sax->string(s);
6955 }
6956
6957 // array (0x00..0x17 data items follow)
6958 case 0x80:
6959 case 0x81:
6960 case 0x82:
6961 case 0x83:
6962 case 0x84:
6963 case 0x85:
6964 case 0x86:
6965 case 0x87:
6966 case 0x88:
6967 case 0x89:
6968 case 0x8A:
6969 case 0x8B:
6970 case 0x8C:
6971 case 0x8D:
6972 case 0x8E:
6973 case 0x8F:
6974 case 0x90:
6975 case 0x91:
6976 case 0x92:
6977 case 0x93:
6978 case 0x94:
6979 case 0x95:
6980 case 0x96:
6981 case 0x97:
6982 return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
6983
6984 case 0x98: // array (one-byte uint8_t for n follows)
6985 {
6986 uint8_t len;
6987 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
6988 }
6989
6990 case 0x99: // array (two-byte uint16_t for n follow)
6991 {
6992 uint16_t len;
6993 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
6994 }
6995
6996 case 0x9A: // array (four-byte uint32_t for n follow)
6997 {
6998 uint32_t len;
6999 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
7000 }
7001
7002 case 0x9B: // array (eight-byte uint64_t for n follow)
7003 {
7004 uint64_t len;
7005 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
7006 }
7007
7008 case 0x9F: // array (indefinite length)
7009 return get_cbor_array(std::size_t(-1));
7010
7011 // map (0x00..0x17 pairs of data items follow)
7012 case 0xA0:
7013 case 0xA1:
7014 case 0xA2:
7015 case 0xA3:
7016 case 0xA4:
7017 case 0xA5:
7018 case 0xA6:
7019 case 0xA7:
7020 case 0xA8:
7021 case 0xA9:
7022 case 0xAA:
7023 case 0xAB:
7024 case 0xAC:
7025 case 0xAD:
7026 case 0xAE:
7027 case 0xAF:
7028 case 0xB0:
7029 case 0xB1:
7030 case 0xB2:
7031 case 0xB3:
7032 case 0xB4:
7033 case 0xB5:
7034 case 0xB6:
7035 case 0xB7:
7036 return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
7037
7038 case 0xB8: // map (one-byte uint8_t for n follows)
7039 {
7040 uint8_t len;
7041 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
7042 }
7043
7044 case 0xB9: // map (two-byte uint16_t for n follow)
7045 {
7046 uint16_t len;
7047 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
7048 }
7049
7050 case 0xBA: // map (four-byte uint32_t for n follow)
7051 {
7052 uint32_t len;
7053 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
7054 }
7055
7056 case 0xBB: // map (eight-byte uint64_t for n follow)
7057 {
7058 uint64_t len;
7059 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
7060 }
7061
7062 case 0xBF: // map (indefinite length)
7063 return get_cbor_object(std::size_t(-1));
7064
7065 case 0xF4: // false
7066 return sax->boolean(false);
7067
7068 case 0xF5: // true
7069 return sax->boolean(true);
7070
7071 case 0xF6: // null
7072 return sax->null();
7073
7074 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
7075 {
7076 const int byte1_raw = get();
7077 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
7078 {
7079 return false;
7080 }
7081 const int byte2_raw = get();
7082 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
7083 {
7084 return false;
7085 }
7086
7087 const auto byte1 = static_cast<unsigned char>(byte1_raw);
7088 const auto byte2 = static_cast<unsigned char>(byte2_raw);
7089
7090 // code from RFC 7049, Appendix D, Figure 3:
7091 // As half-precision floating-point numbers were only added
7092 // to IEEE 754 in 2008, today's programming platforms often
7093 // still only have limited support for them. It is very
7094 // easy to include at least decoding support for them even
7095 // without such support. An example of a small decoder for
7096 // half-precision floating-point numbers in the C language
7097 // is shown in Fig. 3.
7098 const int half = (byte1 << 8) + byte2;
7099 const double val = [&half]
7100 {
7101 const int exp = (half >> 10) & 0x1F;
7102 const int mant = half & 0x3FF;
7103 assert(0 <= exp and exp <= 32);
7104 assert(0 <= mant and mant <= 1024);
7105 switch (exp)
7106 {
7107 case 0:
7108 return std::ldexp(mant, -24);
7109 case 31:
7110 return (mant == 0)
7111 ? std::numeric_limits<double>::infinity()
7112 : std::numeric_limits<double>::quiet_NaN();
7113 default:
7114 return std::ldexp(mant + 1024, exp - 25);
7115 }
7116 }();
7117 return sax->number_float((half & 0x8000) != 0
7118 ? static_cast<number_float_t>(-val)
7119 : static_cast<number_float_t>(val), "");
7120 }
7121
7122 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
7123 {
7124 float number;
7125 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
7126 }
7127
7128 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
7129 {
7130 double number;
7131 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
7132 }
7133
7134 default: // anything else (0xFF is handled inside the other types)
7135 {
7136 auto last_token = get_token_string();
7137 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value")));
7138 }
7139 }
7140 }
7141
7153 bool get_cbor_string(string_t& result)
7154 {
7155 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string")))
7156 {
7157 return false;
7158 }
7159
7160 switch (current)
7161 {
7162 // UTF-8 string (0x00..0x17 bytes follow)
7163 case 0x60:
7164 case 0x61:
7165 case 0x62:
7166 case 0x63:
7167 case 0x64:
7168 case 0x65:
7169 case 0x66:
7170 case 0x67:
7171 case 0x68:
7172 case 0x69:
7173 case 0x6A:
7174 case 0x6B:
7175 case 0x6C:
7176 case 0x6D:
7177 case 0x6E:
7178 case 0x6F:
7179 case 0x70:
7180 case 0x71:
7181 case 0x72:
7182 case 0x73:
7183 case 0x74:
7184 case 0x75:
7185 case 0x76:
7186 case 0x77:
7187 {
7188 return get_string(input_format_t::cbor, current & 0x1F, result);
7189 }
7190
7191 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7192 {
7193 uint8_t len;
7194 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7195 }
7196
7197 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7198 {
7199 uint16_t len;
7200 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7201 }
7202
7203 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
7204 {
7205 uint32_t len;
7206 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7207 }
7208
7209 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
7210 {
7211 uint64_t len;
7212 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7213 }
7214
7215 case 0x7F: // UTF-8 string (indefinite length)
7216 {
7217 while (get() != 0xFF)
7218 {
7219 string_t chunk;
7220 if (not get_cbor_string(chunk))
7221 {
7222 return false;
7223 }
7224 result.append(chunk);
7225 }
7226 return true;
7227 }
7228
7229 default:
7230 {
7231 auto last_token = get_token_string();
7232 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string")));
7233 }
7234 }
7235 }
7236
7242 bool get_cbor_array(const std::size_t len)
7243 {
7244 if (JSON_UNLIKELY(not sax->start_array(len)))
7245 {
7246 return false;
7247 }
7248
7249 if (len != std::size_t(-1))
7250 {
7251 for (std::size_t i = 0; i < len; ++i)
7252 {
7253 if (JSON_UNLIKELY(not parse_cbor_internal()))
7254 {
7255 return false;
7256 }
7257 }
7258 }
7259 else
7260 {
7261 while (get() != 0xFF)
7262 {
7263 if (JSON_UNLIKELY(not parse_cbor_internal(false)))
7264 {
7265 return false;
7266 }
7267 }
7268 }
7269
7270 return sax->end_array();
7271 }
7272
7278 bool get_cbor_object(const std::size_t len)
7279 {
7280 if (not JSON_UNLIKELY(sax->start_object(len)))
7281 {
7282 return false;
7283 }
7284
7285 string_t key;
7286 if (len != std::size_t(-1))
7287 {
7288 for (std::size_t i = 0; i < len; ++i)
7289 {
7290 get();
7291 if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7292 {
7293 return false;
7294 }
7295
7296 if (JSON_UNLIKELY(not parse_cbor_internal()))
7297 {
7298 return false;
7299 }
7300 key.clear();
7301 }
7302 }
7303 else
7304 {
7305 while (get() != 0xFF)
7306 {
7307 if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7308 {
7309 return false;
7310 }
7311
7312 if (JSON_UNLIKELY(not parse_cbor_internal()))
7313 {
7314 return false;
7315 }
7316 key.clear();
7317 }
7318 }
7319
7320 return sax->end_object();
7321 }
7322
7324 // MsgPack //
7326
7330 bool parse_msgpack_internal()
7331 {
7332 switch (get())
7333 {
7334 // EOF
7335 case std::char_traits<char>::eof():
7336 return unexpect_eof(input_format_t::msgpack, "value");
7337
7338 // positive fixint
7339 case 0x00:
7340 case 0x01:
7341 case 0x02:
7342 case 0x03:
7343 case 0x04:
7344 case 0x05:
7345 case 0x06:
7346 case 0x07:
7347 case 0x08:
7348 case 0x09:
7349 case 0x0A:
7350 case 0x0B:
7351 case 0x0C:
7352 case 0x0D:
7353 case 0x0E:
7354 case 0x0F:
7355 case 0x10:
7356 case 0x11:
7357 case 0x12:
7358 case 0x13:
7359 case 0x14:
7360 case 0x15:
7361 case 0x16:
7362 case 0x17:
7363 case 0x18:
7364 case 0x19:
7365 case 0x1A:
7366 case 0x1B:
7367 case 0x1C:
7368 case 0x1D:
7369 case 0x1E:
7370 case 0x1F:
7371 case 0x20:
7372 case 0x21:
7373 case 0x22:
7374 case 0x23:
7375 case 0x24:
7376 case 0x25:
7377 case 0x26:
7378 case 0x27:
7379 case 0x28:
7380 case 0x29:
7381 case 0x2A:
7382 case 0x2B:
7383 case 0x2C:
7384 case 0x2D:
7385 case 0x2E:
7386 case 0x2F:
7387 case 0x30:
7388 case 0x31:
7389 case 0x32:
7390 case 0x33:
7391 case 0x34:
7392 case 0x35:
7393 case 0x36:
7394 case 0x37:
7395 case 0x38:
7396 case 0x39:
7397 case 0x3A:
7398 case 0x3B:
7399 case 0x3C:
7400 case 0x3D:
7401 case 0x3E:
7402 case 0x3F:
7403 case 0x40:
7404 case 0x41:
7405 case 0x42:
7406 case 0x43:
7407 case 0x44:
7408 case 0x45:
7409 case 0x46:
7410 case 0x47:
7411 case 0x48:
7412 case 0x49:
7413 case 0x4A:
7414 case 0x4B:
7415 case 0x4C:
7416 case 0x4D:
7417 case 0x4E:
7418 case 0x4F:
7419 case 0x50:
7420 case 0x51:
7421 case 0x52:
7422 case 0x53:
7423 case 0x54:
7424 case 0x55:
7425 case 0x56:
7426 case 0x57:
7427 case 0x58:
7428 case 0x59:
7429 case 0x5A:
7430 case 0x5B:
7431 case 0x5C:
7432 case 0x5D:
7433 case 0x5E:
7434 case 0x5F:
7435 case 0x60:
7436 case 0x61:
7437 case 0x62:
7438 case 0x63:
7439 case 0x64:
7440 case 0x65:
7441 case 0x66:
7442 case 0x67:
7443 case 0x68:
7444 case 0x69:
7445 case 0x6A:
7446 case 0x6B:
7447 case 0x6C:
7448 case 0x6D:
7449 case 0x6E:
7450 case 0x6F:
7451 case 0x70:
7452 case 0x71:
7453 case 0x72:
7454 case 0x73:
7455 case 0x74:
7456 case 0x75:
7457 case 0x76:
7458 case 0x77:
7459 case 0x78:
7460 case 0x79:
7461 case 0x7A:
7462 case 0x7B:
7463 case 0x7C:
7464 case 0x7D:
7465 case 0x7E:
7466 case 0x7F:
7467 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
7468
7469 // fixmap
7470 case 0x80:
7471 case 0x81:
7472 case 0x82:
7473 case 0x83:
7474 case 0x84:
7475 case 0x85:
7476 case 0x86:
7477 case 0x87:
7478 case 0x88:
7479 case 0x89:
7480 case 0x8A:
7481 case 0x8B:
7482 case 0x8C:
7483 case 0x8D:
7484 case 0x8E:
7485 case 0x8F:
7486 return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
7487
7488 // fixarray
7489 case 0x90:
7490 case 0x91:
7491 case 0x92:
7492 case 0x93:
7493 case 0x94:
7494 case 0x95:
7495 case 0x96:
7496 case 0x97:
7497 case 0x98:
7498 case 0x99:
7499 case 0x9A:
7500 case 0x9B:
7501 case 0x9C:
7502 case 0x9D:
7503 case 0x9E:
7504 case 0x9F:
7505 return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
7506
7507 // fixstr
7508 case 0xA0:
7509 case 0xA1:
7510 case 0xA2:
7511 case 0xA3:
7512 case 0xA4:
7513 case 0xA5:
7514 case 0xA6:
7515 case 0xA7:
7516 case 0xA8:
7517 case 0xA9:
7518 case 0xAA:
7519 case 0xAB:
7520 case 0xAC:
7521 case 0xAD:
7522 case 0xAE:
7523 case 0xAF:
7524 case 0xB0:
7525 case 0xB1:
7526 case 0xB2:
7527 case 0xB3:
7528 case 0xB4:
7529 case 0xB5:
7530 case 0xB6:
7531 case 0xB7:
7532 case 0xB8:
7533 case 0xB9:
7534 case 0xBA:
7535 case 0xBB:
7536 case 0xBC:
7537 case 0xBD:
7538 case 0xBE:
7539 case 0xBF:
7540 {
7541 string_t s;
7542 return get_msgpack_string(s) and sax->string(s);
7543 }
7544
7545 case 0xC0: // nil
7546 return sax->null();
7547
7548 case 0xC2: // false
7549 return sax->boolean(false);
7550
7551 case 0xC3: // true
7552 return sax->boolean(true);
7553
7554 case 0xCA: // float 32
7555 {
7556 float number;
7557 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
7558 }
7559
7560 case 0xCB: // float 64
7561 {
7562 double number;
7563 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
7564 }
7565
7566 case 0xCC: // uint 8
7567 {
7568 uint8_t number;
7569 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7570 }
7571
7572 case 0xCD: // uint 16
7573 {
7574 uint16_t number;
7575 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7576 }
7577
7578 case 0xCE: // uint 32
7579 {
7580 uint32_t number;
7581 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7582 }
7583
7584 case 0xCF: // uint 64
7585 {
7586 uint64_t number;
7587 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7588 }
7589
7590 case 0xD0: // int 8
7591 {
7592 int8_t number;
7593 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7594 }
7595
7596 case 0xD1: // int 16
7597 {
7598 int16_t number;
7599 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7600 }
7601
7602 case 0xD2: // int 32
7603 {
7604 int32_t number;
7605 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7606 }
7607
7608 case 0xD3: // int 64
7609 {
7610 int64_t number;
7611 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7612 }
7613
7614 case 0xD9: // str 8
7615 case 0xDA: // str 16
7616 case 0xDB: // str 32
7617 {
7618 string_t s;
7619 return get_msgpack_string(s) and sax->string(s);
7620 }
7621
7622 case 0xDC: // array 16
7623 {
7624 uint16_t len;
7625 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
7626 }
7627
7628 case 0xDD: // array 32
7629 {
7630 uint32_t len;
7631 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
7632 }
7633
7634 case 0xDE: // map 16
7635 {
7636 uint16_t len;
7637 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
7638 }
7639
7640 case 0xDF: // map 32
7641 {
7642 uint32_t len;
7643 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
7644 }
7645
7646 // negative fixint
7647 case 0xE0:
7648 case 0xE1:
7649 case 0xE2:
7650 case 0xE3:
7651 case 0xE4:
7652 case 0xE5:
7653 case 0xE6:
7654 case 0xE7:
7655 case 0xE8:
7656 case 0xE9:
7657 case 0xEA:
7658 case 0xEB:
7659 case 0xEC:
7660 case 0xED:
7661 case 0xEE:
7662 case 0xEF:
7663 case 0xF0:
7664 case 0xF1:
7665 case 0xF2:
7666 case 0xF3:
7667 case 0xF4:
7668 case 0xF5:
7669 case 0xF6:
7670 case 0xF7:
7671 case 0xF8:
7672 case 0xF9:
7673 case 0xFA:
7674 case 0xFB:
7675 case 0xFC:
7676 case 0xFD:
7677 case 0xFE:
7678 case 0xFF:
7679 return sax->number_integer(static_cast<int8_t>(current));
7680
7681 default: // anything else
7682 {
7683 auto last_token = get_token_string();
7684 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value")));
7685 }
7686 }
7687 }
7688
7699 bool get_msgpack_string(string_t& result)
7700 {
7701 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string")))
7702 {
7703 return false;
7704 }
7705
7706 switch (current)
7707 {
7708 // fixstr
7709 case 0xA0:
7710 case 0xA1:
7711 case 0xA2:
7712 case 0xA3:
7713 case 0xA4:
7714 case 0xA5:
7715 case 0xA6:
7716 case 0xA7:
7717 case 0xA8:
7718 case 0xA9:
7719 case 0xAA:
7720 case 0xAB:
7721 case 0xAC:
7722 case 0xAD:
7723 case 0xAE:
7724 case 0xAF:
7725 case 0xB0:
7726 case 0xB1:
7727 case 0xB2:
7728 case 0xB3:
7729 case 0xB4:
7730 case 0xB5:
7731 case 0xB6:
7732 case 0xB7:
7733 case 0xB8:
7734 case 0xB9:
7735 case 0xBA:
7736 case 0xBB:
7737 case 0xBC:
7738 case 0xBD:
7739 case 0xBE:
7740 case 0xBF:
7741 {
7742 return get_string(input_format_t::msgpack, current & 0x1F, result);
7743 }
7744
7745 case 0xD9: // str 8
7746 {
7747 uint8_t len;
7748 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
7749 }
7750
7751 case 0xDA: // str 16
7752 {
7753 uint16_t len;
7754 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
7755 }
7756
7757 case 0xDB: // str 32
7758 {
7759 uint32_t len;
7760 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
7761 }
7762
7763 default:
7764 {
7765 auto last_token = get_token_string();
7766 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string")));
7767 }
7768 }
7769 }
7770
7775 bool get_msgpack_array(const std::size_t len)
7776 {
7777 if (JSON_UNLIKELY(not sax->start_array(len)))
7778 {
7779 return false;
7780 }
7781
7782 for (std::size_t i = 0; i < len; ++i)
7783 {
7784 if (JSON_UNLIKELY(not parse_msgpack_internal()))
7785 {
7786 return false;
7787 }
7788 }
7789
7790 return sax->end_array();
7791 }
7792
7797 bool get_msgpack_object(const std::size_t len)
7798 {
7799 if (JSON_UNLIKELY(not sax->start_object(len)))
7800 {
7801 return false;
7802 }
7803
7804 string_t key;
7805 for (std::size_t i = 0; i < len; ++i)
7806 {
7807 get();
7808 if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
7809 {
7810 return false;
7811 }
7812
7813 if (JSON_UNLIKELY(not parse_msgpack_internal()))
7814 {
7815 return false;
7816 }
7817 key.clear();
7818 }
7819
7820 return sax->end_object();
7821 }
7822
7824 // UBJSON //
7826
7834 bool parse_ubjson_internal(const bool get_char = true)
7835 {
7836 return get_ubjson_value(get_char ? get_ignore_noop() : current);
7837 }
7838
7853 bool get_ubjson_string(string_t& result, const bool get_char = true)
7854 {
7855 if (get_char)
7856 {
7857 get(); // TODO: may we ignore N here?
7858 }
7859
7860 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
7861 {
7862 return false;
7863 }
7864
7865 switch (current)
7866 {
7867 case 'U':
7868 {
7869 uint8_t len;
7870 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7871 }
7872
7873 case 'i':
7874 {
7875 int8_t len;
7876 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7877 }
7878
7879 case 'I':
7880 {
7881 int16_t len;
7882 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7883 }
7884
7885 case 'l':
7886 {
7887 int32_t len;
7888 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7889 }
7890
7891 case 'L':
7892 {
7893 int64_t len;
7894 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7895 }
7896
7897 default:
7898 auto last_token = get_token_string();
7899 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string")));
7900 }
7901 }
7902
7907 bool get_ubjson_size_value(std::size_t& result)
7908 {
7909 switch (get_ignore_noop())
7910 {
7911 case 'U':
7912 {
7913 uint8_t number;
7914 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7915 {
7916 return false;
7917 }
7918 result = static_cast<std::size_t>(number);
7919 return true;
7920 }
7921
7922 case 'i':
7923 {
7924 int8_t number;
7925 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7926 {
7927 return false;
7928 }
7929 result = static_cast<std::size_t>(number);
7930 return true;
7931 }
7932
7933 case 'I':
7934 {
7935 int16_t number;
7936 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7937 {
7938 return false;
7939 }
7940 result = static_cast<std::size_t>(number);
7941 return true;
7942 }
7943
7944 case 'l':
7945 {
7946 int32_t number;
7947 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7948 {
7949 return false;
7950 }
7951 result = static_cast<std::size_t>(number);
7952 return true;
7953 }
7954
7955 case 'L':
7956 {
7957 int64_t number;
7958 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7959 {
7960 return false;
7961 }
7962 result = static_cast<std::size_t>(number);
7963 return true;
7964 }
7965
7966 default:
7967 {
7968 auto last_token = get_token_string();
7969 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size")));
7970 }
7971 }
7972 }
7973
7984 bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
7985 {
7986 result.first = string_t::npos; // size
7987 result.second = 0; // type
7988
7989 get_ignore_noop();
7990
7991 if (current == '$')
7992 {
7993 result.second = get(); // must not ignore 'N', because 'N' maybe the type
7994 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type")))
7995 {
7996 return false;
7997 }
7998
7999 get_ignore_noop();
8000 if (JSON_UNLIKELY(current != '#'))
8001 {
8002 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
8003 {
8004 return false;
8005 }
8006 auto last_token = get_token_string();
8007 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size")));
8008 }
8009
8010 return get_ubjson_size_value(result.first);
8011 }
8012 else if (current == '#')
8013 {
8014 return get_ubjson_size_value(result.first);
8015 }
8016 return true;
8017 }
8018
8023 bool get_ubjson_value(const int prefix)
8024 {
8025 switch (prefix)
8026 {
8027 case std::char_traits<char>::eof(): // EOF
8028 return unexpect_eof(input_format_t::ubjson, "value");
8029
8030 case 'T': // true
8031 return sax->boolean(true);
8032 case 'F': // false
8033 return sax->boolean(false);
8034
8035 case 'Z': // null
8036 return sax->null();
8037
8038 case 'U':
8039 {
8040 uint8_t number;
8041 return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
8042 }
8043
8044 case 'i':
8045 {
8046 int8_t number;
8047 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
8048 }
8049
8050 case 'I':
8051 {
8052 int16_t number;
8053 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
8054 }
8055
8056 case 'l':
8057 {
8058 int32_t number;
8059 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
8060 }
8061
8062 case 'L':
8063 {
8064 int64_t number;
8065 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
8066 }
8067
8068 case 'd':
8069 {
8070 float number;
8071 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
8072 }
8073
8074 case 'D':
8075 {
8076 double number;
8077 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
8078 }
8079
8080 case 'C': // char
8081 {
8082 get();
8083 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char")))
8084 {
8085 return false;
8086 }
8087 if (JSON_UNLIKELY(current > 127))
8088 {
8089 auto last_token = get_token_string();
8090 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
8091 }
8092 string_t s(1, static_cast<char>(current));
8093 return sax->string(s);
8094 }
8095
8096 case 'S': // string
8097 {
8098 string_t s;
8099 return get_ubjson_string(s) and sax->string(s);
8100 }
8101
8102 case '[': // array
8103 return get_ubjson_array();
8104
8105 case '{': // object
8106 return get_ubjson_object();
8107
8108 default: // anything else
8109 {
8110 auto last_token = get_token_string();
8111 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value")));
8112 }
8113 }
8114 }
8115
8119 bool get_ubjson_array()
8120 {
8121 std::pair<std::size_t, int> size_and_type;
8122 if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
8123 {
8124 return false;
8125 }
8126
8127 if (size_and_type.first != string_t::npos)
8128 {
8129 if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
8130 {
8131 return false;
8132 }
8133
8134 if (size_and_type.second != 0)
8135 {
8136 if (size_and_type.second != 'N')
8137 {
8138 for (std::size_t i = 0; i < size_and_type.first; ++i)
8139 {
8140 if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
8141 {
8142 return false;
8143 }
8144 }
8145 }
8146 }
8147 else
8148 {
8149 for (std::size_t i = 0; i < size_and_type.first; ++i)
8150 {
8151 if (JSON_UNLIKELY(not parse_ubjson_internal()))
8152 {
8153 return false;
8154 }
8155 }
8156 }
8157 }
8158 else
8159 {
8160 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
8161 {
8162 return false;
8163 }
8164
8165 while (current != ']')
8166 {
8167 if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
8168 {
8169 return false;
8170 }
8171 get_ignore_noop();
8172 }
8173 }
8174
8175 return sax->end_array();
8176 }
8177
8181 bool get_ubjson_object()
8182 {
8183 std::pair<std::size_t, int> size_and_type;
8184 if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
8185 {
8186 return false;
8187 }
8188
8189 string_t key;
8190 if (size_and_type.first != string_t::npos)
8191 {
8192 if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
8193 {
8194 return false;
8195 }
8196
8197 if (size_and_type.second != 0)
8198 {
8199 for (std::size_t i = 0; i < size_and_type.first; ++i)
8200 {
8201 if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
8202 {
8203 return false;
8204 }
8205 if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
8206 {
8207 return false;
8208 }
8209 key.clear();
8210 }
8211 }
8212 else
8213 {
8214 for (std::size_t i = 0; i < size_and_type.first; ++i)
8215 {
8216 if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
8217 {
8218 return false;
8219 }
8220 if (JSON_UNLIKELY(not parse_ubjson_internal()))
8221 {
8222 return false;
8223 }
8224 key.clear();
8225 }
8226 }
8227 }
8228 else
8229 {
8230 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
8231 {
8232 return false;
8233 }
8234
8235 while (current != '}')
8236 {
8237 if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
8238 {
8239 return false;
8240 }
8241 if (JSON_UNLIKELY(not parse_ubjson_internal()))
8242 {
8243 return false;
8244 }
8245 get_ignore_noop();
8246 key.clear();
8247 }
8248 }
8249
8250 return sax->end_object();
8251 }
8252
8254 // Utility functions //
8256
8266 int get()
8267 {
8268 ++chars_read;
8269 return (current = ia->get_character());
8270 }
8271
8275 int get_ignore_noop()
8276 {
8277 do
8278 {
8279 get();
8280 }
8281 while (current == 'N');
8282
8283 return current;
8284 }
8285
8286 /*
8287 @brief read a number from the input
8288
8289 @tparam NumberType the type of the number
8290 @param[in] format the current format (for diagnostics)
8291 @param[out] result number of type @a NumberType
8292
8293 @return whether conversion completed
8294
8295 @note This function needs to respect the system's endianess, because
8296 bytes in CBOR, MessagePack, and UBJSON are stored in network order
8297 (big endian) and therefore need reordering on little endian systems.
8298 */
8299 template<typename NumberType, bool InputIsLittleEndian = false>
8300 bool get_number(const input_format_t format, NumberType& result)
8301 {
8302 // step 1: read input into array with system's byte order
8303 std::array<uint8_t, sizeof(NumberType)> vec;
8304 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
8305 {
8306 get();
8307 if (JSON_UNLIKELY(not unexpect_eof(format, "number")))
8308 {
8309 return false;
8310 }
8311
8312 // reverse byte order prior to conversion if necessary
8313 if (is_little_endian && !InputIsLittleEndian)
8314 {
8315 vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
8316 }
8317 else
8318 {
8319 vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
8320 }
8321 }
8322
8323 // step 2: convert array into number of type T and return
8324 std::memcpy(&result, vec.data(), sizeof(NumberType));
8325 return true;
8326 }
8327
8342 template<typename NumberType>
8343 bool get_string(const input_format_t format,
8344 const NumberType len,
8345 string_t& result)
8346 {
8347 bool success = true;
8348 std::generate_n(std::back_inserter(result), len, [this, &success, &format]()
8349 {
8350 get();
8351 if (JSON_UNLIKELY(not unexpect_eof(format, "string")))
8352 {
8353 success = false;
8354 }
8355 return static_cast<char>(current);
8356 });
8357 return success;
8358 }
8359
8365 bool unexpect_eof(const input_format_t format, const char* context) const
8366 {
8367 if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
8368 {
8369 return sax->parse_error(chars_read, "<end of file>",
8370 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
8371 }
8372 return true;
8373 }
8374
8378 std::string get_token_string() const
8379 {
8380 char cr[3];
8381 (std::snprintf)(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
8382 return std::string{cr};
8383 }
8384
8391 std::string exception_message(const input_format_t format,
8392 const std::string& detail,
8393 const std::string& context) const
8394 {
8395 std::string error_msg = "syntax error while parsing ";
8396
8397 switch (format)
8398 {
8400 error_msg += "CBOR";
8401 break;
8402
8404 error_msg += "MessagePack";
8405 break;
8406
8408 error_msg += "UBJSON";
8409 break;
8410
8412 error_msg += "BSON";
8413 break;
8414
8415 // LCOV_EXCL_START
8416 default:
8417 assert(false);
8418 // LCOV_EXCL_STOP
8419 }
8420
8421 return error_msg + " " + context + ": " + detail;
8422 }
8423
8424 private:
8426 input_adapter_t ia = nullptr;
8427
8429 int current = std::char_traits<char>::eof();
8430
8432 std::size_t chars_read = 0;
8433
8435 const bool is_little_endian = little_endianess();
8436
8438 json_sax_t* sax = nullptr;
8439};
8440} // namespace detail
8441} // namespace nlohmann
8442
8443// #include <nlohmann/detail/output/binary_writer.hpp>
8444
8445
8446#include <algorithm> // reverse
8447#include <array> // array
8448#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
8449#include <cstring> // memcpy
8450#include <limits> // numeric_limits
8451
8452// #include <nlohmann/detail/input/binary_reader.hpp>
8453
8454// #include <nlohmann/detail/output/output_adapters.hpp>
8455
8456
8457namespace nlohmann
8458{
8459namespace detail
8460{
8462// binary writer //
8464
8468template<typename BasicJsonType, typename CharType>
8470{
8471 using string_t = typename BasicJsonType::string_t;
8472
8473 public:
8479 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
8480 {
8481 assert(oa);
8482 }
8483
8488 void write_bson(const BasicJsonType& j)
8489 {
8490 switch (j.type())
8491 {
8492 case value_t::object:
8493 {
8494 write_bson_object(*j.m_value.object);
8495 break;
8496 }
8497
8498 default:
8499 {
8500 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
8501 }
8502 }
8503 }
8504
8508 void write_cbor(const BasicJsonType& j)
8509 {
8510 switch (j.type())
8511 {
8512 case value_t::null:
8513 {
8514 oa->write_character(to_char_type(0xF6));
8515 break;
8516 }
8517
8518 case value_t::boolean:
8519 {
8520 oa->write_character(j.m_value.boolean
8521 ? to_char_type(0xF5)
8522 : to_char_type(0xF4));
8523 break;
8524 }
8525
8527 {
8528 if (j.m_value.number_integer >= 0)
8529 {
8530 // CBOR does not differentiate between positive signed
8531 // integers and unsigned integers. Therefore, we used the
8532 // code from the value_t::number_unsigned case here.
8533 if (j.m_value.number_integer <= 0x17)
8534 {
8535 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8536 }
8537 else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
8538 {
8539 oa->write_character(to_char_type(0x18));
8540 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8541 }
8542 else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
8543 {
8544 oa->write_character(to_char_type(0x19));
8545 write_number(static_cast<uint16_t>(j.m_value.number_integer));
8546 }
8547 else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
8548 {
8549 oa->write_character(to_char_type(0x1A));
8550 write_number(static_cast<uint32_t>(j.m_value.number_integer));
8551 }
8552 else
8553 {
8554 oa->write_character(to_char_type(0x1B));
8555 write_number(static_cast<uint64_t>(j.m_value.number_integer));
8556 }
8557 }
8558 else
8559 {
8560 // The conversions below encode the sign in the first
8561 // byte, and the value is converted to a positive number.
8562 const auto positive_number = -1 - j.m_value.number_integer;
8563 if (j.m_value.number_integer >= -24)
8564 {
8565 write_number(static_cast<uint8_t>(0x20 + positive_number));
8566 }
8567 else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
8568 {
8569 oa->write_character(to_char_type(0x38));
8570 write_number(static_cast<uint8_t>(positive_number));
8571 }
8572 else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
8573 {
8574 oa->write_character(to_char_type(0x39));
8575 write_number(static_cast<uint16_t>(positive_number));
8576 }
8577 else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
8578 {
8579 oa->write_character(to_char_type(0x3A));
8580 write_number(static_cast<uint32_t>(positive_number));
8581 }
8582 else
8583 {
8584 oa->write_character(to_char_type(0x3B));
8585 write_number(static_cast<uint64_t>(positive_number));
8586 }
8587 }
8588 break;
8589 }
8590
8592 {
8593 if (j.m_value.number_unsigned <= 0x17)
8594 {
8595 write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
8596 }
8597 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8598 {
8599 oa->write_character(to_char_type(0x18));
8600 write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
8601 }
8602 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8603 {
8604 oa->write_character(to_char_type(0x19));
8605 write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
8606 }
8607 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8608 {
8609 oa->write_character(to_char_type(0x1A));
8610 write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
8611 }
8612 else
8613 {
8614 oa->write_character(to_char_type(0x1B));
8615 write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
8616 }
8617 break;
8618 }
8619
8621 {
8622 oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
8623 write_number(j.m_value.number_float);
8624 break;
8625 }
8626
8627 case value_t::string:
8628 {
8629 // step 1: write control byte and the string length
8630 const auto N = j.m_value.string->size();
8631 if (N <= 0x17)
8632 {
8633 write_number(static_cast<uint8_t>(0x60 + N));
8634 }
8635 else if (N <= (std::numeric_limits<uint8_t>::max)())
8636 {
8637 oa->write_character(to_char_type(0x78));
8638 write_number(static_cast<uint8_t>(N));
8639 }
8640 else if (N <= (std::numeric_limits<uint16_t>::max)())
8641 {
8642 oa->write_character(to_char_type(0x79));
8643 write_number(static_cast<uint16_t>(N));
8644 }
8645 else if (N <= (std::numeric_limits<uint32_t>::max)())
8646 {
8647 oa->write_character(to_char_type(0x7A));
8648 write_number(static_cast<uint32_t>(N));
8649 }
8650 // LCOV_EXCL_START
8651 else if (N <= (std::numeric_limits<uint64_t>::max)())
8652 {
8653 oa->write_character(to_char_type(0x7B));
8654 write_number(static_cast<uint64_t>(N));
8655 }
8656 // LCOV_EXCL_STOP
8657
8658 // step 2: write the string
8659 oa->write_characters(
8660 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8661 j.m_value.string->size());
8662 break;
8663 }
8664
8665 case value_t::array:
8666 {
8667 // step 1: write control byte and the array size
8668 const auto N = j.m_value.array->size();
8669 if (N <= 0x17)
8670 {
8671 write_number(static_cast<uint8_t>(0x80 + N));
8672 }
8673 else if (N <= (std::numeric_limits<uint8_t>::max)())
8674 {
8675 oa->write_character(to_char_type(0x98));
8676 write_number(static_cast<uint8_t>(N));
8677 }
8678 else if (N <= (std::numeric_limits<uint16_t>::max)())
8679 {
8680 oa->write_character(to_char_type(0x99));
8681 write_number(static_cast<uint16_t>(N));
8682 }
8683 else if (N <= (std::numeric_limits<uint32_t>::max)())
8684 {
8685 oa->write_character(to_char_type(0x9A));
8686 write_number(static_cast<uint32_t>(N));
8687 }
8688 // LCOV_EXCL_START
8689 else if (N <= (std::numeric_limits<uint64_t>::max)())
8690 {
8691 oa->write_character(to_char_type(0x9B));
8692 write_number(static_cast<uint64_t>(N));
8693 }
8694 // LCOV_EXCL_STOP
8695
8696 // step 2: write each element
8697 for (const auto& el : *j.m_value.array)
8698 {
8699 write_cbor(el);
8700 }
8701 break;
8702 }
8703
8704 case value_t::object:
8705 {
8706 // step 1: write control byte and the object size
8707 const auto N = j.m_value.object->size();
8708 if (N <= 0x17)
8709 {
8710 write_number(static_cast<uint8_t>(0xA0 + N));
8711 }
8712 else if (N <= (std::numeric_limits<uint8_t>::max)())
8713 {
8714 oa->write_character(to_char_type(0xB8));
8715 write_number(static_cast<uint8_t>(N));
8716 }
8717 else if (N <= (std::numeric_limits<uint16_t>::max)())
8718 {
8719 oa->write_character(to_char_type(0xB9));
8720 write_number(static_cast<uint16_t>(N));
8721 }
8722 else if (N <= (std::numeric_limits<uint32_t>::max)())
8723 {
8724 oa->write_character(to_char_type(0xBA));
8725 write_number(static_cast<uint32_t>(N));
8726 }
8727 // LCOV_EXCL_START
8728 else if (N <= (std::numeric_limits<uint64_t>::max)())
8729 {
8730 oa->write_character(to_char_type(0xBB));
8731 write_number(static_cast<uint64_t>(N));
8732 }
8733 // LCOV_EXCL_STOP
8734
8735 // step 2: write each element
8736 for (const auto& el : *j.m_value.object)
8737 {
8738 write_cbor(el.first);
8739 write_cbor(el.second);
8740 }
8741 break;
8742 }
8743
8744 default:
8745 break;
8746 }
8747 }
8748
8752 void write_msgpack(const BasicJsonType& j)
8753 {
8754 switch (j.type())
8755 {
8756 case value_t::null: // nil
8757 {
8758 oa->write_character(to_char_type(0xC0));
8759 break;
8760 }
8761
8762 case value_t::boolean: // true and false
8763 {
8764 oa->write_character(j.m_value.boolean
8765 ? to_char_type(0xC3)
8766 : to_char_type(0xC2));
8767 break;
8768 }
8769
8771 {
8772 if (j.m_value.number_integer >= 0)
8773 {
8774 // MessagePack does not differentiate between positive
8775 // signed integers and unsigned integers. Therefore, we used
8776 // the code from the value_t::number_unsigned case here.
8777 if (j.m_value.number_unsigned < 128)
8778 {
8779 // positive fixnum
8780 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8781 }
8782 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8783 {
8784 // uint 8
8785 oa->write_character(to_char_type(0xCC));
8786 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8787 }
8788 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8789 {
8790 // uint 16
8791 oa->write_character(to_char_type(0xCD));
8792 write_number(static_cast<uint16_t>(j.m_value.number_integer));
8793 }
8794 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8795 {
8796 // uint 32
8797 oa->write_character(to_char_type(0xCE));
8798 write_number(static_cast<uint32_t>(j.m_value.number_integer));
8799 }
8800 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
8801 {
8802 // uint 64
8803 oa->write_character(to_char_type(0xCF));
8804 write_number(static_cast<uint64_t>(j.m_value.number_integer));
8805 }
8806 }
8807 else
8808 {
8809 if (j.m_value.number_integer >= -32)
8810 {
8811 // negative fixnum
8812 write_number(static_cast<int8_t>(j.m_value.number_integer));
8813 }
8814 else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
8815 j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
8816 {
8817 // int 8
8818 oa->write_character(to_char_type(0xD0));
8819 write_number(static_cast<int8_t>(j.m_value.number_integer));
8820 }
8821 else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
8822 j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
8823 {
8824 // int 16
8825 oa->write_character(to_char_type(0xD1));
8826 write_number(static_cast<int16_t>(j.m_value.number_integer));
8827 }
8828 else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
8829 j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
8830 {
8831 // int 32
8832 oa->write_character(to_char_type(0xD2));
8833 write_number(static_cast<int32_t>(j.m_value.number_integer));
8834 }
8835 else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
8836 j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
8837 {
8838 // int 64
8839 oa->write_character(to_char_type(0xD3));
8840 write_number(static_cast<int64_t>(j.m_value.number_integer));
8841 }
8842 }
8843 break;
8844 }
8845
8847 {
8848 if (j.m_value.number_unsigned < 128)
8849 {
8850 // positive fixnum
8851 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8852 }
8853 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8854 {
8855 // uint 8
8856 oa->write_character(to_char_type(0xCC));
8857 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8858 }
8859 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8860 {
8861 // uint 16
8862 oa->write_character(to_char_type(0xCD));
8863 write_number(static_cast<uint16_t>(j.m_value.number_integer));
8864 }
8865 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8866 {
8867 // uint 32
8868 oa->write_character(to_char_type(0xCE));
8869 write_number(static_cast<uint32_t>(j.m_value.number_integer));
8870 }
8871 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
8872 {
8873 // uint 64
8874 oa->write_character(to_char_type(0xCF));
8875 write_number(static_cast<uint64_t>(j.m_value.number_integer));
8876 }
8877 break;
8878 }
8879
8881 {
8882 oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
8883 write_number(j.m_value.number_float);
8884 break;
8885 }
8886
8887 case value_t::string:
8888 {
8889 // step 1: write control byte and the string length
8890 const auto N = j.m_value.string->size();
8891 if (N <= 31)
8892 {
8893 // fixstr
8894 write_number(static_cast<uint8_t>(0xA0 | N));
8895 }
8896 else if (N <= (std::numeric_limits<uint8_t>::max)())
8897 {
8898 // str 8
8899 oa->write_character(to_char_type(0xD9));
8900 write_number(static_cast<uint8_t>(N));
8901 }
8902 else if (N <= (std::numeric_limits<uint16_t>::max)())
8903 {
8904 // str 16
8905 oa->write_character(to_char_type(0xDA));
8906 write_number(static_cast<uint16_t>(N));
8907 }
8908 else if (N <= (std::numeric_limits<uint32_t>::max)())
8909 {
8910 // str 32
8911 oa->write_character(to_char_type(0xDB));
8912 write_number(static_cast<uint32_t>(N));
8913 }
8914
8915 // step 2: write the string
8916 oa->write_characters(
8917 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8918 j.m_value.string->size());
8919 break;
8920 }
8921
8922 case value_t::array:
8923 {
8924 // step 1: write control byte and the array size
8925 const auto N = j.m_value.array->size();
8926 if (N <= 15)
8927 {
8928 // fixarray
8929 write_number(static_cast<uint8_t>(0x90 | N));
8930 }
8931 else if (N <= (std::numeric_limits<uint16_t>::max)())
8932 {
8933 // array 16
8934 oa->write_character(to_char_type(0xDC));
8935 write_number(static_cast<uint16_t>(N));
8936 }
8937 else if (N <= (std::numeric_limits<uint32_t>::max)())
8938 {
8939 // array 32
8940 oa->write_character(to_char_type(0xDD));
8941 write_number(static_cast<uint32_t>(N));
8942 }
8943
8944 // step 2: write each element
8945 for (const auto& el : *j.m_value.array)
8946 {
8947 write_msgpack(el);
8948 }
8949 break;
8950 }
8951
8952 case value_t::object:
8953 {
8954 // step 1: write control byte and the object size
8955 const auto N = j.m_value.object->size();
8956 if (N <= 15)
8957 {
8958 // fixmap
8959 write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
8960 }
8961 else if (N <= (std::numeric_limits<uint16_t>::max)())
8962 {
8963 // map 16
8964 oa->write_character(to_char_type(0xDE));
8965 write_number(static_cast<uint16_t>(N));
8966 }
8967 else if (N <= (std::numeric_limits<uint32_t>::max)())
8968 {
8969 // map 32
8970 oa->write_character(to_char_type(0xDF));
8971 write_number(static_cast<uint32_t>(N));
8972 }
8973
8974 // step 2: write each element
8975 for (const auto& el : *j.m_value.object)
8976 {
8977 write_msgpack(el.first);
8978 write_msgpack(el.second);
8979 }
8980 break;
8981 }
8982
8983 default:
8984 break;
8985 }
8986 }
8987
8994 void write_ubjson(const BasicJsonType& j, const bool use_count,
8995 const bool use_type, const bool add_prefix = true)
8996 {
8997 switch (j.type())
8998 {
8999 case value_t::null:
9000 {
9001 if (add_prefix)
9002 {
9003 oa->write_character(to_char_type('Z'));
9004 }
9005 break;
9006 }
9007
9008 case value_t::boolean:
9009 {
9010 if (add_prefix)
9011 {
9012 oa->write_character(j.m_value.boolean
9013 ? to_char_type('T')
9014 : to_char_type('F'));
9015 }
9016 break;
9017 }
9018
9020 {
9021 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
9022 break;
9023 }
9024
9026 {
9027 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
9028 break;
9029 }
9030
9032 {
9033 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
9034 break;
9035 }
9036
9037 case value_t::string:
9038 {
9039 if (add_prefix)
9040 {
9041 oa->write_character(to_char_type('S'));
9042 }
9043 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
9044 oa->write_characters(
9045 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
9046 j.m_value.string->size());
9047 break;
9048 }
9049
9050 case value_t::array:
9051 {
9052 if (add_prefix)
9053 {
9054 oa->write_character(to_char_type('['));
9055 }
9056
9057 bool prefix_required = true;
9058 if (use_type and not j.m_value.array->empty())
9059 {
9060 assert(use_count);
9061 const CharType first_prefix = ubjson_prefix(j.front());
9062 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
9063 [this, first_prefix](const BasicJsonType & v)
9064 {
9065 return ubjson_prefix(v) == first_prefix;
9066 });
9067
9068 if (same_prefix)
9069 {
9070 prefix_required = false;
9071 oa->write_character(to_char_type('$'));
9072 oa->write_character(first_prefix);
9073 }
9074 }
9075
9076 if (use_count)
9077 {
9078 oa->write_character(to_char_type('#'));
9079 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
9080 }
9081
9082 for (const auto& el : *j.m_value.array)
9083 {
9084 write_ubjson(el, use_count, use_type, prefix_required);
9085 }
9086
9087 if (not use_count)
9088 {
9089 oa->write_character(to_char_type(']'));
9090 }
9091
9092 break;
9093 }
9094
9095 case value_t::object:
9096 {
9097 if (add_prefix)
9098 {
9099 oa->write_character(to_char_type('{'));
9100 }
9101
9102 bool prefix_required = true;
9103 if (use_type and not j.m_value.object->empty())
9104 {
9105 assert(use_count);
9106 const CharType first_prefix = ubjson_prefix(j.front());
9107 const bool same_prefix = std::all_of(j.begin(), j.end(),
9108 [this, first_prefix](const BasicJsonType & v)
9109 {
9110 return ubjson_prefix(v) == first_prefix;
9111 });
9112
9113 if (same_prefix)
9114 {
9115 prefix_required = false;
9116 oa->write_character(to_char_type('$'));
9117 oa->write_character(first_prefix);
9118 }
9119 }
9120
9121 if (use_count)
9122 {
9123 oa->write_character(to_char_type('#'));
9124 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
9125 }
9126
9127 for (const auto& el : *j.m_value.object)
9128 {
9129 write_number_with_ubjson_prefix(el.first.size(), true);
9130 oa->write_characters(
9131 reinterpret_cast<const CharType*>(el.first.c_str()),
9132 el.first.size());
9133 write_ubjson(el.second, use_count, use_type, prefix_required);
9134 }
9135
9136 if (not use_count)
9137 {
9138 oa->write_character(to_char_type('}'));
9139 }
9140
9141 break;
9142 }
9143
9144 default:
9145 break;
9146 }
9147 }
9148
9149 private:
9151 // BSON //
9153
9158 static std::size_t calc_bson_entry_header_size(const string_t& name)
9159 {
9160 const auto it = name.find(static_cast<typename string_t::value_type>(0));
9161 if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos))
9162 {
9164 "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
9165 }
9166
9167 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
9168 }
9169
9173 void write_bson_entry_header(const string_t& name,
9174 const std::uint8_t element_type)
9175 {
9176 oa->write_character(to_char_type(element_type)); // boolean
9177 oa->write_characters(
9178 reinterpret_cast<const CharType*>(name.c_str()),
9179 name.size() + 1u);
9180 }
9181
9185 void write_bson_boolean(const string_t& name,
9186 const bool value)
9187 {
9188 write_bson_entry_header(name, 0x08);
9189 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
9190 }
9191
9195 void write_bson_double(const string_t& name,
9196 const double value)
9197 {
9198 write_bson_entry_header(name, 0x01);
9199 write_number<double, true>(value);
9200 }
9201
9205 static std::size_t calc_bson_string_size(const string_t& value)
9206 {
9207 return sizeof(std::int32_t) + value.size() + 1ul;
9208 }
9209
9213 void write_bson_string(const string_t& name,
9214 const string_t& value)
9215 {
9216 write_bson_entry_header(name, 0x02);
9217
9218 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
9219 oa->write_characters(
9220 reinterpret_cast<const CharType*>(value.c_str()),
9221 value.size() + 1);
9222 }
9223
9227 void write_bson_null(const string_t& name)
9228 {
9229 write_bson_entry_header(name, 0x0A);
9230 }
9231
9235 static std::size_t calc_bson_integer_size(const std::int64_t value)
9236 {
9237 if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
9238 {
9239 return sizeof(std::int32_t);
9240 }
9241 else
9242 {
9243 return sizeof(std::int64_t);
9244 }
9245 }
9246
9250 void write_bson_integer(const string_t& name,
9251 const std::int64_t value)
9252 {
9253 if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
9254 {
9255 write_bson_entry_header(name, 0x10); // int32
9256 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
9257 }
9258 else
9259 {
9260 write_bson_entry_header(name, 0x12); // int64
9261 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
9262 }
9263 }
9264
9268 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
9269 {
9270 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
9271 ? sizeof(std::int32_t)
9272 : sizeof(std::int64_t);
9273 }
9274
9278 void write_bson_unsigned(const string_t& name,
9279 const std::uint64_t value)
9280 {
9281 if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
9282 {
9283 write_bson_entry_header(name, 0x10 /* int32 */);
9284 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
9285 }
9286 else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
9287 {
9288 write_bson_entry_header(name, 0x12 /* int64 */);
9289 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
9290 }
9291 else
9292 {
9293 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
9294 }
9295 }
9296
9300 void write_bson_object_entry(const string_t& name,
9301 const typename BasicJsonType::object_t& value)
9302 {
9303 write_bson_entry_header(name, 0x03); // object
9304 write_bson_object(value);
9305 }
9306
9310 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
9311 {
9312 std::size_t embedded_document_size = 0ul;
9313 std::size_t array_index = 0ul;
9314
9315 for (const auto& el : value)
9316 {
9317 embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el);
9318 }
9319
9320 return sizeof(std::int32_t) + embedded_document_size + 1ul;
9321 }
9322
9326 void write_bson_array(const string_t& name,
9327 const typename BasicJsonType::array_t& value)
9328 {
9329 write_bson_entry_header(name, 0x04); // array
9330 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
9331
9332 std::size_t array_index = 0ul;
9333
9334 for (const auto& el : value)
9335 {
9336 write_bson_element(std::to_string(array_index++), el);
9337 }
9338
9339 oa->write_character(to_char_type(0x00));
9340 }
9341
9346 static std::size_t calc_bson_element_size(const string_t& name,
9347 const BasicJsonType& j)
9348 {
9349 const auto header_size = calc_bson_entry_header_size(name);
9350 switch (j.type())
9351 {
9352 case value_t::object:
9353 return header_size + calc_bson_object_size(*j.m_value.object);
9354
9355 case value_t::array:
9356 return header_size + calc_bson_array_size(*j.m_value.array);
9357
9358 case value_t::boolean:
9359 return header_size + 1ul;
9360
9362 return header_size + 8ul;
9363
9365 return header_size + calc_bson_integer_size(j.m_value.number_integer);
9366
9368 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
9369
9370 case value_t::string:
9371 return header_size + calc_bson_string_size(*j.m_value.string);
9372
9373 case value_t::null:
9374 return header_size + 0ul;
9375
9376 // LCOV_EXCL_START
9377 default:
9378 assert(false);
9379 return 0ul;
9380 // LCOV_EXCL_STOP
9381 };
9382 }
9383
9391 void write_bson_element(const string_t& name,
9392 const BasicJsonType& j)
9393 {
9394 switch (j.type())
9395 {
9396 case value_t::object:
9397 return write_bson_object_entry(name, *j.m_value.object);
9398
9399 case value_t::array:
9400 return write_bson_array(name, *j.m_value.array);
9401
9402 case value_t::boolean:
9403 return write_bson_boolean(name, j.m_value.boolean);
9404
9406 return write_bson_double(name, j.m_value.number_float);
9407
9409 return write_bson_integer(name, j.m_value.number_integer);
9410
9412 return write_bson_unsigned(name, j.m_value.number_unsigned);
9413
9414 case value_t::string:
9415 return write_bson_string(name, *j.m_value.string);
9416
9417 case value_t::null:
9418 return write_bson_null(name);
9419
9420 // LCOV_EXCL_START
9421 default:
9422 assert(false);
9423 return;
9424 // LCOV_EXCL_STOP
9425 };
9426 }
9427
9434 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
9435 {
9436 std::size_t document_size = std::accumulate(value.begin(), value.end(), 0ul,
9437 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
9438 {
9439 return result += calc_bson_element_size(el.first, el.second);
9440 });
9441
9442 return sizeof(std::int32_t) + document_size + 1ul;
9443 }
9444
9449 void write_bson_object(const typename BasicJsonType::object_t& value)
9450 {
9451 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
9452
9453 for (const auto& el : value)
9454 {
9455 write_bson_element(el.first, el.second);
9456 }
9457
9458 oa->write_character(to_char_type(0x00));
9459 }
9460
9462 // CBOR //
9464
9465 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
9466 {
9467 return to_char_type(0xFA); // Single-Precision Float
9468 }
9469
9470 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
9471 {
9472 return to_char_type(0xFB); // Double-Precision Float
9473 }
9474
9476 // MsgPack //
9478
9479 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
9480 {
9481 return to_char_type(0xCA); // float 32
9482 }
9483
9484 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
9485 {
9486 return to_char_type(0xCB); // float 64
9487 }
9488
9490 // UBJSON //
9492
9493 // UBJSON: write number (floating point)
9494 template<typename NumberType, typename std::enable_if<
9495 std::is_floating_point<NumberType>::value, int>::type = 0>
9496 void write_number_with_ubjson_prefix(const NumberType n,
9497 const bool add_prefix)
9498 {
9499 if (add_prefix)
9500 {
9501 oa->write_character(get_ubjson_float_prefix(n));
9502 }
9503 write_number(n);
9504 }
9505
9506 // UBJSON: write number (unsigned integer)
9507 template<typename NumberType, typename std::enable_if<
9508 std::is_unsigned<NumberType>::value, int>::type = 0>
9509 void write_number_with_ubjson_prefix(const NumberType n,
9510 const bool add_prefix)
9511 {
9512 if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
9513 {
9514 if (add_prefix)
9515 {
9516 oa->write_character(to_char_type('i')); // int8
9517 }
9518 write_number(static_cast<uint8_t>(n));
9519 }
9520 else if (n <= (std::numeric_limits<uint8_t>::max)())
9521 {
9522 if (add_prefix)
9523 {
9524 oa->write_character(to_char_type('U')); // uint8
9525 }
9526 write_number(static_cast<uint8_t>(n));
9527 }
9528 else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
9529 {
9530 if (add_prefix)
9531 {
9532 oa->write_character(to_char_type('I')); // int16
9533 }
9534 write_number(static_cast<int16_t>(n));
9535 }
9536 else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
9537 {
9538 if (add_prefix)
9539 {
9540 oa->write_character(to_char_type('l')); // int32
9541 }
9542 write_number(static_cast<int32_t>(n));
9543 }
9544 else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
9545 {
9546 if (add_prefix)
9547 {
9548 oa->write_character(to_char_type('L')); // int64
9549 }
9550 write_number(static_cast<int64_t>(n));
9551 }
9552 else
9553 {
9554 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
9555 }
9556 }
9557
9558 // UBJSON: write number (signed integer)
9559 template<typename NumberType, typename std::enable_if<
9560 std::is_signed<NumberType>::value and
9561 not std::is_floating_point<NumberType>::value, int>::type = 0>
9562 void write_number_with_ubjson_prefix(const NumberType n,
9563 const bool add_prefix)
9564 {
9565 if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
9566 {
9567 if (add_prefix)
9568 {
9569 oa->write_character(to_char_type('i')); // int8
9570 }
9571 write_number(static_cast<int8_t>(n));
9572 }
9573 else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
9574 {
9575 if (add_prefix)
9576 {
9577 oa->write_character(to_char_type('U')); // uint8
9578 }
9579 write_number(static_cast<uint8_t>(n));
9580 }
9581 else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
9582 {
9583 if (add_prefix)
9584 {
9585 oa->write_character(to_char_type('I')); // int16
9586 }
9587 write_number(static_cast<int16_t>(n));
9588 }
9589 else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
9590 {
9591 if (add_prefix)
9592 {
9593 oa->write_character(to_char_type('l')); // int32
9594 }
9595 write_number(static_cast<int32_t>(n));
9596 }
9597 else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
9598 {
9599 if (add_prefix)
9600 {
9601 oa->write_character(to_char_type('L')); // int64
9602 }
9603 write_number(static_cast<int64_t>(n));
9604 }
9605 // LCOV_EXCL_START
9606 else
9607 {
9608 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
9609 }
9610 // LCOV_EXCL_STOP
9611 }
9612
9622 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
9623 {
9624 switch (j.type())
9625 {
9626 case value_t::null:
9627 return 'Z';
9628
9629 case value_t::boolean:
9630 return j.m_value.boolean ? 'T' : 'F';
9631
9633 {
9634 if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
9635 {
9636 return 'i';
9637 }
9638 if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
9639 {
9640 return 'U';
9641 }
9642 if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
9643 {
9644 return 'I';
9645 }
9646 if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
9647 {
9648 return 'l';
9649 }
9650 // no check and assume int64_t (see note above)
9651 return 'L';
9652 }
9653
9655 {
9656 if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
9657 {
9658 return 'i';
9659 }
9660 if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
9661 {
9662 return 'U';
9663 }
9664 if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
9665 {
9666 return 'I';
9667 }
9668 if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
9669 {
9670 return 'l';
9671 }
9672 // no check and assume int64_t (see note above)
9673 return 'L';
9674 }
9675
9677 return get_ubjson_float_prefix(j.m_value.number_float);
9678
9679 case value_t::string:
9680 return 'S';
9681
9682 case value_t::array:
9683 return '[';
9684
9685 case value_t::object:
9686 return '{';
9687
9688 default: // discarded values
9689 return 'N';
9690 }
9691 }
9692
9693 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
9694 {
9695 return 'd'; // float 32
9696 }
9697
9698 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
9699 {
9700 return 'D'; // float 64
9701 }
9702
9704 // Utility functions //
9706
9707 /*
9708 @brief write a number to output input
9709 @param[in] n number of type @a NumberType
9710 @tparam NumberType the type of the number
9711 @tparam OutputIsLittleEndian Set to true if output data is
9712 required to be little endian
9713
9714 @note This function needs to respect the system's endianess, because bytes
9715 in CBOR, MessagePack, and UBJSON are stored in network order (big
9716 endian) and therefore need reordering on little endian systems.
9717 */
9718 template<typename NumberType, bool OutputIsLittleEndian = false>
9719 void write_number(const NumberType n)
9720 {
9721 // step 1: write number to array of length NumberType
9722 std::array<CharType, sizeof(NumberType)> vec;
9723 std::memcpy(vec.data(), &n, sizeof(NumberType));
9724
9725 // step 2: write array to output (with possible reordering)
9726 if (is_little_endian and not OutputIsLittleEndian)
9727 {
9728 // reverse byte order prior to conversion if necessary
9729 std::reverse(vec.begin(), vec.end());
9730 }
9731
9732 oa->write_characters(vec.data(), sizeof(NumberType));
9733 }
9734
9735 public:
9736 // The following to_char_type functions are implement the conversion
9737 // between uint8_t and CharType. In case CharType is not unsigned,
9738 // such a conversion is required to allow values greater than 128.
9739 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
9740 template < typename C = CharType,
9741 enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
9742 static constexpr CharType to_char_type(std::uint8_t x) noexcept
9743 {
9744 return *reinterpret_cast<char*>(&x);
9745 }
9746
9747 template < typename C = CharType,
9748 enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
9749 static CharType to_char_type(std::uint8_t x) noexcept
9750 {
9751 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
9752 static_assert(std::is_pod<CharType>::value, "CharType must be POD");
9753 CharType result;
9754 std::memcpy(&result, &x, sizeof(x));
9755 return result;
9756 }
9757
9758 template<typename C = CharType,
9760 static constexpr CharType to_char_type(std::uint8_t x) noexcept
9761 {
9762 return x;
9763 }
9764
9765 template < typename InputCharType, typename C = CharType,
9766 enable_if_t <
9767 std::is_signed<C>::value and
9768 std::is_signed<char>::value and
9769 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
9770 > * = nullptr >
9771 static constexpr CharType to_char_type(InputCharType x) noexcept
9772 {
9773 return x;
9774 }
9775
9776 private:
9778 const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
9779
9781 output_adapter_t<CharType> oa = nullptr;
9782};
9783} // namespace detail
9784} // namespace nlohmann
9785
9786// #include <nlohmann/detail/output/serializer.hpp>
9787
9788
9789#include <algorithm> // reverse, remove, fill, find, none_of
9790#include <array> // array
9791#include <cassert> // assert
9792#include <ciso646> // and, or
9793#include <clocale> // localeconv, lconv
9794#include <cmath> // labs, isfinite, isnan, signbit
9795#include <cstddef> // size_t, ptrdiff_t
9796#include <cstdint> // uint8_t
9797#include <cstdio> // snprintf
9798#include <limits> // numeric_limits
9799#include <string> // string
9800#include <type_traits> // is_same
9801
9802// #include <nlohmann/detail/exceptions.hpp>
9803
9804// #include <nlohmann/detail/conversions/to_chars.hpp>
9805
9806
9807#include <cassert> // assert
9808#include <ciso646> // or, and, not
9809#include <cmath> // signbit, isfinite
9810#include <cstdint> // intN_t, uintN_t
9811#include <cstring> // memcpy, memmove
9812
9813namespace nlohmann
9814{
9815namespace detail
9816{
9817
9837namespace dtoa_impl
9838{
9839
9840template <typename Target, typename Source>
9841Target reinterpret_bits(const Source source)
9842{
9843 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
9844
9845 Target target;
9846 std::memcpy(&target, &source, sizeof(Source));
9847 return target;
9848}
9849
9850struct diyfp // f * 2^e
9851{
9852 static constexpr int kPrecision = 64; // = q
9853
9854 uint64_t f = 0;
9855 int e = 0;
9856
9857 constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
9858
9863 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
9864 {
9865 assert(x.e == y.e);
9866 assert(x.f >= y.f);
9867
9868 return {x.f - y.f, x.e};
9869 }
9870
9875 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
9876 {
9877 static_assert(kPrecision == 64, "internal error");
9878
9879 // Computes:
9880 // f = round((x.f * y.f) / 2^q)
9881 // e = x.e + y.e + q
9882
9883 // Emulate the 64-bit * 64-bit multiplication:
9884 //
9885 // p = u * v
9886 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
9887 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
9888 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
9889 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
9890 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
9891 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
9892 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
9893 //
9894 // (Since Q might be larger than 2^32 - 1)
9895 //
9896 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
9897 //
9898 // (Q_hi + H does not overflow a 64-bit int)
9899 //
9900 // = p_lo + 2^64 p_hi
9901
9902 const uint64_t u_lo = x.f & 0xFFFFFFFF;
9903 const uint64_t u_hi = x.f >> 32;
9904 const uint64_t v_lo = y.f & 0xFFFFFFFF;
9905 const uint64_t v_hi = y.f >> 32;
9906
9907 const uint64_t p0 = u_lo * v_lo;
9908 const uint64_t p1 = u_lo * v_hi;
9909 const uint64_t p2 = u_hi * v_lo;
9910 const uint64_t p3 = u_hi * v_hi;
9911
9912 const uint64_t p0_hi = p0 >> 32;
9913 const uint64_t p1_lo = p1 & 0xFFFFFFFF;
9914 const uint64_t p1_hi = p1 >> 32;
9915 const uint64_t p2_lo = p2 & 0xFFFFFFFF;
9916 const uint64_t p2_hi = p2 >> 32;
9917
9918 uint64_t Q = p0_hi + p1_lo + p2_lo;
9919
9920 // The full product might now be computed as
9921 //
9922 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
9923 // p_lo = p0_lo + (Q << 32)
9924 //
9925 // But in this particular case here, the full p_lo is not required.
9926 // Effectively we only need to add the highest bit in p_lo to p_hi (and
9927 // Q_hi + 1 does not overflow).
9928
9929 Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
9930
9931 const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
9932
9933 return {h, x.e + y.e + 64};
9934 }
9935
9940 static diyfp normalize(diyfp x) noexcept
9941 {
9942 assert(x.f != 0);
9943
9944 while ((x.f >> 63) == 0)
9945 {
9946 x.f <<= 1;
9947 x.e--;
9948 }
9949
9950 return x;
9951 }
9952
9957 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
9958 {
9959 const int delta = x.e - target_exponent;
9960
9961 assert(delta >= 0);
9962 assert(((x.f << delta) >> delta) == x.f);
9963
9964 return {x.f << delta, target_exponent};
9965 }
9966};
9967
9974
9981template <typename FloatType>
9983{
9984 assert(std::isfinite(value));
9985 assert(value > 0);
9986
9987 // Convert the IEEE representation into a diyfp.
9988 //
9989 // If v is denormal:
9990 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
9991 // If v is normalized:
9992 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
9993
9994 static_assert(std::numeric_limits<FloatType>::is_iec559,
9995 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
9996
9997 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
9998 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
9999 constexpr int kMinExp = 1 - kBias;
10000 constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
10001
10002 using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
10003
10004 const uint64_t bits = reinterpret_bits<bits_type>(value);
10005 const uint64_t E = bits >> (kPrecision - 1);
10006 const uint64_t F = bits & (kHiddenBit - 1);
10007
10008 const bool is_denormal = (E == 0);
10009 const diyfp v = is_denormal
10010 ? diyfp(F, kMinExp)
10011 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
10012
10013 // Compute the boundaries m- and m+ of the floating-point value
10014 // v = f * 2^e.
10015 //
10016 // Determine v- and v+, the floating-point predecessor and successor if v,
10017 // respectively.
10018 //
10019 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
10020 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
10021 //
10022 // v+ = v + 2^e
10023 //
10024 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
10025 // between m- and m+ round to v, regardless of how the input rounding
10026 // algorithm breaks ties.
10027 //
10028 // ---+-------------+-------------+-------------+-------------+--- (A)
10029 // v- m- v m+ v+
10030 //
10031 // -----------------+------+------+-------------+-------------+--- (B)
10032 // v- m- v m+ v+
10033
10034 const bool lower_boundary_is_closer = (F == 0 and E > 1);
10035 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
10036 const diyfp m_minus = lower_boundary_is_closer
10037 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
10038 : diyfp(2 * v.f - 1, v.e - 1); // (A)
10039
10040 // Determine the normalized w+ = m+.
10041 const diyfp w_plus = diyfp::normalize(m_plus);
10042
10043 // Determine w- = m- such that e_(w-) = e_(w+).
10044 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
10045
10046 return {diyfp::normalize(v), w_minus, w_plus};
10047}
10048
10049// Given normalized diyfp w, Grisu needs to find a (normalized) cached
10050// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
10051// within a certain range [alpha, gamma] (Definition 3.2 from [1])
10052//
10053// alpha <= e = e_c + e_w + q <= gamma
10054//
10055// or
10056//
10057// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
10058// <= f_c * f_w * 2^gamma
10059//
10060// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
10061//
10062// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
10063//
10064// or
10065//
10066// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
10067//
10068// The choice of (alpha,gamma) determines the size of the table and the form of
10069// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
10070// in practice:
10071//
10072// The idea is to cut the number c * w = f * 2^e into two parts, which can be
10073// processed independently: An integral part p1, and a fractional part p2:
10074//
10075// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
10076// = (f div 2^-e) + (f mod 2^-e) * 2^e
10077// = p1 + p2 * 2^e
10078//
10079// The conversion of p1 into decimal form requires a series of divisions and
10080// modulos by (a power of) 10. These operations are faster for 32-bit than for
10081// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
10082// achieved by choosing
10083//
10084// -e >= 32 or e <= -32 := gamma
10085//
10086// In order to convert the fractional part
10087//
10088// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
10089//
10090// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
10091// d[-i] are extracted in order:
10092//
10093// (10 * p2) div 2^-e = d[-1]
10094// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
10095//
10096// The multiplication by 10 must not overflow. It is sufficient to choose
10097//
10098// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
10099//
10100// Since p2 = f mod 2^-e < 2^-e,
10101//
10102// -e <= 60 or e >= -60 := alpha
10103
10104constexpr int kAlpha = -60;
10105constexpr int kGamma = -32;
10106
10107struct cached_power // c = f * 2^e ~= 10^k
10108{
10109 uint64_t f;
10110 int e;
10111 int k;
10112};
10113
10122{
10123 // Now
10124 //
10125 // alpha <= e_c + e + q <= gamma (1)
10126 // ==> f_c * 2^alpha <= c * 2^e * 2^q
10127 //
10128 // and since the c's are normalized, 2^(q-1) <= f_c,
10129 //
10130 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
10131 // ==> 2^(alpha - e - 1) <= c
10132 //
10133 // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
10134 //
10135 // k = ceil( log_10( 2^(alpha - e - 1) ) )
10136 // = ceil( (alpha - e - 1) * log_10(2) )
10137 //
10138 // From the paper:
10139 // "In theory the result of the procedure could be wrong since c is rounded,
10140 // and the computation itself is approximated [...]. In practice, however,
10141 // this simple function is sufficient."
10142 //
10143 // For IEEE double precision floating-point numbers converted into
10144 // normalized diyfp's w = f * 2^e, with q = 64,
10145 //
10146 // e >= -1022 (min IEEE exponent)
10147 // -52 (p - 1)
10148 // -52 (p - 1, possibly normalize denormal IEEE numbers)
10149 // -11 (normalize the diyfp)
10150 // = -1137
10151 //
10152 // and
10153 //
10154 // e <= +1023 (max IEEE exponent)
10155 // -52 (p - 1)
10156 // -11 (normalize the diyfp)
10157 // = 960
10158 //
10159 // This binary exponent range [-1137,960] results in a decimal exponent
10160 // range [-307,324]. One does not need to store a cached power for each
10161 // k in this range. For each such k it suffices to find a cached power
10162 // such that the exponent of the product lies in [alpha,gamma].
10163 // This implies that the difference of the decimal exponents of adjacent
10164 // table entries must be less than or equal to
10165 //
10166 // floor( (gamma - alpha) * log_10(2) ) = 8.
10167 //
10168 // (A smaller distance gamma-alpha would require a larger table.)
10169
10170 // NB:
10171 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
10172
10173 constexpr int kCachedPowersSize = 79;
10174 constexpr int kCachedPowersMinDecExp = -300;
10175 constexpr int kCachedPowersDecStep = 8;
10176
10177 static constexpr cached_power kCachedPowers[] =
10178 {
10179 { 0xAB70FE17C79AC6CA, -1060, -300 },
10180 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
10181 { 0xBE5691EF416BD60C, -1007, -284 },
10182 { 0x8DD01FAD907FFC3C, -980, -276 },
10183 { 0xD3515C2831559A83, -954, -268 },
10184 { 0x9D71AC8FADA6C9B5, -927, -260 },
10185 { 0xEA9C227723EE8BCB, -901, -252 },
10186 { 0xAECC49914078536D, -874, -244 },
10187 { 0x823C12795DB6CE57, -847, -236 },
10188 { 0xC21094364DFB5637, -821, -228 },
10189 { 0x9096EA6F3848984F, -794, -220 },
10190 { 0xD77485CB25823AC7, -768, -212 },
10191 { 0xA086CFCD97BF97F4, -741, -204 },
10192 { 0xEF340A98172AACE5, -715, -196 },
10193 { 0xB23867FB2A35B28E, -688, -188 },
10194 { 0x84C8D4DFD2C63F3B, -661, -180 },
10195 { 0xC5DD44271AD3CDBA, -635, -172 },
10196 { 0x936B9FCEBB25C996, -608, -164 },
10197 { 0xDBAC6C247D62A584, -582, -156 },
10198 { 0xA3AB66580D5FDAF6, -555, -148 },
10199 { 0xF3E2F893DEC3F126, -529, -140 },
10200 { 0xB5B5ADA8AAFF80B8, -502, -132 },
10201 { 0x87625F056C7C4A8B, -475, -124 },
10202 { 0xC9BCFF6034C13053, -449, -116 },
10203 { 0x964E858C91BA2655, -422, -108 },
10204 { 0xDFF9772470297EBD, -396, -100 },
10205 { 0xA6DFBD9FB8E5B88F, -369, -92 },
10206 { 0xF8A95FCF88747D94, -343, -84 },
10207 { 0xB94470938FA89BCF, -316, -76 },
10208 { 0x8A08F0F8BF0F156B, -289, -68 },
10209 { 0xCDB02555653131B6, -263, -60 },
10210 { 0x993FE2C6D07B7FAC, -236, -52 },
10211 { 0xE45C10C42A2B3B06, -210, -44 },
10212 { 0xAA242499697392D3, -183, -36 },
10213 { 0xFD87B5F28300CA0E, -157, -28 },
10214 { 0xBCE5086492111AEB, -130, -20 },
10215 { 0x8CBCCC096F5088CC, -103, -12 },
10216 { 0xD1B71758E219652C, -77, -4 },
10217 { 0x9C40000000000000, -50, 4 },
10218 { 0xE8D4A51000000000, -24, 12 },
10219 { 0xAD78EBC5AC620000, 3, 20 },
10220 { 0x813F3978F8940984, 30, 28 },
10221 { 0xC097CE7BC90715B3, 56, 36 },
10222 { 0x8F7E32CE7BEA5C70, 83, 44 },
10223 { 0xD5D238A4ABE98068, 109, 52 },
10224 { 0x9F4F2726179A2245, 136, 60 },
10225 { 0xED63A231D4C4FB27, 162, 68 },
10226 { 0xB0DE65388CC8ADA8, 189, 76 },
10227 { 0x83C7088E1AAB65DB, 216, 84 },
10228 { 0xC45D1DF942711D9A, 242, 92 },
10229 { 0x924D692CA61BE758, 269, 100 },
10230 { 0xDA01EE641A708DEA, 295, 108 },
10231 { 0xA26DA3999AEF774A, 322, 116 },
10232 { 0xF209787BB47D6B85, 348, 124 },
10233 { 0xB454E4A179DD1877, 375, 132 },
10234 { 0x865B86925B9BC5C2, 402, 140 },
10235 { 0xC83553C5C8965D3D, 428, 148 },
10236 { 0x952AB45CFA97A0B3, 455, 156 },
10237 { 0xDE469FBD99A05FE3, 481, 164 },
10238 { 0xA59BC234DB398C25, 508, 172 },
10239 { 0xF6C69A72A3989F5C, 534, 180 },
10240 { 0xB7DCBF5354E9BECE, 561, 188 },
10241 { 0x88FCF317F22241E2, 588, 196 },
10242 { 0xCC20CE9BD35C78A5, 614, 204 },
10243 { 0x98165AF37B2153DF, 641, 212 },
10244 { 0xE2A0B5DC971F303A, 667, 220 },
10245 { 0xA8D9D1535CE3B396, 694, 228 },
10246 { 0xFB9B7CD9A4A7443C, 720, 236 },
10247 { 0xBB764C4CA7A44410, 747, 244 },
10248 { 0x8BAB8EEFB6409C1A, 774, 252 },
10249 { 0xD01FEF10A657842C, 800, 260 },
10250 { 0x9B10A4E5E9913129, 827, 268 },
10251 { 0xE7109BFBA19C0C9D, 853, 276 },
10252 { 0xAC2820D9623BF429, 880, 284 },
10253 { 0x80444B5E7AA7CF85, 907, 292 },
10254 { 0xBF21E44003ACDD2D, 933, 300 },
10255 { 0x8E679C2F5E44FF8F, 960, 308 },
10256 { 0xD433179D9C8CB841, 986, 316 },
10257 { 0x9E19DB92B4E31BA9, 1013, 324 },
10258 };
10259
10260 // This computation gives exactly the same results for k as
10261 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
10262 // for |e| <= 1500, but doesn't require floating-point operations.
10263 // NB: log_10(2) ~= 78913 / 2^18
10264 assert(e >= -1500);
10265 assert(e <= 1500);
10266 const int f = kAlpha - e - 1;
10267 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
10268
10269 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
10270 assert(index >= 0);
10271 assert(index < kCachedPowersSize);
10272 static_cast<void>(kCachedPowersSize); // Fix warning.
10273
10274 const cached_power cached = kCachedPowers[index];
10275 assert(kAlpha <= cached.e + e + 64);
10276 assert(kGamma >= cached.e + e + 64);
10277
10278 return cached;
10279}
10280
10285inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
10286{
10287 // LCOV_EXCL_START
10288 if (n >= 1000000000)
10289 {
10290 pow10 = 1000000000;
10291 return 10;
10292 }
10293 // LCOV_EXCL_STOP
10294 else if (n >= 100000000)
10295 {
10296 pow10 = 100000000;
10297 return 9;
10298 }
10299 else if (n >= 10000000)
10300 {
10301 pow10 = 10000000;
10302 return 8;
10303 }
10304 else if (n >= 1000000)
10305 {
10306 pow10 = 1000000;
10307 return 7;
10308 }
10309 else if (n >= 100000)
10310 {
10311 pow10 = 100000;
10312 return 6;
10313 }
10314 else if (n >= 10000)
10315 {
10316 pow10 = 10000;
10317 return 5;
10318 }
10319 else if (n >= 1000)
10320 {
10321 pow10 = 1000;
10322 return 4;
10323 }
10324 else if (n >= 100)
10325 {
10326 pow10 = 100;
10327 return 3;
10328 }
10329 else if (n >= 10)
10330 {
10331 pow10 = 10;
10332 return 2;
10333 }
10334 else
10335 {
10336 pow10 = 1;
10337 return 1;
10338 }
10339}
10340
10341inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,
10342 uint64_t rest, uint64_t ten_k)
10343{
10344 assert(len >= 1);
10345 assert(dist <= delta);
10346 assert(rest <= delta);
10347 assert(ten_k > 0);
10348
10349 // <--------------------------- delta ---->
10350 // <---- dist --------->
10351 // --------------[------------------+-------------------]--------------
10352 // M- w M+
10353 //
10354 // ten_k
10355 // <------>
10356 // <---- rest ---->
10357 // --------------[------------------+----+--------------]--------------
10358 // w V
10359 // = buf * 10^k
10360 //
10361 // ten_k represents a unit-in-the-last-place in the decimal representation
10362 // stored in buf.
10363 // Decrement buf by ten_k while this takes buf closer to w.
10364
10365 // The tests are written in this order to avoid overflow in unsigned
10366 // integer arithmetic.
10367
10368 while (rest < dist
10369 and delta - rest >= ten_k
10370 and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
10371 {
10372 assert(buf[len - 1] != '0');
10373 buf[len - 1]--;
10374 rest += ten_k;
10375 }
10376}
10377
10382inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
10383 diyfp M_minus, diyfp w, diyfp M_plus)
10384{
10385 static_assert(kAlpha >= -60, "internal error");
10386 static_assert(kGamma <= -32, "internal error");
10387
10388 // Generates the digits (and the exponent) of a decimal floating-point
10389 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
10390 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
10391 //
10392 // <--------------------------- delta ---->
10393 // <---- dist --------->
10394 // --------------[------------------+-------------------]--------------
10395 // M- w M+
10396 //
10397 // Grisu2 generates the digits of M+ from left to right and stops as soon as
10398 // V is in [M-,M+].
10399
10400 assert(M_plus.e >= kAlpha);
10401 assert(M_plus.e <= kGamma);
10402
10403 uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
10404 uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
10405
10406 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
10407 //
10408 // M+ = f * 2^e
10409 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
10410 // = ((p1 ) * 2^-e + (p2 )) * 2^e
10411 // = p1 + p2 * 2^e
10412
10413 const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
10414
10415 auto p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
10416 uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
10417
10418 // 1)
10419 //
10420 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
10421
10422 assert(p1 > 0);
10423
10424 uint32_t pow10;
10425 const int k = find_largest_pow10(p1, pow10);
10426
10427 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
10428 //
10429 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
10430 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
10431 //
10432 // M+ = p1 + p2 * 2^e
10433 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
10434 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
10435 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
10436 //
10437 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
10438 //
10439 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
10440 //
10441 // but stop as soon as
10442 //
10443 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
10444
10445 int n = k;
10446 while (n > 0)
10447 {
10448 // Invariants:
10449 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
10450 // pow10 = 10^(n-1) <= p1 < 10^n
10451 //
10452 const uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
10453 const uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
10454 //
10455 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
10456 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
10457 //
10458 assert(d <= 9);
10459 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
10460 //
10461 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
10462 //
10463 p1 = r;
10464 n--;
10465 //
10466 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
10467 // pow10 = 10^n
10468 //
10469
10470 // Now check if enough digits have been generated.
10471 // Compute
10472 //
10473 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
10474 //
10475 // Note:
10476 // Since rest and delta share the same exponent e, it suffices to
10477 // compare the significands.
10478 const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
10479 if (rest <= delta)
10480 {
10481 // V = buffer * 10^n, with M- <= V <= M+.
10482
10483 decimal_exponent += n;
10484
10485 // We may now just stop. But instead look if the buffer could be
10486 // decremented to bring V closer to w.
10487 //
10488 // pow10 = 10^n is now 1 ulp in the decimal representation V.
10489 // The rounding procedure works with diyfp's with an implicit
10490 // exponent of e.
10491 //
10492 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
10493 //
10494 const uint64_t ten_n = uint64_t{pow10} << -one.e;
10495 grisu2_round(buffer, length, dist, delta, rest, ten_n);
10496
10497 return;
10498 }
10499
10500 pow10 /= 10;
10501 //
10502 // pow10 = 10^(n-1) <= p1 < 10^n
10503 // Invariants restored.
10504 }
10505
10506 // 2)
10507 //
10508 // The digits of the integral part have been generated:
10509 //
10510 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
10511 // = buffer + p2 * 2^e
10512 //
10513 // Now generate the digits of the fractional part p2 * 2^e.
10514 //
10515 // Note:
10516 // No decimal point is generated: the exponent is adjusted instead.
10517 //
10518 // p2 actually represents the fraction
10519 //
10520 // p2 * 2^e
10521 // = p2 / 2^-e
10522 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
10523 //
10524 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
10525 //
10526 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
10527 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
10528 //
10529 // using
10530 //
10531 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
10532 // = ( d) * 2^-e + ( r)
10533 //
10534 // or
10535 // 10^m * p2 * 2^e = d + r * 2^e
10536 //
10537 // i.e.
10538 //
10539 // M+ = buffer + p2 * 2^e
10540 // = buffer + 10^-m * (d + r * 2^e)
10541 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
10542 //
10543 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
10544
10545 assert(p2 > delta);
10546
10547 int m = 0;
10548 for (;;)
10549 {
10550 // Invariant:
10551 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
10552 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
10553 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
10554 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
10555 //
10556 assert(p2 <= UINT64_MAX / 10);
10557 p2 *= 10;
10558 const uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
10559 const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
10560 //
10561 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
10562 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
10563 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
10564 //
10565 assert(d <= 9);
10566 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
10567 //
10568 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
10569 //
10570 p2 = r;
10571 m++;
10572 //
10573 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
10574 // Invariant restored.
10575
10576 // Check if enough digits have been generated.
10577 //
10578 // 10^-m * p2 * 2^e <= delta * 2^e
10579 // p2 * 2^e <= 10^m * delta * 2^e
10580 // p2 <= 10^m * delta
10581 delta *= 10;
10582 dist *= 10;
10583 if (p2 <= delta)
10584 {
10585 break;
10586 }
10587 }
10588
10589 // V = buffer * 10^-m, with M- <= V <= M+.
10590
10591 decimal_exponent -= m;
10592
10593 // 1 ulp in the decimal representation is now 10^-m.
10594 // Since delta and dist are now scaled by 10^m, we need to do the
10595 // same with ulp in order to keep the units in sync.
10596 //
10597 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
10598 //
10599 const uint64_t ten_m = one.f;
10600 grisu2_round(buffer, length, dist, delta, p2, ten_m);
10601
10602 // By construction this algorithm generates the shortest possible decimal
10603 // number (Loitsch, Theorem 6.2) which rounds back to w.
10604 // For an input number of precision p, at least
10605 //
10606 // N = 1 + ceil(p * log_10(2))
10607 //
10608 // decimal digits are sufficient to identify all binary floating-point
10609 // numbers (Matula, "In-and-Out conversions").
10610 // This implies that the algorithm does not produce more than N decimal
10611 // digits.
10612 //
10613 // N = 17 for p = 53 (IEEE double precision)
10614 // N = 9 for p = 24 (IEEE single precision)
10615}
10616
10622inline void grisu2(char* buf, int& len, int& decimal_exponent,
10623 diyfp m_minus, diyfp v, diyfp m_plus)
10624{
10625 assert(m_plus.e == m_minus.e);
10626 assert(m_plus.e == v.e);
10627
10628 // --------(-----------------------+-----------------------)-------- (A)
10629 // m- v m+
10630 //
10631 // --------------------(-----------+-----------------------)-------- (B)
10632 // m- v m+
10633 //
10634 // First scale v (and m- and m+) such that the exponent is in the range
10635 // [alpha, gamma].
10636
10638
10639 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
10640
10641 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
10642 const diyfp w = diyfp::mul(v, c_minus_k);
10643 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
10644 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
10645
10646 // ----(---+---)---------------(---+---)---------------(---+---)----
10647 // w- w w+
10648 // = c*m- = c*v = c*m+
10649 //
10650 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
10651 // w+ are now off by a small amount.
10652 // In fact:
10653 //
10654 // w - v * 10^k < 1 ulp
10655 //
10656 // To account for this inaccuracy, add resp. subtract 1 ulp.
10657 //
10658 // --------+---[---------------(---+---)---------------]---+--------
10659 // w- M- w M+ w+
10660 //
10661 // Now any number in [M-, M+] (bounds included) will round to w when input,
10662 // regardless of how the input rounding algorithm breaks ties.
10663 //
10664 // And digit_gen generates the shortest possible such number in [M-, M+].
10665 // Note that this does not mean that Grisu2 always generates the shortest
10666 // possible number in the interval (m-, m+).
10667 const diyfp M_minus(w_minus.f + 1, w_minus.e);
10668 const diyfp M_plus (w_plus.f - 1, w_plus.e );
10669
10670 decimal_exponent = -cached.k; // = -(-k) = k
10671
10672 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
10673}
10674
10680template <typename FloatType>
10681void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
10682{
10683 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
10684 "internal error: not enough precision");
10685
10686 assert(std::isfinite(value));
10687 assert(value > 0);
10688
10689 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
10690 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
10691 // decimal representations are not exactly "short".
10692 //
10693 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
10694 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
10695 // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
10696 // does.
10697 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
10698 // representation using the corresponding std::from_chars function recovers value exactly". That
10699 // indicates that single precision floating-point numbers should be recovered using
10700 // 'std::strtof'.
10701 //
10702 // NB: If the neighbors are computed for single-precision numbers, there is a single float
10703 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
10704 // value is off by 1 ulp.
10705#if 0
10706 const boundaries w = compute_boundaries(static_cast<double>(value));
10707#else
10709#endif
10710
10711 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
10712}
10713
10719inline char* append_exponent(char* buf, int e)
10720{
10721 assert(e > -1000);
10722 assert(e < 1000);
10723
10724 if (e < 0)
10725 {
10726 e = -e;
10727 *buf++ = '-';
10728 }
10729 else
10730 {
10731 *buf++ = '+';
10732 }
10733
10734 auto k = static_cast<uint32_t>(e);
10735 if (k < 10)
10736 {
10737 // Always print at least two digits in the exponent.
10738 // This is for compatibility with printf("%g").
10739 *buf++ = '0';
10740 *buf++ = static_cast<char>('0' + k);
10741 }
10742 else if (k < 100)
10743 {
10744 *buf++ = static_cast<char>('0' + k / 10);
10745 k %= 10;
10746 *buf++ = static_cast<char>('0' + k);
10747 }
10748 else
10749 {
10750 *buf++ = static_cast<char>('0' + k / 100);
10751 k %= 100;
10752 *buf++ = static_cast<char>('0' + k / 10);
10753 k %= 10;
10754 *buf++ = static_cast<char>('0' + k);
10755 }
10756
10757 return buf;
10758}
10759
10769inline char* format_buffer(char* buf, int len, int decimal_exponent,
10770 int min_exp, int max_exp)
10771{
10772 assert(min_exp < 0);
10773 assert(max_exp > 0);
10774
10775 const int k = len;
10776 const int n = len + decimal_exponent;
10777
10778 // v = buf * 10^(n-k)
10779 // k is the length of the buffer (number of decimal digits)
10780 // n is the position of the decimal point relative to the start of the buffer.
10781
10782 if (k <= n and n <= max_exp)
10783 {
10784 // digits[000]
10785 // len <= max_exp + 2
10786
10787 std::memset(buf + k, '0', static_cast<size_t>(n - k));
10788 // Make it look like a floating-point number (#362, #378)
10789 buf[n + 0] = '.';
10790 buf[n + 1] = '0';
10791 return buf + (n + 2);
10792 }
10793
10794 if (0 < n and n <= max_exp)
10795 {
10796 // dig.its
10797 // len <= max_digits10 + 1
10798
10799 assert(k > n);
10800
10801 std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
10802 buf[n] = '.';
10803 return buf + (k + 1);
10804 }
10805
10806 if (min_exp < n and n <= 0)
10807 {
10808 // 0.[000]digits
10809 // len <= 2 + (-min_exp - 1) + max_digits10
10810
10811 std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
10812 buf[0] = '0';
10813 buf[1] = '.';
10814 std::memset(buf + 2, '0', static_cast<size_t>(-n));
10815 return buf + (2 + (-n) + k);
10816 }
10817
10818 if (k == 1)
10819 {
10820 // dE+123
10821 // len <= 1 + 5
10822
10823 buf += 1;
10824 }
10825 else
10826 {
10827 // d.igitsE+123
10828 // len <= max_digits10 + 1 + 5
10829
10830 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
10831 buf[1] = '.';
10832 buf += 1 + k;
10833 }
10834
10835 *buf++ = 'e';
10836 return append_exponent(buf, n - 1);
10837}
10838
10839} // namespace dtoa_impl
10840
10851template <typename FloatType>
10852char* to_chars(char* first, const char* last, FloatType value)
10853{
10854 static_cast<void>(last); // maybe unused - fix warning
10855 assert(std::isfinite(value));
10856
10857 // Use signbit(value) instead of (value < 0) since signbit works for -0.
10858 if (std::signbit(value))
10859 {
10860 value = -value;
10861 *first++ = '-';
10862 }
10863
10864 if (value == 0) // +-0
10865 {
10866 *first++ = '0';
10867 // Make it look like a floating-point number (#362, #378)
10868 *first++ = '.';
10869 *first++ = '0';
10870 return first;
10871 }
10872
10873 assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
10874
10875 // Compute v = buffer * 10^decimal_exponent.
10876 // The decimal digits are stored in the buffer, which needs to be interpreted
10877 // as an unsigned decimal integer.
10878 // len is the length of the buffer, i.e. the number of decimal digits.
10879 int len = 0;
10880 int decimal_exponent = 0;
10881 dtoa_impl::grisu2(first, len, decimal_exponent, value);
10882
10883 assert(len <= std::numeric_limits<FloatType>::max_digits10);
10884
10885 // Format the buffer like printf("%.*g", prec, value)
10886 constexpr int kMinExp = -4;
10887 // Use digits10 here to increase compatibility with version 2.
10888 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
10889
10890 assert(last - first >= kMaxExp + 2);
10891 assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
10892 assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
10893
10894 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
10895}
10896
10897} // namespace detail
10898} // namespace nlohmann
10899
10900// #include <nlohmann/detail/macro_scope.hpp>
10901
10902// #include <nlohmann/detail/meta/cpp_future.hpp>
10903
10904// #include <nlohmann/detail/output/binary_writer.hpp>
10905
10906// #include <nlohmann/detail/output/output_adapters.hpp>
10907
10908// #include <nlohmann/detail/value_t.hpp>
10909
10910
10911namespace nlohmann
10912{
10913namespace detail
10914{
10916// serialization //
10918
10921{
10925};
10926
10927template<typename BasicJsonType>
10929{
10930 using string_t = typename BasicJsonType::string_t;
10931 using number_float_t = typename BasicJsonType::number_float_t;
10932 using number_integer_t = typename BasicJsonType::number_integer_t;
10933 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10934 static constexpr uint8_t UTF8_ACCEPT = 0;
10935 static constexpr uint8_t UTF8_REJECT = 1;
10936
10937 public:
10945 : o(std::move(s))
10946 , loc(std::localeconv())
10947 , thousands_sep('\0')
10948 , decimal_point('.')
10949 , indent_char(ichar)
10950 , indent_string(512, indent_char)
10951 , error_handler(error_handler_)
10952 {}
10953
10954 // delete because of pointer members
10955 serializer(const serializer&) = delete;
10959 ~serializer() = default;
10960
10978 void dump(const BasicJsonType& val, const bool pretty_print,
10979 const bool ensure_ascii,
10980 const unsigned int indent_step,
10981 const unsigned int current_indent = 0)
10982 {
10983 switch (val.m_type)
10984 {
10985 case value_t::object:
10986 {
10987 if (val.m_value.object->empty())
10988 {
10989 o->write_characters("{}", 2);
10990 return;
10991 }
10992
10993 if (pretty_print)
10994 {
10995 o->write_characters("{\n", 2);
10996
10997 // variable to hold indentation for recursive calls
10998 const auto new_indent = current_indent + indent_step;
10999 if (JSON_UNLIKELY(indent_string.size() < new_indent))
11000 {
11001 indent_string.resize(indent_string.size() * 2, ' ');
11002 }
11003
11004 // first n-1 elements
11005 auto i = val.m_value.object->cbegin();
11006 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
11007 {
11008 o->write_characters(indent_string.c_str(), new_indent);
11009 o->write_character('\"');
11010 dump_escaped(i->first, ensure_ascii);
11011 o->write_characters("\": ", 3);
11012 dump(i->second, true, ensure_ascii, indent_step, new_indent);
11013 o->write_characters(",\n", 2);
11014 }
11015
11016 // last element
11017 assert(i != val.m_value.object->cend());
11018 assert(std::next(i) == val.m_value.object->cend());
11019 o->write_characters(indent_string.c_str(), new_indent);
11020 o->write_character('\"');
11021 dump_escaped(i->first, ensure_ascii);
11022 o->write_characters("\": ", 3);
11023 dump(i->second, true, ensure_ascii, indent_step, new_indent);
11024
11025 o->write_character('\n');
11026 o->write_characters(indent_string.c_str(), current_indent);
11027 o->write_character('}');
11028 }
11029 else
11030 {
11031 o->write_character('{');
11032
11033 // first n-1 elements
11034 auto i = val.m_value.object->cbegin();
11035 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
11036 {
11037 o->write_character('\"');
11038 dump_escaped(i->first, ensure_ascii);
11039 o->write_characters("\":", 2);
11040 dump(i->second, false, ensure_ascii, indent_step, current_indent);
11041 o->write_character(',');
11042 }
11043
11044 // last element
11045 assert(i != val.m_value.object->cend());
11046 assert(std::next(i) == val.m_value.object->cend());
11047 o->write_character('\"');
11048 dump_escaped(i->first, ensure_ascii);
11049 o->write_characters("\":", 2);
11050 dump(i->second, false, ensure_ascii, indent_step, current_indent);
11051
11052 o->write_character('}');
11053 }
11054
11055 return;
11056 }
11057
11058 case value_t::array:
11059 {
11060 if (val.m_value.array->empty())
11061 {
11062 o->write_characters("[]", 2);
11063 return;
11064 }
11065
11066 if (pretty_print)
11067 {
11068 o->write_characters("[\n", 2);
11069
11070 // variable to hold indentation for recursive calls
11071 const auto new_indent = current_indent + indent_step;
11072 if (JSON_UNLIKELY(indent_string.size() < new_indent))
11073 {
11074 indent_string.resize(indent_string.size() * 2, ' ');
11075 }
11076
11077 // first n-1 elements
11078 for (auto i = val.m_value.array->cbegin();
11079 i != val.m_value.array->cend() - 1; ++i)
11080 {
11081 o->write_characters(indent_string.c_str(), new_indent);
11082 dump(*i, true, ensure_ascii, indent_step, new_indent);
11083 o->write_characters(",\n", 2);
11084 }
11085
11086 // last element
11087 assert(not val.m_value.array->empty());
11088 o->write_characters(indent_string.c_str(), new_indent);
11089 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
11090
11091 o->write_character('\n');
11092 o->write_characters(indent_string.c_str(), current_indent);
11093 o->write_character(']');
11094 }
11095 else
11096 {
11097 o->write_character('[');
11098
11099 // first n-1 elements
11100 for (auto i = val.m_value.array->cbegin();
11101 i != val.m_value.array->cend() - 1; ++i)
11102 {
11103 dump(*i, false, ensure_ascii, indent_step, current_indent);
11104 o->write_character(',');
11105 }
11106
11107 // last element
11108 assert(not val.m_value.array->empty());
11109 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
11110
11111 o->write_character(']');
11112 }
11113
11114 return;
11115 }
11116
11117 case value_t::string:
11118 {
11119 o->write_character('\"');
11120 dump_escaped(*val.m_value.string, ensure_ascii);
11121 o->write_character('\"');
11122 return;
11123 }
11124
11125 case value_t::boolean:
11126 {
11127 if (val.m_value.boolean)
11128 {
11129 o->write_characters("true", 4);
11130 }
11131 else
11132 {
11133 o->write_characters("false", 5);
11134 }
11135 return;
11136 }
11137
11139 {
11140 dump_integer(val.m_value.number_integer);
11141 return;
11142 }
11143
11145 {
11146 dump_integer(val.m_value.number_unsigned);
11147 return;
11148 }
11149
11151 {
11152 dump_float(val.m_value.number_float);
11153 return;
11154 }
11155
11156 case value_t::discarded:
11157 {
11158 o->write_characters("<discarded>", 11);
11159 return;
11160 }
11161
11162 case value_t::null:
11163 {
11164 o->write_characters("null", 4);
11165 return;
11166 }
11167 }
11168 }
11169
11170 private:
11185 void dump_escaped(const string_t& s, const bool ensure_ascii)
11186 {
11187 uint32_t codepoint;
11188 uint8_t state = UTF8_ACCEPT;
11189 std::size_t bytes = 0; // number of bytes written to string_buffer
11190
11191 // number of bytes written at the point of the last valid byte
11192 std::size_t bytes_after_last_accept = 0;
11193 std::size_t undumped_chars = 0;
11194
11195 for (std::size_t i = 0; i < s.size(); ++i)
11196 {
11197 const auto byte = static_cast<uint8_t>(s[i]);
11198
11199 switch (decode(state, codepoint, byte))
11200 {
11201 case UTF8_ACCEPT: // decode found a new code point
11202 {
11203 switch (codepoint)
11204 {
11205 case 0x08: // backspace
11206 {
11207 string_buffer[bytes++] = '\\';
11208 string_buffer[bytes++] = 'b';
11209 break;
11210 }
11211
11212 case 0x09: // horizontal tab
11213 {
11214 string_buffer[bytes++] = '\\';
11215 string_buffer[bytes++] = 't';
11216 break;
11217 }
11218
11219 case 0x0A: // newline
11220 {
11221 string_buffer[bytes++] = '\\';
11222 string_buffer[bytes++] = 'n';
11223 break;
11224 }
11225
11226 case 0x0C: // formfeed
11227 {
11228 string_buffer[bytes++] = '\\';
11229 string_buffer[bytes++] = 'f';
11230 break;
11231 }
11232
11233 case 0x0D: // carriage return
11234 {
11235 string_buffer[bytes++] = '\\';
11236 string_buffer[bytes++] = 'r';
11237 break;
11238 }
11239
11240 case 0x22: // quotation mark
11241 {
11242 string_buffer[bytes++] = '\\';
11243 string_buffer[bytes++] = '\"';
11244 break;
11245 }
11246
11247 case 0x5C: // reverse solidus
11248 {
11249 string_buffer[bytes++] = '\\';
11250 string_buffer[bytes++] = '\\';
11251 break;
11252 }
11253
11254 default:
11255 {
11256 // escape control characters (0x00..0x1F) or, if
11257 // ensure_ascii parameter is used, non-ASCII characters
11258 if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
11259 {
11260 if (codepoint <= 0xFFFF)
11261 {
11262 (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
11263 static_cast<uint16_t>(codepoint));
11264 bytes += 6;
11265 }
11266 else
11267 {
11268 (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
11269 static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
11270 static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
11271 bytes += 12;
11272 }
11273 }
11274 else
11275 {
11276 // copy byte to buffer (all previous bytes
11277 // been copied have in default case above)
11278 string_buffer[bytes++] = s[i];
11279 }
11280 break;
11281 }
11282 }
11283
11284 // write buffer and reset index; there must be 13 bytes
11285 // left, as this is the maximal number of bytes to be
11286 // written ("\uxxxx\uxxxx\0") for one code point
11287 if (string_buffer.size() - bytes < 13)
11288 {
11289 o->write_characters(string_buffer.data(), bytes);
11290 bytes = 0;
11291 }
11292
11293 // remember the byte position of this accept
11294 bytes_after_last_accept = bytes;
11295 undumped_chars = 0;
11296 break;
11297 }
11298
11299 case UTF8_REJECT: // decode found invalid UTF-8 byte
11300 {
11301 switch (error_handler)
11302 {
11304 {
11305 std::string sn(3, '\0');
11306 (std::snprintf)(&sn[0], sn.size(), "%.2X", byte);
11307 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
11308 }
11309
11312 {
11313 // in case we saw this character the first time, we
11314 // would like to read it again, because the byte
11315 // may be OK for itself, but just not OK for the
11316 // previous sequence
11317 if (undumped_chars > 0)
11318 {
11319 --i;
11320 }
11321
11322 // reset length buffer to the last accepted index;
11323 // thus removing/ignoring the invalid characters
11324 bytes = bytes_after_last_accept;
11325
11326 if (error_handler == error_handler_t::replace)
11327 {
11328 // add a replacement character
11329 if (ensure_ascii)
11330 {
11331 string_buffer[bytes++] = '\\';
11332 string_buffer[bytes++] = 'u';
11333 string_buffer[bytes++] = 'f';
11334 string_buffer[bytes++] = 'f';
11335 string_buffer[bytes++] = 'f';
11336 string_buffer[bytes++] = 'd';
11337 }
11338 else
11339 {
11340 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
11341 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
11342 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
11343 }
11344 bytes_after_last_accept = bytes;
11345 }
11346
11347 undumped_chars = 0;
11348
11349 // continue processing the string
11350 state = UTF8_ACCEPT;
11351 break;
11352 }
11353 }
11354 break;
11355 }
11356
11357 default: // decode found yet incomplete multi-byte code point
11358 {
11359 if (not ensure_ascii)
11360 {
11361 // code point will not be escaped - copy byte to buffer
11362 string_buffer[bytes++] = s[i];
11363 }
11364 ++undumped_chars;
11365 break;
11366 }
11367 }
11368 }
11369
11370 // we finished processing the string
11371 if (JSON_LIKELY(state == UTF8_ACCEPT))
11372 {
11373 // write buffer
11374 if (bytes > 0)
11375 {
11376 o->write_characters(string_buffer.data(), bytes);
11377 }
11378 }
11379 else
11380 {
11381 // we finish reading, but do not accept: string was incomplete
11382 switch (error_handler)
11383 {
11385 {
11386 std::string sn(3, '\0');
11387 (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
11388 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
11389 }
11390
11392 {
11393 // write all accepted bytes
11394 o->write_characters(string_buffer.data(), bytes_after_last_accept);
11395 break;
11396 }
11397
11399 {
11400 // write all accepted bytes
11401 o->write_characters(string_buffer.data(), bytes_after_last_accept);
11402 // add a replacement character
11403 if (ensure_ascii)
11404 {
11405 o->write_characters("\\ufffd", 6);
11406 }
11407 else
11408 {
11409 o->write_characters("\xEF\xBF\xBD", 3);
11410 }
11411 break;
11412 }
11413 }
11414 }
11415 }
11416
11426 template<typename NumberType, detail::enable_if_t<
11427 std::is_same<NumberType, number_unsigned_t>::value or
11428 std::is_same<NumberType, number_integer_t>::value,
11429 int> = 0>
11430 void dump_integer(NumberType x)
11431 {
11432 // special case for "0"
11433 if (x == 0)
11434 {
11435 o->write_character('0');
11436 return;
11437 }
11438
11439 const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not (x >= 0); // see issue #755
11440 std::size_t i = 0;
11441
11442 while (x != 0)
11443 {
11444 // spare 1 byte for '\0'
11445 assert(i < number_buffer.size() - 1);
11446
11447 const auto digit = std::labs(static_cast<long>(x % 10));
11448 number_buffer[i++] = static_cast<char>('0' + digit);
11449 x /= 10;
11450 }
11451
11452 if (is_negative)
11453 {
11454 // make sure there is capacity for the '-'
11455 assert(i < number_buffer.size() - 2);
11456 number_buffer[i++] = '-';
11457 }
11458
11459 std::reverse(number_buffer.begin(), number_buffer.begin() + i);
11460 o->write_characters(number_buffer.data(), i);
11461 }
11462
11471 void dump_float(number_float_t x)
11472 {
11473 // NaN / inf
11474 if (not std::isfinite(x))
11475 {
11476 o->write_characters("null", 4);
11477 return;
11478 }
11479
11480 // If number_float_t is an IEEE-754 single or double precision number,
11481 // use the Grisu2 algorithm to produce short numbers which are
11482 // guaranteed to round-trip, using strtof and strtod, resp.
11483 //
11484 // NB: The test below works if <long double> == <double>.
11485 static constexpr bool is_ieee_single_or_double
11486 = (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
11487 (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
11488
11489 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
11490 }
11491
11492 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
11493 {
11494 char* begin = number_buffer.data();
11495 char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
11496
11497 o->write_characters(begin, static_cast<size_t>(end - begin));
11498 }
11499
11500 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
11501 {
11502 // get number of digits for a float -> text -> float round-trip
11503 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
11504
11505 // the actual conversion
11506 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
11507
11508 // negative value indicates an error
11509 assert(len > 0);
11510 // check if buffer was large enough
11511 assert(static_cast<std::size_t>(len) < number_buffer.size());
11512
11513 // erase thousands separator
11514 if (thousands_sep != '\0')
11515 {
11516 const auto end = std::remove(number_buffer.begin(),
11517 number_buffer.begin() + len, thousands_sep);
11518 std::fill(end, number_buffer.end(), '\0');
11519 assert((end - number_buffer.begin()) <= len);
11520 len = (end - number_buffer.begin());
11521 }
11522
11523 // convert decimal point to '.'
11524 if (decimal_point != '\0' and decimal_point != '.')
11525 {
11526 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
11527 if (dec_pos != number_buffer.end())
11528 {
11529 *dec_pos = '.';
11530 }
11531 }
11532
11533 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
11534
11535 // determine if need to append ".0"
11536 const bool value_is_int_like =
11537 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
11538 [](char c)
11539 {
11540 return (c == '.' or c == 'e');
11541 });
11542
11543 if (value_is_int_like)
11544 {
11545 o->write_characters(".0", 2);
11546 }
11547 }
11548
11570 static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
11571 {
11572 static const std::array<uint8_t, 400> utf8d =
11573 {
11574 {
11575 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
11576 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
11577 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
11578 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
11579 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
11580 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
11581 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
11582 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
11583 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
11584 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
11585 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
11586 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
11587 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
11588 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
11589 }
11590 };
11591
11592 const uint8_t type = utf8d[byte];
11593
11594 codep = (state != UTF8_ACCEPT)
11595 ? (byte & 0x3fu) | (codep << 6)
11596 : static_cast<uint32_t>(0xff >> type) & (byte);
11597
11598 state = utf8d[256u + state * 16u + type];
11599 return state;
11600 }
11601
11602 private:
11604 output_adapter_t<char> o = nullptr;
11605
11607 std::array<char, 64> number_buffer{{}};
11608
11610 const std::lconv* loc = nullptr;
11612 const char thousands_sep = '\0';
11614 const char decimal_point = '\0';
11615
11617 std::array<char, 512> string_buffer{{}};
11618
11620 const char indent_char;
11622 string_t indent_string;
11623
11625 const error_handler_t error_handler;
11626};
11627} // namespace detail
11628} // namespace nlohmann
11629
11630// #include <nlohmann/detail/json_ref.hpp>
11631
11632
11633#include <initializer_list>
11634#include <utility>
11635
11636// #include <nlohmann/detail/meta/type_traits.hpp>
11637
11638
11639namespace nlohmann
11640{
11641namespace detail
11642{
11643template<typename BasicJsonType>
11645{
11646 public:
11647 using value_type = BasicJsonType;
11648
11650 : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
11651 {}
11652
11654 : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
11655 {}
11656
11657 json_ref(std::initializer_list<json_ref> init)
11658 : owned_value(init), value_ref(&owned_value), is_rvalue(true)
11659 {}
11660
11661 template <
11662 class... Args,
11663 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
11664 json_ref(Args && ... args)
11665 : owned_value(std::forward<Args>(args)...), value_ref(&owned_value),
11666 is_rvalue(true) {}
11667
11668 // class should be movable only
11669 json_ref(json_ref&&) = default;
11670 json_ref(const json_ref&) = delete;
11671 json_ref& operator=(const json_ref&) = delete;
11673 ~json_ref() = default;
11674
11676 {
11677 if (is_rvalue)
11678 {
11679 return std::move(*value_ref);
11680 }
11681 return *value_ref;
11682 }
11683
11684 value_type const& operator*() const
11685 {
11686 return *static_cast<value_type const*>(value_ref);
11687 }
11688
11689 value_type const* operator->() const
11690 {
11691 return static_cast<value_type const*>(value_ref);
11692 }
11693
11694 private:
11695 mutable value_type owned_value = nullptr;
11696 value_type* value_ref = nullptr;
11697 const bool is_rvalue;
11698};
11699} // namespace detail
11700} // namespace nlohmann
11701
11702// #include <nlohmann/detail/json_pointer.hpp>
11703
11704
11705#include <cassert> // assert
11706#include <numeric> // accumulate
11707#include <string> // string
11708#include <vector> // vector
11709
11710// #include <nlohmann/detail/macro_scope.hpp>
11711
11712// #include <nlohmann/detail/exceptions.hpp>
11713
11714// #include <nlohmann/detail/value_t.hpp>
11715
11716
11717namespace nlohmann
11718{
11719template<typename BasicJsonType>
11721{
11722 // allow basic_json to access private members
11724 friend class basic_json;
11725
11726 public:
11748 explicit json_pointer(const std::string& s = "")
11749 : reference_tokens(split(s))
11750 {}
11751
11767 std::string to_string() const
11768 {
11769 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
11770 std::string{},
11771 [](const std::string & a, const std::string & b)
11772 {
11773 return a + "/" + escape(b);
11774 });
11775 }
11776
11777 /// @copydoc to_string()
11778 operator std::string() const
11779 {
11780 return to_string();
11781 }
11782
11790 static int array_index(const std::string& s)
11791 {
11792 std::size_t processed_chars = 0;
11793 const int res = std::stoi(s, &processed_chars);
11794
11795 // check if the string was completely read
11796 if (JSON_UNLIKELY(processed_chars != s.size()))
11797 {
11798 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
11799 }
11800
11801 return res;
11802 }
11803
11804 private:
11809 std::string pop_back()
11810 {
11811 if (JSON_UNLIKELY(is_root()))
11812 {
11813 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11814 }
11815
11816 auto last = reference_tokens.back();
11817 reference_tokens.pop_back();
11818 return last;
11819 }
11820
11822 bool is_root() const noexcept
11823 {
11824 return reference_tokens.empty();
11825 }
11826
11827 json_pointer top() const
11828 {
11829 if (JSON_UNLIKELY(is_root()))
11830 {
11831 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11832 }
11833
11834 json_pointer result = *this;
11835 result.reference_tokens = {reference_tokens[0]};
11836 return result;
11837 }
11838
11847 BasicJsonType& get_and_create(BasicJsonType& j) const
11848 {
11849 using size_type = typename BasicJsonType::size_type;
11850 auto result = &j;
11851
11852 // in case no reference tokens exist, return a reference to the JSON value
11853 // j which will be overwritten by a primitive value
11854 for (const auto& reference_token : reference_tokens)
11855 {
11856 switch (result->m_type)
11857 {
11858 case detail::value_t::null:
11859 {
11860 if (reference_token == "0")
11861 {
11862 // start a new array if reference token is 0
11863 result = &result->operator[](0);
11864 }
11865 else
11866 {
11867 // start a new object otherwise
11868 result = &result->operator[](reference_token);
11869 }
11870 break;
11871 }
11872
11873 case detail::value_t::object:
11874 {
11875 // create an entry in the object
11876 result = &result->operator[](reference_token);
11877 break;
11878 }
11879
11880 case detail::value_t::array:
11881 {
11882 // create an entry in the array
11883 JSON_TRY
11884 {
11885 result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
11886 }
11887 JSON_CATCH(std::invalid_argument&)
11888 {
11889 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
11890 }
11891 break;
11892 }
11893
11894 /*
11895 The following code is only reached if there exists a reference
11896 token _and_ the current value is primitive. In this case, we have
11897 an error situation, because primitive values may only occur as
11898 single value; that is, with an empty list of reference tokens.
11899 */
11900 default:
11901 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
11902 }
11903 }
11904
11905 return *result;
11906 }
11907
11927 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
11928 {
11929 using size_type = typename BasicJsonType::size_type;
11930 for (const auto& reference_token : reference_tokens)
11931 {
11932 // convert null values to arrays or objects before continuing
11933 if (ptr->m_type == detail::value_t::null)
11934 {
11935 // check if reference token is a number
11936 const bool nums =
11937 std::all_of(reference_token.begin(), reference_token.end(),
11938 [](const char x)
11939 {
11940 return (x >= '0' and x <= '9');
11941 });
11942
11943 // change value to array for numbers or "-" or to object otherwise
11944 *ptr = (nums or reference_token == "-")
11945 ? detail::value_t::array
11946 : detail::value_t::object;
11947 }
11948
11949 switch (ptr->m_type)
11950 {
11951 case detail::value_t::object:
11952 {
11953 // use unchecked object access
11954 ptr = &ptr->operator[](reference_token);
11955 break;
11956 }
11957
11958 case detail::value_t::array:
11959 {
11960 // error condition (cf. RFC 6901, Sect. 4)
11961 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
11962 {
11963 JSON_THROW(detail::parse_error::create(106, 0,
11964 "array index '" + reference_token +
11965 "' must not begin with '0'"));
11966 }
11967
11968 if (reference_token == "-")
11969 {
11970 // explicitly treat "-" as index beyond the end
11971 ptr = &ptr->operator[](ptr->m_value.array->size());
11972 }
11973 else
11974 {
11975 // convert array index to number; unchecked access
11976 JSON_TRY
11977 {
11978 ptr = &ptr->operator[](
11979 static_cast<size_type>(array_index(reference_token)));
11980 }
11981 JSON_CATCH(std::invalid_argument&)
11982 {
11983 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
11984 }
11985 }
11986 break;
11987 }
11988
11989 default:
11990 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
11991 }
11992 }
11993
11994 return *ptr;
11995 }
11996
12003 BasicJsonType& get_checked(BasicJsonType* ptr) const
12004 {
12005 using size_type = typename BasicJsonType::size_type;
12006 for (const auto& reference_token : reference_tokens)
12007 {
12008 switch (ptr->m_type)
12009 {
12010 case detail::value_t::object:
12011 {
12012 // note: at performs range check
12013 ptr = &ptr->at(reference_token);
12014 break;
12015 }
12016
12017 case detail::value_t::array:
12018 {
12019 if (JSON_UNLIKELY(reference_token == "-"))
12020 {
12021 // "-" always fails the range check
12022 JSON_THROW(detail::out_of_range::create(402,
12023 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12024 ") is out of range"));
12025 }
12026
12027 // error condition (cf. RFC 6901, Sect. 4)
12028 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
12029 {
12030 JSON_THROW(detail::parse_error::create(106, 0,
12031 "array index '" + reference_token +
12032 "' must not begin with '0'"));
12033 }
12034
12035 // note: at performs range check
12036 JSON_TRY
12037 {
12038 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
12039 }
12040 JSON_CATCH(std::invalid_argument&)
12041 {
12042 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12043 }
12044 break;
12045 }
12046
12047 default:
12048 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12049 }
12050 }
12051
12052 return *ptr;
12053 }
12054
12068 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
12069 {
12070 using size_type = typename BasicJsonType::size_type;
12071 for (const auto& reference_token : reference_tokens)
12072 {
12073 switch (ptr->m_type)
12074 {
12075 case detail::value_t::object:
12076 {
12077 // use unchecked object access
12078 ptr = &ptr->operator[](reference_token);
12079 break;
12080 }
12081
12082 case detail::value_t::array:
12083 {
12084 if (JSON_UNLIKELY(reference_token == "-"))
12085 {
12086 // "-" cannot be used for const access
12087 JSON_THROW(detail::out_of_range::create(402,
12088 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12089 ") is out of range"));
12090 }
12091
12092 // error condition (cf. RFC 6901, Sect. 4)
12093 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
12094 {
12095 JSON_THROW(detail::parse_error::create(106, 0,
12096 "array index '" + reference_token +
12097 "' must not begin with '0'"));
12098 }
12099
12100 // use unchecked array access
12101 JSON_TRY
12102 {
12103 ptr = &ptr->operator[](
12104 static_cast<size_type>(array_index(reference_token)));
12105 }
12106 JSON_CATCH(std::invalid_argument&)
12107 {
12108 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12109 }
12110 break;
12111 }
12112
12113 default:
12114 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12115 }
12116 }
12117
12118 return *ptr;
12119 }
12120
12127 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12128 {
12129 using size_type = typename BasicJsonType::size_type;
12130 for (const auto& reference_token : reference_tokens)
12131 {
12132 switch (ptr->m_type)
12133 {
12134 case detail::value_t::object:
12135 {
12136 // note: at performs range check
12137 ptr = &ptr->at(reference_token);
12138 break;
12139 }
12140
12141 case detail::value_t::array:
12142 {
12143 if (JSON_UNLIKELY(reference_token == "-"))
12144 {
12145 // "-" always fails the range check
12146 JSON_THROW(detail::out_of_range::create(402,
12147 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12148 ") is out of range"));
12149 }
12150
12151 // error condition (cf. RFC 6901, Sect. 4)
12152 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
12153 {
12154 JSON_THROW(detail::parse_error::create(106, 0,
12155 "array index '" + reference_token +
12156 "' must not begin with '0'"));
12157 }
12158
12159 // note: at performs range check
12160 JSON_TRY
12161 {
12162 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
12163 }
12164 JSON_CATCH(std::invalid_argument&)
12165 {
12166 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12167 }
12168 break;
12169 }
12170
12171 default:
12172 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12173 }
12174 }
12175
12176 return *ptr;
12177 }
12178
12188 static std::vector<std::string> split(const std::string& reference_string)
12189 {
12190 std::vector<std::string> result;
12191
12192 // special case: empty reference string -> no reference tokens
12193 if (reference_string.empty())
12194 {
12195 return result;
12196 }
12197
12198 // check if nonempty reference string begins with slash
12199 if (JSON_UNLIKELY(reference_string[0] != '/'))
12200 {
12201 JSON_THROW(detail::parse_error::create(107, 1,
12202 "JSON pointer must be empty or begin with '/' - was: '" +
12203 reference_string + "'"));
12204 }
12205
12206 // extract the reference tokens:
12207 // - slash: position of the last read slash (or end of string)
12208 // - start: position after the previous slash
12209 for (
12210 // search for the first slash after the first character
12211 std::size_t slash = reference_string.find_first_of('/', 1),
12212 // set the beginning of the first reference token
12213 start = 1;
12214 // we can stop if start == 0 (if slash == std::string::npos)
12215 start != 0;
12216 // set the beginning of the next reference token
12217 // (will eventually be 0 if slash == std::string::npos)
12218 start = (slash == std::string::npos) ? 0 : slash + 1,
12219 // find next slash
12220 slash = reference_string.find_first_of('/', start))
12221 {
12222 // use the text between the beginning of the reference token
12223 // (start) and the last slash (slash).
12224 auto reference_token = reference_string.substr(start, slash - start);
12225
12226 // check reference tokens are properly escaped
12227 for (std::size_t pos = reference_token.find_first_of('~');
12228 pos != std::string::npos;
12229 pos = reference_token.find_first_of('~', pos + 1))
12230 {
12231 assert(reference_token[pos] == '~');
12232
12233 // ~ must be followed by 0 or 1
12234 if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
12235 (reference_token[pos + 1] != '0' and
12236 reference_token[pos + 1] != '1')))
12237 {
12238 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
12239 }
12240 }
12241
12242 // finally, store the reference token
12243 unescape(reference_token);
12244 result.push_back(reference_token);
12245 }
12246
12247 return result;
12248 }
12249
12263 static void replace_substring(std::string& s, const std::string& f,
12264 const std::string& t)
12265 {
12266 assert(not f.empty());
12267 for (auto pos = s.find(f); // find first occurrence of f
12268 pos != std::string::npos; // make sure f was found
12269 s.replace(pos, f.size(), t), // replace with t, and
12270 pos = s.find(f, pos + t.size())) // find next occurrence of f
12271 {}
12272 }
12273
12275 static std::string escape(std::string s)
12276 {
12277 replace_substring(s, "~", "~0");
12278 replace_substring(s, "/", "~1");
12279 return s;
12280 }
12281
12283 static void unescape(std::string& s)
12284 {
12285 replace_substring(s, "~1", "/");
12286 replace_substring(s, "~0", "~");
12287 }
12288
12296 static void flatten(const std::string& reference_string,
12297 const BasicJsonType& value,
12298 BasicJsonType& result)
12299 {
12300 switch (value.m_type)
12301 {
12302 case detail::value_t::array:
12303 {
12304 if (value.m_value.array->empty())
12305 {
12306 // flatten empty array as null
12307 result[reference_string] = nullptr;
12308 }
12309 else
12310 {
12311 // iterate array and use index as reference string
12312 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12313 {
12314 flatten(reference_string + "/" + std::to_string(i),
12315 value.m_value.array->operator[](i), result);
12316 }
12317 }
12318 break;
12319 }
12320
12321 case detail::value_t::object:
12322 {
12323 if (value.m_value.object->empty())
12324 {
12325 // flatten empty object as null
12326 result[reference_string] = nullptr;
12327 }
12328 else
12329 {
12330 // iterate object and use keys as reference string
12331 for (const auto& element : *value.m_value.object)
12332 {
12333 flatten(reference_string + "/" + escape(element.first), element.second, result);
12334 }
12335 }
12336 break;
12337 }
12338
12339 default:
12340 {
12341 // add primitive value with its reference string
12342 result[reference_string] = value;
12343 break;
12344 }
12345 }
12346 }
12347
12358 static BasicJsonType
12359 unflatten(const BasicJsonType& value)
12360 {
12361 if (JSON_UNLIKELY(not value.is_object()))
12362 {
12363 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
12364 }
12365
12366 BasicJsonType result;
12367
12368 // iterate the JSON object values
12369 for (const auto& element : *value.m_value.object)
12370 {
12371 if (JSON_UNLIKELY(not element.second.is_primitive()))
12372 {
12373 JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
12374 }
12375
12376 // assign value to reference pointed to by JSON pointer; Note that if
12377 // the JSON pointer is "" (i.e., points to the whole value), function
12378 // get_and_create returns a reference to result itself. An assignment
12379 // will then create a primitive value.
12380 json_pointer(element.first).get_and_create(result) = element.second;
12381 }
12382
12383 return result;
12384 }
12385
12386 friend bool operator==(json_pointer const& lhs,
12387 json_pointer const& rhs) noexcept
12388 {
12389 return (lhs.reference_tokens == rhs.reference_tokens);
12390 }
12391
12392 friend bool operator!=(json_pointer const& lhs,
12393 json_pointer const& rhs) noexcept
12394 {
12395 return not (lhs == rhs);
12396 }
12397
12399 std::vector<std::string> reference_tokens;
12400};
12401} // namespace nlohmann
12402
12403// #include <nlohmann/adl_serializer.hpp>
12404
12405
12406#include <utility>
12407
12408// #include <nlohmann/detail/conversions/from_json.hpp>
12409
12410// #include <nlohmann/detail/conversions/to_json.hpp>
12411
12412
12413namespace nlohmann
12414{
12415
12416template<typename, typename>
12418{
12428 template<typename BasicJsonType, typename ValueType>
12429 static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
12430 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
12431 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
12432 {
12433 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
12434 }
12435
12445 template <typename BasicJsonType, typename ValueType>
12446 static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
12447 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
12448 -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
12449 {
12450 ::nlohmann::to_json(j, std::forward<ValueType>(val));
12451 }
12452};
12453
12454} // namespace nlohmann
12455
12456
12462namespace nlohmann
12463{
12464
12548{
12549 private:
12550 template<detail::value_t> friend struct detail::external_constructor;
12551 friend ::nlohmann::json_pointer<basic_json>;
12552 friend ::nlohmann::detail::parser<basic_json>;
12553 friend ::nlohmann::detail::serializer<basic_json>;
12554 template<typename BasicJsonType>
12555 friend class ::nlohmann::detail::iter_impl;
12556 template<typename BasicJsonType, typename CharType>
12557 friend class ::nlohmann::detail::binary_writer;
12558 template<typename BasicJsonType, typename SAX>
12559 friend class ::nlohmann::detail::binary_reader;
12560 template<typename BasicJsonType>
12561 friend class ::nlohmann::detail::json_sax_dom_parser;
12562 template<typename BasicJsonType>
12563 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
12564
12566 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
12567
12568 // convenience aliases for types residing in namespace detail;
12571
12572 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
12573 template<typename BasicJsonType>
12575 template<typename BasicJsonType>
12577 template<typename Iterator>
12578 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
12579 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
12580
12581 template<typename CharType>
12582 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
12583
12585 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
12586
12588
12589 public:
12593 template<typename T, typename SFINAE>
12594 using json_serializer = JSONSerializer<T, SFINAE>;
12598 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
12599
12603
12605 // exceptions //
12607
12611
12613 using exception = detail::exception;
12624
12626
12627
12629 // container types //
12631
12636
12638 using value_type = basic_json;
12639
12641 using reference = value_type&;
12643 using const_reference = const value_type&;
12644
12646 using difference_type = std::ptrdiff_t;
12648 using size_type = std::size_t;
12649
12651 using allocator_type = AllocatorType<basic_json>;
12652
12654 using pointer = typename std::allocator_traits<allocator_type>::pointer;
12656 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
12657
12659 using iterator = iter_impl<basic_json>;
12661 using const_iterator = iter_impl<const basic_json>;
12663 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
12665 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
12666
12668
12669
12674 {
12675 return allocator_type();
12676 }
12677
12705 {
12706 basic_json result;
12707
12708 result["copyright"] = "(C) 2013-2017 Niels Lohmann";
12709 result["name"] = "JSON for Modern C++";
12710 result["url"] = "https://github.com/nlohmann/json";
12711 result["version"]["string"] =
12712 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
12713 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
12714 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
12715 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
12716 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
12717 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
12718
12719#ifdef _WIN32
12720 result["platform"] = "win32";
12721#elif defined __linux__
12722 result["platform"] = "linux";
12723#elif defined __APPLE__
12724 result["platform"] = "apple";
12725#elif defined __unix__
12726 result["platform"] = "unix";
12727#else
12728 result["platform"] = "unknown";
12729#endif
12730
12731#if defined(__ICC) || defined(__INTEL_COMPILER)
12732 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
12733#elif defined(__clang__)
12734 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
12735#elif defined(__GNUC__) || defined(__GNUG__)
12736 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
12737#elif defined(__HP_cc) || defined(__HP_aCC)
12738 result["compiler"] = "hp"
12739#elif defined(__IBMCPP__)
12740 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
12741#elif defined(_MSC_VER)
12742 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
12743#elif defined(__PGI)
12744 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
12745#elif defined(__SUNPRO_CC)
12746 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
12747#else
12748 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
12749#endif
12750
12751#ifdef __cplusplus
12752 result["compiler"]["c++"] = std::to_string(__cplusplus);
12753#else
12754 result["compiler"]["c++"] = "unknown";
12755#endif
12756 return result;
12757 }
12758
12759
12761 // JSON value data types //
12763
12768
12769#if defined(JSON_HAS_CPP_14)
12770 // Use transparent comparator if possible, combined with perfect forwarding
12771 // on find() and count() calls prevents unnecessary string construction.
12772 using object_comparator_t = std::less<>;
12773#else
12774 using object_comparator_t = std::less<StringType>;
12775#endif
12776
12860 using object_t = ObjectType<StringType,
12861 basic_json,
12862 object_comparator_t,
12863 AllocatorType<std::pair<const StringType,
12864 basic_json>>>;
12865
12911
12963 using string_t = StringType;
12964
12989 using boolean_t = BooleanType;
12990
13061 using number_integer_t = NumberIntegerType;
13062
13132 using number_unsigned_t = NumberUnsignedType;
13133
13200 using number_float_t = NumberFloatType;
13201
13203
13204 private:
13205
13207 template<typename T, typename... Args>
13208 static T* create(Args&& ... args)
13209 {
13210 AllocatorType<T> alloc;
13211 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
13212
13213 auto deleter = [&](T * object)
13214 {
13215 AllocatorTraits::deallocate(alloc, object, 1);
13216 };
13217 std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
13218 AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
13219 assert(object != nullptr);
13220 return object.release();
13221 }
13222
13224 // JSON value storage //
13226
13251 union json_value
13252 {
13254 object_t* object;
13256 array_t* array;
13258 string_t* string;
13260 boolean_t boolean;
13262 number_integer_t number_integer;
13264 number_unsigned_t number_unsigned;
13266 number_float_t number_float;
13267
13269 json_value() = default;
13271 json_value(boolean_t v) noexcept : boolean(v) {}
13273 json_value(number_integer_t v) noexcept : number_integer(v) {}
13275 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
13277 json_value(number_float_t v) noexcept : number_float(v) {}
13279 json_value(value_t t)
13280 {
13281 switch (t)
13282 {
13283 case value_t::object:
13284 {
13285 object = create<object_t>();
13286 break;
13287 }
13288
13289 case value_t::array:
13290 {
13291 array = create<array_t>();
13292 break;
13293 }
13294
13295 case value_t::string:
13296 {
13297 string = create<string_t>("");
13298 break;
13299 }
13300
13301 case value_t::boolean:
13302 {
13303 boolean = boolean_t(false);
13304 break;
13305 }
13306
13307 case value_t::number_integer:
13308 {
13309 number_integer = number_integer_t(0);
13310 break;
13311 }
13312
13313 case value_t::number_unsigned:
13314 {
13315 number_unsigned = number_unsigned_t(0);
13316 break;
13317 }
13318
13319 case value_t::number_float:
13320 {
13321 number_float = number_float_t(0.0);
13322 break;
13323 }
13324
13325 case value_t::null:
13326 {
13327 object = nullptr; // silence warning, see #821
13328 break;
13329 }
13330
13331 default:
13332 {
13333 object = nullptr; // silence warning, see #821
13334 if (JSON_UNLIKELY(t == value_t::null))
13335 {
13336 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.5.0")); // LCOV_EXCL_LINE
13337 }
13338 break;
13339 }
13340 }
13341 }
13342
13344 json_value(const string_t& value)
13345 {
13346 string = create<string_t>(value);
13347 }
13348
13350 json_value(string_t&& value)
13351 {
13352 string = create<string_t>(std::move(value));
13353 }
13354
13356 json_value(const object_t& value)
13357 {
13358 object = create<object_t>(value);
13359 }
13360
13362 json_value(object_t&& value)
13363 {
13364 object = create<object_t>(std::move(value));
13365 }
13366
13368 json_value(const array_t& value)
13369 {
13370 array = create<array_t>(value);
13371 }
13372
13374 json_value(array_t&& value)
13375 {
13376 array = create<array_t>(std::move(value));
13377 }
13378
13379 void destroy(value_t t) noexcept
13380 {
13381 switch (t)
13382 {
13383 case value_t::object:
13384 {
13385 AllocatorType<object_t> alloc;
13386 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
13387 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
13388 break;
13389 }
13390
13391 case value_t::array:
13392 {
13393 AllocatorType<array_t> alloc;
13394 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
13395 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
13396 break;
13397 }
13398
13399 case value_t::string:
13400 {
13401 AllocatorType<string_t> alloc;
13402 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
13403 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
13404 break;
13405 }
13406
13407 default:
13408 {
13409 break;
13410 }
13411 }
13412 }
13413 };
13414
13424 void assert_invariant() const noexcept
13425 {
13426 assert(m_type != value_t::object or m_value.object != nullptr);
13427 assert(m_type != value_t::array or m_value.array != nullptr);
13428 assert(m_type != value_t::string or m_value.string != nullptr);
13429 }
13430
13431 public:
13433 // JSON parser callback //
13435
13452
13503
13505 // constructors //
13507
13512
13542 basic_json(const value_t v)
13543 : m_type(v), m_value(v)
13544 {
13545 assert_invariant();
13546 }
13547
13566 basic_json(std::nullptr_t = nullptr) noexcept
13567 : basic_json(value_t::null)
13568 {
13569 assert_invariant();
13570 }
13571
13629 template <typename CompatibleType,
13630 typename U = detail::uncvref_t<CompatibleType>,
13631 detail::enable_if_t<
13632 not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0>
13633 basic_json(CompatibleType && val) noexcept(noexcept(
13634 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
13635 std::forward<CompatibleType>(val))))
13636 {
13637 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
13638 assert_invariant();
13639 }
13640
13667 template <typename BasicJsonType,
13668 detail::enable_if_t<
13669 detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
13670 basic_json(const BasicJsonType& val)
13671 {
13672 using other_boolean_t = typename BasicJsonType::boolean_t;
13673 using other_number_float_t = typename BasicJsonType::number_float_t;
13674 using other_number_integer_t = typename BasicJsonType::number_integer_t;
13675 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
13676 using other_string_t = typename BasicJsonType::string_t;
13677 using other_object_t = typename BasicJsonType::object_t;
13678 using other_array_t = typename BasicJsonType::array_t;
13679
13680 switch (val.type())
13681 {
13682 case value_t::boolean:
13683 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
13684 break;
13685 case value_t::number_float:
13686 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
13687 break;
13688 case value_t::number_integer:
13689 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
13690 break;
13691 case value_t::number_unsigned:
13692 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
13693 break;
13694 case value_t::string:
13695 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
13696 break;
13697 case value_t::object:
13698 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
13699 break;
13700 case value_t::array:
13701 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
13702 break;
13703 case value_t::null:
13704 *this = nullptr;
13705 break;
13706 case value_t::discarded:
13707 m_type = value_t::discarded;
13708 break;
13709 }
13710 assert_invariant();
13711 }
13712
13787 basic_json(initializer_list_t init,
13788 bool type_deduction = true,
13789 value_t manual_type = value_t::array)
13790 {
13791 // check if each element is an array with two elements whose first
13792 // element is a string
13793 bool is_an_object = std::all_of(init.begin(), init.end(),
13794 [](const detail::json_ref<basic_json>& element_ref)
13795 {
13796 return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
13797 });
13798
13799 // adjust type if type deduction is not wanted
13800 if (not type_deduction)
13801 {
13802 // if array is wanted, do not create an object though possible
13803 if (manual_type == value_t::array)
13804 {
13805 is_an_object = false;
13806 }
13807
13808 // if object is wanted but impossible, throw an exception
13809 if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
13810 {
13811 JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
13812 }
13813 }
13814
13815 if (is_an_object)
13816 {
13817 // the initializer list is a list of pairs -> create object
13818 m_type = value_t::object;
13819 m_value = value_t::object;
13820
13821 std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
13822 {
13823 auto element = element_ref.moved_or_copied();
13824 m_value.object->emplace(
13825 std::move(*((*element.m_value.array)[0].m_value.string)),
13826 std::move((*element.m_value.array)[1]));
13827 });
13828 }
13829 else
13830 {
13831 // the initializer list describes an array -> create array
13832 m_type = value_t::array;
13833 m_value.array = create<array_t>(init.begin(), init.end());
13834 }
13835
13836 assert_invariant();
13837 }
13838
13876 static basic_json array(initializer_list_t init = {})
13877 {
13878 return basic_json(init, false, value_t::array);
13879 }
13880
13919 static basic_json object(initializer_list_t init = {})
13920 {
13921 return basic_json(init, false, value_t::object);
13922 }
13923
13946 basic_json(size_type cnt, const basic_json& val)
13947 : m_type(value_t::array)
13948 {
13949 m_value.array = create<array_t>(cnt, val);
13950 assert_invariant();
13951 }
13952
14008 template<class InputIT, typename std::enable_if<
14009 std::is_same<InputIT, typename basic_json_t::iterator>::value or
14010 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
14011 basic_json(InputIT first, InputIT last)
14012 {
14013 assert(first.m_object != nullptr);
14014 assert(last.m_object != nullptr);
14015
14016 // make sure iterator fits the current value
14017 if (JSON_UNLIKELY(first.m_object != last.m_object))
14018 {
14019 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
14020 }
14021
14022 // copy type from first iterator
14023 m_type = first.m_object->m_type;
14024
14025 // check if iterator range is complete for primitive values
14026 switch (m_type)
14027 {
14028 case value_t::boolean:
14029 case value_t::number_float:
14030 case value_t::number_integer:
14031 case value_t::number_unsigned:
14032 case value_t::string:
14033 {
14034 if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
14035 or not last.m_it.primitive_iterator.is_end()))
14036 {
14037 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
14038 }
14039 break;
14040 }
14041
14042 default:
14043 break;
14044 }
14045
14046 switch (m_type)
14047 {
14048 case value_t::number_integer:
14049 {
14050 m_value.number_integer = first.m_object->m_value.number_integer;
14051 break;
14052 }
14053
14054 case value_t::number_unsigned:
14055 {
14056 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
14057 break;
14058 }
14059
14060 case value_t::number_float:
14061 {
14062 m_value.number_float = first.m_object->m_value.number_float;
14063 break;
14064 }
14065
14066 case value_t::boolean:
14067 {
14068 m_value.boolean = first.m_object->m_value.boolean;
14069 break;
14070 }
14071
14072 case value_t::string:
14073 {
14074 m_value = *first.m_object->m_value.string;
14075 break;
14076 }
14077
14078 case value_t::object:
14079 {
14080 m_value.object = create<object_t>(first.m_it.object_iterator,
14081 last.m_it.object_iterator);
14082 break;
14083 }
14084
14085 case value_t::array:
14086 {
14087 m_value.array = create<array_t>(first.m_it.array_iterator,
14088 last.m_it.array_iterator);
14089 break;
14090 }
14091
14092 default:
14093 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
14094 std::string(first.m_object->type_name())));
14095 }
14096
14097 assert_invariant();
14098 }
14099
14100
14102 // other constructors and destructor //
14104
14106 basic_json(const detail::json_ref<basic_json>& ref)
14107 : basic_json(ref.moved_or_copied())
14108 {}
14109
14135 basic_json(const basic_json& other)
14136 : m_type(other.m_type)
14137 {
14138 // check of passed value is valid
14139 other.assert_invariant();
14140
14141 switch (m_type)
14142 {
14143 case value_t::object:
14144 {
14145 m_value = *other.m_value.object;
14146 break;
14147 }
14148
14149 case value_t::array:
14150 {
14151 m_value = *other.m_value.array;
14152 break;
14153 }
14154
14155 case value_t::string:
14156 {
14157 m_value = *other.m_value.string;
14158 break;
14159 }
14160
14161 case value_t::boolean:
14162 {
14163 m_value = other.m_value.boolean;
14164 break;
14165 }
14166
14167 case value_t::number_integer:
14168 {
14169 m_value = other.m_value.number_integer;
14170 break;
14171 }
14172
14173 case value_t::number_unsigned:
14174 {
14175 m_value = other.m_value.number_unsigned;
14176 break;
14177 }
14178
14179 case value_t::number_float:
14180 {
14181 m_value = other.m_value.number_float;
14182 break;
14183 }
14184
14185 default:
14186 break;
14187 }
14188
14189 assert_invariant();
14190 }
14191
14218 basic_json(basic_json&& other) noexcept
14219 : m_type(std::move(other.m_type)),
14220 m_value(std::move(other.m_value))
14221 {
14222 // check that passed value is valid
14223 other.assert_invariant();
14224
14225 // invalidate payload
14226 other.m_type = value_t::null;
14227 other.m_value = {};
14228
14229 assert_invariant();
14230 }
14231
14255 basic_json& operator=(basic_json other) noexcept (
14256 std::is_nothrow_move_constructible<value_t>::value and
14257 std::is_nothrow_move_assignable<value_t>::value and
14258 std::is_nothrow_move_constructible<json_value>::value and
14259 std::is_nothrow_move_assignable<json_value>::value
14260 )
14261 {
14262 // check that passed value is valid
14263 other.assert_invariant();
14264
14265 using std::swap;
14266 swap(m_type, other.m_type);
14267 swap(m_value, other.m_value);
14268
14269 assert_invariant();
14270 return *this;
14271 }
14272
14288 ~basic_json() noexcept
14289 {
14290 assert_invariant();
14291 m_value.destroy(m_type);
14292 }
14293
14295
14296 public:
14298 // object inspection //
14300
14304
14346 string_t dump(const int indent = -1,
14347 const char indent_char = ' ',
14348 const bool ensure_ascii = false,
14349 const error_handler_t error_handler = error_handler_t::strict) const
14350 {
14351 string_t result;
14352 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
14353
14354 if (indent >= 0)
14355 {
14356 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
14357 }
14358 else
14359 {
14360 s.dump(*this, false, ensure_ascii, 0);
14361 }
14362
14363 return result;
14364 }
14365
14398 constexpr value_t type() const noexcept
14399 {
14400 return m_type;
14401 }
14402
14428 constexpr bool is_primitive() const noexcept
14429 {
14430 return is_null() or is_string() or is_boolean() or is_number();
14431 }
14432
14455 constexpr bool is_structured() const noexcept
14456 {
14457 return is_array() or is_object();
14458 }
14459
14477 constexpr bool is_null() const noexcept
14478 {
14479 return (m_type == value_t::null);
14480 }
14481
14499 constexpr bool is_boolean() const noexcept
14500 {
14501 return (m_type == value_t::boolean);
14502 }
14503
14529 constexpr bool is_number() const noexcept
14530 {
14531 return is_number_integer() or is_number_float();
14532 }
14533
14558 constexpr bool is_number_integer() const noexcept
14559 {
14560 return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
14561 }
14562
14586 constexpr bool is_number_unsigned() const noexcept
14587 {
14588 return (m_type == value_t::number_unsigned);
14589 }
14590
14614 constexpr bool is_number_float() const noexcept
14615 {
14616 return (m_type == value_t::number_float);
14617 }
14618
14636 constexpr bool is_object() const noexcept
14637 {
14638 return (m_type == value_t::object);
14639 }
14640
14658 constexpr bool is_array() const noexcept
14659 {
14660 return (m_type == value_t::array);
14661 }
14662
14680 constexpr bool is_string() const noexcept
14681 {
14682 return (m_type == value_t::string);
14683 }
14684
14707 constexpr bool is_discarded() const noexcept
14708 {
14709 return (m_type == value_t::discarded);
14710 }
14711
14733 constexpr operator value_t() const noexcept
14734 {
14735 return m_type;
14736 }
14737
14739
14740 private:
14742 // value access //
14744
14746 boolean_t get_impl(boolean_t* /*unused*/) const
14747 {
14748 if (JSON_LIKELY(is_boolean()))
14749 {
14750 return m_value.boolean;
14751 }
14752
14753 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
14754 }
14755
14757 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
14758 {
14759 return is_object() ? m_value.object : nullptr;
14760 }
14761
14763 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
14764 {
14765 return is_object() ? m_value.object : nullptr;
14766 }
14767
14769 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
14770 {
14771 return is_array() ? m_value.array : nullptr;
14772 }
14773
14775 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
14776 {
14777 return is_array() ? m_value.array : nullptr;
14778 }
14779
14781 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
14782 {
14783 return is_string() ? m_value.string : nullptr;
14784 }
14785
14787 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
14788 {
14789 return is_string() ? m_value.string : nullptr;
14790 }
14791
14793 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
14794 {
14795 return is_boolean() ? &m_value.boolean : nullptr;
14796 }
14797
14799 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
14800 {
14801 return is_boolean() ? &m_value.boolean : nullptr;
14802 }
14803
14805 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
14806 {
14807 return is_number_integer() ? &m_value.number_integer : nullptr;
14808 }
14809
14811 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
14812 {
14813 return is_number_integer() ? &m_value.number_integer : nullptr;
14814 }
14815
14817 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
14818 {
14819 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
14820 }
14821
14823 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
14824 {
14825 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
14826 }
14827
14829 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
14830 {
14831 return is_number_float() ? &m_value.number_float : nullptr;
14832 }
14833
14835 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
14836 {
14837 return is_number_float() ? &m_value.number_float : nullptr;
14838 }
14839
14851 template<typename ReferenceType, typename ThisType>
14852 static ReferenceType get_ref_impl(ThisType& obj)
14853 {
14854 // delegate the call to get_ptr<>()
14855 auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
14856
14857 if (JSON_LIKELY(ptr != nullptr))
14858 {
14859 return *ptr;
14860 }
14861
14862 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
14863 }
14864
14865 public:
14869
14884 template<typename BasicJsonType, detail::enable_if_t<
14885 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
14886 int> = 0>
14887 basic_json get() const
14888 {
14889 return *this;
14890 }
14891
14907 template<typename BasicJsonType, detail::enable_if_t<
14908 not std::is_same<BasicJsonType, basic_json>::value and
14909 detail::is_basic_json<BasicJsonType>::value, int> = 0>
14910 BasicJsonType get() const
14911 {
14912 return *this;
14913 }
14914
14954 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
14955 detail::enable_if_t <
14956 not detail::is_basic_json<ValueType>::value and
14957 detail::has_from_json<basic_json_t, ValueType>::value and
14958 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
14959 int> = 0>
14960 ValueType get() const noexcept(noexcept(
14961 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
14962 {
14963 // we cannot static_assert on ValueTypeCV being non-const, because
14964 // there is support for get<const basic_json_t>(), which is why we
14965 // still need the uncvref
14966 static_assert(not std::is_reference<ValueTypeCV>::value,
14967 "get() cannot be used with reference types, you might want to use get_ref()");
14968 static_assert(std::is_default_constructible<ValueType>::value,
14969 "types must be DefaultConstructible when used with get()");
14970
14971 ValueType ret;
14972 JSONSerializer<ValueType>::from_json(*this, ret);
14973 return ret;
14974 }
14975
15007 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
15008 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
15009 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
15010 int> = 0>
15011 ValueType get() const noexcept(noexcept(
15012 JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
15013 {
15014 static_assert(not std::is_reference<ValueTypeCV>::value,
15015 "get() cannot be used with reference types, you might want to use get_ref()");
15016 return JSONSerializer<ValueTypeCV>::from_json(*this);
15017 }
15018
15052 template<typename ValueType,
15053 detail::enable_if_t <
15054 not detail::is_basic_json<ValueType>::value and
15055 detail::has_from_json<basic_json_t, ValueType>::value,
15056 int> = 0>
15057 ValueType & get_to(ValueType& v) const noexcept(noexcept(
15058 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
15059 {
15060 JSONSerializer<ValueType>::from_json(*this, v);
15061 return v;
15062 }
15063
15064
15091 template<typename PointerType, typename std::enable_if<
15092 std::is_pointer<PointerType>::value, int>::type = 0>
15093 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
15094 {
15095 // delegate the call to get_impl_ptr<>()
15096 return get_impl_ptr(static_cast<PointerType>(nullptr));
15097 }
15098
15103 template<typename PointerType, typename std::enable_if<
15104 std::is_pointer<PointerType>::value and
15105 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
15106 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
15107 {
15108 // delegate the call to get_impl_ptr<>() const
15109 return get_impl_ptr(static_cast<PointerType>(nullptr));
15110 }
15111
15139 template<typename PointerType, typename std::enable_if<
15140 std::is_pointer<PointerType>::value, int>::type = 0>
15141 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
15142 {
15143 // delegate the call to get_ptr
15144 return get_ptr<PointerType>();
15145 }
15146
15151 template<typename PointerType, typename std::enable_if<
15152 std::is_pointer<PointerType>::value, int>::type = 0>
15153 constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
15154 {
15155 // delegate the call to get_ptr
15156 return get_ptr<PointerType>();
15157 }
15158
15185 template<typename ReferenceType, typename std::enable_if<
15186 std::is_reference<ReferenceType>::value, int>::type = 0>
15187 ReferenceType get_ref()
15188 {
15189 // delegate call to get_ref_impl
15190 return get_ref_impl<ReferenceType>(*this);
15191 }
15192
15197 template<typename ReferenceType, typename std::enable_if<
15198 std::is_reference<ReferenceType>::value and
15199 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
15200 ReferenceType get_ref() const
15201 {
15202 // delegate call to get_ref_impl
15203 return get_ref_impl<ReferenceType>(*this);
15204 }
15205
15235 template < typename ValueType, typename std::enable_if <
15236 not std::is_pointer<ValueType>::value and
15237 not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
15238 not std::is_same<ValueType, typename string_t::value_type>::value and
15239 not detail::is_basic_json<ValueType>::value
15240
15241#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
15242 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
15243#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
15244 and not std::is_same<ValueType, typename std::string_view>::value
15245#endif
15246#endif
15247 and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
15248 , int >::type = 0 >
15249 operator ValueType() const
15250 {
15251 // delegate the call to get<>() const
15252 return get<ValueType>();
15253 }
15254
15256
15257
15259 // element access //
15261
15265
15292 reference at(size_type idx)
15293 {
15294 // at only works for arrays
15295 if (JSON_LIKELY(is_array()))
15296 {
15297 JSON_TRY
15298 {
15299 return m_value.array->at(idx);
15300 }
15301 JSON_CATCH (std::out_of_range&)
15302 {
15303 // create better exception explanation
15304 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
15305 }
15306 }
15307 else
15308 {
15309 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15310 }
15311 }
15312
15339 const_reference at(size_type idx) const
15340 {
15341 // at only works for arrays
15342 if (JSON_LIKELY(is_array()))
15343 {
15344 JSON_TRY
15345 {
15346 return m_value.array->at(idx);
15347 }
15348 JSON_CATCH (std::out_of_range&)
15349 {
15350 // create better exception explanation
15351 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
15352 }
15353 }
15354 else
15355 {
15356 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15357 }
15358 }
15359
15390 reference at(const typename object_t::key_type& key)
15391 {
15392 // at only works for objects
15393 if (JSON_LIKELY(is_object()))
15394 {
15395 JSON_TRY
15396 {
15397 return m_value.object->at(key);
15398 }
15399 JSON_CATCH (std::out_of_range&)
15400 {
15401 // create better exception explanation
15402 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
15403 }
15404 }
15405 else
15406 {
15407 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15408 }
15409 }
15410
15441 const_reference at(const typename object_t::key_type& key) const
15442 {
15443 // at only works for objects
15444 if (JSON_LIKELY(is_object()))
15445 {
15446 JSON_TRY
15447 {
15448 return m_value.object->at(key);
15449 }
15450 JSON_CATCH (std::out_of_range&)
15451 {
15452 // create better exception explanation
15453 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
15454 }
15455 }
15456 else
15457 {
15458 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15459 }
15460 }
15461
15487 reference operator[](size_type idx)
15488 {
15489 // implicitly convert null value to an empty array
15490 if (is_null())
15491 {
15492 m_type = value_t::array;
15493 m_value.array = create<array_t>();
15494 assert_invariant();
15495 }
15496
15497 // operator[] only works for arrays
15498 if (JSON_LIKELY(is_array()))
15499 {
15500 // fill up array with null values if given idx is outside range
15501 if (idx >= m_value.array->size())
15502 {
15503 m_value.array->insert(m_value.array->end(),
15504 idx - m_value.array->size() + 1,
15505 basic_json());
15506 }
15507
15508 return m_value.array->operator[](idx);
15509 }
15510
15511 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
15512 }
15513
15533 const_reference operator[](size_type idx) const
15534 {
15535 // const operator[] only works for arrays
15536 if (JSON_LIKELY(is_array()))
15537 {
15538 return m_value.array->operator[](idx);
15539 }
15540
15541 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
15542 }
15543
15571 reference operator[](const typename object_t::key_type& key)
15572 {
15573 // implicitly convert null value to an empty object
15574 if (is_null())
15575 {
15576 m_type = value_t::object;
15577 m_value.object = create<object_t>();
15578 assert_invariant();
15579 }
15580
15581 // operator[] only works for objects
15582 if (JSON_LIKELY(is_object()))
15583 {
15584 return m_value.object->operator[](key);
15585 }
15586
15587 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15588 }
15589
15620 const_reference operator[](const typename object_t::key_type& key) const
15621 {
15622 // const operator[] only works for objects
15623 if (JSON_LIKELY(is_object()))
15624 {
15625 assert(m_value.object->find(key) != m_value.object->end());
15626 return m_value.object->find(key)->second;
15627 }
15628
15629 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15630 }
15631
15659 template<typename T>
15660 reference operator[](T* key)
15661 {
15662 // implicitly convert null to object
15663 if (is_null())
15664 {
15665 m_type = value_t::object;
15666 m_value = value_t::object;
15667 assert_invariant();
15668 }
15669
15670 // at only works for objects
15671 if (JSON_LIKELY(is_object()))
15672 {
15673 return m_value.object->operator[](key);
15674 }
15675
15676 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15677 }
15678
15709 template<typename T>
15710 const_reference operator[](T* key) const
15711 {
15712 // at only works for objects
15713 if (JSON_LIKELY(is_object()))
15714 {
15715 assert(m_value.object->find(key) != m_value.object->end());
15716 return m_value.object->find(key)->second;
15717 }
15718
15719 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15720 }
15721
15770 template<class ValueType, typename std::enable_if<
15771 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
15772 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
15773 {
15774 // at only works for objects
15775 if (JSON_LIKELY(is_object()))
15776 {
15777 // if key is found, return value and given default value otherwise
15778 const auto it = find(key);
15779 if (it != end())
15780 {
15781 return *it;
15782 }
15783
15784 return default_value;
15785 }
15786
15787 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
15788 }
15789
15794 string_t value(const typename object_t::key_type& key, const char* default_value) const
15795 {
15796 return value(key, string_t(default_value));
15797 }
15798
15840 template<class ValueType, typename std::enable_if<
15841 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
15842 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
15843 {
15844 // at only works for objects
15845 if (JSON_LIKELY(is_object()))
15846 {
15847 // if pointer resolves a value, return it or use default value
15848 JSON_TRY
15849 {
15850 return ptr.get_checked(this);
15851 }
15852 JSON_INTERNAL_CATCH (out_of_range&)
15853 {
15854 return default_value;
15855 }
15856 }
15857
15858 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
15859 }
15860
15865 string_t value(const json_pointer& ptr, const char* default_value) const
15866 {
15867 return value(ptr, string_t(default_value));
15868 }
15869
15895 reference front()
15896 {
15897 return *begin();
15898 }
15899
15903 const_reference front() const
15904 {
15905 return *cbegin();
15906 }
15907
15939 reference back()
15940 {
15941 auto tmp = end();
15942 --tmp;
15943 return *tmp;
15944 }
15945
15949 const_reference back() const
15950 {
15951 auto tmp = cend();
15952 --tmp;
15953 return *tmp;
15954 }
15955
16002 template<class IteratorType, typename std::enable_if<
16003 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
16004 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
16005 = 0>
16006 IteratorType erase(IteratorType pos)
16007 {
16008 // make sure iterator fits the current value
16009 if (JSON_UNLIKELY(this != pos.m_object))
16010 {
16011 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16012 }
16013
16014 IteratorType result = end();
16015
16016 switch (m_type)
16017 {
16018 case value_t::boolean:
16019 case value_t::number_float:
16020 case value_t::number_integer:
16021 case value_t::number_unsigned:
16022 case value_t::string:
16023 {
16024 if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
16025 {
16026 JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
16027 }
16028
16029 if (is_string())
16030 {
16031 AllocatorType<string_t> alloc;
16032 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
16033 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
16034 m_value.string = nullptr;
16035 }
16036
16037 m_type = value_t::null;
16038 assert_invariant();
16039 break;
16040 }
16041
16042 case value_t::object:
16043 {
16044 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
16045 break;
16046 }
16047
16048 case value_t::array:
16049 {
16050 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
16051 break;
16052 }
16053
16054 default:
16055 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16056 }
16057
16058 return result;
16059 }
16060
16107 template<class IteratorType, typename std::enable_if<
16108 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
16109 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
16110 = 0>
16111 IteratorType erase(IteratorType first, IteratorType last)
16112 {
16113 // make sure iterator fits the current value
16114 if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
16115 {
16116 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
16117 }
16118
16119 IteratorType result = end();
16120
16121 switch (m_type)
16122 {
16123 case value_t::boolean:
16124 case value_t::number_float:
16125 case value_t::number_integer:
16126 case value_t::number_unsigned:
16127 case value_t::string:
16128 {
16129 if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
16130 or not last.m_it.primitive_iterator.is_end()))
16131 {
16132 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
16133 }
16134
16135 if (is_string())
16136 {
16137 AllocatorType<string_t> alloc;
16138 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
16139 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
16140 m_value.string = nullptr;
16141 }
16142
16143 m_type = value_t::null;
16144 assert_invariant();
16145 break;
16146 }
16147
16148 case value_t::object:
16149 {
16150 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
16151 last.m_it.object_iterator);
16152 break;
16153 }
16154
16155 case value_t::array:
16156 {
16157 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
16158 last.m_it.array_iterator);
16159 break;
16160 }
16161
16162 default:
16163 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16164 }
16165
16166 return result;
16167 }
16168
16198 size_type erase(const typename object_t::key_type& key)
16199 {
16200 // this erase only works for objects
16201 if (JSON_LIKELY(is_object()))
16202 {
16203 return m_value.object->erase(key);
16204 }
16205
16206 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16207 }
16208
16233 void erase(const size_type idx)
16234 {
16235 // this erase only works for arrays
16236 if (JSON_LIKELY(is_array()))
16237 {
16238 if (JSON_UNLIKELY(idx >= size()))
16239 {
16240 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
16241 }
16242
16243 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
16244 }
16245 else
16246 {
16247 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16248 }
16249 }
16250
16252
16253
16255 // lookup //
16257
16260
16283 template<typename KeyT>
16284 iterator find(KeyT&& key)
16285 {
16286 auto result = end();
16287
16288 if (is_object())
16289 {
16290 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
16291 }
16292
16293 return result;
16294 }
16295
16300 template<typename KeyT>
16301 const_iterator find(KeyT&& key) const
16302 {
16303 auto result = cend();
16304
16305 if (is_object())
16306 {
16307 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
16308 }
16309
16310 return result;
16311 }
16312
16334 template<typename KeyT>
16335 size_type count(KeyT&& key) const
16336 {
16337 // return 0 for all nonobject types
16338 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
16339 }
16340
16342
16343
16345 // iterators //
16347
16350
16375 iterator begin() noexcept
16376 {
16377 iterator result(this);
16378 result.set_begin();
16379 return result;
16380 }
16381
16385 const_iterator begin() const noexcept
16386 {
16387 return cbegin();
16388 }
16389
16415 const_iterator cbegin() const noexcept
16416 {
16417 const_iterator result(this);
16418 result.set_begin();
16419 return result;
16420 }
16421
16446 iterator end() noexcept
16447 {
16448 iterator result(this);
16449 result.set_end();
16450 return result;
16451 }
16452
16456 const_iterator end() const noexcept
16457 {
16458 return cend();
16459 }
16460
16486 const_iterator cend() const noexcept
16487 {
16488 const_iterator result(this);
16489 result.set_end();
16490 return result;
16491 }
16492
16516 reverse_iterator rbegin() noexcept
16517 {
16518 return reverse_iterator(end());
16519 }
16520
16524 const_reverse_iterator rbegin() const noexcept
16525 {
16526 return crbegin();
16527 }
16528
16553 reverse_iterator rend() noexcept
16554 {
16555 return reverse_iterator(begin());
16556 }
16557
16561 const_reverse_iterator rend() const noexcept
16562 {
16563 return crend();
16564 }
16565
16590 const_reverse_iterator crbegin() const noexcept
16591 {
16592 return const_reverse_iterator(cend());
16593 }
16594
16619 const_reverse_iterator crend() const noexcept
16620 {
16621 return const_reverse_iterator(cbegin());
16622 }
16623
16624 public:
16683 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
16684 {
16685 return ref.items();
16686 }
16687
16692 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
16693 {
16694 return ref.items();
16695 }
16696
16760 iteration_proxy<iterator> items() noexcept
16761 {
16762 return iteration_proxy<iterator>(*this);
16763 }
16764
16768 iteration_proxy<const_iterator> items() const noexcept
16769 {
16770 return iteration_proxy<const_iterator>(*this);
16771 }
16772
16774
16775
16777 // capacity //
16779
16782
16824 bool empty() const noexcept
16825 {
16826 switch (m_type)
16827 {
16828 case value_t::null:
16829 {
16830 // null values are empty
16831 return true;
16832 }
16833
16834 case value_t::array:
16835 {
16836 // delegate call to array_t::empty()
16837 return m_value.array->empty();
16838 }
16839
16840 case value_t::object:
16841 {
16842 // delegate call to object_t::empty()
16843 return m_value.object->empty();
16844 }
16845
16846 default:
16847 {
16848 // all other types are nonempty
16849 return false;
16850 }
16851 }
16852 }
16853
16896 size_type size() const noexcept
16897 {
16898 switch (m_type)
16899 {
16900 case value_t::null:
16901 {
16902 // null values are empty
16903 return 0;
16904 }
16905
16906 case value_t::array:
16907 {
16908 // delegate call to array_t::size()
16909 return m_value.array->size();
16910 }
16911
16912 case value_t::object:
16913 {
16914 // delegate call to object_t::size()
16915 return m_value.object->size();
16916 }
16917
16918 default:
16919 {
16920 // all other types have size 1
16921 return 1;
16922 }
16923 }
16924 }
16925
16966 size_type max_size() const noexcept
16967 {
16968 switch (m_type)
16969 {
16970 case value_t::array:
16971 {
16972 // delegate call to array_t::max_size()
16973 return m_value.array->max_size();
16974 }
16975
16976 case value_t::object:
16977 {
16978 // delegate call to object_t::max_size()
16979 return m_value.object->max_size();
16980 }
16981
16982 default:
16983 {
16984 // all other types have max_size() == size()
16985 return size();
16986 }
16987 }
16988 }
16989
16991
16992
16994 // modifiers //
16996
16999
17036 void clear() noexcept
17037 {
17038 switch (m_type)
17039 {
17040 case value_t::number_integer:
17041 {
17042 m_value.number_integer = 0;
17043 break;
17044 }
17045
17046 case value_t::number_unsigned:
17047 {
17048 m_value.number_unsigned = 0;
17049 break;
17050 }
17051
17052 case value_t::number_float:
17053 {
17054 m_value.number_float = 0.0;
17055 break;
17056 }
17057
17058 case value_t::boolean:
17059 {
17060 m_value.boolean = false;
17061 break;
17062 }
17063
17064 case value_t::string:
17065 {
17066 m_value.string->clear();
17067 break;
17068 }
17069
17070 case value_t::array:
17071 {
17072 m_value.array->clear();
17073 break;
17074 }
17075
17076 case value_t::object:
17077 {
17078 m_value.object->clear();
17079 break;
17080 }
17081
17082 default:
17083 break;
17084 }
17085 }
17086
17107 void push_back(basic_json&& val)
17108 {
17109 // push_back only works for null objects or arrays
17110 if (JSON_UNLIKELY(not(is_null() or is_array())))
17111 {
17112 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17113 }
17114
17115 // transform null object into an array
17116 if (is_null())
17117 {
17118 m_type = value_t::array;
17119 m_value = value_t::array;
17120 assert_invariant();
17121 }
17122
17123 // add element to array (move semantics)
17124 m_value.array->push_back(std::move(val));
17125 // invalidate object
17126 val.m_type = value_t::null;
17127 }
17128
17133 reference operator+=(basic_json&& val)
17134 {
17135 push_back(std::move(val));
17136 return *this;
17137 }
17138
17143 void push_back(const basic_json& val)
17144 {
17145 // push_back only works for null objects or arrays
17146 if (JSON_UNLIKELY(not(is_null() or is_array())))
17147 {
17148 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17149 }
17150
17151 // transform null object into an array
17152 if (is_null())
17153 {
17154 m_type = value_t::array;
17155 m_value = value_t::array;
17156 assert_invariant();
17157 }
17158
17159 // add element to array
17160 m_value.array->push_back(val);
17161 }
17162
17167 reference operator+=(const basic_json& val)
17168 {
17169 push_back(val);
17170 return *this;
17171 }
17172
17193 void push_back(const typename object_t::value_type& val)
17194 {
17195 // push_back only works for null objects or objects
17196 if (JSON_UNLIKELY(not(is_null() or is_object())))
17197 {
17198 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17199 }
17200
17201 // transform null object into an object
17202 if (is_null())
17203 {
17204 m_type = value_t::object;
17205 m_value = value_t::object;
17206 assert_invariant();
17207 }
17208
17209 // add element to array
17210 m_value.object->insert(val);
17211 }
17212
17217 reference operator+=(const typename object_t::value_type& val)
17218 {
17219 push_back(val);
17220 return *this;
17221 }
17222
17248 void push_back(initializer_list_t init)
17249 {
17250 if (is_object() and init.size() == 2 and (*init.begin())->is_string())
17251 {
17252 basic_json&& key = init.begin()->moved_or_copied();
17253 push_back(typename object_t::value_type(
17254 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
17255 }
17256 else
17257 {
17258 push_back(basic_json(init));
17259 }
17260 }
17261
17266 reference operator+=(initializer_list_t init)
17267 {
17268 push_back(init);
17269 return *this;
17270 }
17271
17293 template<class... Args>
17294 void emplace_back(Args&& ... args)
17295 {
17296 // emplace_back only works for null objects or arrays
17297 if (JSON_UNLIKELY(not(is_null() or is_array())))
17298 {
17299 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
17300 }
17301
17302 // transform null object into an array
17303 if (is_null())
17304 {
17305 m_type = value_t::array;
17306 m_value = value_t::array;
17307 assert_invariant();
17308 }
17309
17310 // add element to array (perfect forwarding)
17311 m_value.array->emplace_back(std::forward<Args>(args)...);
17312 }
17313
17341 template<class... Args>
17342 std::pair<iterator, bool> emplace(Args&& ... args)
17343 {
17344 // emplace only works for null objects or arrays
17345 if (JSON_UNLIKELY(not(is_null() or is_object())))
17346 {
17347 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
17348 }
17349
17350 // transform null object into an object
17351 if (is_null())
17352 {
17353 m_type = value_t::object;
17354 m_value = value_t::object;
17355 assert_invariant();
17356 }
17357
17358 // add element to array (perfect forwarding)
17359 auto res = m_value.object->emplace(std::forward<Args>(args)...);
17360 // create result iterator and set iterator to the result of emplace
17361 auto it = begin();
17362 it.m_it.object_iterator = res.first;
17363
17364 // return pair of iterator and boolean
17365 return {it, res.second};
17366 }
17367
17371 template<typename... Args>
17372 iterator insert_iterator(const_iterator pos, Args&& ... args)
17373 {
17374 iterator result(this);
17375 assert(m_value.array != nullptr);
17376
17377 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
17378 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
17379 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
17380
17381 // This could have been written as:
17382 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
17383 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
17384
17385 return result;
17386 }
17387
17410 iterator insert(const_iterator pos, const basic_json& val)
17411 {
17412 // insert only works for arrays
17413 if (JSON_LIKELY(is_array()))
17414 {
17415 // check if iterator pos fits to this JSON value
17416 if (JSON_UNLIKELY(pos.m_object != this))
17417 {
17418 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17419 }
17420
17421 // insert to array and return iterator
17422 return insert_iterator(pos, val);
17423 }
17424
17425 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17426 }
17427
17432 iterator insert(const_iterator pos, basic_json&& val)
17433 {
17434 return insert(pos, val);
17435 }
17436
17461 iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
17462 {
17463 // insert only works for arrays
17464 if (JSON_LIKELY(is_array()))
17465 {
17466 // check if iterator pos fits to this JSON value
17467 if (JSON_UNLIKELY(pos.m_object != this))
17468 {
17469 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17470 }
17471
17472 // insert to array and return iterator
17473 return insert_iterator(pos, cnt, val);
17474 }
17475
17476 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17477 }
17478
17509 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
17510 {
17511 // insert only works for arrays
17512 if (JSON_UNLIKELY(not is_array()))
17513 {
17514 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17515 }
17516
17517 // check if iterator pos fits to this JSON value
17518 if (JSON_UNLIKELY(pos.m_object != this))
17519 {
17520 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17521 }
17522
17523 // check if range iterators belong to the same JSON object
17524 if (JSON_UNLIKELY(first.m_object != last.m_object))
17525 {
17526 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17527 }
17528
17529 if (JSON_UNLIKELY(first.m_object == this))
17530 {
17531 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
17532 }
17533
17534 // insert to array and return iterator
17535 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
17536 }
17537
17562 iterator insert(const_iterator pos, initializer_list_t ilist)
17563 {
17564 // insert only works for arrays
17565 if (JSON_UNLIKELY(not is_array()))
17566 {
17567 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17568 }
17569
17570 // check if iterator pos fits to this JSON value
17571 if (JSON_UNLIKELY(pos.m_object != this))
17572 {
17573 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17574 }
17575
17576 // insert to array and return iterator
17577 return insert_iterator(pos, ilist.begin(), ilist.end());
17578 }
17579
17603 void insert(const_iterator first, const_iterator last)
17604 {
17605 // insert only works for objects
17606 if (JSON_UNLIKELY(not is_object()))
17607 {
17608 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17609 }
17610
17611 // check if range iterators belong to the same JSON object
17612 if (JSON_UNLIKELY(first.m_object != last.m_object))
17613 {
17614 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17615 }
17616
17617 // passed iterators must belong to objects
17618 if (JSON_UNLIKELY(not first.m_object->is_object()))
17619 {
17620 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
17621 }
17622
17623 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
17624 }
17625
17645 void update(const_reference j)
17646 {
17647 // implicitly convert null value to an empty object
17648 if (is_null())
17649 {
17650 m_type = value_t::object;
17651 m_value.object = create<object_t>();
17652 assert_invariant();
17653 }
17654
17655 if (JSON_UNLIKELY(not is_object()))
17656 {
17657 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
17658 }
17659 if (JSON_UNLIKELY(not j.is_object()))
17660 {
17661 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
17662 }
17663
17664 for (auto it = j.cbegin(); it != j.cend(); ++it)
17665 {
17666 m_value.object->operator[](it.key()) = it.value();
17667 }
17668 }
17669
17696 void update(const_iterator first, const_iterator last)
17697 {
17698 // implicitly convert null value to an empty object
17699 if (is_null())
17700 {
17701 m_type = value_t::object;
17702 m_value.object = create<object_t>();
17703 assert_invariant();
17704 }
17705
17706 if (JSON_UNLIKELY(not is_object()))
17707 {
17708 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
17709 }
17710
17711 // check if range iterators belong to the same JSON object
17712 if (JSON_UNLIKELY(first.m_object != last.m_object))
17713 {
17714 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17715 }
17716
17717 // passed iterators must belong to objects
17718 if (JSON_UNLIKELY(not first.m_object->is_object()
17719 or not last.m_object->is_object()))
17720 {
17721 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
17722 }
17723
17724 for (auto it = first; it != last; ++it)
17725 {
17726 m_value.object->operator[](it.key()) = it.value();
17727 }
17728 }
17729
17747 void swap(reference other) noexcept (
17748 std::is_nothrow_move_constructible<value_t>::value and
17749 std::is_nothrow_move_assignable<value_t>::value and
17750 std::is_nothrow_move_constructible<json_value>::value and
17751 std::is_nothrow_move_assignable<json_value>::value
17752 )
17753 {
17754 std::swap(m_type, other.m_type);
17755 std::swap(m_value, other.m_value);
17756 assert_invariant();
17757 }
17758
17779 void swap(array_t& other)
17780 {
17781 // swap only works for arrays
17782 if (JSON_LIKELY(is_array()))
17783 {
17784 std::swap(*(m_value.array), other);
17785 }
17786 else
17787 {
17788 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
17789 }
17790 }
17791
17812 void swap(object_t& other)
17813 {
17814 // swap only works for objects
17815 if (JSON_LIKELY(is_object()))
17816 {
17817 std::swap(*(m_value.object), other);
17818 }
17819 else
17820 {
17821 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
17822 }
17823 }
17824
17845 void swap(string_t& other)
17846 {
17847 // swap only works for strings
17848 if (JSON_LIKELY(is_string()))
17849 {
17850 std::swap(*(m_value.string), other);
17851 }
17852 else
17853 {
17854 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
17855 }
17856 }
17857
17859
17860 public:
17862 // lexicographical comparison operators //
17864
17867
17907 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
17908 {
17909 const auto lhs_type = lhs.type();
17910 const auto rhs_type = rhs.type();
17911
17912 if (lhs_type == rhs_type)
17913 {
17914 switch (lhs_type)
17915 {
17916 case value_t::array:
17917 return (*lhs.m_value.array == *rhs.m_value.array);
17918
17919 case value_t::object:
17920 return (*lhs.m_value.object == *rhs.m_value.object);
17921
17922 case value_t::null:
17923 return true;
17924
17925 case value_t::string:
17926 return (*lhs.m_value.string == *rhs.m_value.string);
17927
17928 case value_t::boolean:
17929 return (lhs.m_value.boolean == rhs.m_value.boolean);
17930
17931 case value_t::number_integer:
17932 return (lhs.m_value.number_integer == rhs.m_value.number_integer);
17933
17934 case value_t::number_unsigned:
17935 return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
17936
17937 case value_t::number_float:
17938 return (lhs.m_value.number_float == rhs.m_value.number_float);
17939
17940 default:
17941 return false;
17942 }
17943 }
17944 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
17945 {
17946 return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
17947 }
17948 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
17949 {
17950 return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
17951 }
17952 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
17953 {
17954 return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
17955 }
17956 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
17957 {
17958 return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
17959 }
17960 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
17961 {
17962 return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
17963 }
17964 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
17965 {
17966 return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
17967 }
17968
17969 return false;
17970 }
17971
17976 template<typename ScalarType, typename std::enable_if<
17977 std::is_scalar<ScalarType>::value, int>::type = 0>
17978 friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
17979 {
17980 return (lhs == basic_json(rhs));
17981 }
17982
17987 template<typename ScalarType, typename std::enable_if<
17988 std::is_scalar<ScalarType>::value, int>::type = 0>
17989 friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
17990 {
17991 return (basic_json(lhs) == rhs);
17992 }
17993
18012 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
18013 {
18014 return not (lhs == rhs);
18015 }
18016
18021 template<typename ScalarType, typename std::enable_if<
18022 std::is_scalar<ScalarType>::value, int>::type = 0>
18023 friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
18024 {
18025 return (lhs != basic_json(rhs));
18026 }
18027
18032 template<typename ScalarType, typename std::enable_if<
18033 std::is_scalar<ScalarType>::value, int>::type = 0>
18034 friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
18035 {
18036 return (basic_json(lhs) != rhs);
18037 }
18038
18065 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
18066 {
18067 const auto lhs_type = lhs.type();
18068 const auto rhs_type = rhs.type();
18069
18070 if (lhs_type == rhs_type)
18071 {
18072 switch (lhs_type)
18073 {
18074 case value_t::array:
18075 return (*lhs.m_value.array) < (*rhs.m_value.array);
18076
18077 case value_t::object:
18078 return *lhs.m_value.object < *rhs.m_value.object;
18079
18080 case value_t::null:
18081 return false;
18082
18083 case value_t::string:
18084 return *lhs.m_value.string < *rhs.m_value.string;
18085
18086 case value_t::boolean:
18087 return lhs.m_value.boolean < rhs.m_value.boolean;
18088
18089 case value_t::number_integer:
18090 return lhs.m_value.number_integer < rhs.m_value.number_integer;
18091
18092 case value_t::number_unsigned:
18093 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
18094
18095 case value_t::number_float:
18096 return lhs.m_value.number_float < rhs.m_value.number_float;
18097
18098 default:
18099 return false;
18100 }
18101 }
18102 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
18103 {
18104 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
18105 }
18106 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
18107 {
18108 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
18109 }
18110 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
18111 {
18112 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
18113 }
18114 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
18115 {
18116 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
18117 }
18118 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
18119 {
18120 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
18121 }
18122 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
18123 {
18124 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
18125 }
18126
18127 // We only reach this line if we cannot compare values. In that case,
18128 // we compare types. Note we have to call the operator explicitly,
18129 // because MSVC has problems otherwise.
18130 return operator<(lhs_type, rhs_type);
18131 }
18132
18137 template<typename ScalarType, typename std::enable_if<
18138 std::is_scalar<ScalarType>::value, int>::type = 0>
18139 friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
18140 {
18141 return (lhs < basic_json(rhs));
18142 }
18143
18148 template<typename ScalarType, typename std::enable_if<
18149 std::is_scalar<ScalarType>::value, int>::type = 0>
18150 friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
18151 {
18152 return (basic_json(lhs) < rhs);
18153 }
18154
18174 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
18175 {
18176 return not (rhs < lhs);
18177 }
18178
18183 template<typename ScalarType, typename std::enable_if<
18184 std::is_scalar<ScalarType>::value, int>::type = 0>
18185 friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
18186 {
18187 return (lhs <= basic_json(rhs));
18188 }
18189
18194 template<typename ScalarType, typename std::enable_if<
18195 std::is_scalar<ScalarType>::value, int>::type = 0>
18196 friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
18197 {
18198 return (basic_json(lhs) <= rhs);
18199 }
18200
18220 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
18221 {
18222 return not (lhs <= rhs);
18223 }
18224
18229 template<typename ScalarType, typename std::enable_if<
18230 std::is_scalar<ScalarType>::value, int>::type = 0>
18231 friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
18232 {
18233 return (lhs > basic_json(rhs));
18234 }
18235
18240 template<typename ScalarType, typename std::enable_if<
18241 std::is_scalar<ScalarType>::value, int>::type = 0>
18242 friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
18243 {
18244 return (basic_json(lhs) > rhs);
18245 }
18246
18266 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
18267 {
18268 return not (lhs < rhs);
18269 }
18270
18275 template<typename ScalarType, typename std::enable_if<
18276 std::is_scalar<ScalarType>::value, int>::type = 0>
18277 friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
18278 {
18279 return (lhs >= basic_json(rhs));
18280 }
18281
18286 template<typename ScalarType, typename std::enable_if<
18287 std::is_scalar<ScalarType>::value, int>::type = 0>
18288 friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
18289 {
18290 return (basic_json(lhs) >= rhs);
18291 }
18292
18294
18296 // serialization //
18298
18301
18333 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
18334 {
18335 // read width member and use it as indentation parameter if nonzero
18336 const bool pretty_print = (o.width() > 0);
18337 const auto indentation = (pretty_print ? o.width() : 0);
18338
18339 // reset width to 0 for subsequent calls to this stream
18340 o.width(0);
18341
18342 // do the actual serialization
18343 serializer s(detail::output_adapter<char>(o), o.fill());
18344 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
18345 return o;
18346 }
18347
18357 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
18358 {
18359 return o << j;
18360 }
18361
18363
18364
18366 // deserialization //
18368
18371
18436 static basic_json parse(detail::input_adapter&& i,
18437 const parser_callback_t cb = nullptr,
18438 const bool allow_exceptions = true)
18439 {
18440 basic_json result;
18441 parser(i, cb, allow_exceptions).parse(true, result);
18442 return result;
18443 }
18444
18445 static bool accept(detail::input_adapter&& i)
18446 {
18447 return parser(i).accept(true);
18448 }
18449
18506 template <typename SAX>
18507 static bool sax_parse(detail::input_adapter&& i, SAX* sax,
18508 input_format_t format = input_format_t::json,
18509 const bool strict = true)
18510 {
18511 assert(sax);
18512 switch (format)
18513 {
18514 case input_format_t::json:
18515 return parser(std::move(i)).sax_parse(sax, strict);
18516 default:
18517 return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
18518 }
18519 }
18520
18568 template<class IteratorType, typename std::enable_if<
18569 std::is_base_of<
18570 std::random_access_iterator_tag,
18571 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18572 static basic_json parse(IteratorType first, IteratorType last,
18573 const parser_callback_t cb = nullptr,
18574 const bool allow_exceptions = true)
18575 {
18576 basic_json result;
18577 parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
18578 return result;
18579 }
18580
18581 template<class IteratorType, typename std::enable_if<
18582 std::is_base_of<
18583 std::random_access_iterator_tag,
18584 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18585 static bool accept(IteratorType first, IteratorType last)
18586 {
18587 return parser(detail::input_adapter(first, last)).accept(true);
18588 }
18589
18590 template<class IteratorType, class SAX, typename std::enable_if<
18591 std::is_base_of<
18592 std::random_access_iterator_tag,
18593 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18594 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
18595 {
18596 return parser(detail::input_adapter(first, last)).sax_parse(sax);
18597 }
18598
18608 friend std::istream& operator<<(basic_json& j, std::istream& i)
18609 {
18610 return operator>>(i, j);
18611 }
18612
18638 friend std::istream& operator>>(std::istream& i, basic_json& j)
18639 {
18640 parser(detail::input_adapter(i)).parse(false, j);
18641 return i;
18642 }
18643
18645
18647 // convenience functions //
18649
18680 const char* type_name() const noexcept
18681 {
18682 {
18683 switch (m_type)
18684 {
18685 case value_t::null:
18686 return "null";
18687 case value_t::object:
18688 return "object";
18689 case value_t::array:
18690 return "array";
18691 case value_t::string:
18692 return "string";
18693 case value_t::boolean:
18694 return "boolean";
18695 case value_t::discarded:
18696 return "discarded";
18697 default:
18698 return "number";
18699 }
18700 }
18701 }
18702
18703
18704 private:
18706 // member variables //
18708
18710 value_t m_type = value_t::null;
18711
18713 json_value m_value = {};
18714
18716 // binary serialization/deserialization //
18718
18721
18722 public:
18811 static std::vector<uint8_t> to_cbor(const basic_json& j)
18812 {
18813 std::vector<uint8_t> result;
18814 to_cbor(j, result);
18815 return result;
18816 }
18817
18818 static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
18819 {
18820 binary_writer<uint8_t>(o).write_cbor(j);
18821 }
18822
18823 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
18824 {
18825 binary_writer<char>(o).write_cbor(j);
18826 }
18827
18907 static std::vector<uint8_t> to_msgpack(const basic_json& j)
18908 {
18909 std::vector<uint8_t> result;
18910 to_msgpack(j, result);
18911 return result;
18912 }
18913
18914 static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
18915 {
18916 binary_writer<uint8_t>(o).write_msgpack(j);
18917 }
18918
18919 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
18920 {
18921 binary_writer<char>(o).write_msgpack(j);
18922 }
18923
19004 static std::vector<uint8_t> to_ubjson(const basic_json& j,
19005 const bool use_size = false,
19006 const bool use_type = false)
19007 {
19008 std::vector<uint8_t> result;
19009 to_ubjson(j, result, use_size, use_type);
19010 return result;
19011 }
19012
19013 static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
19014 const bool use_size = false, const bool use_type = false)
19015 {
19016 binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
19017 }
19018
19019 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
19020 const bool use_size = false, const bool use_type = false)
19021 {
19022 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
19023 }
19024
19025
19081 static std::vector<uint8_t> to_bson(const basic_json& j)
19082 {
19083 std::vector<uint8_t> result;
19084 to_bson(j, result);
19085 return result;
19086 }
19087
19096 static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
19097 {
19098 binary_writer<uint8_t>(o).write_bson(j);
19099 }
19100
19104 static void to_bson(const basic_json& j, detail::output_adapter<char> o)
19105 {
19106 binary_writer<char>(o).write_bson(j);
19107 }
19108
19109
19207 static basic_json from_cbor(detail::input_adapter&& i,
19208 const bool strict = true,
19209 const bool allow_exceptions = true)
19210 {
19211 basic_json result;
19212 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19213 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
19214 return res ? result : basic_json(value_t::discarded);
19215 }
19216
19220 template<typename A1, typename A2,
19221 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19222 static basic_json from_cbor(A1 && a1, A2 && a2,
19223 const bool strict = true,
19224 const bool allow_exceptions = true)
19225 {
19226 basic_json result;
19227 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19228 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
19229 return res ? result : basic_json(value_t::discarded);
19230 }
19231
19312 static basic_json from_msgpack(detail::input_adapter&& i,
19313 const bool strict = true,
19314 const bool allow_exceptions = true)
19315 {
19316 basic_json result;
19317 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19318 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
19319 return res ? result : basic_json(value_t::discarded);
19320 }
19321
19325 template<typename A1, typename A2,
19326 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19327 static basic_json from_msgpack(A1 && a1, A2 && a2,
19328 const bool strict = true,
19329 const bool allow_exceptions = true)
19330 {
19331 basic_json result;
19332 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19333 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
19334 return res ? result : basic_json(value_t::discarded);
19335 }
19336
19396 static basic_json from_ubjson(detail::input_adapter&& i,
19397 const bool strict = true,
19398 const bool allow_exceptions = true)
19399 {
19400 basic_json result;
19401 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19402 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
19403 return res ? result : basic_json(value_t::discarded);
19404 }
19405
19409 template<typename A1, typename A2,
19410 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19411 static basic_json from_ubjson(A1 && a1, A2 && a2,
19412 const bool strict = true,
19413 const bool allow_exceptions = true)
19414 {
19415 basic_json result;
19416 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19417 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
19418 return res ? result : basic_json(value_t::discarded);
19419 }
19420
19479 static basic_json from_bson(detail::input_adapter&& i,
19480 const bool strict = true,
19481 const bool allow_exceptions = true)
19482 {
19483 basic_json result;
19484 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19485 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::bson, &sdp, strict);
19486 return res ? result : basic_json(value_t::discarded);
19487 }
19488
19492 template<typename A1, typename A2,
19493 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19494 static basic_json from_bson(A1 && a1, A2 && a2,
19495 const bool strict = true,
19496 const bool allow_exceptions = true)
19497 {
19498 basic_json result;
19499 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19500 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::bson, &sdp, strict);
19501 return res ? result : basic_json(value_t::discarded);
19502 }
19503
19504
19505
19507
19509 // JSON Pointer support //
19511
19514
19548 reference operator[](const json_pointer& ptr)
19549 {
19550 return ptr.get_unchecked(this);
19551 }
19552
19576 const_reference operator[](const json_pointer& ptr) const
19577 {
19578 return ptr.get_unchecked(this);
19579 }
19580
19619 reference at(const json_pointer& ptr)
19620 {
19621 return ptr.get_checked(this);
19622 }
19623
19662 const_reference at(const json_pointer& ptr) const
19663 {
19664 return ptr.get_checked(this);
19665 }
19666
19689 basic_json flatten() const
19690 {
19691 basic_json result(value_t::object);
19692 json_pointer::flatten("", *this, result);
19693 return result;
19694 }
19695
19726 basic_json unflatten() const
19727 {
19728 return json_pointer::unflatten(*this);
19729 }
19730
19732
19734 // JSON Patch functions //
19736
19739
19787 basic_json patch(const basic_json& json_patch) const
19788 {
19789 // make a working copy to apply the patch to
19790 basic_json result = *this;
19791
19792 // the valid JSON Patch operations
19793 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
19794
19795 const auto get_op = [](const std::string & op)
19796 {
19797 if (op == "add")
19798 {
19799 return patch_operations::add;
19800 }
19801 if (op == "remove")
19802 {
19803 return patch_operations::remove;
19804 }
19805 if (op == "replace")
19806 {
19807 return patch_operations::replace;
19808 }
19809 if (op == "move")
19810 {
19811 return patch_operations::move;
19812 }
19813 if (op == "copy")
19814 {
19815 return patch_operations::copy;
19816 }
19817 if (op == "test")
19818 {
19819 return patch_operations::test;
19820 }
19821
19822 return patch_operations::invalid;
19823 };
19824
19825 // wrapper for "add" operation; add value at ptr
19826 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
19827 {
19828 // adding to the root of the target document means replacing it
19829 if (ptr.is_root())
19830 {
19831 result = val;
19832 }
19833 else
19834 {
19835 // make sure the top element of the pointer exists
19836 json_pointer top_pointer = ptr.top();
19837 if (top_pointer != ptr)
19838 {
19839 result.at(top_pointer);
19840 }
19841
19842 // get reference to parent of JSON pointer ptr
19843 const auto last_path = ptr.pop_back();
19844 basic_json& parent = result[ptr];
19845
19846 switch (parent.m_type)
19847 {
19848 case value_t::null:
19849 case value_t::object:
19850 {
19851 // use operator[] to add value
19852 parent[last_path] = val;
19853 break;
19854 }
19855
19856 case value_t::array:
19857 {
19858 if (last_path == "-")
19859 {
19860 // special case: append to back
19861 parent.push_back(val);
19862 }
19863 else
19864 {
19865 const auto idx = json_pointer::array_index(last_path);
19866 if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
19867 {
19868 // avoid undefined behavior
19869 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
19870 }
19871
19872 // default case: insert add offset
19873 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
19874 }
19875 break;
19876 }
19877
19878 // LCOV_EXCL_START
19879 default:
19880 {
19881 // if there exists a parent it cannot be primitive
19882 assert(false);
19883 }
19884 // LCOV_EXCL_STOP
19885 }
19886 }
19887 };
19888
19889 // wrapper for "remove" operation; remove value at ptr
19890 const auto operation_remove = [&result](json_pointer & ptr)
19891 {
19892 // get reference to parent of JSON pointer ptr
19893 const auto last_path = ptr.pop_back();
19894 basic_json& parent = result.at(ptr);
19895
19896 // remove child
19897 if (parent.is_object())
19898 {
19899 // perform range check
19900 auto it = parent.find(last_path);
19901 if (JSON_LIKELY(it != parent.end()))
19902 {
19903 parent.erase(it);
19904 }
19905 else
19906 {
19907 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
19908 }
19909 }
19910 else if (parent.is_array())
19911 {
19912 // note erase performs range check
19913 parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
19914 }
19915 };
19916
19917 // type check: top level value must be an array
19918 if (JSON_UNLIKELY(not json_patch.is_array()))
19919 {
19920 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
19921 }
19922
19923 // iterate and apply the operations
19924 for (const auto& val : json_patch)
19925 {
19926 // wrapper to get a value for an operation
19927 const auto get_value = [&val](const std::string & op,
19928 const std::string & member,
19929 bool string_type) -> basic_json &
19930 {
19931 // find value
19932 auto it = val.m_value.object->find(member);
19933
19934 // context-sensitive error message
19935 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
19936
19937 // check if desired value is present
19938 if (JSON_UNLIKELY(it == val.m_value.object->end()))
19939 {
19940 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
19941 }
19942
19943 // check if result is of type string
19944 if (JSON_UNLIKELY(string_type and not it->second.is_string()))
19945 {
19946 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
19947 }
19948
19949 // no error: return value
19950 return it->second;
19951 };
19952
19953 // type check: every element of the array must be an object
19954 if (JSON_UNLIKELY(not val.is_object()))
19955 {
19956 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
19957 }
19958
19959 // collect mandatory members
19960 const std::string op = get_value("op", "op", true);
19961 const std::string path = get_value(op, "path", true);
19962 json_pointer ptr(path);
19963
19964 switch (get_op(op))
19965 {
19966 case patch_operations::add:
19967 {
19968 operation_add(ptr, get_value("add", "value", false));
19969 break;
19970 }
19971
19972 case patch_operations::remove:
19973 {
19974 operation_remove(ptr);
19975 break;
19976 }
19977
19978 case patch_operations::replace:
19979 {
19980 // the "path" location must exist - use at()
19981 result.at(ptr) = get_value("replace", "value", false);
19982 break;
19983 }
19984
19985 case patch_operations::move:
19986 {
19987 const std::string from_path = get_value("move", "from", true);
19988 json_pointer from_ptr(from_path);
19989
19990 // the "from" location must exist - use at()
19991 basic_json v = result.at(from_ptr);
19992
19993 // The move operation is functionally identical to a
19994 // "remove" operation on the "from" location, followed
19995 // immediately by an "add" operation at the target
19996 // location with the value that was just removed.
19997 operation_remove(from_ptr);
19998 operation_add(ptr, v);
19999 break;
20000 }
20001
20002 case patch_operations::copy:
20003 {
20004 const std::string from_path = get_value("copy", "from", true);
20005 const json_pointer from_ptr(from_path);
20006
20007 // the "from" location must exist - use at()
20008 basic_json v = result.at(from_ptr);
20009
20010 // The copy is functionally identical to an "add"
20011 // operation at the target location using the value
20012 // specified in the "from" member.
20013 operation_add(ptr, v);
20014 break;
20015 }
20016
20017 case patch_operations::test:
20018 {
20019 bool success = false;
20020 JSON_TRY
20021 {
20022 // check if "value" matches the one at "path"
20023 // the "path" location must exist - use at()
20024 success = (result.at(ptr) == get_value("test", "value", false));
20025 }
20026 JSON_INTERNAL_CATCH (out_of_range&)
20027 {
20028 // ignore out of range errors: success remains false
20029 }
20030
20031 // throw an exception if test fails
20032 if (JSON_UNLIKELY(not success))
20033 {
20034 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
20035 }
20036
20037 break;
20038 }
20039
20040 case patch_operations::invalid:
20041 {
20042 // op must be "add", "remove", "replace", "move", "copy", or
20043 // "test"
20044 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
20045 }
20046 }
20047 }
20048
20049 return result;
20050 }
20051
20085 static basic_json diff(const basic_json& source, const basic_json& target,
20086 const std::string& path = "")
20087 {
20088 // the patch
20089 basic_json result(value_t::array);
20090
20091 // if the values are the same, return empty patch
20092 if (source == target)
20093 {
20094 return result;
20095 }
20096
20097 if (source.type() != target.type())
20098 {
20099 // different types: replace value
20100 result.push_back(
20101 {
20102 {"op", "replace"}, {"path", path}, {"value", target}
20103 });
20104 }
20105 else
20106 {
20107 switch (source.type())
20108 {
20109 case value_t::array:
20110 {
20111 // first pass: traverse common elements
20112 std::size_t i = 0;
20113 while (i < source.size() and i < target.size())
20114 {
20115 // recursive call to compare array values at index i
20116 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
20117 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
20118 ++i;
20119 }
20120
20121 // i now reached the end of at least one array
20122 // in a second pass, traverse the remaining elements
20123
20124 // remove my remaining elements
20125 const auto end_index = static_cast<difference_type>(result.size());
20126 while (i < source.size())
20127 {
20128 // add operations in reverse order to avoid invalid
20129 // indices
20130 result.insert(result.begin() + end_index, object(
20131 {
20132 {"op", "remove"},
20133 {"path", path + "/" + std::to_string(i)}
20134 }));
20135 ++i;
20136 }
20137
20138 // add other remaining elements
20139 while (i < target.size())
20140 {
20141 result.push_back(
20142 {
20143 {"op", "add"},
20144 {"path", path + "/" + std::to_string(i)},
20145 {"value", target[i]}
20146 });
20147 ++i;
20148 }
20149
20150 break;
20151 }
20152
20153 case value_t::object:
20154 {
20155 // first pass: traverse this object's elements
20156 for (auto it = source.cbegin(); it != source.cend(); ++it)
20157 {
20158 // escape the key name to be used in a JSON patch
20159 const auto key = json_pointer::escape(it.key());
20160
20161 if (target.find(it.key()) != target.end())
20162 {
20163 // recursive call to compare object values at key it
20164 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
20165 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
20166 }
20167 else
20168 {
20169 // found a key that is not in o -> remove it
20170 result.push_back(object(
20171 {
20172 {"op", "remove"}, {"path", path + "/" + key}
20173 }));
20174 }
20175 }
20176
20177 // second pass: traverse other object's elements
20178 for (auto it = target.cbegin(); it != target.cend(); ++it)
20179 {
20180 if (source.find(it.key()) == source.end())
20181 {
20182 // found a key that is not in this -> add it
20183 const auto key = json_pointer::escape(it.key());
20184 result.push_back(
20185 {
20186 {"op", "add"}, {"path", path + "/" + key},
20187 {"value", it.value()}
20188 });
20189 }
20190 }
20191
20192 break;
20193 }
20194
20195 default:
20196 {
20197 // both primitive type: replace value
20198 result.push_back(
20199 {
20200 {"op", "replace"}, {"path", path}, {"value", target}
20201 });
20202 break;
20203 }
20204 }
20205 }
20206
20207 return result;
20208 }
20209
20211
20213 // JSON Merge Patch functions //
20215
20218
20261 void merge_patch(const basic_json& apply_patch)
20262 {
20263 if (apply_patch.is_object())
20264 {
20265 if (not is_object())
20266 {
20267 *this = object();
20268 }
20269 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
20270 {
20271 if (it.value().is_null())
20272 {
20273 erase(it.key());
20274 }
20275 else
20276 {
20277 operator[](it.key()).merge_patch(it.value());
20278 }
20279 }
20280 }
20281 else
20282 {
20283 *this = apply_patch;
20284 }
20285 }
20286
20288};
20289} // namespace nlohmann
20290
20292// nonmember support //
20294
20295// specialization of std::swap, and std::hash
20296namespace std
20297{
20298
20300template<>
20301struct hash<nlohmann::json>
20302{
20308 std::size_t operator()(const nlohmann::json& j) const
20309 {
20310 // a naive hashing via the string representation
20311 const auto& h = hash<nlohmann::json::string_t>();
20312 return h(j.dump());
20313 }
20314};
20315
20319template<>
20320struct less< ::nlohmann::detail::value_t>
20321{
20326 bool operator()(nlohmann::detail::value_t lhs,
20327 nlohmann::detail::value_t rhs) const noexcept
20328 {
20329 return nlohmann::detail::operator<(lhs, rhs);
20330 }
20331};
20332
20338template<>
20340 is_nothrow_move_constructible<nlohmann::json>::value and
20341 is_nothrow_move_assignable<nlohmann::json>::value
20342)
20343{
20344 j1.swap(j2);
20345}
20346
20347} // namespace std
20348
20362inline nlohmann::json operator "" _json(const char* s, std::size_t n)
20363{
20364 return nlohmann::json::parse(s, s + n);
20365}
20366
20380inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
20381{
20382 return nlohmann::json::json_pointer(std::string(s, n));
20383}
20384
20385// #include <nlohmann/detail/macro_unscope.hpp>
20386
20387
20388// restore GCC/clang diagnostic settings
20389#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
20390 #pragma GCC diagnostic pop
20391#endif
20392#if defined(__clang__)
20393 #pragma GCC diagnostic pop
20394#endif
20395
20396// clean up
20397#undef JSON_INTERNAL_CATCH
20398#undef JSON_CATCH
20399#undef JSON_THROW
20400#undef JSON_TRY
20401#undef JSON_LIKELY
20402#undef JSON_UNLIKELY
20403#undef JSON_DEPRECATED
20404#undef JSON_HAS_CPP_14
20405#undef JSON_HAS_CPP_17
20406#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
20407#undef NLOHMANN_BASIC_JSON_TPL
20408
20409
20410#endif
Env e
Definition Common.cc:2
void split(std::vector< FontInterfaceImpl::Bezier2d > &vec, FontInterfaceImpl::Bezier2d orig, float t, bool emit_left, bool emit_right)
Definition FreeType2.cc:134
bool operator<(const Dep &a1, const Dep &a2)
Definition GameApi_dep_add_find.cc:2905
void update(Point2d mouse, int button, int ch, int type, int mouse_wheel_y)
Definition GameApi_gui.cc:1424
Complex exp(Complex z, int n)
Definition GameApi_pl.cc:31416
std::istream & operator>>(std::istream &i, Point &p)
Definition VectorTools.cc:35
float cs(float x, float m)
Definition VectorTools.cc:1167
PML clear(AK orig)
Definition accel.cc:803
int add(void *w)
Definition ui.cc:341
void * find(int i)
Definition ui.cc:347
std::ostream & operator<<(std::ostream &, Catch_global_namespace_dummy)
Definition Equalizer.hh:245
Definition Expression.hh:105
a class to store JSON values
Definition json.hpp:12548
iter_impl< basic_json > iterator
Definition json.hpp:12659
detail::out_of_range out_of_range
Definition json.hpp:12621
{ * the type of elements in a basic_json container using value_type=basic_json value_type & reference
Definition json.hpp:12641
detail::input_format_t input_format_t
Definition json.hpp:12600
detail::other_error other_error
Definition json.hpp:12623
std::size_t size_type
Definition json.hpp:12648
detail::type_error type_error
Definition json.hpp:12619
const value_type & const_reference
Definition json.hpp:12643
iter_impl< const basic_json > const_iterator
Definition json.hpp:12661
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:12910
BooleanType boolean_t
a type for a boolean
Definition json.hpp:12989
{ using object_comparator_t=std::less< StringType > ObjectType< StringType, basic_json, object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition json.hpp:12860
StringType string_t
a type for a string
Definition json.hpp:12963
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
Definition json.hpp:12598
::nlohmann::json_pointer< basic_json > json_pointer
Definition json.hpp:12592
*static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:12673
***name constructors and destructors *Constructors of class ref basic_json copy move constructor copy static functions creating and the destructor **the value of the current element json_value m_value
Definition json.hpp:18713
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
Definition json.hpp:12665
JSONSerializer< T, SFINAE > json_serializer
Definition json.hpp:12594
AllocatorType< basic_json > allocator_type
Definition json.hpp:12651
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:13200
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:13061
json_sax< basic_json > json_sax_t
Definition json.hpp:12602
typename parser::parse_event_t parse_event_t
parser event types
Definition json.hpp:13451
typename parser::parser_callback_t parser_callback_t
per-element parser callback type
Definition json.hpp:13502
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:13132
detail::invalid_iterator invalid_iterator
Definition json.hpp:12617
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
Definition json.hpp:12663
detail::error_handler_t error_handler_t
Definition json.hpp:12596
detail::value_t value_t
Definition json.hpp:12590
static basic_json meta()
returns version information on the library
Definition json.hpp:12704
typename std::allocator_traits< allocator_type >::pointer pointer
Definition json.hpp:12654
{ * @copydoc detail::exception using exception=detail::exception detail::parse_error parse_error
Definition json.hpp:12615
std::ptrdiff_t difference_type
Definition json.hpp:12646
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
Definition json.hpp:12656
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:6493
static constexpr bool little_endianess(int num=1) noexcept
determine system byte order
Definition json.hpp:6579
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true)
Definition json.hpp:6519
binary_reader(input_adapter_t adapter)
create a binary reader
Definition json.hpp:6506
serialization to CBOR and MessagePack values
Definition json.hpp:8470
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true)
Definition json.hpp:8994
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition json.hpp:9771
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:8479
static CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:9749
void write_bson(const BasicJsonType &j)
Definition json.hpp:8488
void write_cbor(const BasicJsonType &j)
Definition json.hpp:8508
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:9742
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:8752
general exception of the basic_json class
Definition json.hpp:870
const int id
the id of the exception
Definition json.hpp:879
static std::string name(const std::string &ename, int id_)
Definition json.hpp:884
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:873
exception(int id_, const char *what_arg)
Definition json.hpp:882
Definition json.hpp:2199
std::char_traits< char >::int_type get_character() noexcept override
get a character [0,255] or std::char_traits<char>::eof().
Definition json.hpp:2205
file_input_adapter(std::FILE *f) noexcept
Definition json.hpp:2201
input_adapter(std::FILE *file)
Definition json.hpp:2463
input_adapter(const std::wstring &ws)
Definition json.hpp:2473
input_adapter(CharT b, std::size_t l)
input adapter for buffer
Definition json.hpp:2489
input_adapter(const std::u16string &ws)
Definition json.hpp:2476
input_adapter(CharT b)
input adapter for string literal
Definition json.hpp:2501
input_adapter(const ContiguousContainer &c)
input adapter for contiguous container
Definition json.hpp:2553
input_adapter(T(&array)[N])
input adapter for array
Definition json.hpp:2545
input_adapter(const std::u32string &ws)
Definition json.hpp:2479
input_adapter(IteratorType first, IteratorType last)
input adapter for iterator range with contiguous storage
Definition json.hpp:2510
input_adapter(std::istream &i)
input adapter for input stream
Definition json.hpp:2466
input_adapter(std::istream &&i)
input adapter for input stream
Definition json.hpp:2470
input adapter for buffer input
Definition json.hpp:2266
input_buffer_adapter & operator=(input_buffer_adapter &&)=delete
input_buffer_adapter & operator=(input_buffer_adapter &)=delete
input_buffer_adapter(input_buffer_adapter &&)=delete
input_buffer_adapter(const char *b, const std::size_t l) noexcept
Definition json.hpp:2268
input_buffer_adapter(const input_buffer_adapter &)=delete
std::char_traits< char >::int_type get_character() noexcept override
get a character [0,255] or std::char_traits<char>::eof().
Definition json.hpp:2279
input_stream_adapter(input_stream_adapter &&)=delete
~input_stream_adapter() override
Definition json.hpp:2227
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(const input_stream_adapter &)=delete
input_stream_adapter & operator=(input_stream_adapter &&)=delete
input_stream_adapter(std::istream &i)
Definition json.hpp:2234
std::char_traits< char >::int_type get_character() override
get a character [0,255] or std::char_traits<char>::eof().
Definition json.hpp:2247
exception indicating errors with iterators
Definition json.hpp:1028
static invalid_iterator create(int id_, const std::string &what_arg)
Definition json.hpp:1030
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:5634
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:6001
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:6115
iter_impl const operator--(int)
post-decrement (it–)
Definition json.hpp:5922
bool operator==(const iter_impl &other) const
comparison: equal
Definition json.hpp:5965
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:5659
iter_impl()=default
default constructor
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:5933
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:6126
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:5808
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:6046
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:5728
pointer operator->() const
dereference the iterator
Definition json.hpp:5845
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition json.hpp:5665
iter_impl const operator++(int)
post-increment (it++)
Definition json.hpp:5879
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:5719
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition json.hpp:5679
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:6093
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:6104
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:6178
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:6037
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:5657
reference value() const
return the value of an iterator
Definition json.hpp:6194
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:5890
reference operator[](difference_type n) const
access to successor
Definition json.hpp:6147
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:6028
std::bidirectional_iterator_tag iterator_category
Definition json.hpp:5654
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:6055
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition json.hpp:5992
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition json.hpp:5661
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:6084
bool operator!=(const iteration_proxy_value &o) const noexcept
inequality operator (needed for range-based for)
Definition json.hpp:1713
std::input_iterator_tag iterator_category
Definition json.hpp:1674
value_type * pointer
Definition json.hpp:1672
iteration_proxy_value(IteratorType it) noexcept
Definition json.hpp:1689
value_type & reference
Definition json.hpp:1673
iteration_proxy_value value_type
Definition json.hpp:1671
bool operator==(const iteration_proxy_value &o) const noexcept
equality operator (needed for InputIterator)
Definition json.hpp:1707
const std::string & key() const
return key of the iterator
Definition json.hpp:1719
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:1747
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:1698
iteration_proxy_value & operator*()
dereference operator (needed for range-based for)
Definition json.hpp:1692
std::ptrdiff_t difference_type
Definition json.hpp:1670
proxy class for the items() function
Definition json.hpp:1755
iteration_proxy_value< IteratorType > begin() noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:1766
iteration_proxy_value< IteratorType > end() noexcept
return iterator end (needed for range-based for)
Definition json.hpp:1772
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:1762
json_ref & operator=(const json_ref &)=delete
json_ref(const json_ref &)=delete
json_ref(json_ref &&)=default
value_type const & operator*() const
Definition json.hpp:11684
BasicJsonType value_type
Definition json.hpp:11647
json_ref(Args &&... args)
Definition json.hpp:11664
json_ref(const value_type &value)
Definition json.hpp:11653
value_type const * operator->() const
Definition json.hpp:11689
json_ref & operator=(json_ref &&)=delete
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:11657
json_ref(value_type &&value)
Definition json.hpp:11649
value_type moved_or_copied() const
Definition json.hpp:11675
a template for a reverse iterator class
Definition json.hpp:6244
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:6253
json_reverse_iterator const operator--(int)
post-decrement (it–)
Definition json.hpp:6272
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:6250
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:6296
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:6284
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:6248
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:6257
reference operator[](difference_type n) const
access to successor
Definition json.hpp:6308
std::ptrdiff_t difference_type
Definition json.hpp:6246
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:6302
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:6290
json_reverse_iterator const operator++(int)
post-increment (it++)
Definition json.hpp:6260
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:6314
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:6278
reference value() const
return the value of an iterator
Definition json.hpp:6321
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:6266
Definition json.hpp:4874
bool end_array()
Definition json.hpp:4931
typename BasicJsonType::string_t string_t
Definition json.hpp:4879
bool boolean(bool)
Definition json.hpp:4886
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:4876
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:4878
bool key(string_t &)
Definition json.hpp:4916
bool start_object(std::size_t=std::size_t(-1))
Definition json.hpp:4911
bool start_array(std::size_t=std::size_t(-1))
Definition json.hpp:4926
bool end_object()
Definition json.hpp:4921
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:4936
bool number_integer(number_integer_t)
Definition json.hpp:4891
bool string(string_t &)
Definition json.hpp:4906
bool number_unsigned(number_unsigned_t)
Definition json.hpp:4896
bool null()
Definition json.hpp:4881
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:4877
bool number_float(number_float_t, const string_t &)
Definition json.hpp:4901
typename BasicJsonType::string_t string_t
Definition json.hpp:4566
bool start_object(std::size_t len)
Definition json.hpp:4614
bool key(string_t &val)
Definition json.hpp:4636
constexpr bool is_errored() const
Definition json.hpp:4768
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:4564
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:4563
bool null()
Definition json.hpp:4578
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:4567
bool start_array(std::size_t len)
Definition json.hpp:4688
bool number_integer(number_integer_t val)
Definition json.hpp:4590
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:4565
bool end_array()
Definition json.hpp:4709
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:4568
bool parse_error(std::size_t, const std::string &, const detail::exception &ex)
Definition json.hpp:4740
bool boolean(bool val)
Definition json.hpp:4584
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:4596
bool string(string_t &val)
Definition json.hpp:4608
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:4602
bool end_object()
Definition json.hpp:4653
json_sax_dom_callback_parser(BasicJsonType &r, const parser_callback_t cb, const bool allow_exceptions_=true)
Definition json.hpp:4570
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:4386
bool start_array(std::size_t len)
Definition json.hpp:4464
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:4420
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:4388
bool boolean(bool val)
Definition json.hpp:4408
bool parse_error(std::size_t, const std::string &, const detail::exception &ex)
Definition json.hpp:4483
bool string(string_t &val)
Definition json.hpp:4432
bool end_object()
Definition json.hpp:4458
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:4389
bool start_object(std::size_t len)
Definition json.hpp:4438
bool null()
Definition json.hpp:4402
constexpr bool is_errored() const
Definition json.hpp:4511
bool key(string_t &val)
Definition json.hpp:4451
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:4390
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:4426
bool end_array()
Definition json.hpp:4477
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition json.hpp:4398
typename BasicJsonType::string_t string_t
Definition json.hpp:4391
bool number_integer(number_integer_t val)
Definition json.hpp:4414
lexical analysis
Definition json.hpp:2601
lexer & operator=(lexer &&)=delete
lexer(const lexer &)=delete
constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:3948
lexer & operator=(lexer &)=delete
token_type
token types for the parser
Definition json.hpp:2610
@ value_float
an floating point number – use get_number_float() for actual value
Definition json.hpp:2618
@ begin_array
the character for array begin [
Definition json.hpp:2619
@ value_string
a string – use get_string() for actual value
Definition json.hpp:2615
@ end_array
the character for array end ]
Definition json.hpp:2621
@ uninitialized
indicating the scanner is uninitialized
Definition json.hpp:2611
@ parse_error
indicating a parse error
Definition json.hpp:2625
@ value_integer
a signed integer – use get_number_integer() for actual value
Definition json.hpp:2617
@ value_separator
the value separator ,
Definition json.hpp:2624
@ end_object
the character for object end }
Definition json.hpp:2622
@ literal_true
the true literal
Definition json.hpp:2612
@ begin_object
the character for object begin {
Definition json.hpp:2620
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
Definition json.hpp:2616
@ literal_null
the null literal
Definition json.hpp:2614
@ end_of_input
indicating the end of the input buffer
Definition json.hpp:2626
@ name_separator
the name separator :
Definition json.hpp:2623
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
Definition json.hpp:2627
@ literal_false
the false literal
Definition json.hpp:2613
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:3906
std::string get_token_string() const
Definition json.hpp:3924
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:3894
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:3961
lexer(lexer &&)=delete
static const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:2631
token_type scan()
Definition json.hpp:3975
lexer(detail::input_adapter_t &&adapter)
Definition json.hpp:2674
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:3916
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:3900
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:3888
exception indicating other library errors
Definition json.hpp:1164
static other_error create(int id_, const std::string &what_arg)
Definition json.hpp:1166
exception indicating access out of the defined range
Definition json.hpp:1127
static out_of_range create(int id_, const std::string &what_arg)
Definition json.hpp:1129
output_adapter(std::vector< CharType > &vec)
Definition json.hpp:6431
output_adapter(std::basic_ostream< CharType > &s)
Definition json.hpp:6434
output_adapter(StringType &s)
Definition json.hpp:6437
output adapter for output streams
Definition json.hpp:6384
void write_character(CharType c) override
Definition json.hpp:6390
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:6395
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition json.hpp:6386
output adapter for basic_string
Definition json.hpp:6407
void write_character(CharType c) override
Definition json.hpp:6413
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:6418
output_string_adapter(StringType &s) noexcept
Definition json.hpp:6409
output adapter for byte vectors
Definition json.hpp:6361
output_vector_adapter(std::vector< CharType > &vec) noexcept
Definition json.hpp:6363
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:6372
void write_character(CharType c) override
Definition json.hpp:6367
exception indicating a parse error
Definition json.hpp:939
static parse_error create(int id_, const position_t &pos, const std::string &what_arg)
create a parse error exception
Definition json.hpp:950
const std::size_t byte
byte index of the parse error
Definition json.hpp:974
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg)
Definition json.hpp:957
syntax analysis
Definition json.hpp:4965
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:5013
bool sax_parse(SAX *sax, const bool strict=true)
Definition json.hpp:5081
parser(detail::input_adapter_t &&adapter, const parser_callback_t cb=nullptr, const bool allow_exceptions_=true)
a parser reading from an input adapter
Definition json.hpp:4994
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:5074
parse_event_t
Definition json.hpp:4975
@ key
the parser read a key of a value in an object
Definition json.hpp:4985
@ array_end
the parser read ] and finished processing a JSON array
Definition json.hpp:4983
@ array_start
the parser read [ and started to process a JSON array
Definition json.hpp:4981
@ object_start
the parser read { and started to process a JSON object
Definition json.hpp:4977
@ object_end
the parser read } and finished processing a JSON object
Definition json.hpp:4979
std::function< bool(int depth, parse_event_t event, BasicJsonType &parsed)> parser_callback_t
Definition json.hpp:4990
primitive_iterator_t operator+(difference_type n) noexcept
Definition json.hpp:5507
primitive_iterator_t & operator++() noexcept
Definition json.hpp:5519
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:5492
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition json.hpp:5551
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:5486
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:5502
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:5474
primitive_iterator_t const operator++(int) noexcept
Definition json.hpp:5525
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:5497
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:5514
primitive_iterator_t & operator--() noexcept
Definition json.hpp:5532
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:5480
constexpr difference_type get_value() const noexcept
Definition json.hpp:5468
primitive_iterator_t const operator--(int) noexcept
Definition json.hpp:5538
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition json.hpp:5545
Definition json.hpp:10929
serializer(serializer &&)=delete
serializer & operator=(serializer &&)=delete
serializer & operator=(const serializer &)=delete
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.hpp:10978
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:10943
serializer(const serializer &)=delete
exception indicating executing a member function with a wrong type
Definition json.hpp:1081
static type_error create(int id_, const std::string &what_arg)
Definition json.hpp:1083
std::char_traits< char >::int_type get_character() noexcept override
get a character [0,255] or std::char_traits<char>::eof().
Definition json.hpp:2420
wide_string_input_adapter(const WideStringType &w) noexcept
Definition json.hpp:2416
JSON Pointer.
Definition json.hpp:11721
std::string to_string() const
return a string representation of the JSON pointer
Definition json.hpp:11767
friend bool operator==(json_pointer const &lhs, json_pointer const &rhs) noexcept
Definition json.hpp:12386
friend bool operator!=(json_pointer const &lhs, json_pointer const &rhs) noexcept
Definition json.hpp:12392
json_pointer(const std::string &s="")
create JSON pointer
Definition json.hpp:11748
friend class basic_json
Definition json.hpp:11724
decltype( get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:1810
Definition memory_leak_test.cpp:32
std::string decode(std::string s)
Definition test.cpp:351
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:240
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:35
#define JSON_LIKELY(x)
Definition json.hpp:194
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:166
#define JSON_DEPRECATED
Definition json.hpp:153
#define JSON_CATCH(exception)
Definition json.hpp:165
#define JSON_THROW(exception)
Definition json.hpp:163
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:33
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:248
#define JSON_TRY
Definition json.hpp:164
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:34
#define JSON_UNLIKELY(x)
Definition json.hpp:195
ret($return)
Definition mesh_login_result.php:5
d
Definition meshpage.php:3895
iVBORw0KGgoAAAANSUhEUgAAANcAAAB5CAMAAACdtUQZAAAA51BMVEX</div ></div >< div style="padding: 0px 0px; width: 1324px;">< div style="height: 400px; width: 1324px;"></div >< div itemscope itemtype="https: </div><div itemscope itemtype="https:</div >< div itemscope itemtype="https: </div></div><p><div style="padding:0px 0px;width:1324px;"><div></div><div itemscope itemtype="https:< ul >< li >< b > Application name
8AkrcAgqgAs9wqQ0ey2tkAo8gAuuQfeI4hPUH09fXHy8z4+fng4uNKXF/Lz9BzfoAcgpkQMTUAKjAbOT4Qr9AXhJ8Rl7ktMCwTosA...
Definition meshpage.php:1610
str
Definition meshpage.php:1778
instead of< li > Displaying models works via URL t expect full length movie as the output of this process< li > Different animation models are very limited basically just translate rotate</ul >< h2 > What to do if your hosting location has no php</h2 >< ul >< li > comment out or remove display php lines at the beginning< li > you will lose threads too< li > every zip file distributed by meshpage org has one of those display php files with this issue</ul >< h2 > What should I do to serve the files via http</h2 > I get some random triangles that do not belong to the model</h2 > The engine works correctly The obj file supports quads and polygons But some external tools that create obj files insert random polygons to the file to discourage rendering of polygons We consider polygon rendering is important and our engine should support it by default If you have we have disable_polygons() feature in the engine to get rid of the trash. But real solution is to change the tool you use to create the .obj file/check the .obj file that it doesn 't contain random(invisible) polygons that do not render in competing 3d engines. Our engine does not have the performance problems normally associated with polygons given that triangle quad polygon type change does not cause additional draw commands to the opengl rendering< p > GLTF standard organisation made significant mistake when specifying GLTF file format
Definition meshpage.php:1092
n< br > font size
Definition meshpage.php:3536
auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &
not_this_one end(...)
not_this_one begin(...)
size_t count(const T &t_target, const typename T::key_type &t_key)
Definition bootstrap_stl.hpp:104
void insert(T &t_target, const T &t_other)
Definition bootstrap_stl.hpp:110
void string_type(const std::string &type, Module &m)
Definition bootstrap_stl.hpp:643
void array(const std::string &type, Module &m)
Definition bootstrap.hpp:23
void swap(draco::PseudoPointD< internal_t > &&a, draco::PseudoPointD< internal_t > &&b) noexcept
Definition point_d_vector.h:84
Definition json.hpp:24
implements the Grisu2 algorithm for binary to decimal floating-point conversion.
Definition json.hpp:9838
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:10622
Target reinterpret_bits(const Source source)
Definition json.hpp:9841
boundaries compute_boundaries(FloatType value)
Definition json.hpp:9982
int find_largest_pow10(const uint32_t n, uint32_t &pow10)
Definition json.hpp:10285
constexpr int kGamma
Definition json.hpp:10105
char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition json.hpp:10769
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:10382
void grisu2_round(char *buf, int len, uint64_t dist, uint64_t delta, uint64_t rest, uint64_t ten_k)
Definition json.hpp:10341
constexpr int kAlpha
Definition json.hpp:10104
char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:10719
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:10121
detail namespace with internal helper functions
Definition json.hpp:263
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:437
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:1241
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:449
decltype(std::declval< T & >().number_float( std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition json.hpp:4124
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:1998
value_t
the JSON type enumeration
Definition json.hpp:1219
@ null
null value
Definition json.hpp:1220
@ number_integer
number value (signed integer)
Definition json.hpp:1225
@ boolean
boolean value
Definition json.hpp:1224
@ discarded
discarded by the the parser callback function
Definition json.hpp:1228
@ object
object (unordered set of name/value pairs)
Definition json.hpp:1221
@ string
string value
Definition json.hpp:1223
@ number_float
number value (floating-point)
Definition json.hpp:1227
@ number_unsigned
number value (unsigned integer)
Definition json.hpp:1226
@ array
array (ordered collection of values)
Definition json.hpp:1222
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition json.hpp:1288
void from_json_tuple_impl(const BasicJsonType &j, Tuple &t, index_sequence< Idx... >)
Definition json.hpp:1563
typename T::iterator iterator_t
Definition json.hpp:516
constexpr T static_const< T >::value
Definition json.hpp:314
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition json.hpp:4116
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition json.hpp:1421
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition json.hpp:4128
typename T::iterator_category iterator_category_t
Definition json.hpp:513
typename T::difference_type difference_type_t
Definition json.hpp:504
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:2115
std::shared_ptr< input_adapter_protocol > input_adapter_t
a type to simplify interfaces
Definition json.hpp:2192
error_handler_t
Definition json.hpp:10921
@ strict
throw a type_error exception in case of invalid UTF-8
Definition json.hpp:10922
@ ignore
ignore invalid UTF-8 sequences
Definition json.hpp:10924
@ replace
replace invalid UTF-8 sequences with U+FFFD
Definition json.hpp:10923
typename T::value_type value_type_t
Definition json.hpp:501
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:269
typename make_void< Ts... >::type void_t
Definition json.hpp:344
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:300
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition json.hpp:4136
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:522
typename T::pointer pointer_t
Definition json.hpp:507
typename T::mapped_type mapped_type_t
Definition json.hpp:495
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition json.hpp:1302
typename T::reference reference_t
Definition json.hpp:510
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:525
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:519
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition json.hpp:4143
input_format_t
the supported input formats
Definition json.hpp:2167
@ bson
Definition json.hpp:2167
@ ubjson
Definition json.hpp:2167
@ cbor
Definition json.hpp:2167
@ msgpack
Definition json.hpp:2167
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition json.hpp:4120
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition json.hpp:4132
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:440
char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition json.hpp:10852
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition json.hpp:4140
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:452
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:1781
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:266
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition json.hpp:4147
decltype(std::declval< T & >().null()) null_function_t
Definition json.hpp:4109
typename T::key_type key_type_t
Definition json.hpp:498
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:6356
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:446
detector< Default, void, Op, Args... > detected_or
Definition json.hpp:443
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition json.hpp:4112
decltype(std::declval< T & >().parse_error( std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition json.hpp:4150
namespace for Niels Lohmann
Definition json.hpp:66
basic_json<> json
default JSON class
Definition json.hpp:111
STL namespace.
*specialization for std::less< value_t > *see nlohmann::detail::value_t rhs const noexcept
Definition json.hpp:20328
void swap< nlohmann::json >(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value and is_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
Definition json.hpp:20339
double f(const std::string &, double, bool) noexcept
Definition profile_cpp_calls_2.cpp:4
std::string to_string(int val)
Definition Parser.cc:71
bool is_number(std::string s)
Definition Parser.cc:2943
bool operator==(const short_alloc< T, N, A1 > &x, const short_alloc< U, M, A2 > &y) noexcept
Definition short_alloc.hpp:145
bool operator!=(const short_alloc< T, N, A1 > &x, const short_alloc< U, M, A2 > &y) noexcept
Definition short_alloc.hpp:153
Definition test.cpp:82
Definition GameApi.h:30
Definition GameApi.h:43
Definition GameApi.h:32
Definition GameApi.h:56
Definition GameApi.h:70
Definition GameApi.h:42
Definition GameApi.h:17
default JSONSerializer template argument
Definition json.hpp:12418
static auto to_json(BasicJsonType &j, ValueType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< ValueType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< ValueType >(val)), void())
convert any value type to a JSON value
Definition json.hpp:12446
static auto from_json(BasicJsonType &&j, ValueType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.hpp:12429
Definition json.hpp:424
Default type
Definition json.hpp:426
std::false_type value_t
Definition json.hpp:425
diyfp plus
Definition json.hpp:9972
diyfp w
Definition json.hpp:9970
diyfp minus
Definition json.hpp:9971
uint64_t f
Definition json.hpp:10109
int k
Definition json.hpp:10111
int e
Definition json.hpp:10110
Definition json.hpp:9851
static constexpr int kPrecision
Definition json.hpp:9852
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:9940
constexpr diyfp(uint64_t f_, int e_) noexcept
Definition json.hpp:9857
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.hpp:9957
uint64_t f
Definition json.hpp:9854
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:9875
int e
Definition json.hpp:9855
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:9863
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:1926
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:1950
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:1936
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:1916
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:1908
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:1830
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:1872
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:1896
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:1884
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:1972
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:1964
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:1981
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:1850
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:1860
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:1842
Definition json.hpp:1613
auto operator()(const BasicJsonType &j, T &val) const noexcept(noexcept(from_json(j, val))) -> decltype(from_json(j, val), void())
Definition json.hpp:1615
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:535
Definition json.hpp:529
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:550
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:565
Definition json.hpp:560
Definition json.hpp:275
std::size_t value_type
Definition json.hpp:277
index_sequence type
Definition json.hpp:276
static constexpr std::size_t size() noexcept
Definition json.hpp:278
abstract input adapter interface
Definition json.hpp:2185
virtual std::char_traits< char >::int_type get_character()=0
get a character [0,255] or std::char_traits<char>::eof().
an iterator value
Definition json.hpp:5577
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:5583
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:5581
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:5579
Definition json.hpp:485
Definition json.hpp:598
static constexpr auto value
Definition json.hpp:587
Definition json.hpp:4156
static constexpr bool value
Definition json.hpp:4168
std::random_access_iterator_tag iterator_category
Definition json.hpp:387
Definition json.hpp:375
Definition json.hpp:356
Definition json.hpp:341
void type
Definition json.hpp:342
Definition json.hpp:412
nonesuch(nonesuch const &)=delete
void operator=(nonesuch const &)=delete
abstract output adapter interface
Definition json.hpp:6348
virtual void write_characters(const CharType *s, std::size_t length)=0
virtual void write_character(CharType c)=0
struct to capture the start position of the current token
Definition json.hpp:814
std::size_t lines_read
the number of lines read
Definition json.hpp:820
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:818
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:816
Definition json.hpp:303
Definition json.hpp:309
static constexpr T value
Definition json.hpp:310
Definition json.hpp:2127
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.hpp:2129
static void fill_buffer(const WideStringType &str, size_t &current_wchar, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:2355
static void fill_buffer(const WideStringType &str, size_t &current_wchar, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:2300
SAX interface.
Definition json.hpp:4265
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool string(string_t &val)=0
a string was read
virtual bool null()=0
a null value was read
typename BasicJsonType::number_integer_t number_integer_t
type for (signed) integers
Definition json.hpp:4267
virtual bool end_array()=0
the end of an array was read
virtual bool key(string_t &val)=0
an object key was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
type for unsigned integers
Definition json.hpp:4269
typename BasicJsonType::number_float_t number_float_t
type for floating-point numbers
Definition json.hpp:4271
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
typename BasicJsonType::string_t string_t
type for strings
Definition json.hpp:4273
virtual bool number_float(number_float_t val, const string_t &s)=0
an floating-point number was read
virtual ~json_sax()=default
virtual bool number_integer(number_integer_t val)=0
an integer number was read
std::size_t operator()(const nlohmann::json &j) const
return a hash value for a JSON object
Definition json.hpp:20308
W empty()
Definition ui.cc:634
num
Definition view.php:2821