RavEngine
Loading...
Searching...
No Matches
json.hpp
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
49// #include <nlohmann/json_fwd.hpp>
50#ifndef NLOHMANN_JSON_FWD_HPP
51#define NLOHMANN_JSON_FWD_HPP
52
53#include <cstdint> // int64_t, uint64_t
54#include <map> // map
55#include <memory> // allocator
56#include <string> // string
57#include <vector> // vector
58
64namespace nlohmann
65{
73template<typename T = void, typename SFINAE = void>
74struct adl_serializer;
75
76template<template<typename U, typename V, typename... Args> class ObjectType =
77 std::map,
78 template<typename U, typename... Args> class ArrayType = std::vector,
79 class StringType = std::string, class BooleanType = bool,
80 class NumberIntegerType = std::int64_t,
81 class NumberUnsignedType = std::uint64_t,
82 class NumberFloatType = double,
83 template<typename U> class AllocatorType = std::allocator,
84 template<typename T, typename SFINAE = void> class JSONSerializer =
86class basic_json;
87
99template<typename BasicJsonType>
100class json_pointer;
101
111} // namespace nlohmann
112
113#endif
114
115// #include <nlohmann/detail/macro_scope.hpp>
116
117
118// This file contains all internal macro definitions
119// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
120
121// exclude unsupported compilers
122#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
123 #if defined(__clang__)
124 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
125 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
126 #endif
127 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
128 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
129 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
130 #endif
131 #endif
132#endif
133
134// disable float-equal warnings on GCC/clang
135#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
136 #pragma GCC diagnostic push
137 #pragma GCC diagnostic ignored "-Wfloat-equal"
138#endif
139
140// disable documentation warnings on clang
141#if defined(__clang__)
142 #pragma GCC diagnostic push
143 #pragma GCC diagnostic ignored "-Wdocumentation"
144#endif
145
146// allow for portable deprecation warnings
147#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
148 #define JSON_DEPRECATED __attribute__((deprecated))
149#elif defined(_MSC_VER)
150 #define JSON_DEPRECATED __declspec(deprecated)
151#else
152 #define JSON_DEPRECATED
153#endif
154
155// allow to disable exceptions
156#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
157 #define JSON_THROW(exception) throw exception
158 #define JSON_TRY try
159 #define JSON_CATCH(exception) catch(exception)
160 #define JSON_INTERNAL_CATCH(exception) catch(exception)
161#else
162 #define JSON_THROW(exception) std::abort()
163 #define JSON_TRY if(true)
164 #define JSON_CATCH(exception) if(false)
165 #define JSON_INTERNAL_CATCH(exception) if(false)
166#endif
167
168// override exception macros
169#if defined(JSON_THROW_USER)
170 #undef JSON_THROW
171 #define JSON_THROW JSON_THROW_USER
172#endif
173#if defined(JSON_TRY_USER)
174 #undef JSON_TRY
175 #define JSON_TRY JSON_TRY_USER
176#endif
177#if defined(JSON_CATCH_USER)
178 #undef JSON_CATCH
179 #define JSON_CATCH JSON_CATCH_USER
180 #undef JSON_INTERNAL_CATCH
181 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
182#endif
183#if defined(JSON_INTERNAL_CATCH_USER)
184 #undef JSON_INTERNAL_CATCH
185 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
186#endif
187
188// manual branch prediction
189#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
190 #define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
191 #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
192#else
193 #define JSON_LIKELY(x) x
194 #define JSON_UNLIKELY(x) x
195#endif
196
197// C++ language standard detection
198#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
199 #define JSON_HAS_CPP_17
200 #define JSON_HAS_CPP_14
201#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
202 #define JSON_HAS_CPP_14
203#endif
204
210#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
211 template<typename BasicJsonType> \
212 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
213 { \
214 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
215 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
216 auto it = std::find_if(std::begin(m), std::end(m), \
217 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
218 { \
219 return ej_pair.first == e; \
220 }); \
221 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
222 } \
223 template<typename BasicJsonType> \
224 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
225 { \
226 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
227 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
228 auto it = std::find_if(std::begin(m), std::end(m), \
229 [j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
230 { \
231 return ej_pair.second == j; \
232 }); \
233 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
234 }
235
236// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
237// may be removed in the future once the class is split.
238
239#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
240 template<template<typename, typename, typename...> class ObjectType, \
241 template<typename, typename...> class ArrayType, \
242 class StringType, class BooleanType, class NumberIntegerType, \
243 class NumberUnsignedType, class NumberFloatType, \
244 template<typename> class AllocatorType, \
245 template<typename, typename = void> class JSONSerializer>
246
247#define NLOHMANN_BASIC_JSON_TPL \
248 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
249 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
250 AllocatorType, JSONSerializer>
251
252// #include <nlohmann/detail/meta/cpp_future.hpp>
253
254
255#include <ciso646> // not
256#include <cstddef> // size_t
257#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
258
259namespace nlohmann
260{
261namespace detail
262{
263// alias templates to reduce boilerplate
264template<bool B, typename T = void>
265using enable_if_t = typename std::enable_if<B, T>::type;
266
267template<typename T>
268using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
269
270// implementation of C++14 index_sequence and affiliates
271// source: https://stackoverflow.com/a/32223343
272template<std::size_t... Ints>
274{
275 using type = index_sequence;
276 using value_type = std::size_t;
277 static constexpr std::size_t size() noexcept
278 {
279 return sizeof...(Ints);
280 }
281};
282
283template<class Sequence1, class Sequence2>
285
286template<std::size_t... I1, std::size_t... I2>
288 : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
289
290template<std::size_t N>
292 : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
293 typename make_index_sequence < N - N / 2 >::type > {};
294
295template<> struct make_index_sequence<0> : index_sequence<> {};
296template<> struct make_index_sequence<1> : index_sequence<0> {};
297
298template<typename... Ts>
299using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
300
301// dispatch utility (taken from ranges-v3)
302template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
303template<> struct priority_tag<0> {};
304
305// taken from ranges-v3
306template<typename T>
308{
309 static constexpr T value{};
310};
311
312template<typename T>
313constexpr T static_const<T>::value;
314} // namespace detail
315} // namespace nlohmann
316
317// #include <nlohmann/detail/meta/type_traits.hpp>
318
319
320#include <ciso646> // not
321#include <limits> // numeric_limits
322#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
323#include <utility> // declval
324
325// #include <nlohmann/json_fwd.hpp>
326
327// #include <nlohmann/detail/iterators/iterator_traits.hpp>
328
329
330#include <iterator> // random_access_iterator_tag
331
332// #include <nlohmann/detail/meta/void_t.hpp>
333
334
335namespace nlohmann
336{
337namespace detail
338{
339template <typename ...Ts> struct make_void
340{
341 using type = void;
342};
343template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
344} // namespace detail
345} // namespace nlohmann
346
347// #include <nlohmann/detail/meta/cpp_future.hpp>
348
349
350namespace nlohmann
351{
352namespace detail
353{
354template <typename It, typename = void>
356
357template <typename It>
359 It,
360 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
361 typename It::reference, typename It::iterator_category >>
362{
363 using difference_type = typename It::difference_type;
364 using value_type = typename It::value_type;
365 using pointer = typename It::pointer;
366 using reference = typename It::reference;
367 using iterator_category = typename It::iterator_category;
368};
369
370// This is required as some compilers implement std::iterator_traits in a way that
371// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
372template <typename T, typename = void>
374{
375};
376
377template <typename T>
378struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
379 : iterator_types<T>
380{
381};
382
383template <typename T>
384struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
385{
386 using iterator_category = std::random_access_iterator_tag;
387 using value_type = T;
388 using difference_type = ptrdiff_t;
389 using pointer = T*;
390 using reference = T&;
391};
392}
393}
394
395// #include <nlohmann/detail/meta/cpp_future.hpp>
396
397// #include <nlohmann/detail/meta/detected.hpp>
398
399
400#include <type_traits>
401
402// #include <nlohmann/detail/meta/void_t.hpp>
403
404
405// http://en.cppreference.com/w/cpp/experimental/is_detected
406namespace nlohmann
407{
408namespace detail
409{
411{
412 nonesuch() = delete;
413 ~nonesuch() = delete;
414 nonesuch(nonesuch const&) = delete;
415 void operator=(nonesuch const&) = delete;
416};
417
418template <class Default,
419 class AlwaysVoid,
420 template <class...> class Op,
421 class... Args>
423{
424 using value_t = std::false_type;
425 using type = Default;
426};
427
428template <class Default, template <class...> class Op, class... Args>
429struct detector<Default, void_t<Op<Args...>>, Op, Args...>
430{
431 using value_t = std::true_type;
432 using type = Op<Args...>;
433};
434
435template <template <class...> class Op, class... Args>
436using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
437
438template <template <class...> class Op, class... Args>
439using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
440
441template <class Default, template <class...> class Op, class... Args>
442using detected_or = detector<Default, void, Op, Args...>;
443
444template <class Default, template <class...> class Op, class... Args>
445using detected_or_t = typename detected_or<Default, Op, Args...>::type;
446
447template <class Expected, template <class...> class Op, class... Args>
448using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
449
450template <class To, template <class...> class Op, class... Args>
451using is_detected_convertible =
452 std::is_convertible<detected_t<Op, Args...>, To>;
453} // namespace detail
454} // namespace nlohmann
455
456// #include <nlohmann/detail/macro_scope.hpp>
457
458
459namespace nlohmann
460{
469namespace detail
470{
472// helpers //
474
475// Note to maintainers:
476//
477// Every trait in this file expects a non CV-qualified type.
478// The only exceptions are in the 'aliases for detected' section
479// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
480//
481// In this case, T has to be properly CV-qualified to constraint the function arguments
482// (e.g. to_json(BasicJsonType&, const T&))
483
484template<typename> struct is_basic_json : std::false_type {};
485
486NLOHMANN_BASIC_JSON_TPL_DECLARATION
487struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
488
490// aliases for detected //
492
493template <typename T>
494using mapped_type_t = typename T::mapped_type;
495
496template <typename T>
497using key_type_t = typename T::key_type;
498
499template <typename T>
500using value_type_t = typename T::value_type;
501
502template <typename T>
503using difference_type_t = typename T::difference_type;
504
505template <typename T>
506using pointer_t = typename T::pointer;
507
508template <typename T>
509using reference_t = typename T::reference;
510
511template <typename T>
512using iterator_category_t = typename T::iterator_category;
513
514template <typename T>
515using iterator_t = typename T::iterator;
516
517template <typename T, typename... Args>
518using to_json_function = decltype(T::to_json(std::declval<Args>()...));
519
520template <typename T, typename... Args>
521using from_json_function = decltype(T::from_json(std::declval<Args>()...));
522
523template <typename T, typename U>
524using get_template_function = decltype(std::declval<T>().template get<U>());
525
526// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
527template <typename BasicJsonType, typename T, typename = void>
528struct has_from_json : std::false_type {};
529
530template <typename BasicJsonType, typename T>
531struct has_from_json<BasicJsonType, T,
532 enable_if_t<not is_basic_json<T>::value>>
533{
534 using serializer = typename BasicJsonType::template json_serializer<T, void>;
535
536 static constexpr bool value =
537 is_detected_exact<void, from_json_function, serializer,
538 const BasicJsonType&, T&>::value;
539};
540
541// This trait checks if JSONSerializer<T>::from_json(json const&) exists
542// this overload is used for non-default-constructible user-defined-types
543template <typename BasicJsonType, typename T, typename = void>
544struct has_non_default_from_json : std::false_type {};
545
546template<typename BasicJsonType, typename T>
547struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
548{
549 using serializer = typename BasicJsonType::template json_serializer<T, void>;
550
551 static constexpr bool value =
552 is_detected_exact<T, from_json_function, serializer,
553 const BasicJsonType&>::value;
554};
555
556// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
557// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
558template <typename BasicJsonType, typename T, typename = void>
559struct has_to_json : std::false_type {};
560
561template <typename BasicJsonType, typename T>
562struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
563{
564 using serializer = typename BasicJsonType::template json_serializer<T, void>;
565
566 static constexpr bool value =
567 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
568 T>::value;
569};
570
571
573// is_ functions //
575
576template <typename T, typename = void>
577struct is_iterator_traits : std::false_type {};
578
579template <typename T>
581{
582 private:
584
585 public:
586 static constexpr auto value =
587 is_detected<value_type_t, traits>::value &&
588 is_detected<difference_type_t, traits>::value &&
589 is_detected<pointer_t, traits>::value &&
590 is_detected<iterator_category_t, traits>::value &&
591 is_detected<reference_t, traits>::value;
592};
593
594// source: https://stackoverflow.com/a/37193089/4116453
595
596template <typename T, typename = void>
597struct is_complete_type : std::false_type {};
598
599template <typename T>
600struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
601
602template <typename BasicJsonType, typename CompatibleObjectType,
603 typename = void>
604struct is_compatible_object_type_impl : std::false_type {};
605
606template <typename BasicJsonType, typename CompatibleObjectType>
608 BasicJsonType, CompatibleObjectType,
609 enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
610 is_detected<key_type_t, CompatibleObjectType>::value >>
611{
612
613 using object_t = typename BasicJsonType::object_t;
614
615 // macOS's is_constructible does not play well with nonesuch...
616 static constexpr bool value =
617 std::is_constructible<typename object_t::key_type,
618 typename CompatibleObjectType::key_type>::value and
619 std::is_constructible<typename object_t::mapped_type,
620 typename CompatibleObjectType::mapped_type>::value;
621};
622
623template <typename BasicJsonType, typename CompatibleObjectType>
625 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
626
627template <typename BasicJsonType, typename ConstructibleObjectType,
628 typename = void>
629struct is_constructible_object_type_impl : std::false_type {};
630
631template <typename BasicJsonType, typename ConstructibleObjectType>
633 BasicJsonType, ConstructibleObjectType,
634 enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and
635 is_detected<key_type_t, ConstructibleObjectType>::value >>
636{
637 using object_t = typename BasicJsonType::object_t;
638
639 static constexpr bool value =
640 (std::is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value and
641 std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value) or
644};
645
646template <typename BasicJsonType, typename ConstructibleObjectType>
648 : is_constructible_object_type_impl<BasicJsonType,
649 ConstructibleObjectType> {};
650
651template <typename BasicJsonType, typename CompatibleStringType,
652 typename = void>
653struct is_compatible_string_type_impl : std::false_type {};
654
655template <typename BasicJsonType, typename CompatibleStringType>
657 BasicJsonType, CompatibleStringType,
658 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
659 value_type_t, CompatibleStringType>::value >>
660{
661 static constexpr auto value =
662 std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
663};
664
665template <typename BasicJsonType, typename ConstructibleStringType>
667 : is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
668
669template <typename BasicJsonType, typename ConstructibleStringType,
670 typename = void>
671struct is_constructible_string_type_impl : std::false_type {};
672
673template <typename BasicJsonType, typename ConstructibleStringType>
675 BasicJsonType, ConstructibleStringType,
676 enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
677 value_type_t, ConstructibleStringType>::value >>
678{
679 static constexpr auto value =
680 std::is_constructible<ConstructibleStringType,
681 typename BasicJsonType::string_t>::value;
682};
683
684template <typename BasicJsonType, typename ConstructibleStringType>
686 : is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
687
688template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
689struct is_compatible_array_type_impl : std::false_type {};
690
691template <typename BasicJsonType, typename CompatibleArrayType>
693 BasicJsonType, CompatibleArrayType,
694 enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
695 is_detected<iterator_t, CompatibleArrayType>::value and
696// This is needed because json_reverse_iterator has a ::iterator type...
697// Therefore it is detected as a CompatibleArrayType.
698// The real fix would be to have an Iterable concept.
700 iterator_traits<CompatibleArrayType>>::value >>
701{
702 static constexpr bool value =
703 std::is_constructible<BasicJsonType,
704 typename CompatibleArrayType::value_type>::value;
705};
706
707template <typename BasicJsonType, typename CompatibleArrayType>
709 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
710
711template <typename BasicJsonType, typename ConstructibleArrayType, typename = void>
712struct is_constructible_array_type_impl : std::false_type {};
713
714template <typename BasicJsonType, typename ConstructibleArrayType>
716 BasicJsonType, ConstructibleArrayType,
717 enable_if_t<std::is_same<ConstructibleArrayType,
718 typename BasicJsonType::value_type>::value >>
719 : std::true_type {};
720
721template <typename BasicJsonType, typename ConstructibleArrayType>
723 BasicJsonType, ConstructibleArrayType,
724 enable_if_t<not std::is_same<ConstructibleArrayType,
725 typename BasicJsonType::value_type>::value and
726 is_detected<value_type_t, ConstructibleArrayType>::value and
727 is_detected<iterator_t, ConstructibleArrayType>::value and
729 detected_t<value_type_t, ConstructibleArrayType>>::value >>
730{
731 static constexpr bool value =
732 // This is needed because json_reverse_iterator has a ::iterator type,
733 // furthermore, std::back_insert_iterator (and other iterators) have a base class `iterator`...
734 // Therefore it is detected as a ConstructibleArrayType.
735 // The real fix would be to have an Iterable concept.
738
739 (std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
740 has_from_json<BasicJsonType,
741 typename ConstructibleArrayType::value_type>::value or
743 BasicJsonType, typename ConstructibleArrayType::value_type >::value);
744};
745
746template <typename BasicJsonType, typename ConstructibleArrayType>
748 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
749
750template <typename RealIntegerType, typename CompatibleNumberIntegerType,
751 typename = void>
752struct is_compatible_integer_type_impl : std::false_type {};
753
754template <typename RealIntegerType, typename CompatibleNumberIntegerType>
756 RealIntegerType, CompatibleNumberIntegerType,
757 enable_if_t<std::is_integral<RealIntegerType>::value and
758 std::is_integral<CompatibleNumberIntegerType>::value and
759 not std::is_same<bool, CompatibleNumberIntegerType>::value >>
760{
761 // is there an assert somewhere on overflows?
762 using RealLimits = std::numeric_limits<RealIntegerType>;
763 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
764
765 static constexpr auto value =
766 std::is_constructible<RealIntegerType,
767 CompatibleNumberIntegerType>::value and
768 CompatibleLimits::is_integer and
769 RealLimits::is_signed == CompatibleLimits::is_signed;
770};
771
772template <typename RealIntegerType, typename CompatibleNumberIntegerType>
774 : is_compatible_integer_type_impl<RealIntegerType,
775 CompatibleNumberIntegerType> {};
776
777template <typename BasicJsonType, typename CompatibleType, typename = void>
778struct is_compatible_type_impl: std::false_type {};
779
780template <typename BasicJsonType, typename CompatibleType>
782 BasicJsonType, CompatibleType,
783 enable_if_t<is_complete_type<CompatibleType>::value >>
784{
785 static constexpr bool value =
787};
788
789template <typename BasicJsonType, typename CompatibleType>
791 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
792} // namespace detail
793} // namespace nlohmann
794
795// #include <nlohmann/detail/exceptions.hpp>
796
797
798#include <exception> // exception
799#include <stdexcept> // runtime_error
800#include <string> // to_string
801
802// #include <nlohmann/detail/input/position_t.hpp>
803
804
805#include <cstddef> // size_t
806
807namespace nlohmann
808{
809namespace detail
810{
813{
815 std::size_t chars_read_total = 0;
817 std::size_t chars_read_current_line = 0;
819 std::size_t lines_read = 0;
820
822 constexpr operator size_t() const
823 {
824 return chars_read_total;
825 }
826};
827
828}
829}
830
831
832namespace nlohmann
833{
834namespace detail
835{
837// exceptions //
839
868class exception : public std::exception
869{
870 public:
872 const char* what() const noexcept override
873 {
874 return m.what();
875 }
876
878 const int id;
879
880 protected:
881 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
882
883 static std::string name(const std::string& ename, int id_)
884 {
885 return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
886 }
887
888 private:
890 std::runtime_error m;
891};
892
937class parse_error : public exception
938{
939 public:
949 static parse_error create(int id_, const position_t& pos, const std::string& what_arg)
950 {
951 std::string w = exception::name("parse_error", id_) + "parse error" +
952 position_string(pos) + ": " + what_arg;
953 return parse_error(id_, pos.chars_read_total, w.c_str());
954 }
955
956 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg)
957 {
958 std::string w = exception::name("parse_error", id_) + "parse error" +
959 (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
960 ": " + what_arg;
961 return parse_error(id_, byte_, w.c_str());
962 }
963
973 const std::size_t byte;
974
975 private:
976 parse_error(int id_, std::size_t byte_, const char* what_arg)
977 : exception(id_, what_arg), byte(byte_) {}
978
979 static std::string position_string(const position_t& pos)
980 {
981 return " at line " + std::to_string(pos.lines_read + 1) +
982 ", column " + std::to_string(pos.chars_read_current_line);
983 }
984};
985
1024{
1025 public:
1026 static invalid_iterator create(int id_, const std::string& what_arg)
1027 {
1028 std::string w = exception::name("invalid_iterator", id_) + what_arg;
1029 return invalid_iterator(id_, w.c_str());
1030 }
1031
1032 private:
1033 invalid_iterator(int id_, const char* what_arg)
1034 : exception(id_, what_arg) {}
1035};
1036
1076class type_error : public exception
1077{
1078 public:
1079 static type_error create(int id_, const std::string& what_arg)
1080 {
1081 std::string w = exception::name("type_error", id_) + what_arg;
1082 return type_error(id_, w.c_str());
1083 }
1084
1085 private:
1086 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
1087};
1088
1123{
1124 public:
1125 static out_of_range create(int id_, const std::string& what_arg)
1126 {
1127 std::string w = exception::name("out_of_range", id_) + what_arg;
1128 return out_of_range(id_, w.c_str());
1129 }
1130
1131 private:
1132 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
1133};
1134
1160{
1161 public:
1162 static other_error create(int id_, const std::string& what_arg)
1163 {
1164 std::string w = exception::name("other_error", id_) + what_arg;
1165 return other_error(id_, w.c_str());
1166 }
1167
1168 private:
1169 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
1170};
1171} // namespace detail
1172} // namespace nlohmann
1173
1174// #include <nlohmann/detail/value_t.hpp>
1175
1176
1177#include <array> // array
1178#include <ciso646> // and
1179#include <cstddef> // size_t
1180#include <cstdint> // uint8_t
1181
1182namespace nlohmann
1183{
1184namespace detail
1185{
1187// JSON type enumeration //
1189
1214enum class value_t : std::uint8_t
1215{
1216 null,
1217 object,
1218 array,
1219 string,
1220 boolean,
1221 number_integer,
1222 number_unsigned,
1223 number_float,
1224 discarded
1225};
1226
1237inline bool operator<(const value_t lhs, const value_t rhs) noexcept
1238{
1239 static constexpr std::array<std::uint8_t, 8> order = {{
1240 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
1241 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */
1242 }
1243 };
1244
1245 const auto l_index = static_cast<std::size_t>(lhs);
1246 const auto r_index = static_cast<std::size_t>(rhs);
1247 return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
1248}
1249} // namespace detail
1250} // namespace nlohmann
1251
1252// #include <nlohmann/detail/conversions/from_json.hpp>
1253
1254
1255#include <algorithm> // transform
1256#include <array> // array
1257#include <ciso646> // and, not
1258#include <forward_list> // forward_list
1259#include <iterator> // inserter, front_inserter, end
1260#include <map> // map
1261#include <string> // string
1262#include <tuple> // tuple, make_tuple
1263#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
1264#include <unordered_map> // unordered_map
1265#include <utility> // pair, declval
1266#include <valarray> // valarray
1267
1268// #include <nlohmann/detail/exceptions.hpp>
1269
1270// #include <nlohmann/detail/macro_scope.hpp>
1271
1272// #include <nlohmann/detail/meta/cpp_future.hpp>
1273
1274// #include <nlohmann/detail/meta/type_traits.hpp>
1275
1276// #include <nlohmann/detail/value_t.hpp>
1277
1278
1279namespace nlohmann
1280{
1281namespace detail
1282{
1283template<typename BasicJsonType>
1284void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
1285{
1286 if (JSON_UNLIKELY(not j.is_null()))
1287 {
1288 JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
1289 }
1290 n = nullptr;
1291}
1292
1293// overloads for basic_json template parameters
1294template<typename BasicJsonType, typename ArithmeticType,
1295 enable_if_t<std::is_arithmetic<ArithmeticType>::value and
1296 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1297 int> = 0>
1298void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
1299{
1300 switch (static_cast<value_t>(j))
1301 {
1302 case value_t::number_unsigned:
1303 {
1304 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1305 break;
1306 }
1307 case value_t::number_integer:
1308 {
1309 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1310 break;
1311 }
1312 case value_t::number_float:
1313 {
1314 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1315 break;
1316 }
1317
1318 default:
1319 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1320 }
1321}
1322
1323template<typename BasicJsonType>
1324void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
1325{
1326 if (JSON_UNLIKELY(not j.is_boolean()))
1327 {
1328 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
1329 }
1330 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
1331}
1332
1333template<typename BasicJsonType>
1334void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
1335{
1336 if (JSON_UNLIKELY(not j.is_string()))
1337 {
1338 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1339 }
1340 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1341}
1342
1343template <
1344 typename BasicJsonType, typename ConstructibleStringType,
1345 enable_if_t <
1346 is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and
1347 not std::is_same<typename BasicJsonType::string_t,
1348 ConstructibleStringType>::value,
1349 int > = 0 >
1350void from_json(const BasicJsonType& j, ConstructibleStringType& s)
1351{
1352 if (JSON_UNLIKELY(not j.is_string()))
1353 {
1354 JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
1355 }
1356
1357 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
1358}
1359
1360template<typename BasicJsonType>
1361void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
1362{
1363 get_arithmetic_value(j, val);
1364}
1365
1366template<typename BasicJsonType>
1367void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
1368{
1369 get_arithmetic_value(j, val);
1370}
1371
1372template<typename BasicJsonType>
1373void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
1374{
1375 get_arithmetic_value(j, val);
1376}
1377
1378template<typename BasicJsonType, typename EnumType,
1379 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
1380void from_json(const BasicJsonType& j, EnumType& e)
1381{
1382 typename std::underlying_type<EnumType>::type val;
1383 get_arithmetic_value(j, val);
1384 e = static_cast<EnumType>(val);
1385}
1386
1387// forward_list doesn't have an insert method
1388template<typename BasicJsonType, typename T, typename Allocator,
1389 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1390void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
1391{
1392 if (JSON_UNLIKELY(not j.is_array()))
1393 {
1394 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1395 }
1396 std::transform(j.rbegin(), j.rend(),
1397 std::front_inserter(l), [](const BasicJsonType & i)
1398 {
1399 return i.template get<T>();
1400 });
1401}
1402
1403// valarray doesn't have an insert method
1404template<typename BasicJsonType, typename T,
1405 enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
1406void from_json(const BasicJsonType& j, std::valarray<T>& l)
1407{
1408 if (JSON_UNLIKELY(not j.is_array()))
1409 {
1410 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1411 }
1412 l.resize(j.size());
1413 std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
1414}
1415
1416template<typename BasicJsonType>
1417void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
1418{
1419 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
1420}
1421
1422template <typename BasicJsonType, typename T, std::size_t N>
1423auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
1424 priority_tag<2> /*unused*/)
1425-> decltype(j.template get<T>(), void())
1426{
1427 for (std::size_t i = 0; i < N; ++i)
1428 {
1429 arr[i] = j.at(i).template get<T>();
1430 }
1431}
1432
1433template<typename BasicJsonType, typename ConstructibleArrayType>
1434auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
1435-> decltype(
1436 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
1437 j.template get<typename ConstructibleArrayType::value_type>(),
1438 void())
1439{
1440 using std::end;
1441
1442 arr.reserve(j.size());
1443 std::transform(j.begin(), j.end(),
1444 std::inserter(arr, end(arr)), [](const BasicJsonType & i)
1445 {
1446 // get<BasicJsonType>() returns *this, this won't call a from_json
1447 // method when value_type is BasicJsonType
1448 return i.template get<typename ConstructibleArrayType::value_type>();
1449 });
1450}
1451
1452template <typename BasicJsonType, typename ConstructibleArrayType>
1453void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
1454 priority_tag<0> /*unused*/)
1455{
1456 using std::end;
1457
1458 std::transform(
1459 j.begin(), j.end(), std::inserter(arr, end(arr)),
1460 [](const BasicJsonType & i)
1461 {
1462 // get<BasicJsonType>() returns *this, this won't call a from_json
1463 // method when value_type is BasicJsonType
1464 return i.template get<typename ConstructibleArrayType::value_type>();
1465 });
1466}
1467
1468template <typename BasicJsonType, typename ConstructibleArrayType,
1469 enable_if_t <
1470 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and
1471 not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and
1472 not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and
1473 not is_basic_json<ConstructibleArrayType>::value,
1474 int > = 0 >
1475
1476auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
1477-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
1478j.template get<typename ConstructibleArrayType::value_type>(),
1479void())
1480{
1481 if (JSON_UNLIKELY(not j.is_array()))
1482 {
1483 JSON_THROW(type_error::create(302, "type must be array, but is " +
1484 std::string(j.type_name())));
1485 }
1486
1487 from_json_array_impl(j, arr, priority_tag<3> {});
1488}
1489
1490template<typename BasicJsonType, typename ConstructibleObjectType,
1491 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
1492void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
1493{
1494 if (JSON_UNLIKELY(not j.is_object()))
1495 {
1496 JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
1497 }
1498
1499 auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
1500 using value_type = typename ConstructibleObjectType::value_type;
1501 std::transform(
1502 inner_object->begin(), inner_object->end(),
1503 std::inserter(obj, obj.begin()),
1504 [](typename BasicJsonType::object_t::value_type const & p)
1505 {
1506 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
1507 });
1508}
1509
1510// overload for arithmetic types, not chosen for basic_json template arguments
1511// (BooleanType, etc..); note: Is it really necessary to provide explicit
1512// overloads for boolean_t etc. in case of a custom BooleanType which is not
1513// an arithmetic type?
1514template<typename BasicJsonType, typename ArithmeticType,
1515 enable_if_t <
1516 std::is_arithmetic<ArithmeticType>::value and
1517 not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
1518 not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
1519 not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
1520 not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
1521 int> = 0>
1522void from_json(const BasicJsonType& j, ArithmeticType& val)
1523{
1524 switch (static_cast<value_t>(j))
1525 {
1526 case value_t::number_unsigned:
1527 {
1528 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
1529 break;
1530 }
1531 case value_t::number_integer:
1532 {
1533 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
1534 break;
1535 }
1536 case value_t::number_float:
1537 {
1538 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
1539 break;
1540 }
1541 case value_t::boolean:
1542 {
1543 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
1544 break;
1545 }
1546
1547 default:
1548 JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
1549 }
1550}
1551
1552template<typename BasicJsonType, typename A1, typename A2>
1553void from_json(const BasicJsonType& j, std::pair<A1, A2>& p)
1554{
1555 p = {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
1556}
1557
1558template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
1559void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...> /*unused*/)
1560{
1561 t = std::make_tuple(j.at(Idx).template get<typename std::tuple_element<Idx, Tuple>::type>()...);
1562}
1563
1564template<typename BasicJsonType, typename... Args>
1565void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
1566{
1567 from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
1568}
1569
1570template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
1571 typename = enable_if_t<not std::is_constructible<
1572 typename BasicJsonType::string_t, Key>::value>>
1573void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
1574{
1575 if (JSON_UNLIKELY(not j.is_array()))
1576 {
1577 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1578 }
1579 for (const auto& p : j)
1580 {
1581 if (JSON_UNLIKELY(not p.is_array()))
1582 {
1583 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1584 }
1585 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1586 }
1587}
1588
1589template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
1590 typename = enable_if_t<not std::is_constructible<
1591 typename BasicJsonType::string_t, Key>::value>>
1592void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
1593{
1594 if (JSON_UNLIKELY(not j.is_array()))
1595 {
1596 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
1597 }
1598 for (const auto& p : j)
1599 {
1600 if (JSON_UNLIKELY(not p.is_array()))
1601 {
1602 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
1603 }
1604 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
1605 }
1606}
1607
1608struct from_json_fn
1609{
1610 template<typename BasicJsonType, typename T>
1611 auto operator()(const BasicJsonType& j, T& val) const
1612 noexcept(noexcept(from_json(j, val)))
1613 -> decltype(from_json(j, val), void())
1614 {
1615 return from_json(j, val);
1616 }
1617};
1618} // namespace detail
1619
1623namespace
1624{
1625constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
1626} // namespace
1627} // namespace nlohmann
1628
1629// #include <nlohmann/detail/conversions/to_json.hpp>
1630
1631
1632#include <ciso646> // or, and, not
1633#include <iterator> // begin, end
1634#include <tuple> // tuple, get
1635#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
1636#include <utility> // move, forward, declval, pair
1637#include <valarray> // valarray
1638#include <vector> // vector
1639
1640// #include <nlohmann/detail/meta/cpp_future.hpp>
1641
1642// #include <nlohmann/detail/meta/type_traits.hpp>
1643
1644// #include <nlohmann/detail/value_t.hpp>
1645
1646// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
1647
1648
1649#include <cstddef> // size_t
1650#include <string> // string, to_string
1651#include <iterator> // input_iterator_tag
1652#include <tuple> // tuple_size, get, tuple_element
1653
1654// #include <nlohmann/detail/value_t.hpp>
1655
1656// #include <nlohmann/detail/meta/type_traits.hpp>
1657
1658
1659namespace nlohmann
1660{
1661namespace detail
1662{
1663template <typename IteratorType> class iteration_proxy_value
1664{
1665 public:
1666 using difference_type = std::ptrdiff_t;
1667 using value_type = iteration_proxy_value;
1668 using pointer = value_type * ;
1669 using reference = value_type & ;
1670 using iterator_category = std::input_iterator_tag;
1671
1672 private:
1674 IteratorType anchor;
1676 std::size_t array_index = 0;
1678 mutable std::size_t array_index_last = 0;
1680 mutable std::string array_index_str = "0";
1682 const std::string empty_str = "";
1683
1684 public:
1685 explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
1686
1688 iteration_proxy_value& operator*()
1689 {
1690 return *this;
1691 }
1692
1694 iteration_proxy_value& operator++()
1695 {
1696 ++anchor;
1697 ++array_index;
1698
1699 return *this;
1700 }
1701
1703 bool operator==(const iteration_proxy_value& o) const noexcept
1704 {
1705 return anchor == o.anchor;
1706 }
1707
1709 bool operator!=(const iteration_proxy_value& o) const noexcept
1710 {
1711 return anchor != o.anchor;
1712 }
1713
1715 const std::string& key() const
1716 {
1717 assert(anchor.m_object != nullptr);
1718
1719 switch (anchor.m_object->type())
1720 {
1721 // use integer array index as key
1722 case value_t::array:
1723 {
1724 if (array_index != array_index_last)
1725 {
1726 array_index_str = std::to_string(array_index);
1727 array_index_last = array_index;
1728 }
1729 return array_index_str;
1730 }
1731
1732 // use key from the object
1733 case value_t::object:
1734 return anchor.key();
1735
1736 // use an empty key for all primitive types
1737 default:
1738 return empty_str;
1739 }
1740 }
1741
1743 typename IteratorType::reference value() const
1744 {
1745 return anchor.value();
1746 }
1747};
1748
1750template<typename IteratorType> class iteration_proxy
1751{
1752 private:
1754 typename IteratorType::reference container;
1755
1756 public:
1758 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
1759 : container(cont) {}
1760
1762 iteration_proxy_value<IteratorType> begin() noexcept
1763 {
1764 return iteration_proxy_value<IteratorType>(container.begin());
1765 }
1766
1768 iteration_proxy_value<IteratorType> end() noexcept
1769 {
1770 return iteration_proxy_value<IteratorType>(container.end());
1771 }
1772};
1773// Structured Bindings Support
1774// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1775// And see https://github.com/nlohmann/json/pull/1391
1776template <std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
1777auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
1778{
1779 return i.key();
1780}
1781// Structured Bindings Support
1782// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1783// And see https://github.com/nlohmann/json/pull/1391
1784template <std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
1785auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
1786{
1787 return i.value();
1788}
1789} // namespace detail
1790} // namespace nlohmann
1791
1792// The Addition to the STD Namespace is required to add
1793// Structured Bindings Support to the iteration_proxy_value class
1794// For further reference see https://blog.tartanllama.xyz/structured-bindings/
1795// And see https://github.com/nlohmann/json/pull/1391
1796namespace std
1797{
1798template <typename IteratorType>
1799class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
1800 : public std::integral_constant<std::size_t, 2> {};
1801
1802template <std::size_t N, typename IteratorType>
1803class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
1804{
1805 public:
1806 using type = decltype(
1807 get<N>(std::declval <
1808 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
1809};
1810}
1811
1812namespace nlohmann
1813{
1814namespace detail
1815{
1817// constructors //
1819
1820template<value_t> struct external_constructor;
1821
1822template<>
1823struct external_constructor<value_t::boolean>
1824{
1825 template<typename BasicJsonType>
1826 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
1827 {
1828 j.m_type = value_t::boolean;
1829 j.m_value = b;
1830 j.assert_invariant();
1831 }
1832};
1833
1834template<>
1835struct external_constructor<value_t::string>
1836{
1837 template<typename BasicJsonType>
1838 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
1839 {
1840 j.m_type = value_t::string;
1841 j.m_value = s;
1842 j.assert_invariant();
1843 }
1844
1845 template<typename BasicJsonType>
1846 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
1847 {
1848 j.m_type = value_t::string;
1849 j.m_value = std::move(s);
1850 j.assert_invariant();
1851 }
1852
1853 template<typename BasicJsonType, typename CompatibleStringType,
1854 enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
1855 int> = 0>
1856 static void construct(BasicJsonType& j, const CompatibleStringType& str)
1857 {
1858 j.m_type = value_t::string;
1859 j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
1860 j.assert_invariant();
1861 }
1862};
1863
1864template<>
1865struct external_constructor<value_t::number_float>
1866{
1867 template<typename BasicJsonType>
1868 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
1869 {
1870 j.m_type = value_t::number_float;
1871 j.m_value = val;
1872 j.assert_invariant();
1873 }
1874};
1875
1876template<>
1877struct external_constructor<value_t::number_unsigned>
1878{
1879 template<typename BasicJsonType>
1880 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
1881 {
1882 j.m_type = value_t::number_unsigned;
1883 j.m_value = val;
1884 j.assert_invariant();
1885 }
1886};
1887
1888template<>
1889struct external_constructor<value_t::number_integer>
1890{
1891 template<typename BasicJsonType>
1892 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
1893 {
1894 j.m_type = value_t::number_integer;
1895 j.m_value = val;
1896 j.assert_invariant();
1897 }
1898};
1899
1900template<>
1901struct external_constructor<value_t::array>
1902{
1903 template<typename BasicJsonType>
1904 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
1905 {
1906 j.m_type = value_t::array;
1907 j.m_value = arr;
1908 j.assert_invariant();
1909 }
1910
1911 template<typename BasicJsonType>
1912 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
1913 {
1914 j.m_type = value_t::array;
1915 j.m_value = std::move(arr);
1916 j.assert_invariant();
1917 }
1918
1919 template<typename BasicJsonType, typename CompatibleArrayType,
1920 enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
1921 int> = 0>
1922 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
1923 {
1924 using std::begin;
1925 using std::end;
1926 j.m_type = value_t::array;
1927 j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
1928 j.assert_invariant();
1929 }
1930
1931 template<typename BasicJsonType>
1932 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
1933 {
1934 j.m_type = value_t::array;
1935 j.m_value = value_t::array;
1936 j.m_value.array->reserve(arr.size());
1937 for (const bool x : arr)
1938 {
1939 j.m_value.array->push_back(x);
1940 }
1941 j.assert_invariant();
1942 }
1943
1944 template<typename BasicJsonType, typename T,
1945 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
1946 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
1947 {
1948 j.m_type = value_t::array;
1949 j.m_value = value_t::array;
1950 j.m_value.array->resize(arr.size());
1951 std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
1952 j.assert_invariant();
1953 }
1954};
1955
1956template<>
1957struct external_constructor<value_t::object>
1958{
1959 template<typename BasicJsonType>
1960 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
1961 {
1962 j.m_type = value_t::object;
1963 j.m_value = obj;
1964 j.assert_invariant();
1965 }
1966
1967 template<typename BasicJsonType>
1968 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
1969 {
1970 j.m_type = value_t::object;
1971 j.m_value = std::move(obj);
1972 j.assert_invariant();
1973 }
1974
1975 template<typename BasicJsonType, typename CompatibleObjectType,
1976 enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
1977 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
1978 {
1979 using std::begin;
1980 using std::end;
1981
1982 j.m_type = value_t::object;
1983 j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
1984 j.assert_invariant();
1985 }
1986};
1987
1989// to_json //
1991
1992template<typename BasicJsonType, typename T,
1993 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
1994void to_json(BasicJsonType& j, T b) noexcept
1995{
1997}
1998
1999template<typename BasicJsonType, typename CompatibleString,
2000 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
2001void to_json(BasicJsonType& j, const CompatibleString& s)
2002{
2003 external_constructor<value_t::string>::construct(j, s);
2004}
2005
2006template<typename BasicJsonType>
2007void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
2008{
2009 external_constructor<value_t::string>::construct(j, std::move(s));
2010}
2011
2012template<typename BasicJsonType, typename FloatType,
2013 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
2014void to_json(BasicJsonType& j, FloatType val) noexcept
2015{
2016 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
2017}
2018
2019template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
2020 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
2021void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
2022{
2023 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
2024}
2025
2026template<typename BasicJsonType, typename CompatibleNumberIntegerType,
2027 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
2028void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
2029{
2030 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
2031}
2032
2033template<typename BasicJsonType, typename EnumType,
2034 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
2035void to_json(BasicJsonType& j, EnumType e) noexcept
2036{
2037 using underlying_type = typename std::underlying_type<EnumType>::type;
2038 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
2039}
2040
2041template<typename BasicJsonType>
2042void to_json(BasicJsonType& j, const std::vector<bool>& e)
2043{
2044 external_constructor<value_t::array>::construct(j, e);
2045}
2046
2047template <typename BasicJsonType, typename CompatibleArrayType,
2048 enable_if_t<is_compatible_array_type<BasicJsonType,
2049 CompatibleArrayType>::value and
2050 not is_compatible_object_type<
2051 BasicJsonType, CompatibleArrayType>::value and
2052 not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
2053 not is_basic_json<CompatibleArrayType>::value,
2054 int> = 0>
2055void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
2056{
2057 external_constructor<value_t::array>::construct(j, arr);
2058}
2059
2060template<typename BasicJsonType, typename T,
2061 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
2062void to_json(BasicJsonType& j, const std::valarray<T>& arr)
2063{
2064 external_constructor<value_t::array>::construct(j, std::move(arr));
2065}
2066
2067template<typename BasicJsonType>
2068void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
2069{
2070 external_constructor<value_t::array>::construct(j, std::move(arr));
2071}
2072
2073template<typename BasicJsonType, typename CompatibleObjectType,
2074 enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
2075void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
2076{
2077 external_constructor<value_t::object>::construct(j, obj);
2078}
2079
2080template<typename BasicJsonType>
2081void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
2082{
2083 external_constructor<value_t::object>::construct(j, std::move(obj));
2084}
2085
2086template <
2087 typename BasicJsonType, typename T, std::size_t N,
2088 enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
2089 const T(&)[N]>::value,
2090 int> = 0 >
2091void to_json(BasicJsonType& j, const T(&arr)[N])
2092{
2093 external_constructor<value_t::array>::construct(j, arr);
2094}
2095
2096template<typename BasicJsonType, typename... Args>
2097void to_json(BasicJsonType& j, const std::pair<Args...>& p)
2098{
2099 j = { p.first, p.second };
2100}
2101
2102// for https://github.com/nlohmann/json/pull/1134
2103template < typename BasicJsonType, typename T,
2104 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
2105void to_json(BasicJsonType& j, const T& b)
2106{
2107 j = { {b.key(), b.value()} };
2108}
2109
2110template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
2111void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
2112{
2113 j = { std::get<Idx>(t)... };
2114}
2115
2116template<typename BasicJsonType, typename... Args>
2117void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
2118{
2119 to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
2120}
2121
2123{
2124 template<typename BasicJsonType, typename T>
2125 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
2126 -> decltype(to_json(j, std::forward<T>(val)), void())
2127 {
2128 return to_json(j, std::forward<T>(val));
2129 }
2130};
2131} // namespace detail
2132
2134namespace
2135{
2136constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
2137} // namespace
2138} // namespace nlohmann
2139
2140// #include <nlohmann/detail/input/input_adapters.hpp>
2141
2142
2143#include <cassert> // assert
2144#include <cstddef> // size_t
2145#include <cstring> // strlen
2146#include <istream> // istream
2147#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
2148#include <memory> // shared_ptr, make_shared, addressof
2149#include <numeric> // accumulate
2150#include <string> // string, char_traits
2151#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
2152#include <utility> // pair, declval
2153#include <cstdio> //FILE *
2154
2155// #include <nlohmann/detail/macro_scope.hpp>
2156
2157
2158namespace nlohmann
2159{
2160namespace detail
2161{
2163enum class input_format_t { json, cbor, msgpack, ubjson, bson };
2164
2166// input adapters //
2168
2181{
2183 virtual std::char_traits<char>::int_type get_character() = 0;
2184 virtual ~input_adapter_protocol() = default;
2185};
2186
2188using input_adapter_t = std::shared_ptr<input_adapter_protocol>;
2189
2195{
2196 public:
2197 explicit file_input_adapter(std::FILE* f) noexcept
2198 : m_file(f)
2199 {}
2200
2201 std::char_traits<char>::int_type get_character() noexcept override
2202 {
2203 return std::fgetc(m_file);
2204 }
2205 private:
2207 std::FILE* m_file;
2208};
2209
2210
2221{
2222 public:
2223 ~input_stream_adapter() override
2224 {
2225 // clear stream flags; we use underlying streambuf I/O, do not
2226 // maintain ifstream flags, except eof
2227 is.clear(is.rdstate() & std::ios::eofbit);
2228 }
2229
2230 explicit input_stream_adapter(std::istream& i)
2231 : is(i), sb(*i.rdbuf())
2232 {}
2233
2234 // delete because of pointer members
2236 input_stream_adapter& operator=(input_stream_adapter&) = delete;
2238 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
2239
2240 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
2241 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
2242 // end up as the same value, eg. 0xFFFFFFFF.
2243 std::char_traits<char>::int_type get_character() override
2244 {
2245 auto res = sb.sbumpc();
2246 // set eof manually, as we don't use the istream interface.
2247 if (res == EOF)
2248 {
2249 is.clear(is.rdstate() | std::ios::eofbit);
2250 }
2251 return res;
2252 }
2253
2254 private:
2256 std::istream& is;
2257 std::streambuf& sb;
2258};
2259
2262{
2263 public:
2264 input_buffer_adapter(const char* b, const std::size_t l) noexcept
2265 : cursor(b), limit(b + l)
2266 {}
2267
2268 // delete because of pointer members
2270 input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
2272 input_buffer_adapter& operator=(input_buffer_adapter&&) = delete;
2273 ~input_buffer_adapter() override = default;
2274
2275 std::char_traits<char>::int_type get_character() noexcept override
2276 {
2277 if (JSON_LIKELY(cursor < limit))
2278 {
2279 return std::char_traits<char>::to_int_type(*(cursor++));
2280 }
2281
2282 return std::char_traits<char>::eof();
2283 }
2284
2285 private:
2287 const char* cursor;
2289 const char* const limit;
2290};
2291
2292template<typename WideStringType, size_t T>
2294{
2295 // UTF-32
2296 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)
2297 {
2298 utf8_bytes_index = 0;
2299
2300 if (current_wchar == str.size())
2301 {
2302 utf8_bytes[0] = std::char_traits<char>::eof();
2303 utf8_bytes_filled = 1;
2304 }
2305 else
2306 {
2307 // get the current character
2308 const auto wc = static_cast<int>(str[current_wchar++]);
2309
2310 // UTF-32 to UTF-8 encoding
2311 if (wc < 0x80)
2312 {
2313 utf8_bytes[0] = wc;
2314 utf8_bytes_filled = 1;
2315 }
2316 else if (wc <= 0x7FF)
2317 {
2318 utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
2319 utf8_bytes[1] = 0x80 | (wc & 0x3F);
2320 utf8_bytes_filled = 2;
2321 }
2322 else if (wc <= 0xFFFF)
2323 {
2324 utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
2325 utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2326 utf8_bytes[2] = 0x80 | (wc & 0x3F);
2327 utf8_bytes_filled = 3;
2328 }
2329 else if (wc <= 0x10FFFF)
2330 {
2331 utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);
2332 utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
2333 utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
2334 utf8_bytes[3] = 0x80 | (wc & 0x3F);
2335 utf8_bytes_filled = 4;
2336 }
2337 else
2338 {
2339 // unknown character
2340 utf8_bytes[0] = wc;
2341 utf8_bytes_filled = 1;
2342 }
2343 }
2344 }
2345};
2346
2347template<typename WideStringType>
2348struct wide_string_input_helper<WideStringType, 2>
2349{
2350 // UTF-16
2351 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)
2352 {
2353 utf8_bytes_index = 0;
2354
2355 if (current_wchar == str.size())
2356 {
2357 utf8_bytes[0] = std::char_traits<char>::eof();
2358 utf8_bytes_filled = 1;
2359 }
2360 else
2361 {
2362 // get the current character
2363 const auto wc = static_cast<int>(str[current_wchar++]);
2364
2365 // UTF-16 to UTF-8 encoding
2366 if (wc < 0x80)
2367 {
2368 utf8_bytes[0] = wc;
2369 utf8_bytes_filled = 1;
2370 }
2371 else if (wc <= 0x7FF)
2372 {
2373 utf8_bytes[0] = 0xC0 | ((wc >> 6));
2374 utf8_bytes[1] = 0x80 | (wc & 0x3F);
2375 utf8_bytes_filled = 2;
2376 }
2377 else if (0xD800 > wc or wc >= 0xE000)
2378 {
2379 utf8_bytes[0] = 0xE0 | ((wc >> 12));
2380 utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
2381 utf8_bytes[2] = 0x80 | (wc & 0x3F);
2382 utf8_bytes_filled = 3;
2383 }
2384 else
2385 {
2386 if (current_wchar < str.size())
2387 {
2388 const auto wc2 = static_cast<int>(str[current_wchar++]);
2389 const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
2390 utf8_bytes[0] = 0xf0 | (charcode >> 18);
2391 utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
2392 utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
2393 utf8_bytes[3] = 0x80 | (charcode & 0x3F);
2394 utf8_bytes_filled = 4;
2395 }
2396 else
2397 {
2398 // unknown character
2399 ++current_wchar;
2400 utf8_bytes[0] = wc;
2401 utf8_bytes_filled = 1;
2402 }
2403 }
2404 }
2405 }
2406};
2407
2408template<typename WideStringType>
2410{
2411 public:
2412 explicit wide_string_input_adapter(const WideStringType& w) noexcept
2413 : str(w)
2414 {}
2415
2416 std::char_traits<char>::int_type get_character() noexcept override
2417 {
2418 // check if buffer needs to be filled
2419 if (utf8_bytes_index == utf8_bytes_filled)
2420 {
2421 fill_buffer<sizeof(typename WideStringType::value_type)>();
2422
2423 assert(utf8_bytes_filled > 0);
2424 assert(utf8_bytes_index == 0);
2425 }
2426
2427 // use buffer
2428 assert(utf8_bytes_filled > 0);
2429 assert(utf8_bytes_index < utf8_bytes_filled);
2430 return utf8_bytes[utf8_bytes_index++];
2431 }
2432
2433 private:
2434 template<size_t T>
2435 void fill_buffer()
2436 {
2437 wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
2438 }
2439
2441 const WideStringType& str;
2442
2444 std::size_t current_wchar = 0;
2445
2447 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
2448
2450 std::size_t utf8_bytes_index = 0;
2452 std::size_t utf8_bytes_filled = 0;
2453};
2454
2456{
2457 public:
2458 // native support
2459 input_adapter(std::FILE* file)
2460 : ia(std::make_shared<file_input_adapter>(file)) {}
2462 input_adapter(std::istream& i)
2463 : ia(std::make_shared<input_stream_adapter>(i)) {}
2464
2466 input_adapter(std::istream&& i)
2467 : ia(std::make_shared<input_stream_adapter>(i)) {}
2468
2469 input_adapter(const std::wstring& ws)
2470 : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
2471
2472 input_adapter(const std::u16string& ws)
2473 : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
2474
2475 input_adapter(const std::u32string& ws)
2476 : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
2477
2479 template<typename CharT,
2480 typename std::enable_if<
2481 std::is_pointer<CharT>::value and
2482 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2483 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2484 int>::type = 0>
2485 input_adapter(CharT b, std::size_t l)
2486 : ia(std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(b), l)) {}
2487
2488 // derived support
2489
2491 template<typename CharT,
2492 typename std::enable_if<
2493 std::is_pointer<CharT>::value and
2494 std::is_integral<typename std::remove_pointer<CharT>::type>::value and
2495 sizeof(typename std::remove_pointer<CharT>::type) == 1,
2496 int>::type = 0>
2498 : input_adapter(reinterpret_cast<const char*>(b),
2499 std::strlen(reinterpret_cast<const char*>(b))) {}
2500
2502 template<class IteratorType,
2503 typename std::enable_if<
2504 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
2505 int>::type = 0>
2506 input_adapter(IteratorType first, IteratorType last)
2507 {
2508#ifndef NDEBUG
2509 // assertion to check that the iterator range is indeed contiguous,
2510 // see http://stackoverflow.com/a/35008842/266378 for more discussion
2511 const auto is_contiguous = std::accumulate(
2512 first, last, std::pair<bool, int>(true, 0),
2513 [&first](std::pair<bool, int> res, decltype(*first) val)
2514 {
2515 res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
2516 return res;
2517 }).first;
2518 assert(is_contiguous);
2519#endif
2520
2521 // assertion to check that each element is 1 byte long
2522 static_assert(
2523 sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
2524 "each element in the iterator range must have the size of 1 byte");
2525
2526 const auto len = static_cast<size_t>(std::distance(first, last));
2527 if (JSON_LIKELY(len > 0))
2528 {
2529 // there is at least one element: use the address of first
2530 ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);
2531 }
2532 else
2533 {
2534 // the address of first cannot be used: use nullptr
2535 ia = std::make_shared<input_buffer_adapter>(nullptr, len);
2536 }
2537 }
2538
2540 template<class T, std::size_t N>
2541 input_adapter(T (&array)[N])
2542 : input_adapter(std::begin(array), std::end(array)) {}
2543
2545 template<class ContiguousContainer, typename
2546 std::enable_if<not std::is_pointer<ContiguousContainer>::value and
2547 std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
2548 int>::type = 0>
2549 input_adapter(const ContiguousContainer& c)
2550 : input_adapter(std::begin(c), std::end(c)) {}
2551
2552 operator input_adapter_t()
2553 {
2554 return ia;
2555 }
2556
2557 private:
2559 input_adapter_t ia = nullptr;
2560};
2561} // namespace detail
2562} // namespace nlohmann
2563
2564// #include <nlohmann/detail/input/lexer.hpp>
2565
2566
2567#include <clocale> // localeconv
2568#include <cstddef> // size_t
2569#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
2570#include <cstdio> // snprintf
2571#include <initializer_list> // initializer_list
2572#include <string> // char_traits, string
2573#include <vector> // vector
2574
2575// #include <nlohmann/detail/macro_scope.hpp>
2576
2577// #include <nlohmann/detail/input/input_adapters.hpp>
2578
2579// #include <nlohmann/detail/input/position_t.hpp>
2580
2581
2582namespace nlohmann
2583{
2584namespace detail
2585{
2587// lexer //
2589
2595template<typename BasicJsonType>
2596class lexer
2597{
2598 using number_integer_t = typename BasicJsonType::number_integer_t;
2599 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
2600 using number_float_t = typename BasicJsonType::number_float_t;
2601 using string_t = typename BasicJsonType::string_t;
2602
2603 public:
2605 enum class token_type
2606 {
2607 uninitialized,
2608 literal_true,
2609 literal_false,
2610 literal_null,
2611 value_string,
2612 value_unsigned,
2613 value_integer,
2614 value_float,
2615 begin_array,
2616 begin_object,
2617 end_array,
2618 end_object,
2619 name_separator,
2620 value_separator,
2621 parse_error,
2622 end_of_input,
2623 literal_or_value
2624 };
2625
2627 static const char* token_type_name(const token_type t) noexcept
2628 {
2629 switch (t)
2630 {
2631 case token_type::uninitialized:
2632 return "<uninitialized>";
2633 case token_type::literal_true:
2634 return "true literal";
2635 case token_type::literal_false:
2636 return "false literal";
2637 case token_type::literal_null:
2638 return "null literal";
2639 case token_type::value_string:
2640 return "string literal";
2641 case lexer::token_type::value_unsigned:
2642 case lexer::token_type::value_integer:
2643 case lexer::token_type::value_float:
2644 return "number literal";
2645 case token_type::begin_array:
2646 return "'['";
2647 case token_type::begin_object:
2648 return "'{'";
2649 case token_type::end_array:
2650 return "']'";
2651 case token_type::end_object:
2652 return "'}'";
2653 case token_type::name_separator:
2654 return "':'";
2655 case token_type::value_separator:
2656 return "','";
2657 case token_type::parse_error:
2658 return "<parse error>";
2659 case token_type::end_of_input:
2660 return "end of input";
2661 case token_type::literal_or_value:
2662 return "'[', '{', or a literal";
2663 // LCOV_EXCL_START
2664 default: // catch non-enum values
2665 return "unknown token";
2666 // LCOV_EXCL_STOP
2667 }
2668 }
2669
2670 explicit lexer(detail::input_adapter_t&& adapter)
2671 : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
2672
2673 // delete because of pointer members
2674 lexer(const lexer&) = delete;
2675 lexer(lexer&&) = delete;
2676 lexer& operator=(lexer&) = delete;
2677 lexer& operator=(lexer&&) = delete;
2678 ~lexer() = default;
2679
2680 private:
2682 // locales
2684
2686 static char get_decimal_point() noexcept
2687 {
2688 const auto loc = localeconv();
2689 assert(loc != nullptr);
2690 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
2691 }
2692
2694 // scan functions
2696
2712 int get_codepoint()
2713 {
2714 // this function only makes sense after reading `\u`
2715 assert(current == 'u');
2716 int codepoint = 0;
2717
2718 const auto factors = { 12, 8, 4, 0 };
2719 for (const auto factor : factors)
2720 {
2721 get();
2722
2723 if (current >= '0' and current <= '9')
2724 {
2725 codepoint += ((current - 0x30) << factor);
2726 }
2727 else if (current >= 'A' and current <= 'F')
2728 {
2729 codepoint += ((current - 0x37) << factor);
2730 }
2731 else if (current >= 'a' and current <= 'f')
2732 {
2733 codepoint += ((current - 0x57) << factor);
2734 }
2735 else
2736 {
2737 return -1;
2738 }
2739 }
2740
2741 assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
2742 return codepoint;
2743 }
2744
2760 bool next_byte_in_range(std::initializer_list<int> ranges)
2761 {
2762 assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
2763 add(current);
2764
2765 for (auto range = ranges.begin(); range != ranges.end(); ++range)
2766 {
2767 get();
2768 if (JSON_LIKELY(*range <= current and current <= *(++range)))
2769 {
2770 add(current);
2771 }
2772 else
2773 {
2774 error_message = "invalid string: ill-formed UTF-8 byte";
2775 return false;
2776 }
2777 }
2778
2779 return true;
2780 }
2781
2797 token_type scan_string()
2798 {
2799 // reset token_buffer (ignore opening quote)
2800 reset();
2801
2802 // we entered the function by reading an open quote
2803 assert(current == '\"');
2804
2805 while (true)
2806 {
2807 // get next character
2808 switch (get())
2809 {
2810 // end of file while parsing string
2811 case std::char_traits<char>::eof():
2812 {
2813 error_message = "invalid string: missing closing quote";
2814 return token_type::parse_error;
2815 }
2816
2817 // closing quote
2818 case '\"':
2819 {
2820 return token_type::value_string;
2821 }
2822
2823 // escapes
2824 case '\\':
2825 {
2826 switch (get())
2827 {
2828 // quotation mark
2829 case '\"':
2830 add('\"');
2831 break;
2832 // reverse solidus
2833 case '\\':
2834 add('\\');
2835 break;
2836 // solidus
2837 case '/':
2838 add('/');
2839 break;
2840 // backspace
2841 case 'b':
2842 add('\b');
2843 break;
2844 // form feed
2845 case 'f':
2846 add('\f');
2847 break;
2848 // line feed
2849 case 'n':
2850 add('\n');
2851 break;
2852 // carriage return
2853 case 'r':
2854 add('\r');
2855 break;
2856 // tab
2857 case 't':
2858 add('\t');
2859 break;
2860
2861 // unicode escapes
2862 case 'u':
2863 {
2864 const int codepoint1 = get_codepoint();
2865 int codepoint = codepoint1; // start with codepoint1
2866
2867 if (JSON_UNLIKELY(codepoint1 == -1))
2868 {
2869 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2870 return token_type::parse_error;
2871 }
2872
2873 // check if code point is a high surrogate
2874 if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
2875 {
2876 // expect next \uxxxx entry
2877 if (JSON_LIKELY(get() == '\\' and get() == 'u'))
2878 {
2879 const int codepoint2 = get_codepoint();
2880
2881 if (JSON_UNLIKELY(codepoint2 == -1))
2882 {
2883 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
2884 return token_type::parse_error;
2885 }
2886
2887 // check if codepoint2 is a low surrogate
2888 if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
2889 {
2890 // overwrite codepoint
2891 codepoint =
2892 // high surrogate occupies the most significant 22 bits
2893 (codepoint1 << 10)
2894 // low surrogate occupies the least significant 15 bits
2895 + codepoint2
2896 // there is still the 0xD800, 0xDC00 and 0x10000 noise
2897 // in the result so we have to subtract with:
2898 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
2899 - 0x35FDC00;
2900 }
2901 else
2902 {
2903 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2904 return token_type::parse_error;
2905 }
2906 }
2907 else
2908 {
2909 error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF";
2910 return token_type::parse_error;
2911 }
2912 }
2913 else
2914 {
2915 if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
2916 {
2917 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
2918 return token_type::parse_error;
2919 }
2920 }
2921
2922 // result of the above calculation yields a proper codepoint
2923 assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
2924
2925 // translate codepoint into bytes
2926 if (codepoint < 0x80)
2927 {
2928 // 1-byte characters: 0xxxxxxx (ASCII)
2929 add(codepoint);
2930 }
2931 else if (codepoint <= 0x7FF)
2932 {
2933 // 2-byte characters: 110xxxxx 10xxxxxx
2934 add(0xC0 | (codepoint >> 6));
2935 add(0x80 | (codepoint & 0x3F));
2936 }
2937 else if (codepoint <= 0xFFFF)
2938 {
2939 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
2940 add(0xE0 | (codepoint >> 12));
2941 add(0x80 | ((codepoint >> 6) & 0x3F));
2942 add(0x80 | (codepoint & 0x3F));
2943 }
2944 else
2945 {
2946 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2947 add(0xF0 | (codepoint >> 18));
2948 add(0x80 | ((codepoint >> 12) & 0x3F));
2949 add(0x80 | ((codepoint >> 6) & 0x3F));
2950 add(0x80 | (codepoint & 0x3F));
2951 }
2952
2953 break;
2954 }
2955
2956 // other characters after escape
2957 default:
2958 error_message = "invalid string: forbidden character after backslash";
2959 return token_type::parse_error;
2960 }
2961
2962 break;
2963 }
2964
2965 // invalid control characters
2966 case 0x00:
2967 {
2968 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
2969 return token_type::parse_error;
2970 }
2971
2972 case 0x01:
2973 {
2974 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
2975 return token_type::parse_error;
2976 }
2977
2978 case 0x02:
2979 {
2980 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
2981 return token_type::parse_error;
2982 }
2983
2984 case 0x03:
2985 {
2986 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
2987 return token_type::parse_error;
2988 }
2989
2990 case 0x04:
2991 {
2992 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
2993 return token_type::parse_error;
2994 }
2995
2996 case 0x05:
2997 {
2998 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
2999 return token_type::parse_error;
3000 }
3001
3002 case 0x06:
3003 {
3004 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
3005 return token_type::parse_error;
3006 }
3007
3008 case 0x07:
3009 {
3010 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
3011 return token_type::parse_error;
3012 }
3013
3014 case 0x08:
3015 {
3016 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
3017 return token_type::parse_error;
3018 }
3019
3020 case 0x09:
3021 {
3022 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
3023 return token_type::parse_error;
3024 }
3025
3026 case 0x0A:
3027 {
3028 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
3029 return token_type::parse_error;
3030 }
3031
3032 case 0x0B:
3033 {
3034 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
3035 return token_type::parse_error;
3036 }
3037
3038 case 0x0C:
3039 {
3040 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
3041 return token_type::parse_error;
3042 }
3043
3044 case 0x0D:
3045 {
3046 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
3047 return token_type::parse_error;
3048 }
3049
3050 case 0x0E:
3051 {
3052 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
3053 return token_type::parse_error;
3054 }
3055
3056 case 0x0F:
3057 {
3058 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
3059 return token_type::parse_error;
3060 }
3061
3062 case 0x10:
3063 {
3064 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
3065 return token_type::parse_error;
3066 }
3067
3068 case 0x11:
3069 {
3070 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
3071 return token_type::parse_error;
3072 }
3073
3074 case 0x12:
3075 {
3076 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
3077 return token_type::parse_error;
3078 }
3079
3080 case 0x13:
3081 {
3082 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
3083 return token_type::parse_error;
3084 }
3085
3086 case 0x14:
3087 {
3088 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
3089 return token_type::parse_error;
3090 }
3091
3092 case 0x15:
3093 {
3094 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
3095 return token_type::parse_error;
3096 }
3097
3098 case 0x16:
3099 {
3100 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
3101 return token_type::parse_error;
3102 }
3103
3104 case 0x17:
3105 {
3106 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
3107 return token_type::parse_error;
3108 }
3109
3110 case 0x18:
3111 {
3112 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
3113 return token_type::parse_error;
3114 }
3115
3116 case 0x19:
3117 {
3118 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
3119 return token_type::parse_error;
3120 }
3121
3122 case 0x1A:
3123 {
3124 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
3125 return token_type::parse_error;
3126 }
3127
3128 case 0x1B:
3129 {
3130 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
3131 return token_type::parse_error;
3132 }
3133
3134 case 0x1C:
3135 {
3136 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
3137 return token_type::parse_error;
3138 }
3139
3140 case 0x1D:
3141 {
3142 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
3143 return token_type::parse_error;
3144 }
3145
3146 case 0x1E:
3147 {
3148 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
3149 return token_type::parse_error;
3150 }
3151
3152 case 0x1F:
3153 {
3154 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
3155 return token_type::parse_error;
3156 }
3157
3158 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
3159 case 0x20:
3160 case 0x21:
3161 case 0x23:
3162 case 0x24:
3163 case 0x25:
3164 case 0x26:
3165 case 0x27:
3166 case 0x28:
3167 case 0x29:
3168 case 0x2A:
3169 case 0x2B:
3170 case 0x2C:
3171 case 0x2D:
3172 case 0x2E:
3173 case 0x2F:
3174 case 0x30:
3175 case 0x31:
3176 case 0x32:
3177 case 0x33:
3178 case 0x34:
3179 case 0x35:
3180 case 0x36:
3181 case 0x37:
3182 case 0x38:
3183 case 0x39:
3184 case 0x3A:
3185 case 0x3B:
3186 case 0x3C:
3187 case 0x3D:
3188 case 0x3E:
3189 case 0x3F:
3190 case 0x40:
3191 case 0x41:
3192 case 0x42:
3193 case 0x43:
3194 case 0x44:
3195 case 0x45:
3196 case 0x46:
3197 case 0x47:
3198 case 0x48:
3199 case 0x49:
3200 case 0x4A:
3201 case 0x4B:
3202 case 0x4C:
3203 case 0x4D:
3204 case 0x4E:
3205 case 0x4F:
3206 case 0x50:
3207 case 0x51:
3208 case 0x52:
3209 case 0x53:
3210 case 0x54:
3211 case 0x55:
3212 case 0x56:
3213 case 0x57:
3214 case 0x58:
3215 case 0x59:
3216 case 0x5A:
3217 case 0x5B:
3218 case 0x5D:
3219 case 0x5E:
3220 case 0x5F:
3221 case 0x60:
3222 case 0x61:
3223 case 0x62:
3224 case 0x63:
3225 case 0x64:
3226 case 0x65:
3227 case 0x66:
3228 case 0x67:
3229 case 0x68:
3230 case 0x69:
3231 case 0x6A:
3232 case 0x6B:
3233 case 0x6C:
3234 case 0x6D:
3235 case 0x6E:
3236 case 0x6F:
3237 case 0x70:
3238 case 0x71:
3239 case 0x72:
3240 case 0x73:
3241 case 0x74:
3242 case 0x75:
3243 case 0x76:
3244 case 0x77:
3245 case 0x78:
3246 case 0x79:
3247 case 0x7A:
3248 case 0x7B:
3249 case 0x7C:
3250 case 0x7D:
3251 case 0x7E:
3252 case 0x7F:
3253 {
3254 add(current);
3255 break;
3256 }
3257
3258 // U+0080..U+07FF: bytes C2..DF 80..BF
3259 case 0xC2:
3260 case 0xC3:
3261 case 0xC4:
3262 case 0xC5:
3263 case 0xC6:
3264 case 0xC7:
3265 case 0xC8:
3266 case 0xC9:
3267 case 0xCA:
3268 case 0xCB:
3269 case 0xCC:
3270 case 0xCD:
3271 case 0xCE:
3272 case 0xCF:
3273 case 0xD0:
3274 case 0xD1:
3275 case 0xD2:
3276 case 0xD3:
3277 case 0xD4:
3278 case 0xD5:
3279 case 0xD6:
3280 case 0xD7:
3281 case 0xD8:
3282 case 0xD9:
3283 case 0xDA:
3284 case 0xDB:
3285 case 0xDC:
3286 case 0xDD:
3287 case 0xDE:
3288 case 0xDF:
3289 {
3290 if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
3291 {
3292 return token_type::parse_error;
3293 }
3294 break;
3295 }
3296
3297 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
3298 case 0xE0:
3299 {
3300 if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
3301 {
3302 return token_type::parse_error;
3303 }
3304 break;
3305 }
3306
3307 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
3308 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
3309 case 0xE1:
3310 case 0xE2:
3311 case 0xE3:
3312 case 0xE4:
3313 case 0xE5:
3314 case 0xE6:
3315 case 0xE7:
3316 case 0xE8:
3317 case 0xE9:
3318 case 0xEA:
3319 case 0xEB:
3320 case 0xEC:
3321 case 0xEE:
3322 case 0xEF:
3323 {
3324 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
3325 {
3326 return token_type::parse_error;
3327 }
3328 break;
3329 }
3330
3331 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
3332 case 0xED:
3333 {
3334 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
3335 {
3336 return token_type::parse_error;
3337 }
3338 break;
3339 }
3340
3341 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
3342 case 0xF0:
3343 {
3344 if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
3345 {
3346 return token_type::parse_error;
3347 }
3348 break;
3349 }
3350
3351 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
3352 case 0xF1:
3353 case 0xF2:
3354 case 0xF3:
3355 {
3356 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
3357 {
3358 return token_type::parse_error;
3359 }
3360 break;
3361 }
3362
3363 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
3364 case 0xF4:
3365 {
3366 if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
3367 {
3368 return token_type::parse_error;
3369 }
3370 break;
3371 }
3372
3373 // remaining bytes (80..C1 and F5..FF) are ill-formed
3374 default:
3375 {
3376 error_message = "invalid string: ill-formed UTF-8 byte";
3377 return token_type::parse_error;
3378 }
3379 }
3380 }
3381 }
3382
3383 static void strtof(float& f, const char* str, char** endptr) noexcept
3384 {
3385 f = std::strtof(str, endptr);
3386 }
3387
3388 static void strtof(double& f, const char* str, char** endptr) noexcept
3389 {
3390 f = std::strtod(str, endptr);
3391 }
3392
3393 static void strtof(long double& f, const char* str, char** endptr) noexcept
3394 {
3395 f = std::strtold(str, endptr);
3396 }
3397
3438 token_type scan_number() // lgtm [cpp/use-of-goto]
3439 {
3440 // reset token_buffer to store the number's bytes
3441 reset();
3442
3443 // the type of the parsed number; initially set to unsigned; will be
3444 // changed if minus sign, decimal point or exponent is read
3445 token_type number_type = token_type::value_unsigned;
3446
3447 // state (init): we just found out we need to scan a number
3448 switch (current)
3449 {
3450 case '-':
3451 {
3452 add(current);
3453 goto scan_number_minus;
3454 }
3455
3456 case '0':
3457 {
3458 add(current);
3459 goto scan_number_zero;
3460 }
3461
3462 case '1':
3463 case '2':
3464 case '3':
3465 case '4':
3466 case '5':
3467 case '6':
3468 case '7':
3469 case '8':
3470 case '9':
3471 {
3472 add(current);
3473 goto scan_number_any1;
3474 }
3475
3476 // LCOV_EXCL_START
3477 default:
3478 {
3479 // all other characters are rejected outside scan_number()
3480 assert(false);
3481 }
3482 // LCOV_EXCL_STOP
3483 }
3484
3485scan_number_minus:
3486 // state: we just parsed a leading minus sign
3487 number_type = token_type::value_integer;
3488 switch (get())
3489 {
3490 case '0':
3491 {
3492 add(current);
3493 goto scan_number_zero;
3494 }
3495
3496 case '1':
3497 case '2':
3498 case '3':
3499 case '4':
3500 case '5':
3501 case '6':
3502 case '7':
3503 case '8':
3504 case '9':
3505 {
3506 add(current);
3507 goto scan_number_any1;
3508 }
3509
3510 default:
3511 {
3512 error_message = "invalid number; expected digit after '-'";
3513 return token_type::parse_error;
3514 }
3515 }
3516
3517scan_number_zero:
3518 // state: we just parse a zero (maybe with a leading minus sign)
3519 switch (get())
3520 {
3521 case '.':
3522 {
3523 add(decimal_point_char);
3524 goto scan_number_decimal1;
3525 }
3526
3527 case 'e':
3528 case 'E':
3529 {
3530 add(current);
3531 goto scan_number_exponent;
3532 }
3533
3534 default:
3535 goto scan_number_done;
3536 }
3537
3538scan_number_any1:
3539 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
3540 switch (get())
3541 {
3542 case '0':
3543 case '1':
3544 case '2':
3545 case '3':
3546 case '4':
3547 case '5':
3548 case '6':
3549 case '7':
3550 case '8':
3551 case '9':
3552 {
3553 add(current);
3554 goto scan_number_any1;
3555 }
3556
3557 case '.':
3558 {
3559 add(decimal_point_char);
3560 goto scan_number_decimal1;
3561 }
3562
3563 case 'e':
3564 case 'E':
3565 {
3566 add(current);
3567 goto scan_number_exponent;
3568 }
3569
3570 default:
3571 goto scan_number_done;
3572 }
3573
3574scan_number_decimal1:
3575 // state: we just parsed a decimal point
3576 number_type = token_type::value_float;
3577 switch (get())
3578 {
3579 case '0':
3580 case '1':
3581 case '2':
3582 case '3':
3583 case '4':
3584 case '5':
3585 case '6':
3586 case '7':
3587 case '8':
3588 case '9':
3589 {
3590 add(current);
3591 goto scan_number_decimal2;
3592 }
3593
3594 default:
3595 {
3596 error_message = "invalid number; expected digit after '.'";
3597 return token_type::parse_error;
3598 }
3599 }
3600
3601scan_number_decimal2:
3602 // we just parsed at least one number after a decimal point
3603 switch (get())
3604 {
3605 case '0':
3606 case '1':
3607 case '2':
3608 case '3':
3609 case '4':
3610 case '5':
3611 case '6':
3612 case '7':
3613 case '8':
3614 case '9':
3615 {
3616 add(current);
3617 goto scan_number_decimal2;
3618 }
3619
3620 case 'e':
3621 case 'E':
3622 {
3623 add(current);
3624 goto scan_number_exponent;
3625 }
3626
3627 default:
3628 goto scan_number_done;
3629 }
3630
3631scan_number_exponent:
3632 // we just parsed an exponent
3633 number_type = token_type::value_float;
3634 switch (get())
3635 {
3636 case '+':
3637 case '-':
3638 {
3639 add(current);
3640 goto scan_number_sign;
3641 }
3642
3643 case '0':
3644 case '1':
3645 case '2':
3646 case '3':
3647 case '4':
3648 case '5':
3649 case '6':
3650 case '7':
3651 case '8':
3652 case '9':
3653 {
3654 add(current);
3655 goto scan_number_any2;
3656 }
3657
3658 default:
3659 {
3660 error_message =
3661 "invalid number; expected '+', '-', or digit after exponent";
3662 return token_type::parse_error;
3663 }
3664 }
3665
3666scan_number_sign:
3667 // we just parsed an exponent sign
3668 switch (get())
3669 {
3670 case '0':
3671 case '1':
3672 case '2':
3673 case '3':
3674 case '4':
3675 case '5':
3676 case '6':
3677 case '7':
3678 case '8':
3679 case '9':
3680 {
3681 add(current);
3682 goto scan_number_any2;
3683 }
3684
3685 default:
3686 {
3687 error_message = "invalid number; expected digit after exponent sign";
3688 return token_type::parse_error;
3689 }
3690 }
3691
3692scan_number_any2:
3693 // we just parsed a number after the exponent or exponent sign
3694 switch (get())
3695 {
3696 case '0':
3697 case '1':
3698 case '2':
3699 case '3':
3700 case '4':
3701 case '5':
3702 case '6':
3703 case '7':
3704 case '8':
3705 case '9':
3706 {
3707 add(current);
3708 goto scan_number_any2;
3709 }
3710
3711 default:
3712 goto scan_number_done;
3713 }
3714
3715scan_number_done:
3716 // unget the character after the number (we only read it to know that
3717 // we are done scanning a number)
3718 unget();
3719
3720 char* endptr = nullptr;
3721 errno = 0;
3722
3723 // try to parse integers first and fall back to floats
3724 if (number_type == token_type::value_unsigned)
3725 {
3726 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
3727
3728 // we checked the number format before
3729 assert(endptr == token_buffer.data() + token_buffer.size());
3730
3731 if (errno == 0)
3732 {
3733 value_unsigned = static_cast<number_unsigned_t>(x);
3734 if (value_unsigned == x)
3735 {
3736 return token_type::value_unsigned;
3737 }
3738 }
3739 }
3740 else if (number_type == token_type::value_integer)
3741 {
3742 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
3743
3744 // we checked the number format before
3745 assert(endptr == token_buffer.data() + token_buffer.size());
3746
3747 if (errno == 0)
3748 {
3749 value_integer = static_cast<number_integer_t>(x);
3750 if (value_integer == x)
3751 {
3752 return token_type::value_integer;
3753 }
3754 }
3755 }
3756
3757 // this code is reached if we parse a floating-point number or if an
3758 // integer conversion above failed
3759 strtof(value_float, token_buffer.data(), &endptr);
3760
3761 // we checked the number format before
3762 assert(endptr == token_buffer.data() + token_buffer.size());
3763
3764 return token_type::value_float;
3765 }
3766
3772 token_type scan_literal(const char* literal_text, const std::size_t length,
3773 token_type return_type)
3774 {
3775 assert(current == literal_text[0]);
3776 for (std::size_t i = 1; i < length; ++i)
3777 {
3778 if (JSON_UNLIKELY(get() != literal_text[i]))
3779 {
3780 error_message = "invalid literal";
3781 return token_type::parse_error;
3782 }
3783 }
3784 return return_type;
3785 }
3786
3788 // input management
3790
3792 void reset() noexcept
3793 {
3794 token_buffer.clear();
3795 token_string.clear();
3796 token_string.push_back(std::char_traits<char>::to_char_type(current));
3797 }
3798
3799 /*
3800 @brief get next character from the input
3801
3802 This function provides the interface to the used input adapter. It does
3803 not throw in case the input reached EOF, but returns a
3804 `std::char_traits<char>::eof()` in that case. Stores the scanned characters
3805 for use in error messages.
3806
3807 @return character read from the input
3808 */
3809 std::char_traits<char>::int_type get()
3810 {
3811 ++position.chars_read_total;
3812 ++position.chars_read_current_line;
3813
3814 if (next_unget)
3815 {
3816 // just reset the next_unget variable and work with current
3817 next_unget = false;
3818 }
3819 else
3820 {
3821 current = ia->get_character();
3822 }
3823
3824 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3825 {
3826 token_string.push_back(std::char_traits<char>::to_char_type(current));
3827 }
3828
3829 if (current == '\n')
3830 {
3831 ++position.lines_read;
3832 ++position.chars_read_current_line = 0;
3833 }
3834
3835 return current;
3836 }
3837
3846 void unget()
3847 {
3848 next_unget = true;
3849
3850 --position.chars_read_total;
3851
3852 // in case we "unget" a newline, we have to also decrement the lines_read
3853 if (position.chars_read_current_line == 0)
3854 {
3855 if (position.lines_read > 0)
3856 {
3857 --position.lines_read;
3858 }
3859 }
3860 else
3861 {
3862 --position.chars_read_current_line;
3863 }
3864
3865 if (JSON_LIKELY(current != std::char_traits<char>::eof()))
3866 {
3867 assert(token_string.size() != 0);
3868 token_string.pop_back();
3869 }
3870 }
3871
3873 void add(int c)
3874 {
3875 token_buffer.push_back(std::char_traits<char>::to_char_type(c));
3876 }
3877
3878 public:
3880 // value getters
3882
3884 constexpr number_integer_t get_number_integer() const noexcept
3885 {
3886 return value_integer;
3887 }
3888
3890 constexpr number_unsigned_t get_number_unsigned() const noexcept
3891 {
3892 return value_unsigned;
3893 }
3894
3896 constexpr number_float_t get_number_float() const noexcept
3897 {
3898 return value_float;
3899 }
3900
3902 string_t& get_string()
3903 {
3904 return token_buffer;
3905 }
3906
3908 // diagnostics
3910
3912 constexpr position_t get_position() const noexcept
3913 {
3914 return position;
3915 }
3916
3920 std::string get_token_string() const
3921 {
3922 // escape control characters
3923 std::string result;
3924 for (const auto c : token_string)
3925 {
3926 if ('\x00' <= c and c <= '\x1F')
3927 {
3928 // escape control characters
3929 char cs[9];
3930 (std::snprintf)(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
3931 result += cs;
3932 }
3933 else
3934 {
3935 // add character as is
3936 result.push_back(c);
3937 }
3938 }
3939
3940 return result;
3941 }
3942
3944 constexpr const char* get_error_message() const noexcept
3945 {
3946 return error_message;
3947 }
3948
3950 // actual scanner
3952
3957 bool skip_bom()
3958 {
3959 if (get() == 0xEF)
3960 {
3961 // check if we completely parse the BOM
3962 return get() == 0xBB and get() == 0xBF;
3963 }
3964
3965 // the first character is not the beginning of the BOM; unget it to
3966 // process is later
3967 unget();
3968 return true;
3969 }
3970
3971 token_type scan()
3972 {
3973 // initially, skip the BOM
3974 if (position.chars_read_total == 0 and not skip_bom())
3975 {
3976 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
3977 return token_type::parse_error;
3978 }
3979
3980 // read next character and ignore whitespace
3981 do
3982 {
3983 get();
3984 }
3985 while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
3986
3987 switch (current)
3988 {
3989 // structural characters
3990 case '[':
3991 return token_type::begin_array;
3992 case ']':
3993 return token_type::end_array;
3994 case '{':
3995 return token_type::begin_object;
3996 case '}':
3997 return token_type::end_object;
3998 case ':':
3999 return token_type::name_separator;
4000 case ',':
4001 return token_type::value_separator;
4002
4003 // literals
4004 case 't':
4005 return scan_literal("true", 4, token_type::literal_true);
4006 case 'f':
4007 return scan_literal("false", 5, token_type::literal_false);
4008 case 'n':
4009 return scan_literal("null", 4, token_type::literal_null);
4010
4011 // string
4012 case '\"':
4013 return scan_string();
4014
4015 // number
4016 case '-':
4017 case '0':
4018 case '1':
4019 case '2':
4020 case '3':
4021 case '4':
4022 case '5':
4023 case '6':
4024 case '7':
4025 case '8':
4026 case '9':
4027 return scan_number();
4028
4029 // end of input (the null byte is needed when parsing from
4030 // string literals)
4031 case '\0':
4032 case std::char_traits<char>::eof():
4033 return token_type::end_of_input;
4034
4035 // error
4036 default:
4037 error_message = "invalid literal";
4038 return token_type::parse_error;
4039 }
4040 }
4041
4042 private:
4044 detail::input_adapter_t ia = nullptr;
4045
4047 std::char_traits<char>::int_type current = std::char_traits<char>::eof();
4048
4050 bool next_unget = false;
4051
4053 position_t position;
4054
4056 std::vector<char> token_string {};
4057
4059 string_t token_buffer {};
4060
4062 const char* error_message = "";
4063
4064 // number values
4065 number_integer_t value_integer = 0;
4066 number_unsigned_t value_unsigned = 0;
4067 number_float_t value_float = 0;
4068
4070 const char decimal_point_char = '.';
4071};
4072} // namespace detail
4073} // namespace nlohmann
4074
4075// #include <nlohmann/detail/input/parser.hpp>
4076
4077
4078#include <cassert> // assert
4079#include <cmath> // isfinite
4080#include <cstdint> // uint8_t
4081#include <functional> // function
4082#include <string> // string
4083#include <utility> // move
4084
4085// #include <nlohmann/detail/exceptions.hpp>
4086
4087// #include <nlohmann/detail/macro_scope.hpp>
4088
4089// #include <nlohmann/detail/meta/is_sax.hpp>
4090
4091
4092#include <cstdint> // size_t
4093#include <utility> // declval
4094
4095// #include <nlohmann/detail/meta/detected.hpp>
4096
4097// #include <nlohmann/detail/meta/type_traits.hpp>
4098
4099
4100namespace nlohmann
4101{
4102namespace detail
4103{
4104template <typename T>
4105using null_function_t = decltype(std::declval<T&>().null());
4106
4107template <typename T>
4108using boolean_function_t =
4109 decltype(std::declval<T&>().boolean(std::declval<bool>()));
4110
4111template <typename T, typename Integer>
4112using number_integer_function_t =
4113 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
4114
4115template <typename T, typename Unsigned>
4116using number_unsigned_function_t =
4117 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
4118
4119template <typename T, typename Float, typename String>
4120using number_float_function_t = decltype(std::declval<T&>().number_float(
4121 std::declval<Float>(), std::declval<const String&>()));
4122
4123template <typename T, typename String>
4124using string_function_t =
4125 decltype(std::declval<T&>().string(std::declval<String&>()));
4126
4127template <typename T>
4128using start_object_function_t =
4129 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
4130
4131template <typename T, typename String>
4132using key_function_t =
4133 decltype(std::declval<T&>().key(std::declval<String&>()));
4134
4135template <typename T>
4136using end_object_function_t = decltype(std::declval<T&>().end_object());
4137
4138template <typename T>
4139using start_array_function_t =
4140 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
4141
4142template <typename T>
4143using end_array_function_t = decltype(std::declval<T&>().end_array());
4144
4145template <typename T, typename Exception>
4146using parse_error_function_t = decltype(std::declval<T&>().parse_error(
4147 std::declval<std::size_t>(), std::declval<const std::string&>(),
4148 std::declval<const Exception&>()));
4149
4150template <typename SAX, typename BasicJsonType>
4152{
4153 private:
4155 "BasicJsonType must be of type basic_json<...>");
4156
4157 using number_integer_t = typename BasicJsonType::number_integer_t;
4158 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4159 using number_float_t = typename BasicJsonType::number_float_t;
4160 using string_t = typename BasicJsonType::string_t;
4161 using exception_t = typename BasicJsonType::exception;
4162
4163 public:
4164 static constexpr bool value =
4165 is_detected_exact<bool, null_function_t, SAX>::value &&
4166 is_detected_exact<bool, boolean_function_t, SAX>::value &&
4167 is_detected_exact<bool, number_integer_function_t, SAX,
4168 number_integer_t>::value &&
4169 is_detected_exact<bool, number_unsigned_function_t, SAX,
4170 number_unsigned_t>::value &&
4171 is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
4172 string_t>::value &&
4173 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
4174 is_detected_exact<bool, start_object_function_t, SAX>::value &&
4175 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
4176 is_detected_exact<bool, end_object_function_t, SAX>::value &&
4177 is_detected_exact<bool, start_array_function_t, SAX>::value &&
4178 is_detected_exact<bool, end_array_function_t, SAX>::value &&
4179 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
4180};
4181
4182template <typename SAX, typename BasicJsonType>
4184{
4185 private:
4187 "BasicJsonType must be of type basic_json<...>");
4188
4189 using number_integer_t = typename BasicJsonType::number_integer_t;
4190 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4191 using number_float_t = typename BasicJsonType::number_float_t;
4192 using string_t = typename BasicJsonType::string_t;
4193 using exception_t = typename BasicJsonType::exception;
4194
4195 public:
4196 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
4197 "Missing/invalid function: bool null()");
4198 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
4199 "Missing/invalid function: bool boolean(bool)");
4200 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
4201 "Missing/invalid function: bool boolean(bool)");
4202 static_assert(
4203 is_detected_exact<bool, number_integer_function_t, SAX,
4204 number_integer_t>::value,
4205 "Missing/invalid function: bool number_integer(number_integer_t)");
4206 static_assert(
4207 is_detected_exact<bool, number_unsigned_function_t, SAX,
4208 number_unsigned_t>::value,
4209 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
4210 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
4211 number_float_t, string_t>::value,
4212 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
4213 static_assert(
4214 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
4215 "Missing/invalid function: bool string(string_t&)");
4216 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
4217 "Missing/invalid function: bool start_object(std::size_t)");
4218 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
4219 "Missing/invalid function: bool key(string_t&)");
4220 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
4221 "Missing/invalid function: bool end_object()");
4222 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
4223 "Missing/invalid function: bool start_array(std::size_t)");
4224 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
4225 "Missing/invalid function: bool end_array()");
4226 static_assert(
4227 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
4228 "Missing/invalid function: bool parse_error(std::size_t, const "
4229 "std::string&, const exception&)");
4230};
4231} // namespace detail
4232} // namespace nlohmann
4233
4234// #include <nlohmann/detail/input/input_adapters.hpp>
4235
4236// #include <nlohmann/detail/input/json_sax.hpp>
4237
4238
4239#include <cstddef>
4240#include <string>
4241#include <vector>
4242
4243// #include <nlohmann/detail/input/parser.hpp>
4244
4245// #include <nlohmann/detail/exceptions.hpp>
4246
4247
4248namespace nlohmann
4249{
4250
4259template<typename BasicJsonType>
4261{
4263 using number_integer_t = typename BasicJsonType::number_integer_t;
4265 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4267 using number_float_t = typename BasicJsonType::number_float_t;
4269 using string_t = typename BasicJsonType::string_t;
4270
4275 virtual bool null() = 0;
4276
4282 virtual bool boolean(bool val) = 0;
4283
4289 virtual bool number_integer(number_integer_t val) = 0;
4290
4296 virtual bool number_unsigned(number_unsigned_t val) = 0;
4297
4304 virtual bool number_float(number_float_t val, const string_t& s) = 0;
4305
4312 virtual bool string(string_t& val) = 0;
4313
4320 virtual bool start_object(std::size_t elements) = 0;
4321
4328 virtual bool key(string_t& val) = 0;
4329
4334 virtual bool end_object() = 0;
4335
4342 virtual bool start_array(std::size_t elements) = 0;
4343
4348 virtual bool end_array() = 0;
4349
4357 virtual bool parse_error(std::size_t position,
4358 const std::string& last_token,
4359 const detail::exception& ex) = 0;
4360
4361 virtual ~json_sax() = default;
4362};
4363
4364
4365namespace detail
4366{
4380template<typename BasicJsonType>
4382{
4383 public:
4384 using number_integer_t = typename BasicJsonType::number_integer_t;
4385 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4386 using number_float_t = typename BasicJsonType::number_float_t;
4387 using string_t = typename BasicJsonType::string_t;
4388
4394 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
4395 : root(r), allow_exceptions(allow_exceptions_)
4396 {}
4397
4398 bool null()
4399 {
4400 handle_value(nullptr);
4401 return true;
4402 }
4403
4404 bool boolean(bool val)
4405 {
4406 handle_value(val);
4407 return true;
4408 }
4409
4410 bool number_integer(number_integer_t val)
4411 {
4412 handle_value(val);
4413 return true;
4414 }
4415
4416 bool number_unsigned(number_unsigned_t val)
4417 {
4418 handle_value(val);
4419 return true;
4420 }
4421
4422 bool number_float(number_float_t val, const string_t& /*unused*/)
4423 {
4424 handle_value(val);
4425 return true;
4426 }
4427
4428 bool string(string_t& val)
4429 {
4430 handle_value(val);
4431 return true;
4432 }
4433
4434 bool start_object(std::size_t len)
4435 {
4436 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
4437
4438 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4439 {
4440 JSON_THROW(out_of_range::create(408,
4441 "excessive object size: " + std::to_string(len)));
4442 }
4443
4444 return true;
4445 }
4446
4447 bool key(string_t& val)
4448 {
4449 // add null at given key and store the reference for later
4450 object_element = &(ref_stack.back()->m_value.object->operator[](val));
4451 return true;
4452 }
4453
4454 bool end_object()
4455 {
4456 ref_stack.pop_back();
4457 return true;
4458 }
4459
4460 bool start_array(std::size_t len)
4461 {
4462 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
4463
4464 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4465 {
4466 JSON_THROW(out_of_range::create(408,
4467 "excessive array size: " + std::to_string(len)));
4468 }
4469
4470 return true;
4471 }
4472
4473 bool end_array()
4474 {
4475 ref_stack.pop_back();
4476 return true;
4477 }
4478
4479 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
4480 const detail::exception& ex)
4481 {
4482 errored = true;
4483 if (allow_exceptions)
4484 {
4485 // determine the proper exception type from the id
4486 switch ((ex.id / 100) % 100)
4487 {
4488 case 1:
4489 JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
4490 case 4:
4491 JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
4492 // LCOV_EXCL_START
4493 case 2:
4494 JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4495 case 3:
4496 JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4497 case 5:
4498 JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4499 default:
4500 assert(false);
4501 // LCOV_EXCL_STOP
4502 }
4503 }
4504 return false;
4505 }
4506
4507 constexpr bool is_errored() const
4508 {
4509 return errored;
4510 }
4511
4512 private:
4519 template<typename Value>
4520 BasicJsonType* handle_value(Value&& v)
4521 {
4522 if (ref_stack.empty())
4523 {
4524 root = BasicJsonType(std::forward<Value>(v));
4525 return &root;
4526 }
4527
4528 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4529
4530 if (ref_stack.back()->is_array())
4531 {
4532 ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
4533 return &(ref_stack.back()->m_value.array->back());
4534 }
4535 else
4536 {
4537 assert(object_element);
4538 *object_element = BasicJsonType(std::forward<Value>(v));
4539 return object_element;
4540 }
4541 }
4542
4544 BasicJsonType& root;
4546 std::vector<BasicJsonType*> ref_stack;
4548 BasicJsonType* object_element = nullptr;
4550 bool errored = false;
4552 const bool allow_exceptions = true;
4553};
4554
4555template<typename BasicJsonType>
4557{
4558 public:
4559 using number_integer_t = typename BasicJsonType::number_integer_t;
4560 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4561 using number_float_t = typename BasicJsonType::number_float_t;
4562 using string_t = typename BasicJsonType::string_t;
4563 using parser_callback_t = typename BasicJsonType::parser_callback_t;
4564 using parse_event_t = typename BasicJsonType::parse_event_t;
4565
4566 json_sax_dom_callback_parser(BasicJsonType& r,
4567 const parser_callback_t cb,
4568 const bool allow_exceptions_ = true)
4569 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
4570 {
4571 keep_stack.push_back(true);
4572 }
4573
4574 bool null()
4575 {
4576 handle_value(nullptr);
4577 return true;
4578 }
4579
4580 bool boolean(bool val)
4581 {
4582 handle_value(val);
4583 return true;
4584 }
4585
4586 bool number_integer(number_integer_t val)
4587 {
4588 handle_value(val);
4589 return true;
4590 }
4591
4592 bool number_unsigned(number_unsigned_t val)
4593 {
4594 handle_value(val);
4595 return true;
4596 }
4597
4598 bool number_float(number_float_t val, const string_t& /*unused*/)
4599 {
4600 handle_value(val);
4601 return true;
4602 }
4603
4604 bool string(string_t& val)
4605 {
4606 handle_value(val);
4607 return true;
4608 }
4609
4610 bool start_object(std::size_t len)
4611 {
4612 // check callback for object start
4613 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
4614 keep_stack.push_back(keep);
4615
4616 auto val = handle_value(BasicJsonType::value_t::object, true);
4617 ref_stack.push_back(val.second);
4618
4619 // check object limit
4620 if (ref_stack.back())
4621 {
4622 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4623 {
4624 JSON_THROW(out_of_range::create(408,
4625 "excessive object size: " + std::to_string(len)));
4626 }
4627 }
4628
4629 return true;
4630 }
4631
4632 bool key(string_t& val)
4633 {
4634 BasicJsonType k = BasicJsonType(val);
4635
4636 // check callback for key
4637 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
4638 key_keep_stack.push_back(keep);
4639
4640 // add discarded value at given key and store the reference for later
4641 if (keep and ref_stack.back())
4642 {
4643 object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
4644 }
4645
4646 return true;
4647 }
4648
4649 bool end_object()
4650 {
4651 if (ref_stack.back())
4652 {
4653 if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
4654 {
4655 // discard object
4656 *ref_stack.back() = discarded;
4657 }
4658 }
4659
4660 assert(not ref_stack.empty());
4661 assert(not keep_stack.empty());
4662 ref_stack.pop_back();
4663 keep_stack.pop_back();
4664
4665 if (not ref_stack.empty() and ref_stack.back())
4666 {
4667 // remove discarded value
4668 if (ref_stack.back()->is_object())
4669 {
4670 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
4671 {
4672 if (it->is_discarded())
4673 {
4674 ref_stack.back()->erase(it);
4675 break;
4676 }
4677 }
4678 }
4679 }
4680
4681 return true;
4682 }
4683
4684 bool start_array(std::size_t len)
4685 {
4686 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
4687 keep_stack.push_back(keep);
4688
4689 auto val = handle_value(BasicJsonType::value_t::array, true);
4690 ref_stack.push_back(val.second);
4691
4692 // check array limit
4693 if (ref_stack.back())
4694 {
4695 if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
4696 {
4697 JSON_THROW(out_of_range::create(408,
4698 "excessive array size: " + std::to_string(len)));
4699 }
4700 }
4701
4702 return true;
4703 }
4704
4705 bool end_array()
4706 {
4707 bool keep = true;
4708
4709 if (ref_stack.back())
4710 {
4711 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
4712 if (not keep)
4713 {
4714 // discard array
4715 *ref_stack.back() = discarded;
4716 }
4717 }
4718
4719 assert(not ref_stack.empty());
4720 assert(not keep_stack.empty());
4721 ref_stack.pop_back();
4722 keep_stack.pop_back();
4723
4724 // remove discarded value
4725 if (not keep and not ref_stack.empty())
4726 {
4727 if (ref_stack.back()->is_array())
4728 {
4729 ref_stack.back()->m_value.array->pop_back();
4730 }
4731 }
4732
4733 return true;
4734 }
4735
4736 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
4737 const detail::exception& ex)
4738 {
4739 errored = true;
4740 if (allow_exceptions)
4741 {
4742 // determine the proper exception type from the id
4743 switch ((ex.id / 100) % 100)
4744 {
4745 case 1:
4746 JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
4747 case 4:
4748 JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
4749 // LCOV_EXCL_START
4750 case 2:
4751 JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
4752 case 3:
4753 JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
4754 case 5:
4755 JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
4756 default:
4757 assert(false);
4758 // LCOV_EXCL_STOP
4759 }
4760 }
4761 return false;
4762 }
4763
4764 constexpr bool is_errored() const
4765 {
4766 return errored;
4767 }
4768
4769 private:
4785 template<typename Value>
4786 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
4787 {
4788 assert(not keep_stack.empty());
4789
4790 // do not handle this value if we know it would be added to a discarded
4791 // container
4792 if (not keep_stack.back())
4793 {
4794 return {false, nullptr};
4795 }
4796
4797 // create value
4798 auto value = BasicJsonType(std::forward<Value>(v));
4799
4800 // check callback
4801 const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
4802
4803 // do not handle this value if we just learnt it shall be discarded
4804 if (not keep)
4805 {
4806 return {false, nullptr};
4807 }
4808
4809 if (ref_stack.empty())
4810 {
4811 root = std::move(value);
4812 return {true, &root};
4813 }
4814
4815 // skip this value if we already decided to skip the parent
4816 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
4817 if (not ref_stack.back())
4818 {
4819 return {false, nullptr};
4820 }
4821
4822 // we now only expect arrays and objects
4823 assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
4824
4825 if (ref_stack.back()->is_array())
4826 {
4827 ref_stack.back()->m_value.array->push_back(std::move(value));
4828 return {true, &(ref_stack.back()->m_value.array->back())};
4829 }
4830 else
4831 {
4832 // check if we should store an element for the current key
4833 assert(not key_keep_stack.empty());
4834 const bool store_element = key_keep_stack.back();
4835 key_keep_stack.pop_back();
4836
4837 if (not store_element)
4838 {
4839 return {false, nullptr};
4840 }
4841
4842 assert(object_element);
4843 *object_element = std::move(value);
4844 return {true, object_element};
4845 }
4846 }
4847
4849 BasicJsonType& root;
4851 std::vector<BasicJsonType*> ref_stack;
4853 std::vector<bool> keep_stack;
4855 std::vector<bool> key_keep_stack;
4857 BasicJsonType* object_element = nullptr;
4859 bool errored = false;
4861 const parser_callback_t callback = nullptr;
4863 const bool allow_exceptions = true;
4865 BasicJsonType discarded = BasicJsonType::value_t::discarded;
4866};
4867
4868template<typename BasicJsonType>
4870{
4871 public:
4872 using number_integer_t = typename BasicJsonType::number_integer_t;
4873 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4874 using number_float_t = typename BasicJsonType::number_float_t;
4875 using string_t = typename BasicJsonType::string_t;
4876
4877 bool null()
4878 {
4879 return true;
4880 }
4881
4882 bool boolean(bool /*unused*/)
4883 {
4884 return true;
4885 }
4886
4887 bool number_integer(number_integer_t /*unused*/)
4888 {
4889 return true;
4890 }
4891
4892 bool number_unsigned(number_unsigned_t /*unused*/)
4893 {
4894 return true;
4895 }
4896
4897 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
4898 {
4899 return true;
4900 }
4901
4902 bool string(string_t& /*unused*/)
4903 {
4904 return true;
4905 }
4906
4907 bool start_object(std::size_t /*unused*/ = std::size_t(-1))
4908 {
4909 return true;
4910 }
4911
4912 bool key(string_t& /*unused*/)
4913 {
4914 return true;
4915 }
4916
4917 bool end_object()
4918 {
4919 return true;
4920 }
4921
4922 bool start_array(std::size_t /*unused*/ = std::size_t(-1))
4923 {
4924 return true;
4925 }
4926
4927 bool end_array()
4928 {
4929 return true;
4930 }
4931
4932 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
4933 {
4934 return false;
4935 }
4936};
4937} // namespace detail
4938
4939} // namespace nlohmann
4940
4941// #include <nlohmann/detail/input/lexer.hpp>
4942
4943// #include <nlohmann/detail/value_t.hpp>
4944
4945
4946namespace nlohmann
4947{
4948namespace detail
4949{
4951// parser //
4953
4959template<typename BasicJsonType>
4961{
4962 using number_integer_t = typename BasicJsonType::number_integer_t;
4963 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
4964 using number_float_t = typename BasicJsonType::number_float_t;
4965 using string_t = typename BasicJsonType::string_t;
4966 using lexer_t = lexer<BasicJsonType>;
4967 using token_type = typename lexer_t::token_type;
4968
4969 public:
4970 enum class parse_event_t : uint8_t
4971 {
4975 object_end,
4979 array_end,
4981 key,
4983 value
4984 };
4985
4986 using parser_callback_t =
4987 std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
4988
4991 const parser_callback_t cb = nullptr,
4992 const bool allow_exceptions_ = true)
4993 : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
4994 {
4995 // read first token
4996 get_token();
4997 }
4998
5009 void parse(const bool strict, BasicJsonType& result)
5010 {
5011 if (callback)
5012 {
5013 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
5014 sax_parse_internal(&sdp);
5015 result.assert_invariant();
5016
5017 // in strict mode, input must be completely read
5018 if (strict and (get_token() != token_type::end_of_input))
5019 {
5020 sdp.parse_error(m_lexer.get_position(),
5021 m_lexer.get_token_string(),
5022 parse_error::create(101, m_lexer.get_position(),
5023 exception_message(token_type::end_of_input, "value")));
5024 }
5025
5026 // in case of an error, return discarded value
5027 if (sdp.is_errored())
5028 {
5029 result = value_t::discarded;
5030 return;
5031 }
5032
5033 // set top-level value to null if it was discarded by the callback
5034 // function
5035 if (result.is_discarded())
5036 {
5037 result = nullptr;
5038 }
5039 }
5040 else
5041 {
5042 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
5043 sax_parse_internal(&sdp);
5044 result.assert_invariant();
5045
5046 // in strict mode, input must be completely read
5047 if (strict and (get_token() != token_type::end_of_input))
5048 {
5049 sdp.parse_error(m_lexer.get_position(),
5050 m_lexer.get_token_string(),
5051 parse_error::create(101, m_lexer.get_position(),
5052 exception_message(token_type::end_of_input, "value")));
5053 }
5054
5055 // in case of an error, return discarded value
5056 if (sdp.is_errored())
5057 {
5058 result = value_t::discarded;
5059 return;
5060 }
5061 }
5062 }
5063
5070 bool accept(const bool strict = true)
5071 {
5073 return sax_parse(&sax_acceptor, strict);
5074 }
5075
5076 template <typename SAX>
5077 bool sax_parse(SAX* sax, const bool strict = true)
5078 {
5080 const bool result = sax_parse_internal(sax);
5081
5082 // strict mode: next byte must be EOF
5083 if (result and strict and (get_token() != token_type::end_of_input))
5084 {
5085 return sax->parse_error(m_lexer.get_position(),
5086 m_lexer.get_token_string(),
5087 parse_error::create(101, m_lexer.get_position(),
5088 exception_message(token_type::end_of_input, "value")));
5089 }
5090
5091 return result;
5092 }
5093
5094 private:
5095 template <typename SAX>
5096 bool sax_parse_internal(SAX* sax)
5097 {
5098 // stack to remember the hierarchy of structured values we are parsing
5099 // true = array; false = object
5100 std::vector<bool> states;
5101 // value to avoid a goto (see comment where set to true)
5102 bool skip_to_state_evaluation = false;
5103
5104 while (true)
5105 {
5106 if (not skip_to_state_evaluation)
5107 {
5108 // invariant: get_token() was called before each iteration
5109 switch (last_token)
5110 {
5111 case token_type::begin_object:
5112 {
5113 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
5114 {
5115 return false;
5116 }
5117
5118 // closing } -> we are done
5119 if (get_token() == token_type::end_object)
5120 {
5121 if (JSON_UNLIKELY(not sax->end_object()))
5122 {
5123 return false;
5124 }
5125 break;
5126 }
5127
5128 // parse key
5129 if (JSON_UNLIKELY(last_token != token_type::value_string))
5130 {
5131 return sax->parse_error(m_lexer.get_position(),
5132 m_lexer.get_token_string(),
5133 parse_error::create(101, m_lexer.get_position(),
5134 exception_message(token_type::value_string, "object key")));
5135 }
5136 if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
5137 {
5138 return false;
5139 }
5140
5141 // parse separator (:)
5142 if (JSON_UNLIKELY(get_token() != token_type::name_separator))
5143 {
5144 return sax->parse_error(m_lexer.get_position(),
5145 m_lexer.get_token_string(),
5146 parse_error::create(101, m_lexer.get_position(),
5147 exception_message(token_type::name_separator, "object separator")));
5148 }
5149
5150 // remember we are now inside an object
5151 states.push_back(false);
5152
5153 // parse values
5154 get_token();
5155 continue;
5156 }
5157
5158 case token_type::begin_array:
5159 {
5160 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
5161 {
5162 return false;
5163 }
5164
5165 // closing ] -> we are done
5166 if (get_token() == token_type::end_array)
5167 {
5168 if (JSON_UNLIKELY(not sax->end_array()))
5169 {
5170 return false;
5171 }
5172 break;
5173 }
5174
5175 // remember we are now inside an array
5176 states.push_back(true);
5177
5178 // parse values (no need to call get_token)
5179 continue;
5180 }
5181
5182 case token_type::value_float:
5183 {
5184 const auto res = m_lexer.get_number_float();
5185
5186 if (JSON_UNLIKELY(not std::isfinite(res)))
5187 {
5188 return sax->parse_error(m_lexer.get_position(),
5189 m_lexer.get_token_string(),
5190 out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
5191 }
5192 else
5193 {
5194 if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
5195 {
5196 return false;
5197 }
5198 break;
5199 }
5200 }
5201
5202 case token_type::literal_false:
5203 {
5204 if (JSON_UNLIKELY(not sax->boolean(false)))
5205 {
5206 return false;
5207 }
5208 break;
5209 }
5210
5211 case token_type::literal_null:
5212 {
5213 if (JSON_UNLIKELY(not sax->null()))
5214 {
5215 return false;
5216 }
5217 break;
5218 }
5219
5220 case token_type::literal_true:
5221 {
5222 if (JSON_UNLIKELY(not sax->boolean(true)))
5223 {
5224 return false;
5225 }
5226 break;
5227 }
5228
5229 case token_type::value_integer:
5230 {
5231 if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
5232 {
5233 return false;
5234 }
5235 break;
5236 }
5237
5238 case token_type::value_string:
5239 {
5240 if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
5241 {
5242 return false;
5243 }
5244 break;
5245 }
5246
5247 case token_type::value_unsigned:
5248 {
5249 if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
5250 {
5251 return false;
5252 }
5253 break;
5254 }
5255
5256 case token_type::parse_error:
5257 {
5258 // using "uninitialized" to avoid "expected" message
5259 return sax->parse_error(m_lexer.get_position(),
5260 m_lexer.get_token_string(),
5261 parse_error::create(101, m_lexer.get_position(),
5262 exception_message(token_type::uninitialized, "value")));
5263 }
5264
5265 default: // the last token was unexpected
5266 {
5267 return sax->parse_error(m_lexer.get_position(),
5268 m_lexer.get_token_string(),
5269 parse_error::create(101, m_lexer.get_position(),
5270 exception_message(token_type::literal_or_value, "value")));
5271 }
5272 }
5273 }
5274 else
5275 {
5276 skip_to_state_evaluation = false;
5277 }
5278
5279 // we reached this line after we successfully parsed a value
5280 if (states.empty())
5281 {
5282 // empty stack: we reached the end of the hierarchy: done
5283 return true;
5284 }
5285 else
5286 {
5287 if (states.back()) // array
5288 {
5289 // comma -> next value
5290 if (get_token() == token_type::value_separator)
5291 {
5292 // parse a new value
5293 get_token();
5294 continue;
5295 }
5296
5297 // closing ]
5298 if (JSON_LIKELY(last_token == token_type::end_array))
5299 {
5300 if (JSON_UNLIKELY(not sax->end_array()))
5301 {
5302 return false;
5303 }
5304
5305 // We are done with this array. Before we can parse a
5306 // new value, we need to evaluate the new state first.
5307 // By setting skip_to_state_evaluation to false, we
5308 // are effectively jumping to the beginning of this if.
5309 assert(not states.empty());
5310 states.pop_back();
5311 skip_to_state_evaluation = true;
5312 continue;
5313 }
5314 else
5315 {
5316 return sax->parse_error(m_lexer.get_position(),
5317 m_lexer.get_token_string(),
5318 parse_error::create(101, m_lexer.get_position(),
5319 exception_message(token_type::end_array, "array")));
5320 }
5321 }
5322 else // object
5323 {
5324 // comma -> next value
5325 if (get_token() == token_type::value_separator)
5326 {
5327 // parse key
5328 if (JSON_UNLIKELY(get_token() != token_type::value_string))
5329 {
5330 return sax->parse_error(m_lexer.get_position(),
5331 m_lexer.get_token_string(),
5332 parse_error::create(101, m_lexer.get_position(),
5333 exception_message(token_type::value_string, "object key")));
5334 }
5335 else
5336 {
5337 if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
5338 {
5339 return false;
5340 }
5341 }
5342
5343 // parse separator (:)
5344 if (JSON_UNLIKELY(get_token() != token_type::name_separator))
5345 {
5346 return sax->parse_error(m_lexer.get_position(),
5347 m_lexer.get_token_string(),
5348 parse_error::create(101, m_lexer.get_position(),
5349 exception_message(token_type::name_separator, "object separator")));
5350 }
5351
5352 // parse values
5353 get_token();
5354 continue;
5355 }
5356
5357 // closing }
5358 if (JSON_LIKELY(last_token == token_type::end_object))
5359 {
5360 if (JSON_UNLIKELY(not sax->end_object()))
5361 {
5362 return false;
5363 }
5364
5365 // We are done with this object. Before we can parse a
5366 // new value, we need to evaluate the new state first.
5367 // By setting skip_to_state_evaluation to false, we
5368 // are effectively jumping to the beginning of this if.
5369 assert(not states.empty());
5370 states.pop_back();
5371 skip_to_state_evaluation = true;
5372 continue;
5373 }
5374 else
5375 {
5376 return sax->parse_error(m_lexer.get_position(),
5377 m_lexer.get_token_string(),
5378 parse_error::create(101, m_lexer.get_position(),
5379 exception_message(token_type::end_object, "object")));
5380 }
5381 }
5382 }
5383 }
5384 }
5385
5387 token_type get_token()
5388 {
5389 return (last_token = m_lexer.scan());
5390 }
5391
5392 std::string exception_message(const token_type expected, const std::string& context)
5393 {
5394 std::string error_msg = "syntax error ";
5395
5396 if (not context.empty())
5397 {
5398 error_msg += "while parsing " + context + " ";
5399 }
5400
5401 error_msg += "- ";
5402
5403 if (last_token == token_type::parse_error)
5404 {
5405 error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
5406 m_lexer.get_token_string() + "'";
5407 }
5408 else
5409 {
5410 error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
5411 }
5412
5413 if (expected != token_type::uninitialized)
5414 {
5415 error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
5416 }
5417
5418 return error_msg;
5419 }
5420
5421 private:
5423 const parser_callback_t callback = nullptr;
5425 token_type last_token = token_type::uninitialized;
5427 lexer_t m_lexer;
5429 const bool allow_exceptions = true;
5430};
5431} // namespace detail
5432} // namespace nlohmann
5433
5434// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5435
5436
5437#include <cstddef> // ptrdiff_t
5438#include <limits> // numeric_limits
5439
5440namespace nlohmann
5441{
5442namespace detail
5443{
5444/*
5445@brief an iterator for primitive JSON types
5446
5447This class models an iterator for primitive JSON types (boolean, number,
5448string). It's only purpose is to allow the iterator/const_iterator classes
5449to "iterate" over primitive values. Internally, the iterator is modeled by
5450a `difference_type` variable. Value begin_value (`0`) models the begin,
5451end_value (`1`) models past the end.
5452*/
5454{
5455 private:
5456 using difference_type = std::ptrdiff_t;
5457 static constexpr difference_type begin_value = 0;
5458 static constexpr difference_type end_value = begin_value + 1;
5459
5461 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
5462
5463 public:
5464 constexpr difference_type get_value() const noexcept
5465 {
5466 return m_it;
5467 }
5468
5470 void set_begin() noexcept
5471 {
5472 m_it = begin_value;
5473 }
5474
5476 void set_end() noexcept
5477 {
5478 m_it = end_value;
5479 }
5480
5482 constexpr bool is_begin() const noexcept
5483 {
5484 return m_it == begin_value;
5485 }
5486
5488 constexpr bool is_end() const noexcept
5489 {
5490 return m_it == end_value;
5491 }
5492
5493 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5494 {
5495 return lhs.m_it == rhs.m_it;
5496 }
5497
5498 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5499 {
5500 return lhs.m_it < rhs.m_it;
5501 }
5502
5503 primitive_iterator_t operator+(difference_type n) noexcept
5504 {
5505 auto result = *this;
5506 result += n;
5507 return result;
5508 }
5509
5510 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
5511 {
5512 return lhs.m_it - rhs.m_it;
5513 }
5514
5515 primitive_iterator_t& operator++() noexcept
5516 {
5517 ++m_it;
5518 return *this;
5519 }
5520
5521 primitive_iterator_t const operator++(int) noexcept
5522 {
5523 auto result = *this;
5524 ++m_it;
5525 return result;
5526 }
5527
5528 primitive_iterator_t& operator--() noexcept
5529 {
5530 --m_it;
5531 return *this;
5532 }
5533
5534 primitive_iterator_t const operator--(int) noexcept
5535 {
5536 auto result = *this;
5537 --m_it;
5538 return result;
5539 }
5540
5541 primitive_iterator_t& operator+=(difference_type n) noexcept
5542 {
5543 m_it += n;
5544 return *this;
5545 }
5546
5547 primitive_iterator_t& operator-=(difference_type n) noexcept
5548 {
5549 m_it -= n;
5550 return *this;
5551 }
5552};
5553} // namespace detail
5554} // namespace nlohmann
5555
5556// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5557
5558
5559// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5560
5561
5562namespace nlohmann
5563{
5564namespace detail
5565{
5572template<typename BasicJsonType> struct internal_iterator
5573{
5575 typename BasicJsonType::object_t::iterator object_iterator {};
5577 typename BasicJsonType::array_t::iterator array_iterator {};
5580};
5581} // namespace detail
5582} // namespace nlohmann
5583
5584// #include <nlohmann/detail/iterators/iter_impl.hpp>
5585
5586
5587#include <ciso646> // not
5588#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
5589#include <type_traits> // conditional, is_const, remove_const
5590
5591// #include <nlohmann/detail/exceptions.hpp>
5592
5593// #include <nlohmann/detail/iterators/internal_iterator.hpp>
5594
5595// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
5596
5597// #include <nlohmann/detail/macro_scope.hpp>
5598
5599// #include <nlohmann/detail/meta/cpp_future.hpp>
5600
5601// #include <nlohmann/detail/value_t.hpp>
5602
5603
5604namespace nlohmann
5605{
5606namespace detail
5607{
5608// forward declare, to be able to friend it later on
5609template<typename IteratorType> class iteration_proxy;
5610template<typename IteratorType> class iteration_proxy_value;
5611
5628template<typename BasicJsonType>
5630{
5632 friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
5633 friend BasicJsonType;
5634 friend iteration_proxy<iter_impl>;
5635 friend iteration_proxy_value<iter_impl>;
5636
5637 using object_t = typename BasicJsonType::object_t;
5638 using array_t = typename BasicJsonType::array_t;
5639 // make sure BasicJsonType is basic_json or const basic_json
5641 "iter_impl only accepts (const) basic_json");
5642
5643 public:
5644
5650 using iterator_category = std::bidirectional_iterator_tag;
5651
5653 using value_type = typename BasicJsonType::value_type;
5655 using difference_type = typename BasicJsonType::difference_type;
5657 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
5658 typename BasicJsonType::const_pointer,
5659 typename BasicJsonType::pointer>::type;
5662 typename std::conditional<std::is_const<BasicJsonType>::value,
5663 typename BasicJsonType::const_reference,
5664 typename BasicJsonType::reference>::type;
5665
5667 iter_impl() = default;
5668
5675 explicit iter_impl(pointer object) noexcept : m_object(object)
5676 {
5677 assert(m_object != nullptr);
5678
5679 switch (m_object->m_type)
5680 {
5681 case value_t::object:
5682 {
5683 m_it.object_iterator = typename object_t::iterator();
5684 break;
5685 }
5686
5687 case value_t::array:
5688 {
5689 m_it.array_iterator = typename array_t::iterator();
5690 break;
5691 }
5692
5693 default:
5694 {
5696 break;
5697 }
5698 }
5699 }
5700
5715 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5716 : m_object(other.m_object), m_it(other.m_it) {}
5717
5724 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
5725 {
5726 m_object = other.m_object;
5727 m_it = other.m_it;
5728 return *this;
5729 }
5730
5731 private:
5736 void set_begin() noexcept
5737 {
5738 assert(m_object != nullptr);
5739
5740 switch (m_object->m_type)
5741 {
5742 case value_t::object:
5743 {
5744 m_it.object_iterator = m_object->m_value.object->begin();
5745 break;
5746 }
5747
5748 case value_t::array:
5749 {
5750 m_it.array_iterator = m_object->m_value.array->begin();
5751 break;
5752 }
5753
5754 case value_t::null:
5755 {
5756 // set to end so begin()==end() is true: null is empty
5758 break;
5759 }
5760
5761 default:
5762 {
5764 break;
5765 }
5766 }
5767 }
5768
5773 void set_end() noexcept
5774 {
5775 assert(m_object != nullptr);
5776
5777 switch (m_object->m_type)
5778 {
5779 case value_t::object:
5780 {
5781 m_it.object_iterator = m_object->m_value.object->end();
5782 break;
5783 }
5784
5785 case value_t::array:
5786 {
5787 m_it.array_iterator = m_object->m_value.array->end();
5788 break;
5789 }
5790
5791 default:
5792 {
5794 break;
5795 }
5796 }
5797 }
5798
5799 public:
5805 {
5806 assert(m_object != nullptr);
5807
5808 switch (m_object->m_type)
5809 {
5810 case value_t::object:
5811 {
5812 assert(m_it.object_iterator != m_object->m_value.object->end());
5813 return m_it.object_iterator->second;
5814 }
5815
5816 case value_t::array:
5817 {
5818 assert(m_it.array_iterator != m_object->m_value.array->end());
5819 return *m_it.array_iterator;
5820 }
5821
5822 case value_t::null:
5823 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5824
5825 default:
5826 {
5827 if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5828 {
5829 return *m_object;
5830 }
5831
5832 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5833 }
5834 }
5835 }
5836
5842 {
5843 assert(m_object != nullptr);
5844
5845 switch (m_object->m_type)
5846 {
5847 case value_t::object:
5848 {
5849 assert(m_it.object_iterator != m_object->m_value.object->end());
5850 return &(m_it.object_iterator->second);
5851 }
5852
5853 case value_t::array:
5854 {
5855 assert(m_it.array_iterator != m_object->m_value.array->end());
5856 return &*m_it.array_iterator;
5857 }
5858
5859 default:
5860 {
5861 if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
5862 {
5863 return m_object;
5864 }
5865
5866 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
5867 }
5868 }
5869 }
5870
5876 {
5877 auto result = *this;
5878 ++(*this);
5879 return result;
5880 }
5881
5887 {
5888 assert(m_object != nullptr);
5889
5890 switch (m_object->m_type)
5891 {
5892 case value_t::object:
5893 {
5894 std::advance(m_it.object_iterator, 1);
5895 break;
5896 }
5897
5898 case value_t::array:
5899 {
5900 std::advance(m_it.array_iterator, 1);
5901 break;
5902 }
5903
5904 default:
5905 {
5906 ++m_it.primitive_iterator;
5907 break;
5908 }
5909 }
5910
5911 return *this;
5912 }
5913
5919 {
5920 auto result = *this;
5921 --(*this);
5922 return result;
5923 }
5924
5930 {
5931 assert(m_object != nullptr);
5932
5933 switch (m_object->m_type)
5934 {
5935 case value_t::object:
5936 {
5937 std::advance(m_it.object_iterator, -1);
5938 break;
5939 }
5940
5941 case value_t::array:
5942 {
5943 std::advance(m_it.array_iterator, -1);
5944 break;
5945 }
5946
5947 default:
5948 {
5949 --m_it.primitive_iterator;
5950 break;
5951 }
5952 }
5953
5954 return *this;
5955 }
5956
5961 bool operator==(const iter_impl& other) const
5962 {
5963 // if objects are not the same, the comparison is undefined
5964 if (JSON_UNLIKELY(m_object != other.m_object))
5965 {
5966 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
5967 }
5968
5969 assert(m_object != nullptr);
5970
5971 switch (m_object->m_type)
5972 {
5973 case value_t::object:
5974 return (m_it.object_iterator == other.m_it.object_iterator);
5975
5976 case value_t::array:
5977 return (m_it.array_iterator == other.m_it.array_iterator);
5978
5979 default:
5980 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
5981 }
5982 }
5983
5988 bool operator!=(const iter_impl& other) const
5989 {
5990 return not operator==(other);
5991 }
5992
5997 bool operator<(const iter_impl& other) const
5998 {
5999 // if objects are not the same, the comparison is undefined
6000 if (JSON_UNLIKELY(m_object != other.m_object))
6001 {
6002 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
6003 }
6004
6005 assert(m_object != nullptr);
6006
6007 switch (m_object->m_type)
6008 {
6009 case value_t::object:
6010 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
6011
6012 case value_t::array:
6013 return (m_it.array_iterator < other.m_it.array_iterator);
6014
6015 default:
6016 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
6017 }
6018 }
6019
6024 bool operator<=(const iter_impl& other) const
6025 {
6026 return not other.operator < (*this);
6027 }
6028
6033 bool operator>(const iter_impl& other) const
6034 {
6035 return not operator<=(other);
6036 }
6037
6042 bool operator>=(const iter_impl& other) const
6043 {
6044 return not operator<(other);
6045 }
6046
6052 {
6053 assert(m_object != nullptr);
6054
6055 switch (m_object->m_type)
6056 {
6057 case value_t::object:
6058 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
6059
6060 case value_t::array:
6061 {
6062 std::advance(m_it.array_iterator, i);
6063 break;
6064 }
6065
6066 default:
6067 {
6068 m_it.primitive_iterator += i;
6069 break;
6070 }
6071 }
6072
6073 return *this;
6074 }
6075
6081 {
6082 return operator+=(-i);
6083 }
6084
6090 {
6091 auto result = *this;
6092 result += i;
6093 return result;
6094 }
6095
6101 {
6102 auto result = it;
6103 result += i;
6104 return result;
6105 }
6106
6112 {
6113 auto result = *this;
6114 result -= i;
6115 return result;
6116 }
6117
6123 {
6124 assert(m_object != nullptr);
6125
6126 switch (m_object->m_type)
6127 {
6128 case value_t::object:
6129 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
6130
6131 case value_t::array:
6132 return m_it.array_iterator - other.m_it.array_iterator;
6133
6134 default:
6135 return m_it.primitive_iterator - other.m_it.primitive_iterator;
6136 }
6137 }
6138
6144 {
6145 assert(m_object != nullptr);
6146
6147 switch (m_object->m_type)
6148 {
6149 case value_t::object:
6150 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
6151
6152 case value_t::array:
6153 return *std::next(m_it.array_iterator, n);
6154
6155 case value_t::null:
6156 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
6157
6158 default:
6159 {
6160 if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
6161 {
6162 return *m_object;
6163 }
6164
6165 JSON_THROW(invalid_iterator::create(214, "cannot get value"));
6166 }
6167 }
6168 }
6169
6174 const typename object_t::key_type& key() const
6175 {
6176 assert(m_object != nullptr);
6177
6178 if (JSON_LIKELY(m_object->is_object()))
6179 {
6180 return m_it.object_iterator->first;
6181 }
6182
6183 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
6184 }
6185
6191 {
6192 return operator*();
6193 }
6194
6195 private:
6197 pointer m_object = nullptr;
6200};
6201} // namespace detail
6202} // namespace nlohmann
6203// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
6204
6205// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
6206
6207
6208#include <cstddef> // ptrdiff_t
6209#include <iterator> // reverse_iterator
6210#include <utility> // declval
6211
6212namespace nlohmann
6213{
6214namespace detail
6215{
6217// reverse_iterator //
6219
6238template<typename Base>
6239class json_reverse_iterator : public std::reverse_iterator<Base>
6240{
6241 public:
6242 using difference_type = std::ptrdiff_t;
6244 using base_iterator = std::reverse_iterator<Base>;
6246 using reference = typename Base::reference;
6247
6249 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
6250 : base_iterator(it) {}
6251
6253 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
6254
6256 json_reverse_iterator const operator++(int)
6257 {
6258 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
6259 }
6260
6262 json_reverse_iterator& operator++()
6263 {
6264 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
6265 }
6266
6268 json_reverse_iterator const operator--(int)
6269 {
6270 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
6271 }
6272
6274 json_reverse_iterator& operator--()
6275 {
6276 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
6277 }
6278
6280 json_reverse_iterator& operator+=(difference_type i)
6281 {
6282 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
6283 }
6284
6286 json_reverse_iterator operator+(difference_type i) const
6287 {
6288 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
6289 }
6290
6292 json_reverse_iterator operator-(difference_type i) const
6293 {
6294 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
6295 }
6296
6298 difference_type operator-(const json_reverse_iterator& other) const
6299 {
6300 return base_iterator(*this) - base_iterator(other);
6301 }
6302
6304 reference operator[](difference_type n) const
6305 {
6306 return *(this->operator+(n));
6307 }
6308
6310 auto key() const -> decltype(std::declval<Base>().key())
6311 {
6312 auto it = --this->base();
6313 return it.key();
6314 }
6315
6317 reference value() const
6318 {
6319 auto it = --this->base();
6320 return it.operator * ();
6321 }
6322};
6323} // namespace detail
6324} // namespace nlohmann
6325
6326// #include <nlohmann/detail/output/output_adapters.hpp>
6327
6328
6329#include <algorithm> // copy
6330#include <cstddef> // size_t
6331#include <ios> // streamsize
6332#include <iterator> // back_inserter
6333#include <memory> // shared_ptr, make_shared
6334#include <ostream> // basic_ostream
6335#include <string> // basic_string
6336#include <vector> // vector
6337
6338namespace nlohmann
6339{
6340namespace detail
6341{
6343template<typename CharType> struct output_adapter_protocol
6344{
6345 virtual void write_character(CharType c) = 0;
6346 virtual void write_characters(const CharType* s, std::size_t length) = 0;
6347 virtual ~output_adapter_protocol() = default;
6348};
6349
6351template<typename CharType>
6352using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
6353
6355template<typename CharType>
6357{
6358 public:
6359 explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
6360 : v(vec)
6361 {}
6362
6363 void write_character(CharType c) override
6364 {
6365 v.push_back(c);
6366 }
6367
6368 void write_characters(const CharType* s, std::size_t length) override
6369 {
6370 std::copy(s, s + length, std::back_inserter(v));
6371 }
6372
6373 private:
6374 std::vector<CharType>& v;
6375};
6376
6378template<typename CharType>
6380{
6381 public:
6382 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
6383 : stream(s)
6384 {}
6385
6386 void write_character(CharType c) override
6387 {
6388 stream.put(c);
6389 }
6390
6391 void write_characters(const CharType* s, std::size_t length) override
6392 {
6393 stream.write(s, static_cast<std::streamsize>(length));
6394 }
6395
6396 private:
6397 std::basic_ostream<CharType>& stream;
6398};
6399
6401template<typename CharType, typename StringType = std::basic_string<CharType>>
6403{
6404 public:
6405 explicit output_string_adapter(StringType& s) noexcept
6406 : str(s)
6407 {}
6408
6409 void write_character(CharType c) override
6410 {
6411 str.push_back(c);
6412 }
6413
6414 void write_characters(const CharType* s, std::size_t length) override
6415 {
6416 str.append(s, length);
6417 }
6418
6419 private:
6420 StringType& str;
6421};
6422
6423template<typename CharType, typename StringType = std::basic_string<CharType>>
6425{
6426 public:
6427 output_adapter(std::vector<CharType>& vec)
6428 : oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
6429
6430 output_adapter(std::basic_ostream<CharType>& s)
6431 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
6432
6433 output_adapter(StringType& s)
6434 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
6435
6437 {
6438 return oa;
6439 }
6440
6441 private:
6442 output_adapter_t<CharType> oa = nullptr;
6443};
6444} // namespace detail
6445} // namespace nlohmann
6446
6447// #include <nlohmann/detail/input/binary_reader.hpp>
6448
6449
6450#include <algorithm> // generate_n
6451#include <array> // array
6452#include <cassert> // assert
6453#include <cmath> // ldexp
6454#include <cstddef> // size_t
6455#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6456#include <cstdio> // snprintf
6457#include <cstring> // memcpy
6458#include <iterator> // back_inserter
6459#include <limits> // numeric_limits
6460#include <string> // char_traits, string
6461#include <utility> // make_pair, move
6462
6463// #include <nlohmann/detail/input/input_adapters.hpp>
6464
6465// #include <nlohmann/detail/input/json_sax.hpp>
6466
6467// #include <nlohmann/detail/exceptions.hpp>
6468
6469// #include <nlohmann/detail/macro_scope.hpp>
6470
6471// #include <nlohmann/detail/meta/is_sax.hpp>
6472
6473// #include <nlohmann/detail/value_t.hpp>
6474
6475
6476namespace nlohmann
6477{
6478namespace detail
6479{
6481// binary reader //
6483
6487template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
6488class binary_reader
6489{
6490 using number_integer_t = typename BasicJsonType::number_integer_t;
6491 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6492 using number_float_t = typename BasicJsonType::number_float_t;
6493 using string_t = typename BasicJsonType::string_t;
6494 using json_sax_t = SAX;
6495
6496 public:
6502 explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
6503 {
6504 (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
6505 assert(ia);
6506 }
6507
6515 bool sax_parse(const input_format_t format,
6516 json_sax_t* sax_,
6517 const bool strict = true)
6518 {
6519 sax = sax_;
6520 bool result = false;
6521
6522 switch (format)
6523 {
6524 case input_format_t::bson:
6525 result = parse_bson_internal();
6526 break;
6527
6528 case input_format_t::cbor:
6529 result = parse_cbor_internal();
6530 break;
6531
6532 case input_format_t::msgpack:
6533 result = parse_msgpack_internal();
6534 break;
6535
6536 case input_format_t::ubjson:
6537 result = parse_ubjson_internal();
6538 break;
6539
6540 // LCOV_EXCL_START
6541 default:
6542 assert(false);
6543 // LCOV_EXCL_STOP
6544 }
6545
6546 // strict mode: next byte must be EOF
6547 if (result and strict)
6548 {
6549 if (format == input_format_t::ubjson)
6550 {
6551 get_ignore_noop();
6552 }
6553 else
6554 {
6555 get();
6556 }
6557
6558 if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
6559 {
6560 return sax->parse_error(chars_read, get_token_string(),
6561 parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
6562 }
6563 }
6564
6565 return result;
6566 }
6567
6575 static constexpr bool little_endianess(int num = 1) noexcept
6576 {
6577 return (*reinterpret_cast<char*>(&num) == 1);
6578 }
6579
6580 private:
6582 // BSON //
6584
6589 bool parse_bson_internal()
6590 {
6591 std::int32_t document_size;
6592 get_number<std::int32_t, true>(input_format_t::bson, document_size);
6593
6594 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
6595 {
6596 return false;
6597 }
6598
6599 if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))
6600 {
6601 return false;
6602 }
6603
6604 return sax->end_object();
6605 }
6606
6614 bool get_bson_cstr(string_t& result)
6615 {
6616 auto out = std::back_inserter(result);
6617 while (true)
6618 {
6619 get();
6620 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring")))
6621 {
6622 return false;
6623 }
6624 if (current == 0x00)
6625 {
6626 return true;
6627 }
6628 *out++ = static_cast<char>(current);
6629 }
6630
6631 return true;
6632 }
6633
6645 template<typename NumberType>
6646 bool get_bson_string(const NumberType len, string_t& result)
6647 {
6648 if (JSON_UNLIKELY(len < 1))
6649 {
6650 auto last_token = get_token_string();
6651 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")));
6652 }
6653
6654 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) and get() != std::char_traits<char>::eof();
6655 }
6656
6667 bool parse_bson_element_internal(const int element_type,
6668 const std::size_t element_type_parse_position)
6669 {
6670 switch (element_type)
6671 {
6672 case 0x01: // double
6673 {
6674 double number;
6675 return get_number<double, true>(input_format_t::bson, number) and sax->number_float(static_cast<number_float_t>(number), "");
6676 }
6677
6678 case 0x02: // string
6679 {
6680 std::int32_t len;
6681 string_t value;
6682 return get_number<std::int32_t, true>(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value);
6683 }
6684
6685 case 0x03: // object
6686 {
6687 return parse_bson_internal();
6688 }
6689
6690 case 0x04: // array
6691 {
6692 return parse_bson_array();
6693 }
6694
6695 case 0x08: // boolean
6696 {
6697 return sax->boolean(get() != 0);
6698 }
6699
6700 case 0x0A: // null
6701 {
6702 return sax->null();
6703 }
6704
6705 case 0x10: // int32
6706 {
6707 std::int32_t value;
6708 return get_number<std::int32_t, true>(input_format_t::bson, value) and sax->number_integer(value);
6709 }
6710
6711 case 0x12: // int64
6712 {
6713 std::int64_t value;
6714 return get_number<std::int64_t, true>(input_format_t::bson, value) and sax->number_integer(value);
6715 }
6716
6717 default: // anything else not supported (yet)
6718 {
6719 char cr[3];
6720 (std::snprintf)(cr, sizeof(cr), "%.2hhX", static_cast<unsigned char>(element_type));
6721 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)));
6722 }
6723 }
6724 }
6725
6738 bool parse_bson_element_list(const bool is_array)
6739 {
6740 string_t key;
6741 while (int element_type = get())
6742 {
6743 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list")))
6744 {
6745 return false;
6746 }
6747
6748 const std::size_t element_type_parse_position = chars_read;
6749 if (JSON_UNLIKELY(not get_bson_cstr(key)))
6750 {
6751 return false;
6752 }
6753
6754 if (not is_array)
6755 {
6756 if (not sax->key(key))
6757 {
6758 return false;
6759 }
6760 }
6761
6762 if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
6763 {
6764 return false;
6765 }
6766
6767 // get_bson_cstr only appends
6768 key.clear();
6769 }
6770
6771 return true;
6772 }
6773
6778 bool parse_bson_array()
6779 {
6780 std::int32_t document_size;
6781 get_number<std::int32_t, true>(input_format_t::bson, document_size);
6782
6783 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
6784 {
6785 return false;
6786 }
6787
6788 if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))
6789 {
6790 return false;
6791 }
6792
6793 return sax->end_array();
6794 }
6795
6797 // CBOR //
6799
6807 bool parse_cbor_internal(const bool get_char = true)
6808 {
6809 switch (get_char ? get() : current)
6810 {
6811 // EOF
6812 case std::char_traits<char>::eof():
6813 return unexpect_eof(input_format_t::cbor, "value");
6814
6815 // Integer 0x00..0x17 (0..23)
6816 case 0x00:
6817 case 0x01:
6818 case 0x02:
6819 case 0x03:
6820 case 0x04:
6821 case 0x05:
6822 case 0x06:
6823 case 0x07:
6824 case 0x08:
6825 case 0x09:
6826 case 0x0A:
6827 case 0x0B:
6828 case 0x0C:
6829 case 0x0D:
6830 case 0x0E:
6831 case 0x0F:
6832 case 0x10:
6833 case 0x11:
6834 case 0x12:
6835 case 0x13:
6836 case 0x14:
6837 case 0x15:
6838 case 0x16:
6839 case 0x17:
6840 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
6841
6842 case 0x18: // Unsigned integer (one-byte uint8_t follows)
6843 {
6844 uint8_t number;
6845 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6846 }
6847
6848 case 0x19: // Unsigned integer (two-byte uint16_t follows)
6849 {
6850 uint16_t number;
6851 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6852 }
6853
6854 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
6855 {
6856 uint32_t number;
6857 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6858 }
6859
6860 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
6861 {
6862 uint64_t number;
6863 return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
6864 }
6865
6866 // Negative integer -1-0x00..-1-0x17 (-1..-24)
6867 case 0x20:
6868 case 0x21:
6869 case 0x22:
6870 case 0x23:
6871 case 0x24:
6872 case 0x25:
6873 case 0x26:
6874 case 0x27:
6875 case 0x28:
6876 case 0x29:
6877 case 0x2A:
6878 case 0x2B:
6879 case 0x2C:
6880 case 0x2D:
6881 case 0x2E:
6882 case 0x2F:
6883 case 0x30:
6884 case 0x31:
6885 case 0x32:
6886 case 0x33:
6887 case 0x34:
6888 case 0x35:
6889 case 0x36:
6890 case 0x37:
6891 return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
6892
6893 case 0x38: // Negative integer (one-byte uint8_t follows)
6894 {
6895 uint8_t number;
6896 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6897 }
6898
6899 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
6900 {
6901 uint16_t number;
6902 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6903 }
6904
6905 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
6906 {
6907 uint32_t number;
6908 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
6909 }
6910
6911 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
6912 {
6913 uint64_t number;
6914 return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
6915 - static_cast<number_integer_t>(number));
6916 }
6917
6918 // UTF-8 string (0x00..0x17 bytes follow)
6919 case 0x60:
6920 case 0x61:
6921 case 0x62:
6922 case 0x63:
6923 case 0x64:
6924 case 0x65:
6925 case 0x66:
6926 case 0x67:
6927 case 0x68:
6928 case 0x69:
6929 case 0x6A:
6930 case 0x6B:
6931 case 0x6C:
6932 case 0x6D:
6933 case 0x6E:
6934 case 0x6F:
6935 case 0x70:
6936 case 0x71:
6937 case 0x72:
6938 case 0x73:
6939 case 0x74:
6940 case 0x75:
6941 case 0x76:
6942 case 0x77:
6943 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
6944 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
6945 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
6946 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
6947 case 0x7F: // UTF-8 string (indefinite length)
6948 {
6949 string_t s;
6950 return get_cbor_string(s) and sax->string(s);
6951 }
6952
6953 // array (0x00..0x17 data items follow)
6954 case 0x80:
6955 case 0x81:
6956 case 0x82:
6957 case 0x83:
6958 case 0x84:
6959 case 0x85:
6960 case 0x86:
6961 case 0x87:
6962 case 0x88:
6963 case 0x89:
6964 case 0x8A:
6965 case 0x8B:
6966 case 0x8C:
6967 case 0x8D:
6968 case 0x8E:
6969 case 0x8F:
6970 case 0x90:
6971 case 0x91:
6972 case 0x92:
6973 case 0x93:
6974 case 0x94:
6975 case 0x95:
6976 case 0x96:
6977 case 0x97:
6978 return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
6979
6980 case 0x98: // array (one-byte uint8_t for n follows)
6981 {
6982 uint8_t len;
6983 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
6984 }
6985
6986 case 0x99: // array (two-byte uint16_t for n follow)
6987 {
6988 uint16_t len;
6989 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
6990 }
6991
6992 case 0x9A: // array (four-byte uint32_t for n follow)
6993 {
6994 uint32_t len;
6995 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
6996 }
6997
6998 case 0x9B: // array (eight-byte uint64_t for n follow)
6999 {
7000 uint64_t len;
7001 return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
7002 }
7003
7004 case 0x9F: // array (indefinite length)
7005 return get_cbor_array(std::size_t(-1));
7006
7007 // map (0x00..0x17 pairs of data items follow)
7008 case 0xA0:
7009 case 0xA1:
7010 case 0xA2:
7011 case 0xA3:
7012 case 0xA4:
7013 case 0xA5:
7014 case 0xA6:
7015 case 0xA7:
7016 case 0xA8:
7017 case 0xA9:
7018 case 0xAA:
7019 case 0xAB:
7020 case 0xAC:
7021 case 0xAD:
7022 case 0xAE:
7023 case 0xAF:
7024 case 0xB0:
7025 case 0xB1:
7026 case 0xB2:
7027 case 0xB3:
7028 case 0xB4:
7029 case 0xB5:
7030 case 0xB6:
7031 case 0xB7:
7032 return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
7033
7034 case 0xB8: // map (one-byte uint8_t for n follows)
7035 {
7036 uint8_t len;
7037 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
7038 }
7039
7040 case 0xB9: // map (two-byte uint16_t for n follow)
7041 {
7042 uint16_t len;
7043 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
7044 }
7045
7046 case 0xBA: // map (four-byte uint32_t for n follow)
7047 {
7048 uint32_t len;
7049 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
7050 }
7051
7052 case 0xBB: // map (eight-byte uint64_t for n follow)
7053 {
7054 uint64_t len;
7055 return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
7056 }
7057
7058 case 0xBF: // map (indefinite length)
7059 return get_cbor_object(std::size_t(-1));
7060
7061 case 0xF4: // false
7062 return sax->boolean(false);
7063
7064 case 0xF5: // true
7065 return sax->boolean(true);
7066
7067 case 0xF6: // null
7068 return sax->null();
7069
7070 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
7071 {
7072 const int byte1_raw = get();
7073 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
7074 {
7075 return false;
7076 }
7077 const int byte2_raw = get();
7078 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
7079 {
7080 return false;
7081 }
7082
7083 const auto byte1 = static_cast<unsigned char>(byte1_raw);
7084 const auto byte2 = static_cast<unsigned char>(byte2_raw);
7085
7086 // code from RFC 7049, Appendix D, Figure 3:
7087 // As half-precision floating-point numbers were only added
7088 // to IEEE 754 in 2008, today's programming platforms often
7089 // still only have limited support for them. It is very
7090 // easy to include at least decoding support for them even
7091 // without such support. An example of a small decoder for
7092 // half-precision floating-point numbers in the C language
7093 // is shown in Fig. 3.
7094 const int half = (byte1 << 8) + byte2;
7095 const double val = [&half]
7096 {
7097 const int exp = (half >> 10) & 0x1F;
7098 const int mant = half & 0x3FF;
7099 assert(0 <= exp and exp <= 32);
7100 assert(0 <= mant and mant <= 1024);
7101 switch (exp)
7102 {
7103 case 0:
7104 return std::ldexp(mant, -24);
7105 case 31:
7106 return (mant == 0)
7107 ? std::numeric_limits<double>::infinity()
7108 : std::numeric_limits<double>::quiet_NaN();
7109 default:
7110 return std::ldexp(mant + 1024, exp - 25);
7111 }
7112 }();
7113 return sax->number_float((half & 0x8000) != 0
7114 ? static_cast<number_float_t>(-val)
7115 : static_cast<number_float_t>(val), "");
7116 }
7117
7118 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
7119 {
7120 float number;
7121 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
7122 }
7123
7124 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
7125 {
7126 double number;
7127 return get_number(input_format_t::cbor, number) and sax->number_float(static_cast<number_float_t>(number), "");
7128 }
7129
7130 default: // anything else (0xFF is handled inside the other types)
7131 {
7132 auto last_token = get_token_string();
7133 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")));
7134 }
7135 }
7136 }
7137
7149 bool get_cbor_string(string_t& result)
7150 {
7151 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string")))
7152 {
7153 return false;
7154 }
7155
7156 switch (current)
7157 {
7158 // UTF-8 string (0x00..0x17 bytes follow)
7159 case 0x60:
7160 case 0x61:
7161 case 0x62:
7162 case 0x63:
7163 case 0x64:
7164 case 0x65:
7165 case 0x66:
7166 case 0x67:
7167 case 0x68:
7168 case 0x69:
7169 case 0x6A:
7170 case 0x6B:
7171 case 0x6C:
7172 case 0x6D:
7173 case 0x6E:
7174 case 0x6F:
7175 case 0x70:
7176 case 0x71:
7177 case 0x72:
7178 case 0x73:
7179 case 0x74:
7180 case 0x75:
7181 case 0x76:
7182 case 0x77:
7183 {
7184 return get_string(input_format_t::cbor, current & 0x1F, result);
7185 }
7186
7187 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
7188 {
7189 uint8_t len;
7190 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7191 }
7192
7193 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
7194 {
7195 uint16_t len;
7196 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7197 }
7198
7199 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
7200 {
7201 uint32_t len;
7202 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7203 }
7204
7205 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
7206 {
7207 uint64_t len;
7208 return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
7209 }
7210
7211 case 0x7F: // UTF-8 string (indefinite length)
7212 {
7213 while (get() != 0xFF)
7214 {
7215 string_t chunk;
7216 if (not get_cbor_string(chunk))
7217 {
7218 return false;
7219 }
7220 result.append(chunk);
7221 }
7222 return true;
7223 }
7224
7225 default:
7226 {
7227 auto last_token = get_token_string();
7228 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")));
7229 }
7230 }
7231 }
7232
7238 bool get_cbor_array(const std::size_t len)
7239 {
7240 if (JSON_UNLIKELY(not sax->start_array(len)))
7241 {
7242 return false;
7243 }
7244
7245 if (len != std::size_t(-1))
7246 {
7247 for (std::size_t i = 0; i < len; ++i)
7248 {
7249 if (JSON_UNLIKELY(not parse_cbor_internal()))
7250 {
7251 return false;
7252 }
7253 }
7254 }
7255 else
7256 {
7257 while (get() != 0xFF)
7258 {
7259 if (JSON_UNLIKELY(not parse_cbor_internal(false)))
7260 {
7261 return false;
7262 }
7263 }
7264 }
7265
7266 return sax->end_array();
7267 }
7268
7274 bool get_cbor_object(const std::size_t len)
7275 {
7276 if (not JSON_UNLIKELY(sax->start_object(len)))
7277 {
7278 return false;
7279 }
7280
7281 string_t key;
7282 if (len != std::size_t(-1))
7283 {
7284 for (std::size_t i = 0; i < len; ++i)
7285 {
7286 get();
7287 if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7288 {
7289 return false;
7290 }
7291
7292 if (JSON_UNLIKELY(not parse_cbor_internal()))
7293 {
7294 return false;
7295 }
7296 key.clear();
7297 }
7298 }
7299 else
7300 {
7301 while (get() != 0xFF)
7302 {
7303 if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
7304 {
7305 return false;
7306 }
7307
7308 if (JSON_UNLIKELY(not parse_cbor_internal()))
7309 {
7310 return false;
7311 }
7312 key.clear();
7313 }
7314 }
7315
7316 return sax->end_object();
7317 }
7318
7320 // MsgPack //
7322
7326 bool parse_msgpack_internal()
7327 {
7328 switch (get())
7329 {
7330 // EOF
7331 case std::char_traits<char>::eof():
7332 return unexpect_eof(input_format_t::msgpack, "value");
7333
7334 // positive fixint
7335 case 0x00:
7336 case 0x01:
7337 case 0x02:
7338 case 0x03:
7339 case 0x04:
7340 case 0x05:
7341 case 0x06:
7342 case 0x07:
7343 case 0x08:
7344 case 0x09:
7345 case 0x0A:
7346 case 0x0B:
7347 case 0x0C:
7348 case 0x0D:
7349 case 0x0E:
7350 case 0x0F:
7351 case 0x10:
7352 case 0x11:
7353 case 0x12:
7354 case 0x13:
7355 case 0x14:
7356 case 0x15:
7357 case 0x16:
7358 case 0x17:
7359 case 0x18:
7360 case 0x19:
7361 case 0x1A:
7362 case 0x1B:
7363 case 0x1C:
7364 case 0x1D:
7365 case 0x1E:
7366 case 0x1F:
7367 case 0x20:
7368 case 0x21:
7369 case 0x22:
7370 case 0x23:
7371 case 0x24:
7372 case 0x25:
7373 case 0x26:
7374 case 0x27:
7375 case 0x28:
7376 case 0x29:
7377 case 0x2A:
7378 case 0x2B:
7379 case 0x2C:
7380 case 0x2D:
7381 case 0x2E:
7382 case 0x2F:
7383 case 0x30:
7384 case 0x31:
7385 case 0x32:
7386 case 0x33:
7387 case 0x34:
7388 case 0x35:
7389 case 0x36:
7390 case 0x37:
7391 case 0x38:
7392 case 0x39:
7393 case 0x3A:
7394 case 0x3B:
7395 case 0x3C:
7396 case 0x3D:
7397 case 0x3E:
7398 case 0x3F:
7399 case 0x40:
7400 case 0x41:
7401 case 0x42:
7402 case 0x43:
7403 case 0x44:
7404 case 0x45:
7405 case 0x46:
7406 case 0x47:
7407 case 0x48:
7408 case 0x49:
7409 case 0x4A:
7410 case 0x4B:
7411 case 0x4C:
7412 case 0x4D:
7413 case 0x4E:
7414 case 0x4F:
7415 case 0x50:
7416 case 0x51:
7417 case 0x52:
7418 case 0x53:
7419 case 0x54:
7420 case 0x55:
7421 case 0x56:
7422 case 0x57:
7423 case 0x58:
7424 case 0x59:
7425 case 0x5A:
7426 case 0x5B:
7427 case 0x5C:
7428 case 0x5D:
7429 case 0x5E:
7430 case 0x5F:
7431 case 0x60:
7432 case 0x61:
7433 case 0x62:
7434 case 0x63:
7435 case 0x64:
7436 case 0x65:
7437 case 0x66:
7438 case 0x67:
7439 case 0x68:
7440 case 0x69:
7441 case 0x6A:
7442 case 0x6B:
7443 case 0x6C:
7444 case 0x6D:
7445 case 0x6E:
7446 case 0x6F:
7447 case 0x70:
7448 case 0x71:
7449 case 0x72:
7450 case 0x73:
7451 case 0x74:
7452 case 0x75:
7453 case 0x76:
7454 case 0x77:
7455 case 0x78:
7456 case 0x79:
7457 case 0x7A:
7458 case 0x7B:
7459 case 0x7C:
7460 case 0x7D:
7461 case 0x7E:
7462 case 0x7F:
7463 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
7464
7465 // fixmap
7466 case 0x80:
7467 case 0x81:
7468 case 0x82:
7469 case 0x83:
7470 case 0x84:
7471 case 0x85:
7472 case 0x86:
7473 case 0x87:
7474 case 0x88:
7475 case 0x89:
7476 case 0x8A:
7477 case 0x8B:
7478 case 0x8C:
7479 case 0x8D:
7480 case 0x8E:
7481 case 0x8F:
7482 return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
7483
7484 // fixarray
7485 case 0x90:
7486 case 0x91:
7487 case 0x92:
7488 case 0x93:
7489 case 0x94:
7490 case 0x95:
7491 case 0x96:
7492 case 0x97:
7493 case 0x98:
7494 case 0x99:
7495 case 0x9A:
7496 case 0x9B:
7497 case 0x9C:
7498 case 0x9D:
7499 case 0x9E:
7500 case 0x9F:
7501 return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
7502
7503 // fixstr
7504 case 0xA0:
7505 case 0xA1:
7506 case 0xA2:
7507 case 0xA3:
7508 case 0xA4:
7509 case 0xA5:
7510 case 0xA6:
7511 case 0xA7:
7512 case 0xA8:
7513 case 0xA9:
7514 case 0xAA:
7515 case 0xAB:
7516 case 0xAC:
7517 case 0xAD:
7518 case 0xAE:
7519 case 0xAF:
7520 case 0xB0:
7521 case 0xB1:
7522 case 0xB2:
7523 case 0xB3:
7524 case 0xB4:
7525 case 0xB5:
7526 case 0xB6:
7527 case 0xB7:
7528 case 0xB8:
7529 case 0xB9:
7530 case 0xBA:
7531 case 0xBB:
7532 case 0xBC:
7533 case 0xBD:
7534 case 0xBE:
7535 case 0xBF:
7536 {
7537 string_t s;
7538 return get_msgpack_string(s) and sax->string(s);
7539 }
7540
7541 case 0xC0: // nil
7542 return sax->null();
7543
7544 case 0xC2: // false
7545 return sax->boolean(false);
7546
7547 case 0xC3: // true
7548 return sax->boolean(true);
7549
7550 case 0xCA: // float 32
7551 {
7552 float number;
7553 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
7554 }
7555
7556 case 0xCB: // float 64
7557 {
7558 double number;
7559 return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast<number_float_t>(number), "");
7560 }
7561
7562 case 0xCC: // uint 8
7563 {
7564 uint8_t number;
7565 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7566 }
7567
7568 case 0xCD: // uint 16
7569 {
7570 uint16_t number;
7571 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7572 }
7573
7574 case 0xCE: // uint 32
7575 {
7576 uint32_t number;
7577 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7578 }
7579
7580 case 0xCF: // uint 64
7581 {
7582 uint64_t number;
7583 return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
7584 }
7585
7586 case 0xD0: // int 8
7587 {
7588 int8_t number;
7589 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7590 }
7591
7592 case 0xD1: // int 16
7593 {
7594 int16_t number;
7595 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7596 }
7597
7598 case 0xD2: // int 32
7599 {
7600 int32_t number;
7601 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7602 }
7603
7604 case 0xD3: // int 64
7605 {
7606 int64_t number;
7607 return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
7608 }
7609
7610 case 0xD9: // str 8
7611 case 0xDA: // str 16
7612 case 0xDB: // str 32
7613 {
7614 string_t s;
7615 return get_msgpack_string(s) and sax->string(s);
7616 }
7617
7618 case 0xDC: // array 16
7619 {
7620 uint16_t len;
7621 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
7622 }
7623
7624 case 0xDD: // array 32
7625 {
7626 uint32_t len;
7627 return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
7628 }
7629
7630 case 0xDE: // map 16
7631 {
7632 uint16_t len;
7633 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
7634 }
7635
7636 case 0xDF: // map 32
7637 {
7638 uint32_t len;
7639 return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
7640 }
7641
7642 // negative fixint
7643 case 0xE0:
7644 case 0xE1:
7645 case 0xE2:
7646 case 0xE3:
7647 case 0xE4:
7648 case 0xE5:
7649 case 0xE6:
7650 case 0xE7:
7651 case 0xE8:
7652 case 0xE9:
7653 case 0xEA:
7654 case 0xEB:
7655 case 0xEC:
7656 case 0xED:
7657 case 0xEE:
7658 case 0xEF:
7659 case 0xF0:
7660 case 0xF1:
7661 case 0xF2:
7662 case 0xF3:
7663 case 0xF4:
7664 case 0xF5:
7665 case 0xF6:
7666 case 0xF7:
7667 case 0xF8:
7668 case 0xF9:
7669 case 0xFA:
7670 case 0xFB:
7671 case 0xFC:
7672 case 0xFD:
7673 case 0xFE:
7674 case 0xFF:
7675 return sax->number_integer(static_cast<int8_t>(current));
7676
7677 default: // anything else
7678 {
7679 auto last_token = get_token_string();
7680 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")));
7681 }
7682 }
7683 }
7684
7695 bool get_msgpack_string(string_t& result)
7696 {
7697 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string")))
7698 {
7699 return false;
7700 }
7701
7702 switch (current)
7703 {
7704 // fixstr
7705 case 0xA0:
7706 case 0xA1:
7707 case 0xA2:
7708 case 0xA3:
7709 case 0xA4:
7710 case 0xA5:
7711 case 0xA6:
7712 case 0xA7:
7713 case 0xA8:
7714 case 0xA9:
7715 case 0xAA:
7716 case 0xAB:
7717 case 0xAC:
7718 case 0xAD:
7719 case 0xAE:
7720 case 0xAF:
7721 case 0xB0:
7722 case 0xB1:
7723 case 0xB2:
7724 case 0xB3:
7725 case 0xB4:
7726 case 0xB5:
7727 case 0xB6:
7728 case 0xB7:
7729 case 0xB8:
7730 case 0xB9:
7731 case 0xBA:
7732 case 0xBB:
7733 case 0xBC:
7734 case 0xBD:
7735 case 0xBE:
7736 case 0xBF:
7737 {
7738 return get_string(input_format_t::msgpack, current & 0x1F, result);
7739 }
7740
7741 case 0xD9: // str 8
7742 {
7743 uint8_t len;
7744 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
7745 }
7746
7747 case 0xDA: // str 16
7748 {
7749 uint16_t len;
7750 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
7751 }
7752
7753 case 0xDB: // str 32
7754 {
7755 uint32_t len;
7756 return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
7757 }
7758
7759 default:
7760 {
7761 auto last_token = get_token_string();
7762 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")));
7763 }
7764 }
7765 }
7766
7771 bool get_msgpack_array(const std::size_t len)
7772 {
7773 if (JSON_UNLIKELY(not sax->start_array(len)))
7774 {
7775 return false;
7776 }
7777
7778 for (std::size_t i = 0; i < len; ++i)
7779 {
7780 if (JSON_UNLIKELY(not parse_msgpack_internal()))
7781 {
7782 return false;
7783 }
7784 }
7785
7786 return sax->end_array();
7787 }
7788
7793 bool get_msgpack_object(const std::size_t len)
7794 {
7795 if (JSON_UNLIKELY(not sax->start_object(len)))
7796 {
7797 return false;
7798 }
7799
7800 string_t key;
7801 for (std::size_t i = 0; i < len; ++i)
7802 {
7803 get();
7804 if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
7805 {
7806 return false;
7807 }
7808
7809 if (JSON_UNLIKELY(not parse_msgpack_internal()))
7810 {
7811 return false;
7812 }
7813 key.clear();
7814 }
7815
7816 return sax->end_object();
7817 }
7818
7820 // UBJSON //
7822
7830 bool parse_ubjson_internal(const bool get_char = true)
7831 {
7832 return get_ubjson_value(get_char ? get_ignore_noop() : current);
7833 }
7834
7849 bool get_ubjson_string(string_t& result, const bool get_char = true)
7850 {
7851 if (get_char)
7852 {
7853 get(); // TODO: may we ignore N here?
7854 }
7855
7856 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
7857 {
7858 return false;
7859 }
7860
7861 switch (current)
7862 {
7863 case 'U':
7864 {
7865 uint8_t len;
7866 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7867 }
7868
7869 case 'i':
7870 {
7871 int8_t len;
7872 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7873 }
7874
7875 case 'I':
7876 {
7877 int16_t len;
7878 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7879 }
7880
7881 case 'l':
7882 {
7883 int32_t len;
7884 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7885 }
7886
7887 case 'L':
7888 {
7889 int64_t len;
7890 return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
7891 }
7892
7893 default:
7894 auto last_token = get_token_string();
7895 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")));
7896 }
7897 }
7898
7903 bool get_ubjson_size_value(std::size_t& result)
7904 {
7905 switch (get_ignore_noop())
7906 {
7907 case 'U':
7908 {
7909 uint8_t number;
7910 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7911 {
7912 return false;
7913 }
7914 result = static_cast<std::size_t>(number);
7915 return true;
7916 }
7917
7918 case 'i':
7919 {
7920 int8_t number;
7921 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7922 {
7923 return false;
7924 }
7925 result = static_cast<std::size_t>(number);
7926 return true;
7927 }
7928
7929 case 'I':
7930 {
7931 int16_t number;
7932 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7933 {
7934 return false;
7935 }
7936 result = static_cast<std::size_t>(number);
7937 return true;
7938 }
7939
7940 case 'l':
7941 {
7942 int32_t number;
7943 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7944 {
7945 return false;
7946 }
7947 result = static_cast<std::size_t>(number);
7948 return true;
7949 }
7950
7951 case 'L':
7952 {
7953 int64_t number;
7954 if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
7955 {
7956 return false;
7957 }
7958 result = static_cast<std::size_t>(number);
7959 return true;
7960 }
7961
7962 default:
7963 {
7964 auto last_token = get_token_string();
7965 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")));
7966 }
7967 }
7968 }
7969
7980 bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
7981 {
7982 result.first = string_t::npos; // size
7983 result.second = 0; // type
7984
7985 get_ignore_noop();
7986
7987 if (current == '$')
7988 {
7989 result.second = get(); // must not ignore 'N', because 'N' maybe the type
7990 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type")))
7991 {
7992 return false;
7993 }
7994
7995 get_ignore_noop();
7996 if (JSON_UNLIKELY(current != '#'))
7997 {
7998 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
7999 {
8000 return false;
8001 }
8002 auto last_token = get_token_string();
8003 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")));
8004 }
8005
8006 return get_ubjson_size_value(result.first);
8007 }
8008 else if (current == '#')
8009 {
8010 return get_ubjson_size_value(result.first);
8011 }
8012 return true;
8013 }
8014
8019 bool get_ubjson_value(const int prefix)
8020 {
8021 switch (prefix)
8022 {
8023 case std::char_traits<char>::eof(): // EOF
8024 return unexpect_eof(input_format_t::ubjson, "value");
8025
8026 case 'T': // true
8027 return sax->boolean(true);
8028 case 'F': // false
8029 return sax->boolean(false);
8030
8031 case 'Z': // null
8032 return sax->null();
8033
8034 case 'U':
8035 {
8036 uint8_t number;
8037 return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
8038 }
8039
8040 case 'i':
8041 {
8042 int8_t number;
8043 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
8044 }
8045
8046 case 'I':
8047 {
8048 int16_t number;
8049 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
8050 }
8051
8052 case 'l':
8053 {
8054 int32_t number;
8055 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
8056 }
8057
8058 case 'L':
8059 {
8060 int64_t number;
8061 return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
8062 }
8063
8064 case 'd':
8065 {
8066 float number;
8067 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
8068 }
8069
8070 case 'D':
8071 {
8072 double number;
8073 return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast<number_float_t>(number), "");
8074 }
8075
8076 case 'C': // char
8077 {
8078 get();
8079 if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char")))
8080 {
8081 return false;
8082 }
8083 if (JSON_UNLIKELY(current > 127))
8084 {
8085 auto last_token = get_token_string();
8086 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")));
8087 }
8088 string_t s(1, static_cast<char>(current));
8089 return sax->string(s);
8090 }
8091
8092 case 'S': // string
8093 {
8094 string_t s;
8095 return get_ubjson_string(s) and sax->string(s);
8096 }
8097
8098 case '[': // array
8099 return get_ubjson_array();
8100
8101 case '{': // object
8102 return get_ubjson_object();
8103
8104 default: // anything else
8105 {
8106 auto last_token = get_token_string();
8107 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")));
8108 }
8109 }
8110 }
8111
8115 bool get_ubjson_array()
8116 {
8117 std::pair<std::size_t, int> size_and_type;
8118 if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
8119 {
8120 return false;
8121 }
8122
8123 if (size_and_type.first != string_t::npos)
8124 {
8125 if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
8126 {
8127 return false;
8128 }
8129
8130 if (size_and_type.second != 0)
8131 {
8132 if (size_and_type.second != 'N')
8133 {
8134 for (std::size_t i = 0; i < size_and_type.first; ++i)
8135 {
8136 if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
8137 {
8138 return false;
8139 }
8140 }
8141 }
8142 }
8143 else
8144 {
8145 for (std::size_t i = 0; i < size_and_type.first; ++i)
8146 {
8147 if (JSON_UNLIKELY(not parse_ubjson_internal()))
8148 {
8149 return false;
8150 }
8151 }
8152 }
8153 }
8154 else
8155 {
8156 if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
8157 {
8158 return false;
8159 }
8160
8161 while (current != ']')
8162 {
8163 if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
8164 {
8165 return false;
8166 }
8167 get_ignore_noop();
8168 }
8169 }
8170
8171 return sax->end_array();
8172 }
8173
8177 bool get_ubjson_object()
8178 {
8179 std::pair<std::size_t, int> size_and_type;
8180 if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
8181 {
8182 return false;
8183 }
8184
8185 string_t key;
8186 if (size_and_type.first != string_t::npos)
8187 {
8188 if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
8189 {
8190 return false;
8191 }
8192
8193 if (size_and_type.second != 0)
8194 {
8195 for (std::size_t i = 0; i < size_and_type.first; ++i)
8196 {
8197 if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
8198 {
8199 return false;
8200 }
8201 if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
8202 {
8203 return false;
8204 }
8205 key.clear();
8206 }
8207 }
8208 else
8209 {
8210 for (std::size_t i = 0; i < size_and_type.first; ++i)
8211 {
8212 if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
8213 {
8214 return false;
8215 }
8216 if (JSON_UNLIKELY(not parse_ubjson_internal()))
8217 {
8218 return false;
8219 }
8220 key.clear();
8221 }
8222 }
8223 }
8224 else
8225 {
8226 if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
8227 {
8228 return false;
8229 }
8230
8231 while (current != '}')
8232 {
8233 if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
8234 {
8235 return false;
8236 }
8237 if (JSON_UNLIKELY(not parse_ubjson_internal()))
8238 {
8239 return false;
8240 }
8241 get_ignore_noop();
8242 key.clear();
8243 }
8244 }
8245
8246 return sax->end_object();
8247 }
8248
8250 // Utility functions //
8252
8262 int get()
8263 {
8264 ++chars_read;
8265 return (current = ia->get_character());
8266 }
8267
8271 int get_ignore_noop()
8272 {
8273 do
8274 {
8275 get();
8276 }
8277 while (current == 'N');
8278
8279 return current;
8280 }
8281
8282 /*
8283 @brief read a number from the input
8284
8285 @tparam NumberType the type of the number
8286 @param[in] format the current format (for diagnostics)
8287 @param[out] result number of type @a NumberType
8288
8289 @return whether conversion completed
8290
8291 @note This function needs to respect the system's endianess, because
8292 bytes in CBOR, MessagePack, and UBJSON are stored in network order
8293 (big endian) and therefore need reordering on little endian systems.
8294 */
8295 template<typename NumberType, bool InputIsLittleEndian = false>
8296 bool get_number(const input_format_t format, NumberType& result)
8297 {
8298 // step 1: read input into array with system's byte order
8299 std::array<uint8_t, sizeof(NumberType)> vec;
8300 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
8301 {
8302 get();
8303 if (JSON_UNLIKELY(not unexpect_eof(format, "number")))
8304 {
8305 return false;
8306 }
8307
8308 // reverse byte order prior to conversion if necessary
8309 if (is_little_endian && !InputIsLittleEndian)
8310 {
8311 vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
8312 }
8313 else
8314 {
8315 vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
8316 }
8317 }
8318
8319 // step 2: convert array into number of type T and return
8320 std::memcpy(&result, vec.data(), sizeof(NumberType));
8321 return true;
8322 }
8323
8338 template<typename NumberType>
8339 bool get_string(const input_format_t format,
8340 const NumberType len,
8341 string_t& result)
8342 {
8343 bool success = true;
8344 std::generate_n(std::back_inserter(result), len, [this, &success, &format]()
8345 {
8346 get();
8347 if (JSON_UNLIKELY(not unexpect_eof(format, "string")))
8348 {
8349 success = false;
8350 }
8351 return static_cast<char>(current);
8352 });
8353 return success;
8354 }
8355
8361 bool unexpect_eof(const input_format_t format, const char* context) const
8362 {
8363 if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
8364 {
8365 return sax->parse_error(chars_read, "<end of file>",
8366 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
8367 }
8368 return true;
8369 }
8370
8374 std::string get_token_string() const
8375 {
8376 char cr[3];
8377 (std::snprintf)(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
8378 return std::string{cr};
8379 }
8380
8387 std::string exception_message(const input_format_t format,
8388 const std::string& detail,
8389 const std::string& context) const
8390 {
8391 std::string error_msg = "syntax error while parsing ";
8392
8393 switch (format)
8394 {
8395 case input_format_t::cbor:
8396 error_msg += "CBOR";
8397 break;
8398
8399 case input_format_t::msgpack:
8400 error_msg += "MessagePack";
8401 break;
8402
8403 case input_format_t::ubjson:
8404 error_msg += "UBJSON";
8405 break;
8406
8407 case input_format_t::bson:
8408 error_msg += "BSON";
8409 break;
8410
8411 // LCOV_EXCL_START
8412 default:
8413 assert(false);
8414 // LCOV_EXCL_STOP
8415 }
8416
8417 return error_msg + " " + context + ": " + detail;
8418 }
8419
8420 private:
8422 input_adapter_t ia = nullptr;
8423
8425 int current = std::char_traits<char>::eof();
8426
8428 std::size_t chars_read = 0;
8429
8431 const bool is_little_endian = little_endianess();
8432
8434 json_sax_t* sax = nullptr;
8435};
8436} // namespace detail
8437} // namespace nlohmann
8438
8439// #include <nlohmann/detail/output/binary_writer.hpp>
8440
8441
8442#include <algorithm> // reverse
8443#include <array> // array
8444#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
8445#include <cstring> // memcpy
8446#include <limits> // numeric_limits
8447
8448// #include <nlohmann/detail/input/binary_reader.hpp>
8449
8450// #include <nlohmann/detail/output/output_adapters.hpp>
8451
8452
8453namespace nlohmann
8454{
8455namespace detail
8456{
8458// binary writer //
8460
8464template<typename BasicJsonType, typename CharType>
8465class binary_writer
8466{
8467 using string_t = typename BasicJsonType::string_t;
8468
8469 public:
8475 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
8476 {
8477 assert(oa);
8478 }
8479
8484 void write_bson(const BasicJsonType& j)
8485 {
8486 switch (j.type())
8487 {
8488 case value_t::object:
8489 {
8490 write_bson_object(*j.m_value.object);
8491 break;
8492 }
8493
8494 default:
8495 {
8496 JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
8497 }
8498 }
8499 }
8500
8504 void write_cbor(const BasicJsonType& j)
8505 {
8506 switch (j.type())
8507 {
8508 case value_t::null:
8509 {
8510 oa->write_character(to_char_type(0xF6));
8511 break;
8512 }
8513
8514 case value_t::boolean:
8515 {
8516 oa->write_character(j.m_value.boolean
8517 ? to_char_type(0xF5)
8518 : to_char_type(0xF4));
8519 break;
8520 }
8521
8522 case value_t::number_integer:
8523 {
8524 if (j.m_value.number_integer >= 0)
8525 {
8526 // CBOR does not differentiate between positive signed
8527 // integers and unsigned integers. Therefore, we used the
8528 // code from the value_t::number_unsigned case here.
8529 if (j.m_value.number_integer <= 0x17)
8530 {
8531 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8532 }
8533 else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
8534 {
8535 oa->write_character(to_char_type(0x18));
8536 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8537 }
8538 else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
8539 {
8540 oa->write_character(to_char_type(0x19));
8541 write_number(static_cast<uint16_t>(j.m_value.number_integer));
8542 }
8543 else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
8544 {
8545 oa->write_character(to_char_type(0x1A));
8546 write_number(static_cast<uint32_t>(j.m_value.number_integer));
8547 }
8548 else
8549 {
8550 oa->write_character(to_char_type(0x1B));
8551 write_number(static_cast<uint64_t>(j.m_value.number_integer));
8552 }
8553 }
8554 else
8555 {
8556 // The conversions below encode the sign in the first
8557 // byte, and the value is converted to a positive number.
8558 const auto positive_number = -1 - j.m_value.number_integer;
8559 if (j.m_value.number_integer >= -24)
8560 {
8561 write_number(static_cast<uint8_t>(0x20 + positive_number));
8562 }
8563 else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
8564 {
8565 oa->write_character(to_char_type(0x38));
8566 write_number(static_cast<uint8_t>(positive_number));
8567 }
8568 else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
8569 {
8570 oa->write_character(to_char_type(0x39));
8571 write_number(static_cast<uint16_t>(positive_number));
8572 }
8573 else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
8574 {
8575 oa->write_character(to_char_type(0x3A));
8576 write_number(static_cast<uint32_t>(positive_number));
8577 }
8578 else
8579 {
8580 oa->write_character(to_char_type(0x3B));
8581 write_number(static_cast<uint64_t>(positive_number));
8582 }
8583 }
8584 break;
8585 }
8586
8587 case value_t::number_unsigned:
8588 {
8589 if (j.m_value.number_unsigned <= 0x17)
8590 {
8591 write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
8592 }
8593 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8594 {
8595 oa->write_character(to_char_type(0x18));
8596 write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
8597 }
8598 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8599 {
8600 oa->write_character(to_char_type(0x19));
8601 write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
8602 }
8603 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8604 {
8605 oa->write_character(to_char_type(0x1A));
8606 write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
8607 }
8608 else
8609 {
8610 oa->write_character(to_char_type(0x1B));
8611 write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
8612 }
8613 break;
8614 }
8615
8616 case value_t::number_float:
8617 {
8618 oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
8619 write_number(j.m_value.number_float);
8620 break;
8621 }
8622
8623 case value_t::string:
8624 {
8625 // step 1: write control byte and the string length
8626 const auto N = j.m_value.string->size();
8627 if (N <= 0x17)
8628 {
8629 write_number(static_cast<uint8_t>(0x60 + N));
8630 }
8631 else if (N <= (std::numeric_limits<uint8_t>::max)())
8632 {
8633 oa->write_character(to_char_type(0x78));
8634 write_number(static_cast<uint8_t>(N));
8635 }
8636 else if (N <= (std::numeric_limits<uint16_t>::max)())
8637 {
8638 oa->write_character(to_char_type(0x79));
8639 write_number(static_cast<uint16_t>(N));
8640 }
8641 else if (N <= (std::numeric_limits<uint32_t>::max)())
8642 {
8643 oa->write_character(to_char_type(0x7A));
8644 write_number(static_cast<uint32_t>(N));
8645 }
8646 // LCOV_EXCL_START
8647 else if (N <= (std::numeric_limits<uint64_t>::max)())
8648 {
8649 oa->write_character(to_char_type(0x7B));
8650 write_number(static_cast<uint64_t>(N));
8651 }
8652 // LCOV_EXCL_STOP
8653
8654 // step 2: write the string
8655 oa->write_characters(
8656 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8657 j.m_value.string->size());
8658 break;
8659 }
8660
8661 case value_t::array:
8662 {
8663 // step 1: write control byte and the array size
8664 const auto N = j.m_value.array->size();
8665 if (N <= 0x17)
8666 {
8667 write_number(static_cast<uint8_t>(0x80 + N));
8668 }
8669 else if (N <= (std::numeric_limits<uint8_t>::max)())
8670 {
8671 oa->write_character(to_char_type(0x98));
8672 write_number(static_cast<uint8_t>(N));
8673 }
8674 else if (N <= (std::numeric_limits<uint16_t>::max)())
8675 {
8676 oa->write_character(to_char_type(0x99));
8677 write_number(static_cast<uint16_t>(N));
8678 }
8679 else if (N <= (std::numeric_limits<uint32_t>::max)())
8680 {
8681 oa->write_character(to_char_type(0x9A));
8682 write_number(static_cast<uint32_t>(N));
8683 }
8684 // LCOV_EXCL_START
8685 else if (N <= (std::numeric_limits<uint64_t>::max)())
8686 {
8687 oa->write_character(to_char_type(0x9B));
8688 write_number(static_cast<uint64_t>(N));
8689 }
8690 // LCOV_EXCL_STOP
8691
8692 // step 2: write each element
8693 for (const auto& el : *j.m_value.array)
8694 {
8695 write_cbor(el);
8696 }
8697 break;
8698 }
8699
8700 case value_t::object:
8701 {
8702 // step 1: write control byte and the object size
8703 const auto N = j.m_value.object->size();
8704 if (N <= 0x17)
8705 {
8706 write_number(static_cast<uint8_t>(0xA0 + N));
8707 }
8708 else if (N <= (std::numeric_limits<uint8_t>::max)())
8709 {
8710 oa->write_character(to_char_type(0xB8));
8711 write_number(static_cast<uint8_t>(N));
8712 }
8713 else if (N <= (std::numeric_limits<uint16_t>::max)())
8714 {
8715 oa->write_character(to_char_type(0xB9));
8716 write_number(static_cast<uint16_t>(N));
8717 }
8718 else if (N <= (std::numeric_limits<uint32_t>::max)())
8719 {
8720 oa->write_character(to_char_type(0xBA));
8721 write_number(static_cast<uint32_t>(N));
8722 }
8723 // LCOV_EXCL_START
8724 else if (N <= (std::numeric_limits<uint64_t>::max)())
8725 {
8726 oa->write_character(to_char_type(0xBB));
8727 write_number(static_cast<uint64_t>(N));
8728 }
8729 // LCOV_EXCL_STOP
8730
8731 // step 2: write each element
8732 for (const auto& el : *j.m_value.object)
8733 {
8734 write_cbor(el.first);
8735 write_cbor(el.second);
8736 }
8737 break;
8738 }
8739
8740 default:
8741 break;
8742 }
8743 }
8744
8748 void write_msgpack(const BasicJsonType& j)
8749 {
8750 switch (j.type())
8751 {
8752 case value_t::null: // nil
8753 {
8754 oa->write_character(to_char_type(0xC0));
8755 break;
8756 }
8757
8758 case value_t::boolean: // true and false
8759 {
8760 oa->write_character(j.m_value.boolean
8761 ? to_char_type(0xC3)
8762 : to_char_type(0xC2));
8763 break;
8764 }
8765
8766 case value_t::number_integer:
8767 {
8768 if (j.m_value.number_integer >= 0)
8769 {
8770 // MessagePack does not differentiate between positive
8771 // signed integers and unsigned integers. Therefore, we used
8772 // the code from the value_t::number_unsigned case here.
8773 if (j.m_value.number_unsigned < 128)
8774 {
8775 // positive fixnum
8776 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8777 }
8778 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8779 {
8780 // uint 8
8781 oa->write_character(to_char_type(0xCC));
8782 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8783 }
8784 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8785 {
8786 // uint 16
8787 oa->write_character(to_char_type(0xCD));
8788 write_number(static_cast<uint16_t>(j.m_value.number_integer));
8789 }
8790 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8791 {
8792 // uint 32
8793 oa->write_character(to_char_type(0xCE));
8794 write_number(static_cast<uint32_t>(j.m_value.number_integer));
8795 }
8796 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
8797 {
8798 // uint 64
8799 oa->write_character(to_char_type(0xCF));
8800 write_number(static_cast<uint64_t>(j.m_value.number_integer));
8801 }
8802 }
8803 else
8804 {
8805 if (j.m_value.number_integer >= -32)
8806 {
8807 // negative fixnum
8808 write_number(static_cast<int8_t>(j.m_value.number_integer));
8809 }
8810 else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
8811 j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
8812 {
8813 // int 8
8814 oa->write_character(to_char_type(0xD0));
8815 write_number(static_cast<int8_t>(j.m_value.number_integer));
8816 }
8817 else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
8818 j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
8819 {
8820 // int 16
8821 oa->write_character(to_char_type(0xD1));
8822 write_number(static_cast<int16_t>(j.m_value.number_integer));
8823 }
8824 else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
8825 j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
8826 {
8827 // int 32
8828 oa->write_character(to_char_type(0xD2));
8829 write_number(static_cast<int32_t>(j.m_value.number_integer));
8830 }
8831 else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
8832 j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
8833 {
8834 // int 64
8835 oa->write_character(to_char_type(0xD3));
8836 write_number(static_cast<int64_t>(j.m_value.number_integer));
8837 }
8838 }
8839 break;
8840 }
8841
8842 case value_t::number_unsigned:
8843 {
8844 if (j.m_value.number_unsigned < 128)
8845 {
8846 // positive fixnum
8847 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8848 }
8849 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
8850 {
8851 // uint 8
8852 oa->write_character(to_char_type(0xCC));
8853 write_number(static_cast<uint8_t>(j.m_value.number_integer));
8854 }
8855 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
8856 {
8857 // uint 16
8858 oa->write_character(to_char_type(0xCD));
8859 write_number(static_cast<uint16_t>(j.m_value.number_integer));
8860 }
8861 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
8862 {
8863 // uint 32
8864 oa->write_character(to_char_type(0xCE));
8865 write_number(static_cast<uint32_t>(j.m_value.number_integer));
8866 }
8867 else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
8868 {
8869 // uint 64
8870 oa->write_character(to_char_type(0xCF));
8871 write_number(static_cast<uint64_t>(j.m_value.number_integer));
8872 }
8873 break;
8874 }
8875
8876 case value_t::number_float:
8877 {
8878 oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
8879 write_number(j.m_value.number_float);
8880 break;
8881 }
8882
8883 case value_t::string:
8884 {
8885 // step 1: write control byte and the string length
8886 const auto N = j.m_value.string->size();
8887 if (N <= 31)
8888 {
8889 // fixstr
8890 write_number(static_cast<uint8_t>(0xA0 | N));
8891 }
8892 else if (N <= (std::numeric_limits<uint8_t>::max)())
8893 {
8894 // str 8
8895 oa->write_character(to_char_type(0xD9));
8896 write_number(static_cast<uint8_t>(N));
8897 }
8898 else if (N <= (std::numeric_limits<uint16_t>::max)())
8899 {
8900 // str 16
8901 oa->write_character(to_char_type(0xDA));
8902 write_number(static_cast<uint16_t>(N));
8903 }
8904 else if (N <= (std::numeric_limits<uint32_t>::max)())
8905 {
8906 // str 32
8907 oa->write_character(to_char_type(0xDB));
8908 write_number(static_cast<uint32_t>(N));
8909 }
8910
8911 // step 2: write the string
8912 oa->write_characters(
8913 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
8914 j.m_value.string->size());
8915 break;
8916 }
8917
8918 case value_t::array:
8919 {
8920 // step 1: write control byte and the array size
8921 const auto N = j.m_value.array->size();
8922 if (N <= 15)
8923 {
8924 // fixarray
8925 write_number(static_cast<uint8_t>(0x90 | N));
8926 }
8927 else if (N <= (std::numeric_limits<uint16_t>::max)())
8928 {
8929 // array 16
8930 oa->write_character(to_char_type(0xDC));
8931 write_number(static_cast<uint16_t>(N));
8932 }
8933 else if (N <= (std::numeric_limits<uint32_t>::max)())
8934 {
8935 // array 32
8936 oa->write_character(to_char_type(0xDD));
8937 write_number(static_cast<uint32_t>(N));
8938 }
8939
8940 // step 2: write each element
8941 for (const auto& el : *j.m_value.array)
8942 {
8943 write_msgpack(el);
8944 }
8945 break;
8946 }
8947
8948 case value_t::object:
8949 {
8950 // step 1: write control byte and the object size
8951 const auto N = j.m_value.object->size();
8952 if (N <= 15)
8953 {
8954 // fixmap
8955 write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
8956 }
8957 else if (N <= (std::numeric_limits<uint16_t>::max)())
8958 {
8959 // map 16
8960 oa->write_character(to_char_type(0xDE));
8961 write_number(static_cast<uint16_t>(N));
8962 }
8963 else if (N <= (std::numeric_limits<uint32_t>::max)())
8964 {
8965 // map 32
8966 oa->write_character(to_char_type(0xDF));
8967 write_number(static_cast<uint32_t>(N));
8968 }
8969
8970 // step 2: write each element
8971 for (const auto& el : *j.m_value.object)
8972 {
8973 write_msgpack(el.first);
8974 write_msgpack(el.second);
8975 }
8976 break;
8977 }
8978
8979 default:
8980 break;
8981 }
8982 }
8983
8990 void write_ubjson(const BasicJsonType& j, const bool use_count,
8991 const bool use_type, const bool add_prefix = true)
8992 {
8993 switch (j.type())
8994 {
8995 case value_t::null:
8996 {
8997 if (add_prefix)
8998 {
8999 oa->write_character(to_char_type('Z'));
9000 }
9001 break;
9002 }
9003
9004 case value_t::boolean:
9005 {
9006 if (add_prefix)
9007 {
9008 oa->write_character(j.m_value.boolean
9009 ? to_char_type('T')
9010 : to_char_type('F'));
9011 }
9012 break;
9013 }
9014
9015 case value_t::number_integer:
9016 {
9017 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
9018 break;
9019 }
9020
9021 case value_t::number_unsigned:
9022 {
9023 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
9024 break;
9025 }
9026
9027 case value_t::number_float:
9028 {
9029 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
9030 break;
9031 }
9032
9033 case value_t::string:
9034 {
9035 if (add_prefix)
9036 {
9037 oa->write_character(to_char_type('S'));
9038 }
9039 write_number_with_ubjson_prefix(j.m_value.string->size(), true);
9040 oa->write_characters(
9041 reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
9042 j.m_value.string->size());
9043 break;
9044 }
9045
9046 case value_t::array:
9047 {
9048 if (add_prefix)
9049 {
9050 oa->write_character(to_char_type('['));
9051 }
9052
9053 bool prefix_required = true;
9054 if (use_type and not j.m_value.array->empty())
9055 {
9056 assert(use_count);
9057 const CharType first_prefix = ubjson_prefix(j.front());
9058 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
9059 [this, first_prefix](const BasicJsonType & v)
9060 {
9061 return ubjson_prefix(v) == first_prefix;
9062 });
9063
9064 if (same_prefix)
9065 {
9066 prefix_required = false;
9067 oa->write_character(to_char_type('$'));
9068 oa->write_character(first_prefix);
9069 }
9070 }
9071
9072 if (use_count)
9073 {
9074 oa->write_character(to_char_type('#'));
9075 write_number_with_ubjson_prefix(j.m_value.array->size(), true);
9076 }
9077
9078 for (const auto& el : *j.m_value.array)
9079 {
9080 write_ubjson(el, use_count, use_type, prefix_required);
9081 }
9082
9083 if (not use_count)
9084 {
9085 oa->write_character(to_char_type(']'));
9086 }
9087
9088 break;
9089 }
9090
9091 case value_t::object:
9092 {
9093 if (add_prefix)
9094 {
9095 oa->write_character(to_char_type('{'));
9096 }
9097
9098 bool prefix_required = true;
9099 if (use_type and not j.m_value.object->empty())
9100 {
9101 assert(use_count);
9102 const CharType first_prefix = ubjson_prefix(j.front());
9103 const bool same_prefix = std::all_of(j.begin(), j.end(),
9104 [this, first_prefix](const BasicJsonType & v)
9105 {
9106 return ubjson_prefix(v) == first_prefix;
9107 });
9108
9109 if (same_prefix)
9110 {
9111 prefix_required = false;
9112 oa->write_character(to_char_type('$'));
9113 oa->write_character(first_prefix);
9114 }
9115 }
9116
9117 if (use_count)
9118 {
9119 oa->write_character(to_char_type('#'));
9120 write_number_with_ubjson_prefix(j.m_value.object->size(), true);
9121 }
9122
9123 for (const auto& el : *j.m_value.object)
9124 {
9125 write_number_with_ubjson_prefix(el.first.size(), true);
9126 oa->write_characters(
9127 reinterpret_cast<const CharType*>(el.first.c_str()),
9128 el.first.size());
9129 write_ubjson(el.second, use_count, use_type, prefix_required);
9130 }
9131
9132 if (not use_count)
9133 {
9134 oa->write_character(to_char_type('}'));
9135 }
9136
9137 break;
9138 }
9139
9140 default:
9141 break;
9142 }
9143 }
9144
9145 private:
9147 // BSON //
9149
9154 static std::size_t calc_bson_entry_header_size(const string_t& name)
9155 {
9156 const auto it = name.find(static_cast<typename string_t::value_type>(0));
9157 if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos))
9158 {
9159 JSON_THROW(out_of_range::create(409,
9160 "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
9161 }
9162
9163 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
9164 }
9165
9169 void write_bson_entry_header(const string_t& name,
9170 const std::uint8_t element_type)
9171 {
9172 oa->write_character(to_char_type(element_type)); // boolean
9173 oa->write_characters(
9174 reinterpret_cast<const CharType*>(name.c_str()),
9175 name.size() + 1u);
9176 }
9177
9181 void write_bson_boolean(const string_t& name,
9182 const bool value)
9183 {
9184 write_bson_entry_header(name, 0x08);
9185 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
9186 }
9187
9191 void write_bson_double(const string_t& name,
9192 const double value)
9193 {
9194 write_bson_entry_header(name, 0x01);
9195 write_number<double, true>(value);
9196 }
9197
9201 static std::size_t calc_bson_string_size(const string_t& value)
9202 {
9203 return sizeof(std::int32_t) + value.size() + 1ul;
9204 }
9205
9209 void write_bson_string(const string_t& name,
9210 const string_t& value)
9211 {
9212 write_bson_entry_header(name, 0x02);
9213
9214 write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
9215 oa->write_characters(
9216 reinterpret_cast<const CharType*>(value.c_str()),
9217 value.size() + 1);
9218 }
9219
9223 void write_bson_null(const string_t& name)
9224 {
9225 write_bson_entry_header(name, 0x0A);
9226 }
9227
9231 static std::size_t calc_bson_integer_size(const std::int64_t value)
9232 {
9233 if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
9234 {
9235 return sizeof(std::int32_t);
9236 }
9237 else
9238 {
9239 return sizeof(std::int64_t);
9240 }
9241 }
9242
9246 void write_bson_integer(const string_t& name,
9247 const std::int64_t value)
9248 {
9249 if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
9250 {
9251 write_bson_entry_header(name, 0x10); // int32
9252 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
9253 }
9254 else
9255 {
9256 write_bson_entry_header(name, 0x12); // int64
9257 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
9258 }
9259 }
9260
9264 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
9265 {
9266 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
9267 ? sizeof(std::int32_t)
9268 : sizeof(std::int64_t);
9269 }
9270
9274 void write_bson_unsigned(const string_t& name,
9275 const std::uint64_t value)
9276 {
9277 if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
9278 {
9279 write_bson_entry_header(name, 0x10 /* int32 */);
9280 write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
9281 }
9282 else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
9283 {
9284 write_bson_entry_header(name, 0x12 /* int64 */);
9285 write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
9286 }
9287 else
9288 {
9289 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
9290 }
9291 }
9292
9296 void write_bson_object_entry(const string_t& name,
9297 const typename BasicJsonType::object_t& value)
9298 {
9299 write_bson_entry_header(name, 0x03); // object
9300 write_bson_object(value);
9301 }
9302
9306 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
9307 {
9308 std::size_t embedded_document_size = 0ul;
9309 std::size_t array_index = 0ul;
9310
9311 for (const auto& el : value)
9312 {
9313 embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el);
9314 }
9315
9316 return sizeof(std::int32_t) + embedded_document_size + 1ul;
9317 }
9318
9322 void write_bson_array(const string_t& name,
9323 const typename BasicJsonType::array_t& value)
9324 {
9325 write_bson_entry_header(name, 0x04); // array
9326 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
9327
9328 std::size_t array_index = 0ul;
9329
9330 for (const auto& el : value)
9331 {
9332 write_bson_element(std::to_string(array_index++), el);
9333 }
9334
9335 oa->write_character(to_char_type(0x00));
9336 }
9337
9342 static std::size_t calc_bson_element_size(const string_t& name,
9343 const BasicJsonType& j)
9344 {
9345 const auto header_size = calc_bson_entry_header_size(name);
9346 switch (j.type())
9347 {
9348 case value_t::object:
9349 return header_size + calc_bson_object_size(*j.m_value.object);
9350
9351 case value_t::array:
9352 return header_size + calc_bson_array_size(*j.m_value.array);
9353
9354 case value_t::boolean:
9355 return header_size + 1ul;
9356
9357 case value_t::number_float:
9358 return header_size + 8ul;
9359
9360 case value_t::number_integer:
9361 return header_size + calc_bson_integer_size(j.m_value.number_integer);
9362
9363 case value_t::number_unsigned:
9364 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
9365
9366 case value_t::string:
9367 return header_size + calc_bson_string_size(*j.m_value.string);
9368
9369 case value_t::null:
9370 return header_size + 0ul;
9371
9372 // LCOV_EXCL_START
9373 default:
9374 assert(false);
9375 return 0ul;
9376 // LCOV_EXCL_STOP
9377 };
9378 }
9379
9387 void write_bson_element(const string_t& name,
9388 const BasicJsonType& j)
9389 {
9390 switch (j.type())
9391 {
9392 case value_t::object:
9393 return write_bson_object_entry(name, *j.m_value.object);
9394
9395 case value_t::array:
9396 return write_bson_array(name, *j.m_value.array);
9397
9398 case value_t::boolean:
9399 return write_bson_boolean(name, j.m_value.boolean);
9400
9401 case value_t::number_float:
9402 return write_bson_double(name, j.m_value.number_float);
9403
9404 case value_t::number_integer:
9405 return write_bson_integer(name, j.m_value.number_integer);
9406
9407 case value_t::number_unsigned:
9408 return write_bson_unsigned(name, j.m_value.number_unsigned);
9409
9410 case value_t::string:
9411 return write_bson_string(name, *j.m_value.string);
9412
9413 case value_t::null:
9414 return write_bson_null(name);
9415
9416 // LCOV_EXCL_START
9417 default:
9418 assert(false);
9419 return;
9420 // LCOV_EXCL_STOP
9421 };
9422 }
9423
9430 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
9431 {
9432 std::size_t document_size = std::accumulate(value.begin(), value.end(), 0ul,
9433 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
9434 {
9435 return result += calc_bson_element_size(el.first, el.second);
9436 });
9437
9438 return sizeof(std::int32_t) + document_size + 1ul;
9439 }
9440
9445 void write_bson_object(const typename BasicJsonType::object_t& value)
9446 {
9447 write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
9448
9449 for (const auto& el : value)
9450 {
9451 write_bson_element(el.first, el.second);
9452 }
9453
9454 oa->write_character(to_char_type(0x00));
9455 }
9456
9458 // CBOR //
9460
9461 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
9462 {
9463 return to_char_type(0xFA); // Single-Precision Float
9464 }
9465
9466 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
9467 {
9468 return to_char_type(0xFB); // Double-Precision Float
9469 }
9470
9472 // MsgPack //
9474
9475 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
9476 {
9477 return to_char_type(0xCA); // float 32
9478 }
9479
9480 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
9481 {
9482 return to_char_type(0xCB); // float 64
9483 }
9484
9486 // UBJSON //
9488
9489 // UBJSON: write number (floating point)
9490 template<typename NumberType, typename std::enable_if<
9491 std::is_floating_point<NumberType>::value, int>::type = 0>
9492 void write_number_with_ubjson_prefix(const NumberType n,
9493 const bool add_prefix)
9494 {
9495 if (add_prefix)
9496 {
9497 oa->write_character(get_ubjson_float_prefix(n));
9498 }
9499 write_number(n);
9500 }
9501
9502 // UBJSON: write number (unsigned integer)
9503 template<typename NumberType, typename std::enable_if<
9504 std::is_unsigned<NumberType>::value, int>::type = 0>
9505 void write_number_with_ubjson_prefix(const NumberType n,
9506 const bool add_prefix)
9507 {
9508 if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
9509 {
9510 if (add_prefix)
9511 {
9512 oa->write_character(to_char_type('i')); // int8
9513 }
9514 write_number(static_cast<uint8_t>(n));
9515 }
9516 else if (n <= (std::numeric_limits<uint8_t>::max)())
9517 {
9518 if (add_prefix)
9519 {
9520 oa->write_character(to_char_type('U')); // uint8
9521 }
9522 write_number(static_cast<uint8_t>(n));
9523 }
9524 else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
9525 {
9526 if (add_prefix)
9527 {
9528 oa->write_character(to_char_type('I')); // int16
9529 }
9530 write_number(static_cast<int16_t>(n));
9531 }
9532 else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
9533 {
9534 if (add_prefix)
9535 {
9536 oa->write_character(to_char_type('l')); // int32
9537 }
9538 write_number(static_cast<int32_t>(n));
9539 }
9540 else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
9541 {
9542 if (add_prefix)
9543 {
9544 oa->write_character(to_char_type('L')); // int64
9545 }
9546 write_number(static_cast<int64_t>(n));
9547 }
9548 else
9549 {
9550 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
9551 }
9552 }
9553
9554 // UBJSON: write number (signed integer)
9555 template<typename NumberType, typename std::enable_if<
9556 std::is_signed<NumberType>::value and
9557 not std::is_floating_point<NumberType>::value, int>::type = 0>
9558 void write_number_with_ubjson_prefix(const NumberType n,
9559 const bool add_prefix)
9560 {
9561 if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
9562 {
9563 if (add_prefix)
9564 {
9565 oa->write_character(to_char_type('i')); // int8
9566 }
9567 write_number(static_cast<int8_t>(n));
9568 }
9569 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)()))
9570 {
9571 if (add_prefix)
9572 {
9573 oa->write_character(to_char_type('U')); // uint8
9574 }
9575 write_number(static_cast<uint8_t>(n));
9576 }
9577 else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
9578 {
9579 if (add_prefix)
9580 {
9581 oa->write_character(to_char_type('I')); // int16
9582 }
9583 write_number(static_cast<int16_t>(n));
9584 }
9585 else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
9586 {
9587 if (add_prefix)
9588 {
9589 oa->write_character(to_char_type('l')); // int32
9590 }
9591 write_number(static_cast<int32_t>(n));
9592 }
9593 else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
9594 {
9595 if (add_prefix)
9596 {
9597 oa->write_character(to_char_type('L')); // int64
9598 }
9599 write_number(static_cast<int64_t>(n));
9600 }
9601 // LCOV_EXCL_START
9602 else
9603 {
9604 JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
9605 }
9606 // LCOV_EXCL_STOP
9607 }
9608
9618 CharType ubjson_prefix(const BasicJsonType& j) const noexcept
9619 {
9620 switch (j.type())
9621 {
9622 case value_t::null:
9623 return 'Z';
9624
9625 case value_t::boolean:
9626 return j.m_value.boolean ? 'T' : 'F';
9627
9628 case value_t::number_integer:
9629 {
9630 if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
9631 {
9632 return 'i';
9633 }
9634 if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
9635 {
9636 return 'U';
9637 }
9638 if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
9639 {
9640 return 'I';
9641 }
9642 if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
9643 {
9644 return 'l';
9645 }
9646 // no check and assume int64_t (see note above)
9647 return 'L';
9648 }
9649
9650 case value_t::number_unsigned:
9651 {
9652 if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
9653 {
9654 return 'i';
9655 }
9656 if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
9657 {
9658 return 'U';
9659 }
9660 if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
9661 {
9662 return 'I';
9663 }
9664 if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
9665 {
9666 return 'l';
9667 }
9668 // no check and assume int64_t (see note above)
9669 return 'L';
9670 }
9671
9672 case value_t::number_float:
9673 return get_ubjson_float_prefix(j.m_value.number_float);
9674
9675 case value_t::string:
9676 return 'S';
9677
9678 case value_t::array:
9679 return '[';
9680
9681 case value_t::object:
9682 return '{';
9683
9684 default: // discarded values
9685 return 'N';
9686 }
9687 }
9688
9689 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
9690 {
9691 return 'd'; // float 32
9692 }
9693
9694 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
9695 {
9696 return 'D'; // float 64
9697 }
9698
9700 // Utility functions //
9702
9703 /*
9704 @brief write a number to output input
9705 @param[in] n number of type @a NumberType
9706 @tparam NumberType the type of the number
9707 @tparam OutputIsLittleEndian Set to true if output data is
9708 required to be little endian
9709
9710 @note This function needs to respect the system's endianess, because bytes
9711 in CBOR, MessagePack, and UBJSON are stored in network order (big
9712 endian) and therefore need reordering on little endian systems.
9713 */
9714 template<typename NumberType, bool OutputIsLittleEndian = false>
9715 void write_number(const NumberType n)
9716 {
9717 // step 1: write number to array of length NumberType
9718 std::array<CharType, sizeof(NumberType)> vec;
9719 std::memcpy(vec.data(), &n, sizeof(NumberType));
9720
9721 // step 2: write array to output (with possible reordering)
9722 if (is_little_endian and not OutputIsLittleEndian)
9723 {
9724 // reverse byte order prior to conversion if necessary
9725 std::reverse(vec.begin(), vec.end());
9726 }
9727
9728 oa->write_characters(vec.data(), sizeof(NumberType));
9729 }
9730
9731 public:
9732 // The following to_char_type functions are implement the conversion
9733 // between uint8_t and CharType. In case CharType is not unsigned,
9734 // such a conversion is required to allow values greater than 128.
9735 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
9736 template < typename C = CharType,
9737 enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
9738 static constexpr CharType to_char_type(std::uint8_t x) noexcept
9739 {
9740 return *reinterpret_cast<char*>(&x);
9741 }
9742
9743 template < typename C = CharType,
9744 enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
9745 static CharType to_char_type(std::uint8_t x) noexcept
9746 {
9747 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
9748 static_assert(std::is_standard_layout<CharType>::value && std::is_trivial<CharType>::value, "CharType must be POD");
9749 CharType result;
9750 std::memcpy(&result, &x, sizeof(x));
9751 return result;
9752 }
9753
9754 template<typename C = CharType,
9755 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
9756 static constexpr CharType to_char_type(std::uint8_t x) noexcept
9757 {
9758 return x;
9759 }
9760
9761 template < typename InputCharType, typename C = CharType,
9762 enable_if_t <
9763 std::is_signed<C>::value and
9764 std::is_signed<char>::value and
9765 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
9766 > * = nullptr >
9767 static constexpr CharType to_char_type(InputCharType x) noexcept
9768 {
9769 return x;
9770 }
9771
9772 private:
9774 const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
9775
9777 output_adapter_t<CharType> oa = nullptr;
9778};
9779} // namespace detail
9780} // namespace nlohmann
9781
9782// #include <nlohmann/detail/output/serializer.hpp>
9783
9784
9785#include <algorithm> // reverse, remove, fill, find, none_of
9786#include <array> // array
9787#include <cassert> // assert
9788#include <ciso646> // and, or
9789#include <clocale> // localeconv, lconv
9790#include <cmath> // labs, isfinite, isnan, signbit
9791#include <cstddef> // size_t, ptrdiff_t
9792#include <cstdint> // uint8_t
9793#include <cstdio> // snprintf
9794#include <limits> // numeric_limits
9795#include <string> // string
9796#include <type_traits> // is_same
9797
9798// #include <nlohmann/detail/exceptions.hpp>
9799
9800// #include <nlohmann/detail/conversions/to_chars.hpp>
9801
9802
9803#include <cassert> // assert
9804#include <ciso646> // or, and, not
9805#include <cmath> // signbit, isfinite
9806#include <cstdint> // intN_t, uintN_t
9807#include <cstring> // memcpy, memmove
9808
9809namespace nlohmann
9810{
9811namespace detail
9812{
9813
9833namespace dtoa_impl
9834{
9835
9836template <typename Target, typename Source>
9837Target reinterpret_bits(const Source source)
9838{
9839 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
9840
9841 Target target;
9842 std::memcpy(&target, &source, sizeof(Source));
9843 return target;
9844}
9845
9846struct diyfp // f * 2^e
9847{
9848 static constexpr int kPrecision = 64; // = q
9849
9850 uint64_t f = 0;
9851 int e = 0;
9852
9853 constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
9854
9859 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
9860 {
9861 assert(x.e == y.e);
9862 assert(x.f >= y.f);
9863
9864 return {x.f - y.f, x.e};
9865 }
9866
9871 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
9872 {
9873 static_assert(kPrecision == 64, "internal error");
9874
9875 // Computes:
9876 // f = round((x.f * y.f) / 2^q)
9877 // e = x.e + y.e + q
9878
9879 // Emulate the 64-bit * 64-bit multiplication:
9880 //
9881 // p = u * v
9882 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
9883 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
9884 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
9885 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
9886 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
9887 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
9888 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
9889 //
9890 // (Since Q might be larger than 2^32 - 1)
9891 //
9892 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
9893 //
9894 // (Q_hi + H does not overflow a 64-bit int)
9895 //
9896 // = p_lo + 2^64 p_hi
9897
9898 const uint64_t u_lo = x.f & 0xFFFFFFFF;
9899 const uint64_t u_hi = x.f >> 32;
9900 const uint64_t v_lo = y.f & 0xFFFFFFFF;
9901 const uint64_t v_hi = y.f >> 32;
9902
9903 const uint64_t p0 = u_lo * v_lo;
9904 const uint64_t p1 = u_lo * v_hi;
9905 const uint64_t p2 = u_hi * v_lo;
9906 const uint64_t p3 = u_hi * v_hi;
9907
9908 const uint64_t p0_hi = p0 >> 32;
9909 const uint64_t p1_lo = p1 & 0xFFFFFFFF;
9910 const uint64_t p1_hi = p1 >> 32;
9911 const uint64_t p2_lo = p2 & 0xFFFFFFFF;
9912 const uint64_t p2_hi = p2 >> 32;
9913
9914 uint64_t Q = p0_hi + p1_lo + p2_lo;
9915
9916 // The full product might now be computed as
9917 //
9918 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
9919 // p_lo = p0_lo + (Q << 32)
9920 //
9921 // But in this particular case here, the full p_lo is not required.
9922 // Effectively we only need to add the highest bit in p_lo to p_hi (and
9923 // Q_hi + 1 does not overflow).
9924
9925 Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
9926
9927 const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
9928
9929 return {h, x.e + y.e + 64};
9930 }
9931
9936 static diyfp normalize(diyfp x) noexcept
9937 {
9938 assert(x.f != 0);
9939
9940 while ((x.f >> 63) == 0)
9941 {
9942 x.f <<= 1;
9943 x.e--;
9944 }
9945
9946 return x;
9947 }
9948
9953 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
9954 {
9955 const int delta = x.e - target_exponent;
9956
9957 assert(delta >= 0);
9958 assert(((x.f << delta) >> delta) == x.f);
9959
9960 return {x.f << delta, target_exponent};
9961 }
9962};
9963
9964struct boundaries
9965{
9966 diyfp w;
9967 diyfp minus;
9968 diyfp plus;
9969};
9970
9977template <typename FloatType>
9978boundaries compute_boundaries(FloatType value)
9979{
9980 assert(std::isfinite(value));
9981 assert(value > 0);
9982
9983 // Convert the IEEE representation into a diyfp.
9984 //
9985 // If v is denormal:
9986 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
9987 // If v is normalized:
9988 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
9989
9990 static_assert(std::numeric_limits<FloatType>::is_iec559,
9991 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
9992
9993 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
9994 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
9995 constexpr int kMinExp = 1 - kBias;
9996 constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
9997
9998 using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
9999
10000 const uint64_t bits = reinterpret_bits<bits_type>(value);
10001 const uint64_t E = bits >> (kPrecision - 1);
10002 const uint64_t F = bits & (kHiddenBit - 1);
10003
10004 const bool is_denormal = (E == 0);
10005 const diyfp v = is_denormal
10006 ? diyfp(F, kMinExp)
10007 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
10008
10009 // Compute the boundaries m- and m+ of the floating-point value
10010 // v = f * 2^e.
10011 //
10012 // Determine v- and v+, the floating-point predecessor and successor if v,
10013 // respectively.
10014 //
10015 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
10016 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
10017 //
10018 // v+ = v + 2^e
10019 //
10020 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
10021 // between m- and m+ round to v, regardless of how the input rounding
10022 // algorithm breaks ties.
10023 //
10024 // ---+-------------+-------------+-------------+-------------+--- (A)
10025 // v- m- v m+ v+
10026 //
10027 // -----------------+------+------+-------------+-------------+--- (B)
10028 // v- m- v m+ v+
10029
10030 const bool lower_boundary_is_closer = (F == 0 and E > 1);
10031 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
10032 const diyfp m_minus = lower_boundary_is_closer
10033 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
10034 : diyfp(2 * v.f - 1, v.e - 1); // (A)
10035
10036 // Determine the normalized w+ = m+.
10037 const diyfp w_plus = diyfp::normalize(m_plus);
10038
10039 // Determine w- = m- such that e_(w-) = e_(w+).
10040 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
10041
10042 return {diyfp::normalize(v), w_minus, w_plus};
10043}
10044
10045// Given normalized diyfp w, Grisu needs to find a (normalized) cached
10046// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
10047// within a certain range [alpha, gamma] (Definition 3.2 from [1])
10048//
10049// alpha <= e = e_c + e_w + q <= gamma
10050//
10051// or
10052//
10053// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
10054// <= f_c * f_w * 2^gamma
10055//
10056// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
10057//
10058// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
10059//
10060// or
10061//
10062// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
10063//
10064// The choice of (alpha,gamma) determines the size of the table and the form of
10065// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
10066// in practice:
10067//
10068// The idea is to cut the number c * w = f * 2^e into two parts, which can be
10069// processed independently: An integral part p1, and a fractional part p2:
10070//
10071// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
10072// = (f div 2^-e) + (f mod 2^-e) * 2^e
10073// = p1 + p2 * 2^e
10074//
10075// The conversion of p1 into decimal form requires a series of divisions and
10076// modulos by (a power of) 10. These operations are faster for 32-bit than for
10077// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
10078// achieved by choosing
10079//
10080// -e >= 32 or e <= -32 := gamma
10081//
10082// In order to convert the fractional part
10083//
10084// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
10085//
10086// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
10087// d[-i] are extracted in order:
10088//
10089// (10 * p2) div 2^-e = d[-1]
10090// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
10091//
10092// The multiplication by 10 must not overflow. It is sufficient to choose
10093//
10094// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
10095//
10096// Since p2 = f mod 2^-e < 2^-e,
10097//
10098// -e <= 60 or e >= -60 := alpha
10099
10100constexpr int kAlpha = -60;
10101constexpr int kGamma = -32;
10102
10103struct cached_power // c = f * 2^e ~= 10^k
10104{
10105 uint64_t f;
10106 int e;
10107 int k;
10108};
10109
10117inline cached_power get_cached_power_for_binary_exponent(int e)
10118{
10119 // Now
10120 //
10121 // alpha <= e_c + e + q <= gamma (1)
10122 // ==> f_c * 2^alpha <= c * 2^e * 2^q
10123 //
10124 // and since the c's are normalized, 2^(q-1) <= f_c,
10125 //
10126 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
10127 // ==> 2^(alpha - e - 1) <= c
10128 //
10129 // If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
10130 //
10131 // k = ceil( log_10( 2^(alpha - e - 1) ) )
10132 // = ceil( (alpha - e - 1) * log_10(2) )
10133 //
10134 // From the paper:
10135 // "In theory the result of the procedure could be wrong since c is rounded,
10136 // and the computation itself is approximated [...]. In practice, however,
10137 // this simple function is sufficient."
10138 //
10139 // For IEEE double precision floating-point numbers converted into
10140 // normalized diyfp's w = f * 2^e, with q = 64,
10141 //
10142 // e >= -1022 (min IEEE exponent)
10143 // -52 (p - 1)
10144 // -52 (p - 1, possibly normalize denormal IEEE numbers)
10145 // -11 (normalize the diyfp)
10146 // = -1137
10147 //
10148 // and
10149 //
10150 // e <= +1023 (max IEEE exponent)
10151 // -52 (p - 1)
10152 // -11 (normalize the diyfp)
10153 // = 960
10154 //
10155 // This binary exponent range [-1137,960] results in a decimal exponent
10156 // range [-307,324]. One does not need to store a cached power for each
10157 // k in this range. For each such k it suffices to find a cached power
10158 // such that the exponent of the product lies in [alpha,gamma].
10159 // This implies that the difference of the decimal exponents of adjacent
10160 // table entries must be less than or equal to
10161 //
10162 // floor( (gamma - alpha) * log_10(2) ) = 8.
10163 //
10164 // (A smaller distance gamma-alpha would require a larger table.)
10165
10166 // NB:
10167 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
10168
10169 constexpr int kCachedPowersSize = 79;
10170 constexpr int kCachedPowersMinDecExp = -300;
10171 constexpr int kCachedPowersDecStep = 8;
10172
10173 static constexpr cached_power kCachedPowers[] =
10174 {
10175 { 0xAB70FE17C79AC6CA, -1060, -300 },
10176 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
10177 { 0xBE5691EF416BD60C, -1007, -284 },
10178 { 0x8DD01FAD907FFC3C, -980, -276 },
10179 { 0xD3515C2831559A83, -954, -268 },
10180 { 0x9D71AC8FADA6C9B5, -927, -260 },
10181 { 0xEA9C227723EE8BCB, -901, -252 },
10182 { 0xAECC49914078536D, -874, -244 },
10183 { 0x823C12795DB6CE57, -847, -236 },
10184 { 0xC21094364DFB5637, -821, -228 },
10185 { 0x9096EA6F3848984F, -794, -220 },
10186 { 0xD77485CB25823AC7, -768, -212 },
10187 { 0xA086CFCD97BF97F4, -741, -204 },
10188 { 0xEF340A98172AACE5, -715, -196 },
10189 { 0xB23867FB2A35B28E, -688, -188 },
10190 { 0x84C8D4DFD2C63F3B, -661, -180 },
10191 { 0xC5DD44271AD3CDBA, -635, -172 },
10192 { 0x936B9FCEBB25C996, -608, -164 },
10193 { 0xDBAC6C247D62A584, -582, -156 },
10194 { 0xA3AB66580D5FDAF6, -555, -148 },
10195 { 0xF3E2F893DEC3F126, -529, -140 },
10196 { 0xB5B5ADA8AAFF80B8, -502, -132 },
10197 { 0x87625F056C7C4A8B, -475, -124 },
10198 { 0xC9BCFF6034C13053, -449, -116 },
10199 { 0x964E858C91BA2655, -422, -108 },
10200 { 0xDFF9772470297EBD, -396, -100 },
10201 { 0xA6DFBD9FB8E5B88F, -369, -92 },
10202 { 0xF8A95FCF88747D94, -343, -84 },
10203 { 0xB94470938FA89BCF, -316, -76 },
10204 { 0x8A08F0F8BF0F156B, -289, -68 },
10205 { 0xCDB02555653131B6, -263, -60 },
10206 { 0x993FE2C6D07B7FAC, -236, -52 },
10207 { 0xE45C10C42A2B3B06, -210, -44 },
10208 { 0xAA242499697392D3, -183, -36 },
10209 { 0xFD87B5F28300CA0E, -157, -28 },
10210 { 0xBCE5086492111AEB, -130, -20 },
10211 { 0x8CBCCC096F5088CC, -103, -12 },
10212 { 0xD1B71758E219652C, -77, -4 },
10213 { 0x9C40000000000000, -50, 4 },
10214 { 0xE8D4A51000000000, -24, 12 },
10215 { 0xAD78EBC5AC620000, 3, 20 },
10216 { 0x813F3978F8940984, 30, 28 },
10217 { 0xC097CE7BC90715B3, 56, 36 },
10218 { 0x8F7E32CE7BEA5C70, 83, 44 },
10219 { 0xD5D238A4ABE98068, 109, 52 },
10220 { 0x9F4F2726179A2245, 136, 60 },
10221 { 0xED63A231D4C4FB27, 162, 68 },
10222 { 0xB0DE65388CC8ADA8, 189, 76 },
10223 { 0x83C7088E1AAB65DB, 216, 84 },
10224 { 0xC45D1DF942711D9A, 242, 92 },
10225 { 0x924D692CA61BE758, 269, 100 },
10226 { 0xDA01EE641A708DEA, 295, 108 },
10227 { 0xA26DA3999AEF774A, 322, 116 },
10228 { 0xF209787BB47D6B85, 348, 124 },
10229 { 0xB454E4A179DD1877, 375, 132 },
10230 { 0x865B86925B9BC5C2, 402, 140 },
10231 { 0xC83553C5C8965D3D, 428, 148 },
10232 { 0x952AB45CFA97A0B3, 455, 156 },
10233 { 0xDE469FBD99A05FE3, 481, 164 },
10234 { 0xA59BC234DB398C25, 508, 172 },
10235 { 0xF6C69A72A3989F5C, 534, 180 },
10236 { 0xB7DCBF5354E9BECE, 561, 188 },
10237 { 0x88FCF317F22241E2, 588, 196 },
10238 { 0xCC20CE9BD35C78A5, 614, 204 },
10239 { 0x98165AF37B2153DF, 641, 212 },
10240 { 0xE2A0B5DC971F303A, 667, 220 },
10241 { 0xA8D9D1535CE3B396, 694, 228 },
10242 { 0xFB9B7CD9A4A7443C, 720, 236 },
10243 { 0xBB764C4CA7A44410, 747, 244 },
10244 { 0x8BAB8EEFB6409C1A, 774, 252 },
10245 { 0xD01FEF10A657842C, 800, 260 },
10246 { 0x9B10A4E5E9913129, 827, 268 },
10247 { 0xE7109BFBA19C0C9D, 853, 276 },
10248 { 0xAC2820D9623BF429, 880, 284 },
10249 { 0x80444B5E7AA7CF85, 907, 292 },
10250 { 0xBF21E44003ACDD2D, 933, 300 },
10251 { 0x8E679C2F5E44FF8F, 960, 308 },
10252 { 0xD433179D9C8CB841, 986, 316 },
10253 { 0x9E19DB92B4E31BA9, 1013, 324 },
10254 };
10255
10256 // This computation gives exactly the same results for k as
10257 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
10258 // for |e| <= 1500, but doesn't require floating-point operations.
10259 // NB: log_10(2) ~= 78913 / 2^18
10260 assert(e >= -1500);
10261 assert(e <= 1500);
10262 const int f = kAlpha - e - 1;
10263 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
10264
10265 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
10266 assert(index >= 0);
10267 assert(index < kCachedPowersSize);
10268 static_cast<void>(kCachedPowersSize); // Fix warning.
10269
10270 const cached_power cached = kCachedPowers[index];
10271 assert(kAlpha <= cached.e + e + 64);
10272 assert(kGamma >= cached.e + e + 64);
10273
10274 return cached;
10275}
10276
10281inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
10282{
10283 // LCOV_EXCL_START
10284 if (n >= 1000000000)
10285 {
10286 pow10 = 1000000000;
10287 return 10;
10288 }
10289 // LCOV_EXCL_STOP
10290 else if (n >= 100000000)
10291 {
10292 pow10 = 100000000;
10293 return 9;
10294 }
10295 else if (n >= 10000000)
10296 {
10297 pow10 = 10000000;
10298 return 8;
10299 }
10300 else if (n >= 1000000)
10301 {
10302 pow10 = 1000000;
10303 return 7;
10304 }
10305 else if (n >= 100000)
10306 {
10307 pow10 = 100000;
10308 return 6;
10309 }
10310 else if (n >= 10000)
10311 {
10312 pow10 = 10000;
10313 return 5;
10314 }
10315 else if (n >= 1000)
10316 {
10317 pow10 = 1000;
10318 return 4;
10319 }
10320 else if (n >= 100)
10321 {
10322 pow10 = 100;
10323 return 3;
10324 }
10325 else if (n >= 10)
10326 {
10327 pow10 = 10;
10328 return 2;
10329 }
10330 else
10331 {
10332 pow10 = 1;
10333 return 1;
10334 }
10335}
10336
10337inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,
10338 uint64_t rest, uint64_t ten_k)
10339{
10340 assert(len >= 1);
10341 assert(dist <= delta);
10342 assert(rest <= delta);
10343 assert(ten_k > 0);
10344
10345 // <--------------------------- delta ---->
10346 // <---- dist --------->
10347 // --------------[------------------+-------------------]--------------
10348 // M- w M+
10349 //
10350 // ten_k
10351 // <------>
10352 // <---- rest ---->
10353 // --------------[------------------+----+--------------]--------------
10354 // w V
10355 // = buf * 10^k
10356 //
10357 // ten_k represents a unit-in-the-last-place in the decimal representation
10358 // stored in buf.
10359 // Decrement buf by ten_k while this takes buf closer to w.
10360
10361 // The tests are written in this order to avoid overflow in unsigned
10362 // integer arithmetic.
10363
10364 while (rest < dist
10365 and delta - rest >= ten_k
10366 and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
10367 {
10368 assert(buf[len - 1] != '0');
10369 buf[len - 1]--;
10370 rest += ten_k;
10371 }
10372}
10373
10378inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
10379 diyfp M_minus, diyfp w, diyfp M_plus)
10380{
10381 static_assert(kAlpha >= -60, "internal error");
10382 static_assert(kGamma <= -32, "internal error");
10383
10384 // Generates the digits (and the exponent) of a decimal floating-point
10385 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
10386 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
10387 //
10388 // <--------------------------- delta ---->
10389 // <---- dist --------->
10390 // --------------[------------------+-------------------]--------------
10391 // M- w M+
10392 //
10393 // Grisu2 generates the digits of M+ from left to right and stops as soon as
10394 // V is in [M-,M+].
10395
10396 assert(M_plus.e >= kAlpha);
10397 assert(M_plus.e <= kGamma);
10398
10399 uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
10400 uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
10401
10402 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
10403 //
10404 // M+ = f * 2^e
10405 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
10406 // = ((p1 ) * 2^-e + (p2 )) * 2^e
10407 // = p1 + p2 * 2^e
10408
10409 const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
10410
10411 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.)
10412 uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
10413
10414 // 1)
10415 //
10416 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
10417
10418 assert(p1 > 0);
10419
10420 uint32_t pow10;
10421 const int k = find_largest_pow10(p1, pow10);
10422
10423 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
10424 //
10425 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
10426 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
10427 //
10428 // M+ = p1 + p2 * 2^e
10429 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
10430 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
10431 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
10432 //
10433 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
10434 //
10435 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
10436 //
10437 // but stop as soon as
10438 //
10439 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
10440
10441 int n = k;
10442 while (n > 0)
10443 {
10444 // Invariants:
10445 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
10446 // pow10 = 10^(n-1) <= p1 < 10^n
10447 //
10448 const uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
10449 const uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
10450 //
10451 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
10452 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
10453 //
10454 assert(d <= 9);
10455 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
10456 //
10457 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
10458 //
10459 p1 = r;
10460 n--;
10461 //
10462 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
10463 // pow10 = 10^n
10464 //
10465
10466 // Now check if enough digits have been generated.
10467 // Compute
10468 //
10469 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
10470 //
10471 // Note:
10472 // Since rest and delta share the same exponent e, it suffices to
10473 // compare the significands.
10474 const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
10475 if (rest <= delta)
10476 {
10477 // V = buffer * 10^n, with M- <= V <= M+.
10478
10479 decimal_exponent += n;
10480
10481 // We may now just stop. But instead look if the buffer could be
10482 // decremented to bring V closer to w.
10483 //
10484 // pow10 = 10^n is now 1 ulp in the decimal representation V.
10485 // The rounding procedure works with diyfp's with an implicit
10486 // exponent of e.
10487 //
10488 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
10489 //
10490 const uint64_t ten_n = uint64_t{pow10} << -one.e;
10491 grisu2_round(buffer, length, dist, delta, rest, ten_n);
10492
10493 return;
10494 }
10495
10496 pow10 /= 10;
10497 //
10498 // pow10 = 10^(n-1) <= p1 < 10^n
10499 // Invariants restored.
10500 }
10501
10502 // 2)
10503 //
10504 // The digits of the integral part have been generated:
10505 //
10506 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
10507 // = buffer + p2 * 2^e
10508 //
10509 // Now generate the digits of the fractional part p2 * 2^e.
10510 //
10511 // Note:
10512 // No decimal point is generated: the exponent is adjusted instead.
10513 //
10514 // p2 actually represents the fraction
10515 //
10516 // p2 * 2^e
10517 // = p2 / 2^-e
10518 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
10519 //
10520 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
10521 //
10522 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
10523 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
10524 //
10525 // using
10526 //
10527 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
10528 // = ( d) * 2^-e + ( r)
10529 //
10530 // or
10531 // 10^m * p2 * 2^e = d + r * 2^e
10532 //
10533 // i.e.
10534 //
10535 // M+ = buffer + p2 * 2^e
10536 // = buffer + 10^-m * (d + r * 2^e)
10537 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
10538 //
10539 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
10540
10541 assert(p2 > delta);
10542
10543 int m = 0;
10544 for (;;)
10545 {
10546 // Invariant:
10547 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
10548 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
10549 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
10550 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
10551 //
10552 assert(p2 <= UINT64_MAX / 10);
10553 p2 *= 10;
10554 const uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
10555 const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
10556 //
10557 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
10558 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
10559 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
10560 //
10561 assert(d <= 9);
10562 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
10563 //
10564 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
10565 //
10566 p2 = r;
10567 m++;
10568 //
10569 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
10570 // Invariant restored.
10571
10572 // Check if enough digits have been generated.
10573 //
10574 // 10^-m * p2 * 2^e <= delta * 2^e
10575 // p2 * 2^e <= 10^m * delta * 2^e
10576 // p2 <= 10^m * delta
10577 delta *= 10;
10578 dist *= 10;
10579 if (p2 <= delta)
10580 {
10581 break;
10582 }
10583 }
10584
10585 // V = buffer * 10^-m, with M- <= V <= M+.
10586
10587 decimal_exponent -= m;
10588
10589 // 1 ulp in the decimal representation is now 10^-m.
10590 // Since delta and dist are now scaled by 10^m, we need to do the
10591 // same with ulp in order to keep the units in sync.
10592 //
10593 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
10594 //
10595 const uint64_t ten_m = one.f;
10596 grisu2_round(buffer, length, dist, delta, p2, ten_m);
10597
10598 // By construction this algorithm generates the shortest possible decimal
10599 // number (Loitsch, Theorem 6.2) which rounds back to w.
10600 // For an input number of precision p, at least
10601 //
10602 // N = 1 + ceil(p * log_10(2))
10603 //
10604 // decimal digits are sufficient to identify all binary floating-point
10605 // numbers (Matula, "In-and-Out conversions").
10606 // This implies that the algorithm does not produce more than N decimal
10607 // digits.
10608 //
10609 // N = 17 for p = 53 (IEEE double precision)
10610 // N = 9 for p = 24 (IEEE single precision)
10611}
10612
10618inline void grisu2(char* buf, int& len, int& decimal_exponent,
10619 diyfp m_minus, diyfp v, diyfp m_plus)
10620{
10621 assert(m_plus.e == m_minus.e);
10622 assert(m_plus.e == v.e);
10623
10624 // --------(-----------------------+-----------------------)-------- (A)
10625 // m- v m+
10626 //
10627 // --------------------(-----------+-----------------------)-------- (B)
10628 // m- v m+
10629 //
10630 // First scale v (and m- and m+) such that the exponent is in the range
10631 // [alpha, gamma].
10632
10633 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
10634
10635 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
10636
10637 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
10638 const diyfp w = diyfp::mul(v, c_minus_k);
10639 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
10640 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
10641
10642 // ----(---+---)---------------(---+---)---------------(---+---)----
10643 // w- w w+
10644 // = c*m- = c*v = c*m+
10645 //
10646 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
10647 // w+ are now off by a small amount.
10648 // In fact:
10649 //
10650 // w - v * 10^k < 1 ulp
10651 //
10652 // To account for this inaccuracy, add resp. subtract 1 ulp.
10653 //
10654 // --------+---[---------------(---+---)---------------]---+--------
10655 // w- M- w M+ w+
10656 //
10657 // Now any number in [M-, M+] (bounds included) will round to w when input,
10658 // regardless of how the input rounding algorithm breaks ties.
10659 //
10660 // And digit_gen generates the shortest possible such number in [M-, M+].
10661 // Note that this does not mean that Grisu2 always generates the shortest
10662 // possible number in the interval (m-, m+).
10663 const diyfp M_minus(w_minus.f + 1, w_minus.e);
10664 const diyfp M_plus (w_plus.f - 1, w_plus.e );
10665
10666 decimal_exponent = -cached.k; // = -(-k) = k
10667
10668 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
10669}
10670
10676template <typename FloatType>
10677void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
10678{
10679 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
10680 "internal error: not enough precision");
10681
10682 assert(std::isfinite(value));
10683 assert(value > 0);
10684
10685 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
10686 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
10687 // decimal representations are not exactly "short".
10688 //
10689 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
10690 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
10691 // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
10692 // does.
10693 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
10694 // representation using the corresponding std::from_chars function recovers value exactly". That
10695 // indicates that single precision floating-point numbers should be recovered using
10696 // 'std::strtof'.
10697 //
10698 // NB: If the neighbors are computed for single-precision numbers, there is a single float
10699 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
10700 // value is off by 1 ulp.
10701#if 0
10702 const boundaries w = compute_boundaries(static_cast<double>(value));
10703#else
10704 const boundaries w = compute_boundaries(value);
10705#endif
10706
10707 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
10708}
10709
10715inline char* append_exponent(char* buf, int e)
10716{
10717 assert(e > -1000);
10718 assert(e < 1000);
10719
10720 if (e < 0)
10721 {
10722 e = -e;
10723 *buf++ = '-';
10724 }
10725 else
10726 {
10727 *buf++ = '+';
10728 }
10729
10730 auto k = static_cast<uint32_t>(e);
10731 if (k < 10)
10732 {
10733 // Always print at least two digits in the exponent.
10734 // This is for compatibility with printf("%g").
10735 *buf++ = '0';
10736 *buf++ = static_cast<char>('0' + k);
10737 }
10738 else if (k < 100)
10739 {
10740 *buf++ = static_cast<char>('0' + k / 10);
10741 k %= 10;
10742 *buf++ = static_cast<char>('0' + k);
10743 }
10744 else
10745 {
10746 *buf++ = static_cast<char>('0' + k / 100);
10747 k %= 100;
10748 *buf++ = static_cast<char>('0' + k / 10);
10749 k %= 10;
10750 *buf++ = static_cast<char>('0' + k);
10751 }
10752
10753 return buf;
10754}
10755
10765inline char* format_buffer(char* buf, int len, int decimal_exponent,
10766 int min_exp, int max_exp)
10767{
10768 assert(min_exp < 0);
10769 assert(max_exp > 0);
10770
10771 const int k = len;
10772 const int n = len + decimal_exponent;
10773
10774 // v = buf * 10^(n-k)
10775 // k is the length of the buffer (number of decimal digits)
10776 // n is the position of the decimal point relative to the start of the buffer.
10777
10778 if (k <= n and n <= max_exp)
10779 {
10780 // digits[000]
10781 // len <= max_exp + 2
10782
10783 std::memset(buf + k, '0', static_cast<size_t>(n - k));
10784 // Make it look like a floating-point number (#362, #378)
10785 buf[n + 0] = '.';
10786 buf[n + 1] = '0';
10787 return buf + (n + 2);
10788 }
10789
10790 if (0 < n and n <= max_exp)
10791 {
10792 // dig.its
10793 // len <= max_digits10 + 1
10794
10795 assert(k > n);
10796
10797 std::memmove(buf + (n + 1), buf + n, static_cast<size_t>(k - n));
10798 buf[n] = '.';
10799 return buf + (k + 1);
10800 }
10801
10802 if (min_exp < n and n <= 0)
10803 {
10804 // 0.[000]digits
10805 // len <= 2 + (-min_exp - 1) + max_digits10
10806
10807 std::memmove(buf + (2 + -n), buf, static_cast<size_t>(k));
10808 buf[0] = '0';
10809 buf[1] = '.';
10810 std::memset(buf + 2, '0', static_cast<size_t>(-n));
10811 return buf + (2 + (-n) + k);
10812 }
10813
10814 if (k == 1)
10815 {
10816 // dE+123
10817 // len <= 1 + 5
10818
10819 buf += 1;
10820 }
10821 else
10822 {
10823 // d.igitsE+123
10824 // len <= max_digits10 + 1 + 5
10825
10826 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k - 1));
10827 buf[1] = '.';
10828 buf += 1 + k;
10829 }
10830
10831 *buf++ = 'e';
10832 return append_exponent(buf, n - 1);
10833}
10834
10835} // namespace dtoa_impl
10836
10847template <typename FloatType>
10848char* to_chars(char* first, const char* last, FloatType value)
10849{
10850 static_cast<void>(last); // maybe unused - fix warning
10851 assert(std::isfinite(value));
10852
10853 // Use signbit(value) instead of (value < 0) since signbit works for -0.
10854 if (std::signbit(value))
10855 {
10856 value = -value;
10857 *first++ = '-';
10858 }
10859
10860 if (value == 0) // +-0
10861 {
10862 *first++ = '0';
10863 // Make it look like a floating-point number (#362, #378)
10864 *first++ = '.';
10865 *first++ = '0';
10866 return first;
10867 }
10868
10869 assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
10870
10871 // Compute v = buffer * 10^decimal_exponent.
10872 // The decimal digits are stored in the buffer, which needs to be interpreted
10873 // as an unsigned decimal integer.
10874 // len is the length of the buffer, i.e. the number of decimal digits.
10875 int len = 0;
10876 int decimal_exponent = 0;
10877 dtoa_impl::grisu2(first, len, decimal_exponent, value);
10878
10879 assert(len <= std::numeric_limits<FloatType>::max_digits10);
10880
10881 // Format the buffer like printf("%.*g", prec, value)
10882 constexpr int kMinExp = -4;
10883 // Use digits10 here to increase compatibility with version 2.
10884 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
10885
10886 assert(last - first >= kMaxExp + 2);
10887 assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
10888 assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
10889
10890 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
10891}
10892
10893} // namespace detail
10894} // namespace nlohmann
10895
10896// #include <nlohmann/detail/macro_scope.hpp>
10897
10898// #include <nlohmann/detail/meta/cpp_future.hpp>
10899
10900// #include <nlohmann/detail/output/binary_writer.hpp>
10901
10902// #include <nlohmann/detail/output/output_adapters.hpp>
10903
10904// #include <nlohmann/detail/value_t.hpp>
10905
10906
10907namespace nlohmann
10908{
10909namespace detail
10910{
10912// serialization //
10914
10917{
10918 strict,
10919 replace,
10920 ignore
10921};
10922
10923template<typename BasicJsonType>
10925{
10926 using string_t = typename BasicJsonType::string_t;
10927 using number_float_t = typename BasicJsonType::number_float_t;
10928 using number_integer_t = typename BasicJsonType::number_integer_t;
10929 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
10930 static constexpr uint8_t UTF8_ACCEPT = 0;
10931 static constexpr uint8_t UTF8_REJECT = 1;
10932
10933 public:
10941 : o(std::move(s))
10942 , loc(std::localeconv())
10943 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep))
10944 , decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point))
10945 , indent_char(ichar)
10946 , indent_string(512, indent_char)
10947 , error_handler(error_handler_)
10948 {}
10949
10950 // delete because of pointer members
10951 serializer(const serializer&) = delete;
10952 serializer& operator=(const serializer&) = delete;
10953 serializer(serializer&&) = delete;
10954 serializer& operator=(serializer&&) = delete;
10955 ~serializer() = default;
10956
10974 void dump(const BasicJsonType& val, const bool pretty_print,
10975 const bool ensure_ascii,
10976 const unsigned int indent_step,
10977 const unsigned int current_indent = 0)
10978 {
10979 switch (val.m_type)
10980 {
10981 case value_t::object:
10982 {
10983 if (val.m_value.object->empty())
10984 {
10985 o->write_characters("{}", 2);
10986 return;
10987 }
10988
10989 if (pretty_print)
10990 {
10991 o->write_characters("{\n", 2);
10992
10993 // variable to hold indentation for recursive calls
10994 const auto new_indent = current_indent + indent_step;
10995 if (JSON_UNLIKELY(indent_string.size() < new_indent))
10996 {
10997 indent_string.resize(indent_string.size() * 2, ' ');
10998 }
10999
11000 // first n-1 elements
11001 auto i = val.m_value.object->cbegin();
11002 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
11003 {
11004 o->write_characters(indent_string.c_str(), new_indent);
11005 o->write_character('\"');
11006 dump_escaped(i->first, ensure_ascii);
11007 o->write_characters("\": ", 3);
11008 dump(i->second, true, ensure_ascii, indent_step, new_indent);
11009 o->write_characters(",\n", 2);
11010 }
11011
11012 // last element
11013 assert(i != val.m_value.object->cend());
11014 assert(std::next(i) == val.m_value.object->cend());
11015 o->write_characters(indent_string.c_str(), new_indent);
11016 o->write_character('\"');
11017 dump_escaped(i->first, ensure_ascii);
11018 o->write_characters("\": ", 3);
11019 dump(i->second, true, ensure_ascii, indent_step, new_indent);
11020
11021 o->write_character('\n');
11022 o->write_characters(indent_string.c_str(), current_indent);
11023 o->write_character('}');
11024 }
11025 else
11026 {
11027 o->write_character('{');
11028
11029 // first n-1 elements
11030 auto i = val.m_value.object->cbegin();
11031 for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
11032 {
11033 o->write_character('\"');
11034 dump_escaped(i->first, ensure_ascii);
11035 o->write_characters("\":", 2);
11036 dump(i->second, false, ensure_ascii, indent_step, current_indent);
11037 o->write_character(',');
11038 }
11039
11040 // last element
11041 assert(i != val.m_value.object->cend());
11042 assert(std::next(i) == val.m_value.object->cend());
11043 o->write_character('\"');
11044 dump_escaped(i->first, ensure_ascii);
11045 o->write_characters("\":", 2);
11046 dump(i->second, false, ensure_ascii, indent_step, current_indent);
11047
11048 o->write_character('}');
11049 }
11050
11051 return;
11052 }
11053
11054 case value_t::array:
11055 {
11056 if (val.m_value.array->empty())
11057 {
11058 o->write_characters("[]", 2);
11059 return;
11060 }
11061
11062 if (pretty_print)
11063 {
11064 o->write_characters("[\n", 2);
11065
11066 // variable to hold indentation for recursive calls
11067 const auto new_indent = current_indent + indent_step;
11068 if (JSON_UNLIKELY(indent_string.size() < new_indent))
11069 {
11070 indent_string.resize(indent_string.size() * 2, ' ');
11071 }
11072
11073 // first n-1 elements
11074 for (auto i = val.m_value.array->cbegin();
11075 i != val.m_value.array->cend() - 1; ++i)
11076 {
11077 o->write_characters(indent_string.c_str(), new_indent);
11078 dump(*i, true, ensure_ascii, indent_step, new_indent);
11079 o->write_characters(",\n", 2);
11080 }
11081
11082 // last element
11083 assert(not val.m_value.array->empty());
11084 o->write_characters(indent_string.c_str(), new_indent);
11085 dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
11086
11087 o->write_character('\n');
11088 o->write_characters(indent_string.c_str(), current_indent);
11089 o->write_character(']');
11090 }
11091 else
11092 {
11093 o->write_character('[');
11094
11095 // first n-1 elements
11096 for (auto i = val.m_value.array->cbegin();
11097 i != val.m_value.array->cend() - 1; ++i)
11098 {
11099 dump(*i, false, ensure_ascii, indent_step, current_indent);
11100 o->write_character(',');
11101 }
11102
11103 // last element
11104 assert(not val.m_value.array->empty());
11105 dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
11106
11107 o->write_character(']');
11108 }
11109
11110 return;
11111 }
11112
11113 case value_t::string:
11114 {
11115 o->write_character('\"');
11116 dump_escaped(*val.m_value.string, ensure_ascii);
11117 o->write_character('\"');
11118 return;
11119 }
11120
11121 case value_t::boolean:
11122 {
11123 if (val.m_value.boolean)
11124 {
11125 o->write_characters("true", 4);
11126 }
11127 else
11128 {
11129 o->write_characters("false", 5);
11130 }
11131 return;
11132 }
11133
11134 case value_t::number_integer:
11135 {
11136 dump_integer(val.m_value.number_integer);
11137 return;
11138 }
11139
11140 case value_t::number_unsigned:
11141 {
11142 dump_integer(val.m_value.number_unsigned);
11143 return;
11144 }
11145
11146 case value_t::number_float:
11147 {
11148 dump_float(val.m_value.number_float);
11149 return;
11150 }
11151
11152 case value_t::discarded:
11153 {
11154 o->write_characters("<discarded>", 11);
11155 return;
11156 }
11157
11158 case value_t::null:
11159 {
11160 o->write_characters("null", 4);
11161 return;
11162 }
11163 }
11164 }
11165
11166 private:
11181 void dump_escaped(const string_t& s, const bool ensure_ascii)
11182 {
11183 uint32_t codepoint;
11184 uint8_t state = UTF8_ACCEPT;
11185 std::size_t bytes = 0; // number of bytes written to string_buffer
11186
11187 // number of bytes written at the point of the last valid byte
11188 std::size_t bytes_after_last_accept = 0;
11189 std::size_t undumped_chars = 0;
11190
11191 for (std::size_t i = 0; i < s.size(); ++i)
11192 {
11193 const auto byte = static_cast<uint8_t>(s[i]);
11194
11195 switch (decode(state, codepoint, byte))
11196 {
11197 case UTF8_ACCEPT: // decode found a new code point
11198 {
11199 switch (codepoint)
11200 {
11201 case 0x08: // backspace
11202 {
11203 string_buffer[bytes++] = '\\';
11204 string_buffer[bytes++] = 'b';
11205 break;
11206 }
11207
11208 case 0x09: // horizontal tab
11209 {
11210 string_buffer[bytes++] = '\\';
11211 string_buffer[bytes++] = 't';
11212 break;
11213 }
11214
11215 case 0x0A: // newline
11216 {
11217 string_buffer[bytes++] = '\\';
11218 string_buffer[bytes++] = 'n';
11219 break;
11220 }
11221
11222 case 0x0C: // formfeed
11223 {
11224 string_buffer[bytes++] = '\\';
11225 string_buffer[bytes++] = 'f';
11226 break;
11227 }
11228
11229 case 0x0D: // carriage return
11230 {
11231 string_buffer[bytes++] = '\\';
11232 string_buffer[bytes++] = 'r';
11233 break;
11234 }
11235
11236 case 0x22: // quotation mark
11237 {
11238 string_buffer[bytes++] = '\\';
11239 string_buffer[bytes++] = '\"';
11240 break;
11241 }
11242
11243 case 0x5C: // reverse solidus
11244 {
11245 string_buffer[bytes++] = '\\';
11246 string_buffer[bytes++] = '\\';
11247 break;
11248 }
11249
11250 default:
11251 {
11252 // escape control characters (0x00..0x1F) or, if
11253 // ensure_ascii parameter is used, non-ASCII characters
11254 if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
11255 {
11256 if (codepoint <= 0xFFFF)
11257 {
11258 (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
11259 static_cast<uint16_t>(codepoint));
11260 bytes += 6;
11261 }
11262 else
11263 {
11264 (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
11265 static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
11266 static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
11267 bytes += 12;
11268 }
11269 }
11270 else
11271 {
11272 // copy byte to buffer (all previous bytes
11273 // been copied have in default case above)
11274 string_buffer[bytes++] = s[i];
11275 }
11276 break;
11277 }
11278 }
11279
11280 // write buffer and reset index; there must be 13 bytes
11281 // left, as this is the maximal number of bytes to be
11282 // written ("\uxxxx\uxxxx\0") for one code point
11283 if (string_buffer.size() - bytes < 13)
11284 {
11285 o->write_characters(string_buffer.data(), bytes);
11286 bytes = 0;
11287 }
11288
11289 // remember the byte position of this accept
11290 bytes_after_last_accept = bytes;
11291 undumped_chars = 0;
11292 break;
11293 }
11294
11295 case UTF8_REJECT: // decode found invalid UTF-8 byte
11296 {
11297 switch (error_handler)
11298 {
11300 {
11301 std::string sn(3, '\0');
11302 (std::snprintf)(&sn[0], sn.size(), "%.2X", byte);
11303 JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
11304 }
11305
11308 {
11309 // in case we saw this character the first time, we
11310 // would like to read it again, because the byte
11311 // may be OK for itself, but just not OK for the
11312 // previous sequence
11313 if (undumped_chars > 0)
11314 {
11315 --i;
11316 }
11317
11318 // reset length buffer to the last accepted index;
11319 // thus removing/ignoring the invalid characters
11320 bytes = bytes_after_last_accept;
11321
11322 if (error_handler == error_handler_t::replace)
11323 {
11324 // add a replacement character
11325 if (ensure_ascii)
11326 {
11327 string_buffer[bytes++] = '\\';
11328 string_buffer[bytes++] = 'u';
11329 string_buffer[bytes++] = 'f';
11330 string_buffer[bytes++] = 'f';
11331 string_buffer[bytes++] = 'f';
11332 string_buffer[bytes++] = 'd';
11333 }
11334 else
11335 {
11336 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
11337 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
11338 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
11339 }
11340 bytes_after_last_accept = bytes;
11341 }
11342
11343 undumped_chars = 0;
11344
11345 // continue processing the string
11346 state = UTF8_ACCEPT;
11347 break;
11348 }
11349 }
11350 break;
11351 }
11352
11353 default: // decode found yet incomplete multi-byte code point
11354 {
11355 if (not ensure_ascii)
11356 {
11357 // code point will not be escaped - copy byte to buffer
11358 string_buffer[bytes++] = s[i];
11359 }
11360 ++undumped_chars;
11361 break;
11362 }
11363 }
11364 }
11365
11366 // we finished processing the string
11367 if (JSON_LIKELY(state == UTF8_ACCEPT))
11368 {
11369 // write buffer
11370 if (bytes > 0)
11371 {
11372 o->write_characters(string_buffer.data(), bytes);
11373 }
11374 }
11375 else
11376 {
11377 // we finish reading, but do not accept: string was incomplete
11378 switch (error_handler)
11379 {
11381 {
11382 std::string sn(3, '\0');
11383 (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
11384 JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
11385 }
11386
11388 {
11389 // write all accepted bytes
11390 o->write_characters(string_buffer.data(), bytes_after_last_accept);
11391 break;
11392 }
11393
11395 {
11396 // write all accepted bytes
11397 o->write_characters(string_buffer.data(), bytes_after_last_accept);
11398 // add a replacement character
11399 if (ensure_ascii)
11400 {
11401 o->write_characters("\\ufffd", 6);
11402 }
11403 else
11404 {
11405 o->write_characters("\xEF\xBF\xBD", 3);
11406 }
11407 break;
11408 }
11409 }
11410 }
11411 }
11412
11422 template<typename NumberType, detail::enable_if_t<
11423 std::is_same<NumberType, number_unsigned_t>::value or
11424 std::is_same<NumberType, number_integer_t>::value,
11425 int> = 0>
11426 void dump_integer(NumberType x)
11427 {
11428 // special case for "0"
11429 if (x == 0)
11430 {
11431 o->write_character('0');
11432 return;
11433 }
11434
11435 const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not (x >= 0); // see issue #755
11436 std::size_t i = 0;
11437
11438 while (x != 0)
11439 {
11440 // spare 1 byte for '\0'
11441 assert(i < number_buffer.size() - 1);
11442
11443 const auto digit = std::labs(static_cast<long>(x % 10));
11444 number_buffer[i++] = static_cast<char>('0' + digit);
11445 x /= 10;
11446 }
11447
11448 if (is_negative)
11449 {
11450 // make sure there is capacity for the '-'
11451 assert(i < number_buffer.size() - 2);
11452 number_buffer[i++] = '-';
11453 }
11454
11455 std::reverse(number_buffer.begin(), number_buffer.begin() + i);
11456 o->write_characters(number_buffer.data(), i);
11457 }
11458
11467 void dump_float(number_float_t x)
11468 {
11469 // NaN / inf
11470 if (not std::isfinite(x))
11471 {
11472 o->write_characters("null", 4);
11473 return;
11474 }
11475
11476 // If number_float_t is an IEEE-754 single or double precision number,
11477 // use the Grisu2 algorithm to produce short numbers which are
11478 // guaranteed to round-trip, using strtof and strtod, resp.
11479 //
11480 // NB: The test below works if <long double> == <double>.
11481 static constexpr bool is_ieee_single_or_double
11482 = (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
11483 (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);
11484
11485 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
11486 }
11487
11488 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
11489 {
11490 char* begin = number_buffer.data();
11491 char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
11492
11493 o->write_characters(begin, static_cast<size_t>(end - begin));
11494 }
11495
11496 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
11497 {
11498 // get number of digits for a float -> text -> float round-trip
11499 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
11500
11501 // the actual conversion
11502 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
11503
11504 // negative value indicates an error
11505 assert(len > 0);
11506 // check if buffer was large enough
11507 assert(static_cast<std::size_t>(len) < number_buffer.size());
11508
11509 // erase thousands separator
11510 if (thousands_sep != '\0')
11511 {
11512 const auto end = std::remove(number_buffer.begin(),
11513 number_buffer.begin() + len, thousands_sep);
11514 std::fill(end, number_buffer.end(), '\0');
11515 assert((end - number_buffer.begin()) <= len);
11516 len = (end - number_buffer.begin());
11517 }
11518
11519 // convert decimal point to '.'
11520 if (decimal_point != '\0' and decimal_point != '.')
11521 {
11522 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
11523 if (dec_pos != number_buffer.end())
11524 {
11525 *dec_pos = '.';
11526 }
11527 }
11528
11529 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
11530
11531 // determine if need to append ".0"
11532 const bool value_is_int_like =
11533 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
11534 [](char c)
11535 {
11536 return (c == '.' or c == 'e');
11537 });
11538
11539 if (value_is_int_like)
11540 {
11541 o->write_characters(".0", 2);
11542 }
11543 }
11544
11566 static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
11567 {
11568 static const std::array<uint8_t, 400> utf8d =
11569 {
11570 {
11571 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
11572 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
11573 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
11574 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
11575 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
11576 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
11577 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
11578 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
11579 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
11580 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
11581 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
11582 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
11583 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
11584 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
11585 }
11586 };
11587
11588 const uint8_t type = utf8d[byte];
11589
11590 codep = (state != UTF8_ACCEPT)
11591 ? (byte & 0x3fu) | (codep << 6)
11592 : static_cast<uint32_t>(0xff >> type) & (byte);
11593
11594 state = utf8d[256u + state * 16u + type];
11595 return state;
11596 }
11597
11598 private:
11600 output_adapter_t<char> o = nullptr;
11601
11603 std::array<char, 64> number_buffer{{}};
11604
11606 const std::lconv* loc = nullptr;
11608 const char thousands_sep = '\0';
11610 const char decimal_point = '\0';
11611
11613 std::array<char, 512> string_buffer{{}};
11614
11616 const char indent_char;
11618 string_t indent_string;
11619
11621 const error_handler_t error_handler;
11622};
11623} // namespace detail
11624} // namespace nlohmann
11625
11626// #include <nlohmann/detail/json_ref.hpp>
11627
11628
11629#include <initializer_list>
11630#include <utility>
11631
11632// #include <nlohmann/detail/meta/type_traits.hpp>
11633
11634
11635namespace nlohmann
11636{
11637namespace detail
11638{
11639template<typename BasicJsonType>
11640class json_ref
11641{
11642 public:
11643 using value_type = BasicJsonType;
11644
11645 json_ref(value_type&& value)
11646 : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
11647 {}
11648
11649 json_ref(const value_type& value)
11650 : value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
11651 {}
11652
11653 json_ref(std::initializer_list<json_ref> init)
11654 : owned_value(init), value_ref(&owned_value), is_rvalue(true)
11655 {}
11656
11657 template <
11658 class... Args,
11659 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
11660 json_ref(Args && ... args)
11661 : owned_value(std::forward<Args>(args)...), value_ref(&owned_value),
11662 is_rvalue(true) {}
11663
11664 // class should be movable only
11665 json_ref(json_ref&&) = default;
11666 json_ref(const json_ref&) = delete;
11667 json_ref& operator=(const json_ref&) = delete;
11668 json_ref& operator=(json_ref&&) = delete;
11669 ~json_ref() = default;
11670
11671 value_type moved_or_copied() const
11672 {
11673 if (is_rvalue)
11674 {
11675 return std::move(*value_ref);
11676 }
11677 return *value_ref;
11678 }
11679
11680 value_type const& operator*() const
11681 {
11682 return *static_cast<value_type const*>(value_ref);
11683 }
11684
11685 value_type const* operator->() const
11686 {
11687 return static_cast<value_type const*>(value_ref);
11688 }
11689
11690 private:
11691 mutable value_type owned_value = nullptr;
11692 value_type* value_ref = nullptr;
11693 const bool is_rvalue;
11694};
11695} // namespace detail
11696} // namespace nlohmann
11697
11698// #include <nlohmann/detail/json_pointer.hpp>
11699
11700
11701#include <cassert> // assert
11702#include <numeric> // accumulate
11703#include <string> // string
11704#include <vector> // vector
11705
11706// #include <nlohmann/detail/macro_scope.hpp>
11707
11708// #include <nlohmann/detail/exceptions.hpp>
11709
11710// #include <nlohmann/detail/value_t.hpp>
11711
11712
11713namespace nlohmann
11714{
11715template<typename BasicJsonType>
11717{
11718 // allow basic_json to access private members
11719 NLOHMANN_BASIC_JSON_TPL_DECLARATION
11720 friend class basic_json;
11721
11722 public:
11744 explicit json_pointer(const std::string& s = "")
11745 : reference_tokens(split(s))
11746 {}
11747
11763 std::string to_string() const
11764 {
11765 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
11766 std::string{},
11767 [](const std::string & a, const std::string & b)
11768 {
11769 return a + "/" + escape(b);
11770 });
11771 }
11772
11774 operator std::string() const
11775 {
11776 return to_string();
11777 }
11778
11786 static int array_index(const std::string& s)
11787 {
11788 std::size_t processed_chars = 0;
11789 const int res = std::stoi(s, &processed_chars);
11790
11791 // check if the string was completely read
11792 if (JSON_UNLIKELY(processed_chars != s.size()))
11793 {
11794 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
11795 }
11796
11797 return res;
11798 }
11799
11800 private:
11805 std::string pop_back()
11806 {
11807 if (JSON_UNLIKELY(is_root()))
11808 {
11809 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11810 }
11811
11812 auto last = reference_tokens.back();
11813 reference_tokens.pop_back();
11814 return last;
11815 }
11816
11818 bool is_root() const noexcept
11819 {
11820 return reference_tokens.empty();
11821 }
11822
11823 json_pointer top() const
11824 {
11825 if (JSON_UNLIKELY(is_root()))
11826 {
11827 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
11828 }
11829
11830 json_pointer result = *this;
11831 result.reference_tokens = {reference_tokens[0]};
11832 return result;
11833 }
11834
11843 BasicJsonType& get_and_create(BasicJsonType& j) const
11844 {
11845 using size_type = typename BasicJsonType::size_type;
11846 auto result = &j;
11847
11848 // in case no reference tokens exist, return a reference to the JSON value
11849 // j which will be overwritten by a primitive value
11850 for (const auto& reference_token : reference_tokens)
11851 {
11852 switch (result->m_type)
11853 {
11854 case detail::value_t::null:
11855 {
11856 if (reference_token == "0")
11857 {
11858 // start a new array if reference token is 0
11859 result = &result->operator[](0);
11860 }
11861 else
11862 {
11863 // start a new object otherwise
11864 result = &result->operator[](reference_token);
11865 }
11866 break;
11867 }
11868
11869 case detail::value_t::object:
11870 {
11871 // create an entry in the object
11872 result = &result->operator[](reference_token);
11873 break;
11874 }
11875
11876 case detail::value_t::array:
11877 {
11878 // create an entry in the array
11879 JSON_TRY
11880 {
11881 result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
11882 }
11883 JSON_CATCH(std::invalid_argument&)
11884 {
11885 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
11886 }
11887 break;
11888 }
11889
11890 /*
11891 The following code is only reached if there exists a reference
11892 token _and_ the current value is primitive. In this case, we have
11893 an error situation, because primitive values may only occur as
11894 single value; that is, with an empty list of reference tokens.
11895 */
11896 default:
11897 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
11898 }
11899 }
11900
11901 return *result;
11902 }
11903
11923 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
11924 {
11925 using size_type = typename BasicJsonType::size_type;
11926 for (const auto& reference_token : reference_tokens)
11927 {
11928 // convert null values to arrays or objects before continuing
11929 if (ptr->m_type == detail::value_t::null)
11930 {
11931 // check if reference token is a number
11932 const bool nums =
11933 std::all_of(reference_token.begin(), reference_token.end(),
11934 [](const char x)
11935 {
11936 return (x >= '0' and x <= '9');
11937 });
11938
11939 // change value to array for numbers or "-" or to object otherwise
11940 *ptr = (nums or reference_token == "-")
11941 ? detail::value_t::array
11942 : detail::value_t::object;
11943 }
11944
11945 switch (ptr->m_type)
11946 {
11947 case detail::value_t::object:
11948 {
11949 // use unchecked object access
11950 ptr = &ptr->operator[](reference_token);
11951 break;
11952 }
11953
11954 case detail::value_t::array:
11955 {
11956 // error condition (cf. RFC 6901, Sect. 4)
11957 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
11958 {
11959 JSON_THROW(detail::parse_error::create(106, 0,
11960 "array index '" + reference_token +
11961 "' must not begin with '0'"));
11962 }
11963
11964 if (reference_token == "-")
11965 {
11966 // explicitly treat "-" as index beyond the end
11967 ptr = &ptr->operator[](ptr->m_value.array->size());
11968 }
11969 else
11970 {
11971 // convert array index to number; unchecked access
11972 JSON_TRY
11973 {
11974 ptr = &ptr->operator[](
11975 static_cast<size_type>(array_index(reference_token)));
11976 }
11977 JSON_CATCH(std::invalid_argument&)
11978 {
11979 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
11980 }
11981 }
11982 break;
11983 }
11984
11985 default:
11986 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
11987 }
11988 }
11989
11990 return *ptr;
11991 }
11992
11999 BasicJsonType& get_checked(BasicJsonType* ptr) const
12000 {
12001 using size_type = typename BasicJsonType::size_type;
12002 for (const auto& reference_token : reference_tokens)
12003 {
12004 switch (ptr->m_type)
12005 {
12006 case detail::value_t::object:
12007 {
12008 // note: at performs range check
12009 ptr = &ptr->at(reference_token);
12010 break;
12011 }
12012
12013 case detail::value_t::array:
12014 {
12015 if (JSON_UNLIKELY(reference_token == "-"))
12016 {
12017 // "-" always fails the range check
12018 JSON_THROW(detail::out_of_range::create(402,
12019 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12020 ") is out of range"));
12021 }
12022
12023 // error condition (cf. RFC 6901, Sect. 4)
12024 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
12025 {
12026 JSON_THROW(detail::parse_error::create(106, 0,
12027 "array index '" + reference_token +
12028 "' must not begin with '0'"));
12029 }
12030
12031 // note: at performs range check
12032 JSON_TRY
12033 {
12034 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
12035 }
12036 JSON_CATCH(std::invalid_argument&)
12037 {
12038 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12039 }
12040 break;
12041 }
12042
12043 default:
12044 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12045 }
12046 }
12047
12048 return *ptr;
12049 }
12050
12064 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
12065 {
12066 using size_type = typename BasicJsonType::size_type;
12067 for (const auto& reference_token : reference_tokens)
12068 {
12069 switch (ptr->m_type)
12070 {
12071 case detail::value_t::object:
12072 {
12073 // use unchecked object access
12074 ptr = &ptr->operator[](reference_token);
12075 break;
12076 }
12077
12078 case detail::value_t::array:
12079 {
12080 if (JSON_UNLIKELY(reference_token == "-"))
12081 {
12082 // "-" cannot be used for const access
12083 JSON_THROW(detail::out_of_range::create(402,
12084 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12085 ") is out of range"));
12086 }
12087
12088 // error condition (cf. RFC 6901, Sect. 4)
12089 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
12090 {
12091 JSON_THROW(detail::parse_error::create(106, 0,
12092 "array index '" + reference_token +
12093 "' must not begin with '0'"));
12094 }
12095
12096 // use unchecked array access
12097 JSON_TRY
12098 {
12099 ptr = &ptr->operator[](
12100 static_cast<size_type>(array_index(reference_token)));
12101 }
12102 JSON_CATCH(std::invalid_argument&)
12103 {
12104 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12105 }
12106 break;
12107 }
12108
12109 default:
12110 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12111 }
12112 }
12113
12114 return *ptr;
12115 }
12116
12123 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
12124 {
12125 using size_type = typename BasicJsonType::size_type;
12126 for (const auto& reference_token : reference_tokens)
12127 {
12128 switch (ptr->m_type)
12129 {
12130 case detail::value_t::object:
12131 {
12132 // note: at performs range check
12133 ptr = &ptr->at(reference_token);
12134 break;
12135 }
12136
12137 case detail::value_t::array:
12138 {
12139 if (JSON_UNLIKELY(reference_token == "-"))
12140 {
12141 // "-" always fails the range check
12142 JSON_THROW(detail::out_of_range::create(402,
12143 "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
12144 ") is out of range"));
12145 }
12146
12147 // error condition (cf. RFC 6901, Sect. 4)
12148 if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
12149 {
12150 JSON_THROW(detail::parse_error::create(106, 0,
12151 "array index '" + reference_token +
12152 "' must not begin with '0'"));
12153 }
12154
12155 // note: at performs range check
12156 JSON_TRY
12157 {
12158 ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
12159 }
12160 JSON_CATCH(std::invalid_argument&)
12161 {
12162 JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
12163 }
12164 break;
12165 }
12166
12167 default:
12168 JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
12169 }
12170 }
12171
12172 return *ptr;
12173 }
12174
12184 static std::vector<std::string> split(const std::string& reference_string)
12185 {
12186 std::vector<std::string> result;
12187
12188 // special case: empty reference string -> no reference tokens
12189 if (reference_string.empty())
12190 {
12191 return result;
12192 }
12193
12194 // check if nonempty reference string begins with slash
12195 if (JSON_UNLIKELY(reference_string[0] != '/'))
12196 {
12197 JSON_THROW(detail::parse_error::create(107, 1,
12198 "JSON pointer must be empty or begin with '/' - was: '" +
12199 reference_string + "'"));
12200 }
12201
12202 // extract the reference tokens:
12203 // - slash: position of the last read slash (or end of string)
12204 // - start: position after the previous slash
12205 for (
12206 // search for the first slash after the first character
12207 std::size_t slash = reference_string.find_first_of('/', 1),
12208 // set the beginning of the first reference token
12209 start = 1;
12210 // we can stop if start == 0 (if slash == std::string::npos)
12211 start != 0;
12212 // set the beginning of the next reference token
12213 // (will eventually be 0 if slash == std::string::npos)
12214 start = (slash == std::string::npos) ? 0 : slash + 1,
12215 // find next slash
12216 slash = reference_string.find_first_of('/', start))
12217 {
12218 // use the text between the beginning of the reference token
12219 // (start) and the last slash (slash).
12220 auto reference_token = reference_string.substr(start, slash - start);
12221
12222 // check reference tokens are properly escaped
12223 for (std::size_t pos = reference_token.find_first_of('~');
12224 pos != std::string::npos;
12225 pos = reference_token.find_first_of('~', pos + 1))
12226 {
12227 assert(reference_token[pos] == '~');
12228
12229 // ~ must be followed by 0 or 1
12230 if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
12231 (reference_token[pos + 1] != '0' and
12232 reference_token[pos + 1] != '1')))
12233 {
12234 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
12235 }
12236 }
12237
12238 // finally, store the reference token
12239 unescape(reference_token);
12240 result.push_back(reference_token);
12241 }
12242
12243 return result;
12244 }
12245
12259 static void replace_substring(std::string& s, const std::string& f,
12260 const std::string& t)
12261 {
12262 assert(not f.empty());
12263 for (auto pos = s.find(f); // find first occurrence of f
12264 pos != std::string::npos; // make sure f was found
12265 s.replace(pos, f.size(), t), // replace with t, and
12266 pos = s.find(f, pos + t.size())) // find next occurrence of f
12267 {}
12268 }
12269
12271 static std::string escape(std::string s)
12272 {
12273 replace_substring(s, "~", "~0");
12274 replace_substring(s, "/", "~1");
12275 return s;
12276 }
12277
12279 static void unescape(std::string& s)
12280 {
12281 replace_substring(s, "~1", "/");
12282 replace_substring(s, "~0", "~");
12283 }
12284
12292 static void flatten(const std::string& reference_string,
12293 const BasicJsonType& value,
12294 BasicJsonType& result)
12295 {
12296 switch (value.m_type)
12297 {
12298 case detail::value_t::array:
12299 {
12300 if (value.m_value.array->empty())
12301 {
12302 // flatten empty array as null
12303 result[reference_string] = nullptr;
12304 }
12305 else
12306 {
12307 // iterate array and use index as reference string
12308 for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
12309 {
12310 flatten(reference_string + "/" + std::to_string(i),
12311 value.m_value.array->operator[](i), result);
12312 }
12313 }
12314 break;
12315 }
12316
12317 case detail::value_t::object:
12318 {
12319 if (value.m_value.object->empty())
12320 {
12321 // flatten empty object as null
12322 result[reference_string] = nullptr;
12323 }
12324 else
12325 {
12326 // iterate object and use keys as reference string
12327 for (const auto& element : *value.m_value.object)
12328 {
12329 flatten(reference_string + "/" + escape(element.first), element.second, result);
12330 }
12331 }
12332 break;
12333 }
12334
12335 default:
12336 {
12337 // add primitive value with its reference string
12338 result[reference_string] = value;
12339 break;
12340 }
12341 }
12342 }
12343
12354 static BasicJsonType
12355 unflatten(const BasicJsonType& value)
12356 {
12357 if (JSON_UNLIKELY(not value.is_object()))
12358 {
12359 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
12360 }
12361
12362 BasicJsonType result;
12363
12364 // iterate the JSON object values
12365 for (const auto& element : *value.m_value.object)
12366 {
12367 if (JSON_UNLIKELY(not element.second.is_primitive()))
12368 {
12369 JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
12370 }
12371
12372 // assign value to reference pointed to by JSON pointer; Note that if
12373 // the JSON pointer is "" (i.e., points to the whole value), function
12374 // get_and_create returns a reference to result itself. An assignment
12375 // will then create a primitive value.
12376 json_pointer(element.first).get_and_create(result) = element.second;
12377 }
12378
12379 return result;
12380 }
12381
12382 friend bool operator==(json_pointer const& lhs,
12383 json_pointer const& rhs) noexcept
12384 {
12385 return (lhs.reference_tokens == rhs.reference_tokens);
12386 }
12387
12388 friend bool operator!=(json_pointer const& lhs,
12389 json_pointer const& rhs) noexcept
12390 {
12391 return not (lhs == rhs);
12392 }
12393
12395 std::vector<std::string> reference_tokens;
12396};
12397} // namespace nlohmann
12398
12399// #include <nlohmann/adl_serializer.hpp>
12400
12401
12402#include <utility>
12403
12404// #include <nlohmann/detail/conversions/from_json.hpp>
12405
12406// #include <nlohmann/detail/conversions/to_json.hpp>
12407
12408
12409namespace nlohmann
12410{
12411
12412template<typename, typename>
12414{
12424 template<typename BasicJsonType, typename ValueType>
12425 static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
12426 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
12427 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
12428 {
12429 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
12430 }
12431
12441 template <typename BasicJsonType, typename ValueType>
12442 static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
12443 noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
12444 -> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
12445 {
12446 ::nlohmann::to_json(j, std::forward<ValueType>(val));
12447 }
12448};
12449
12450} // namespace nlohmann
12451
12452
12458namespace nlohmann
12459{
12460
12542NLOHMANN_BASIC_JSON_TPL_DECLARATION
12544{
12545 private:
12546 template<detail::value_t> friend struct detail::external_constructor;
12547 friend ::nlohmann::json_pointer<basic_json>;
12548 friend ::nlohmann::detail::parser<basic_json>;
12549 friend ::nlohmann::detail::serializer<basic_json>;
12550 template<typename BasicJsonType>
12551 friend class ::nlohmann::detail::iter_impl;
12552 template<typename BasicJsonType, typename CharType>
12553 friend class ::nlohmann::detail::binary_writer;
12554 template<typename BasicJsonType, typename SAX>
12555 friend class ::nlohmann::detail::binary_reader;
12556 template<typename BasicJsonType>
12557 friend class ::nlohmann::detail::json_sax_dom_parser;
12558 template<typename BasicJsonType>
12559 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
12560
12562 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
12563
12564 // convenience aliases for types residing in namespace detail;
12565 using lexer = ::nlohmann::detail::lexer<basic_json>;
12567
12569 template<typename BasicJsonType>
12571 template<typename BasicJsonType>
12573 template<typename Iterator>
12574 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
12575 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
12576
12577 template<typename CharType>
12578 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
12579
12580 using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
12581 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
12582
12584
12585 public:
12586 using value_t = detail::value_t;
12589 template<typename T, typename SFINAE>
12590 using json_serializer = JSONSerializer<T, SFINAE>;
12594 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
12595
12599
12601 // exceptions //
12603
12607
12620
12622
12623
12625 // container types //
12627
12632
12635
12640
12642 using difference_type = std::ptrdiff_t;
12644 using size_type = std::size_t;
12645
12647 using allocator_type = AllocatorType<basic_json>;
12648
12650 using pointer = typename std::allocator_traits<allocator_type>::pointer;
12652 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
12653
12659 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
12661 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
12662
12664
12665
12670 {
12671 return allocator_type();
12672 }
12673
12701 {
12702 basic_json result;
12703
12704 result["copyright"] = "(C) 2013-2017 Niels Lohmann";
12705 result["name"] = "JSON for Modern C++";
12706 result["url"] = "https://github.com/nlohmann/json";
12707 result["version"]["string"] =
12708 std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
12709 std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
12710 std::to_string(NLOHMANN_JSON_VERSION_PATCH);
12711 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
12712 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
12713 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
12714
12715#ifdef _WIN32
12716 result["platform"] = "win32";
12717#elif defined __linux__
12718 result["platform"] = "linux";
12719#elif defined __APPLE__
12720 result["platform"] = "apple";
12721#elif defined __unix__
12722 result["platform"] = "unix";
12723#else
12724 result["platform"] = "unknown";
12725#endif
12726
12727#if defined(__ICC) || defined(__INTEL_COMPILER)
12728 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
12729#elif defined(__clang__)
12730 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
12731#elif defined(__GNUC__) || defined(__GNUG__)
12732 result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
12733#elif defined(__HP_cc) || defined(__HP_aCC)
12734 result["compiler"] = "hp"
12735#elif defined(__IBMCPP__)
12736 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
12737#elif defined(_MSC_VER)
12738 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
12739#elif defined(__PGI)
12740 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
12741#elif defined(__SUNPRO_CC)
12742 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
12743#else
12744 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
12745#endif
12746
12747#ifdef __cplusplus
12748 result["compiler"]["c++"] = std::to_string(__cplusplus);
12749#else
12750 result["compiler"]["c++"] = "unknown";
12751#endif
12752 return result;
12753 }
12754
12755
12757 // JSON value data types //
12759
12764
12765#if defined(JSON_HAS_CPP_14)
12766 // Use transparent comparator if possible, combined with perfect forwarding
12767 // on find() and count() calls prevents unnecessary string construction.
12768 using object_comparator_t = std::less<>;
12769#else
12770 using object_comparator_t = std::less<StringType>;
12771#endif
12772
12856 using object_t = ObjectType<StringType,
12857 basic_json,
12858 object_comparator_t,
12859 AllocatorType<std::pair<const StringType,
12860 basic_json>>>;
12861
12906 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
12907
12959 using string_t = StringType;
12960
12985 using boolean_t = BooleanType;
12986
13057 using number_integer_t = NumberIntegerType;
13058
13128 using number_unsigned_t = NumberUnsignedType;
13129
13196 using number_float_t = NumberFloatType;
13197
13199
13200 private:
13201
13203 template<typename T, typename... Args>
13204 static T* create(Args&& ... args)
13205 {
13206 AllocatorType<T> alloc;
13207 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
13208
13209 auto deleter = [&](T * object)
13210 {
13211 AllocatorTraits::deallocate(alloc, object, 1);
13212 };
13213 std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
13214 AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
13215 assert(object != nullptr);
13216 return object.release();
13217 }
13218
13220 // JSON value storage //
13222
13247 union json_value
13248 {
13250 object_t* object;
13252 array_t* array;
13254 string_t* string;
13256 boolean_t boolean;
13258 number_integer_t number_integer;
13260 number_unsigned_t number_unsigned;
13262 number_float_t number_float;
13263
13265 json_value() = default;
13267 json_value(boolean_t v) noexcept : boolean(v) {}
13269 json_value(number_integer_t v) noexcept : number_integer(v) {}
13271 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
13273 json_value(number_float_t v) noexcept : number_float(v) {}
13275 json_value(value_t t)
13276 {
13277 switch (t)
13278 {
13279 case value_t::object:
13280 {
13281 object = create<object_t>();
13282 break;
13283 }
13284
13285 case value_t::array:
13286 {
13287 array = create<array_t>();
13288 break;
13289 }
13290
13291 case value_t::string:
13292 {
13293 string = create<string_t>("");
13294 break;
13295 }
13296
13297 case value_t::boolean:
13298 {
13299 boolean = boolean_t(false);
13300 break;
13301 }
13302
13303 case value_t::number_integer:
13304 {
13305 number_integer = number_integer_t(0);
13306 break;
13307 }
13308
13309 case value_t::number_unsigned:
13310 {
13311 number_unsigned = number_unsigned_t(0);
13312 break;
13313 }
13314
13315 case value_t::number_float:
13316 {
13317 number_float = number_float_t(0.0);
13318 break;
13319 }
13320
13321 case value_t::null:
13322 {
13323 object = nullptr; // silence warning, see #821
13324 break;
13325 }
13326
13327 default:
13328 {
13329 object = nullptr; // silence warning, see #821
13330 if (JSON_UNLIKELY(t == value_t::null))
13331 {
13332 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.5.0")); // LCOV_EXCL_LINE
13333 }
13334 break;
13335 }
13336 }
13337 }
13338
13340 json_value(const string_t& value)
13341 {
13342 string = create<string_t>(value);
13343 }
13344
13346 json_value(string_t&& value)
13347 {
13348 string = create<string_t>(std::move(value));
13349 }
13350
13352 json_value(const object_t& value)
13353 {
13354 object = create<object_t>(value);
13355 }
13356
13358 json_value(object_t&& value)
13359 {
13360 object = create<object_t>(std::move(value));
13361 }
13362
13364 json_value(const array_t& value)
13365 {
13366 array = create<array_t>(value);
13367 }
13368
13370 json_value(array_t&& value)
13371 {
13372 array = create<array_t>(std::move(value));
13373 }
13374
13375 void destroy(value_t t) noexcept
13376 {
13377 switch (t)
13378 {
13379 case value_t::object:
13380 {
13381 AllocatorType<object_t> alloc;
13382 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
13383 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
13384 break;
13385 }
13386
13387 case value_t::array:
13388 {
13389 AllocatorType<array_t> alloc;
13390 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
13391 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
13392 break;
13393 }
13394
13395 case value_t::string:
13396 {
13397 AllocatorType<string_t> alloc;
13398 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
13399 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
13400 break;
13401 }
13402
13403 default:
13404 {
13405 break;
13406 }
13407 }
13408 }
13409 };
13410
13420 void assert_invariant() const noexcept
13421 {
13422 assert(m_type != value_t::object or m_value.object != nullptr);
13423 assert(m_type != value_t::array or m_value.array != nullptr);
13424 assert(m_type != value_t::string or m_value.string != nullptr);
13425 }
13426
13427 public:
13429 // JSON parser callback //
13431
13448
13498 using parser_callback_t = typename parser::parser_callback_t;
13499
13501 // constructors //
13503
13508
13538 basic_json(const value_t v)
13539 : m_type(v), m_value(v)
13540 {
13541 assert_invariant();
13542 }
13543
13562 basic_json(std::nullptr_t = nullptr) noexcept
13563 : basic_json(value_t::null)
13564 {
13565 assert_invariant();
13566 }
13567
13625 template <typename CompatibleType,
13626 typename U = detail::uncvref_t<CompatibleType>,
13627 detail::enable_if_t<
13629 basic_json(CompatibleType && val) noexcept(noexcept(
13630 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
13631 std::forward<CompatibleType>(val))))
13632 {
13633 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
13634 assert_invariant();
13635 }
13636
13663 template <typename BasicJsonType,
13664 detail::enable_if_t<
13665 detail::is_basic_json<BasicJsonType>::value and not std::is_same<basic_json, BasicJsonType>::value, int> = 0>
13666 basic_json(const BasicJsonType& val)
13667 {
13668 using other_boolean_t = typename BasicJsonType::boolean_t;
13669 using other_number_float_t = typename BasicJsonType::number_float_t;
13670 using other_number_integer_t = typename BasicJsonType::number_integer_t;
13671 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
13672 using other_string_t = typename BasicJsonType::string_t;
13673 using other_object_t = typename BasicJsonType::object_t;
13674 using other_array_t = typename BasicJsonType::array_t;
13675
13676 switch (val.type())
13677 {
13678 case value_t::boolean:
13679 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
13680 break;
13681 case value_t::number_float:
13682 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
13683 break;
13684 case value_t::number_integer:
13685 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
13686 break;
13687 case value_t::number_unsigned:
13688 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
13689 break;
13690 case value_t::string:
13691 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
13692 break;
13693 case value_t::object:
13694 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
13695 break;
13696 case value_t::array:
13697 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
13698 break;
13699 case value_t::null:
13700 *this = nullptr;
13701 break;
13702 case value_t::discarded:
13703 m_type = value_t::discarded;
13704 break;
13705 }
13706 assert_invariant();
13707 }
13708
13784 bool type_deduction = true,
13785 value_t manual_type = value_t::array)
13786 {
13787 // check if each element is an array with two elements whose first
13788 // element is a string
13789 bool is_an_object = std::all_of(init.begin(), init.end(),
13790 [](const detail::json_ref<basic_json>& element_ref)
13791 {
13792 return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
13793 });
13794
13795 // adjust type if type deduction is not wanted
13796 if (not type_deduction)
13797 {
13798 // if array is wanted, do not create an object though possible
13799 if (manual_type == value_t::array)
13800 {
13801 is_an_object = false;
13802 }
13803
13804 // if object is wanted but impossible, throw an exception
13805 if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
13806 {
13807 JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
13808 }
13809 }
13810
13811 if (is_an_object)
13812 {
13813 // the initializer list is a list of pairs -> create object
13814 m_type = value_t::object;
13815 m_value = value_t::object;
13816
13817 std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
13818 {
13819 auto element = element_ref.moved_or_copied();
13820 m_value.object->emplace(
13821 std::move(*((*element.m_value.array)[0].m_value.string)),
13822 std::move((*element.m_value.array)[1]));
13823 });
13824 }
13825 else
13826 {
13827 // the initializer list describes an array -> create array
13828 m_type = value_t::array;
13829 m_value.array = create<array_t>(init.begin(), init.end());
13830 }
13831
13832 assert_invariant();
13833 }
13834
13873 {
13874 return basic_json(init, false, value_t::array);
13875 }
13876
13916 {
13917 return basic_json(init, false, value_t::object);
13918 }
13919
13943 : m_type(value_t::array)
13944 {
13945 m_value.array = create<array_t>(cnt, val);
13946 assert_invariant();
13947 }
13948
14004 template<class InputIT, typename std::enable_if<
14005 std::is_same<InputIT, typename basic_json_t::iterator>::value or
14006 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int>::type = 0>
14007 basic_json(InputIT first, InputIT last)
14008 {
14009 assert(first.m_object != nullptr);
14010 assert(last.m_object != nullptr);
14011
14012 // make sure iterator fits the current value
14013 if (JSON_UNLIKELY(first.m_object != last.m_object))
14014 {
14015 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
14016 }
14017
14018 // copy type from first iterator
14019 m_type = first.m_object->m_type;
14020
14021 // check if iterator range is complete for primitive values
14022 switch (m_type)
14023 {
14024 case value_t::boolean:
14025 case value_t::number_float:
14026 case value_t::number_integer:
14027 case value_t::number_unsigned:
14028 case value_t::string:
14029 {
14030 if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
14031 or not last.m_it.primitive_iterator.is_end()))
14032 {
14033 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
14034 }
14035 break;
14036 }
14037
14038 default:
14039 break;
14040 }
14041
14042 switch (m_type)
14043 {
14044 case value_t::number_integer:
14045 {
14046 m_value.number_integer = first.m_object->m_value.number_integer;
14047 break;
14048 }
14049
14050 case value_t::number_unsigned:
14051 {
14052 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
14053 break;
14054 }
14055
14056 case value_t::number_float:
14057 {
14058 m_value.number_float = first.m_object->m_value.number_float;
14059 break;
14060 }
14061
14062 case value_t::boolean:
14063 {
14064 m_value.boolean = first.m_object->m_value.boolean;
14065 break;
14066 }
14067
14068 case value_t::string:
14069 {
14070 m_value = *first.m_object->m_value.string;
14071 break;
14072 }
14073
14074 case value_t::object:
14075 {
14076 m_value.object = create<object_t>(first.m_it.object_iterator,
14077 last.m_it.object_iterator);
14078 break;
14079 }
14080
14081 case value_t::array:
14082 {
14083 m_value.array = create<array_t>(first.m_it.array_iterator,
14084 last.m_it.array_iterator);
14085 break;
14086 }
14087
14088 default:
14089 JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
14090 std::string(first.m_object->type_name())));
14091 }
14092
14093 assert_invariant();
14094 }
14095
14096
14098 // other constructors and destructor //
14100
14102 basic_json(const detail::json_ref<basic_json>& ref)
14103 : basic_json(ref.moved_or_copied())
14104 {}
14105
14132 : m_type(other.m_type)
14133 {
14134 // check of passed value is valid
14135 other.assert_invariant();
14136
14137 switch (m_type)
14138 {
14139 case value_t::object:
14140 {
14141 m_value = *other.m_value.object;
14142 break;
14143 }
14144
14145 case value_t::array:
14146 {
14147 m_value = *other.m_value.array;
14148 break;
14149 }
14150
14151 case value_t::string:
14152 {
14153 m_value = *other.m_value.string;
14154 break;
14155 }
14156
14157 case value_t::boolean:
14158 {
14159 m_value = other.m_value.boolean;
14160 break;
14161 }
14162
14163 case value_t::number_integer:
14164 {
14165 m_value = other.m_value.number_integer;
14166 break;
14167 }
14168
14169 case value_t::number_unsigned:
14170 {
14171 m_value = other.m_value.number_unsigned;
14172 break;
14173 }
14174
14175 case value_t::number_float:
14176 {
14177 m_value = other.m_value.number_float;
14178 break;
14179 }
14180
14181 default:
14182 break;
14183 }
14184
14185 assert_invariant();
14186 }
14187
14214 basic_json(basic_json&& other) noexcept
14215 : m_type(std::move(other.m_type)),
14216 m_value(std::move(other.m_value))
14217 {
14218 // check that passed value is valid
14219 other.assert_invariant();
14220
14221 // invalidate payload
14222 other.m_type = value_t::null;
14223 other.m_value = {};
14224
14225 assert_invariant();
14226 }
14227
14252 std::is_nothrow_move_constructible<value_t>::value and
14253 std::is_nothrow_move_assignable<value_t>::value and
14254 std::is_nothrow_move_constructible<json_value>::value and
14255 std::is_nothrow_move_assignable<json_value>::value
14256 )
14257 {
14258 // check that passed value is valid
14259 other.assert_invariant();
14260
14261 using std::swap;
14262 swap(m_type, other.m_type);
14263 swap(m_value, other.m_value);
14264
14265 assert_invariant();
14266 return *this;
14267 }
14268
14284 ~basic_json() noexcept
14285 {
14286 assert_invariant();
14287 m_value.destroy(m_type);
14288 }
14289
14291
14292 public:
14294 // object inspection //
14296
14300
14342 string_t dump(const int indent = -1,
14343 const char indent_char = ' ',
14344 const bool ensure_ascii = false,
14345 const error_handler_t error_handler = error_handler_t::strict) const
14346 {
14347 string_t result;
14348 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
14349
14350 if (indent >= 0)
14351 {
14352 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
14353 }
14354 else
14355 {
14356 s.dump(*this, false, ensure_ascii, 0);
14357 }
14358
14359 return result;
14360 }
14361
14394 constexpr value_t type() const noexcept
14395 {
14396 return m_type;
14397 }
14398
14424 constexpr bool is_primitive() const noexcept
14425 {
14426 return is_null() or is_string() or is_boolean() or is_number();
14427 }
14428
14451 constexpr bool is_structured() const noexcept
14452 {
14453 return is_array() or is_object();
14454 }
14455
14473 constexpr bool is_null() const noexcept
14474 {
14475 return (m_type == value_t::null);
14476 }
14477
14495 constexpr bool is_boolean() const noexcept
14496 {
14497 return (m_type == value_t::boolean);
14498 }
14499
14525 constexpr bool is_number() const noexcept
14526 {
14527 return is_number_integer() or is_number_float();
14528 }
14529
14554 constexpr bool is_number_integer() const noexcept
14555 {
14556 return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
14557 }
14558
14582 constexpr bool is_number_unsigned() const noexcept
14583 {
14584 return (m_type == value_t::number_unsigned);
14585 }
14586
14610 constexpr bool is_number_float() const noexcept
14611 {
14612 return (m_type == value_t::number_float);
14613 }
14614
14632 constexpr bool is_object() const noexcept
14633 {
14634 return (m_type == value_t::object);
14635 }
14636
14654 constexpr bool is_array() const noexcept
14655 {
14656 return (m_type == value_t::array);
14657 }
14658
14676 constexpr bool is_string() const noexcept
14677 {
14678 return (m_type == value_t::string);
14679 }
14680
14703 constexpr bool is_discarded() const noexcept
14704 {
14705 return (m_type == value_t::discarded);
14706 }
14707
14729 constexpr operator value_t() const noexcept
14730 {
14731 return m_type;
14732 }
14733
14735
14736 private:
14738 // value access //
14740
14742 boolean_t get_impl(boolean_t* /*unused*/) const
14743 {
14744 if (JSON_LIKELY(is_boolean()))
14745 {
14746 return m_value.boolean;
14747 }
14748
14749 JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
14750 }
14751
14753 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
14754 {
14755 return is_object() ? m_value.object : nullptr;
14756 }
14757
14759 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
14760 {
14761 return is_object() ? m_value.object : nullptr;
14762 }
14763
14765 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
14766 {
14767 return is_array() ? m_value.array : nullptr;
14768 }
14769
14771 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
14772 {
14773 return is_array() ? m_value.array : nullptr;
14774 }
14775
14777 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
14778 {
14779 return is_string() ? m_value.string : nullptr;
14780 }
14781
14783 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
14784 {
14785 return is_string() ? m_value.string : nullptr;
14786 }
14787
14789 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
14790 {
14791 return is_boolean() ? &m_value.boolean : nullptr;
14792 }
14793
14795 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
14796 {
14797 return is_boolean() ? &m_value.boolean : nullptr;
14798 }
14799
14801 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
14802 {
14803 return is_number_integer() ? &m_value.number_integer : nullptr;
14804 }
14805
14807 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
14808 {
14809 return is_number_integer() ? &m_value.number_integer : nullptr;
14810 }
14811
14813 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
14814 {
14815 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
14816 }
14817
14819 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
14820 {
14821 return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
14822 }
14823
14825 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
14826 {
14827 return is_number_float() ? &m_value.number_float : nullptr;
14828 }
14829
14831 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
14832 {
14833 return is_number_float() ? &m_value.number_float : nullptr;
14834 }
14835
14847 template<typename ReferenceType, typename ThisType>
14848 static ReferenceType get_ref_impl(ThisType& obj)
14849 {
14850 // delegate the call to get_ptr<>()
14851 auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
14852
14853 if (JSON_LIKELY(ptr != nullptr))
14854 {
14855 return *ptr;
14856 }
14857
14858 JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
14859 }
14860
14861 public:
14865
14880 template<typename BasicJsonType, detail::enable_if_t<
14881 std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
14882 int> = 0>
14884 {
14885 return *this;
14886 }
14887
14903 template<typename BasicJsonType, detail::enable_if_t<
14904 not std::is_same<BasicJsonType, basic_json>::value and
14906 BasicJsonType get() const
14907 {
14908 return *this;
14909 }
14910
14950 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
14951 detail::enable_if_t <
14952 not detail::is_basic_json<ValueType>::value and
14953 detail::has_from_json<basic_json_t, ValueType>::value and
14954 not detail::has_non_default_from_json<basic_json_t, ValueType>::value,
14955 int> = 0>
14956 ValueType get() const noexcept(noexcept(
14957 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
14958 {
14959 // we cannot static_assert on ValueTypeCV being non-const, because
14960 // there is support for get<const basic_json_t>(), which is why we
14961 // still need the uncvref
14962 static_assert(not std::is_reference<ValueTypeCV>::value,
14963 "get() cannot be used with reference types, you might want to use get_ref()");
14964 static_assert(std::is_default_constructible<ValueType>::value,
14965 "types must be DefaultConstructible when used with get()");
14966
14967 ValueType ret;
14968 JSONSerializer<ValueType>::from_json(*this, ret);
14969 return ret;
14970 }
14971
15003 template<typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
15004 detail::enable_if_t<not std::is_same<basic_json_t, ValueType>::value and
15005 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
15006 int> = 0>
15007 ValueType get() const noexcept(noexcept(
15008 JSONSerializer<ValueTypeCV>::from_json(std::declval<const basic_json_t&>())))
15009 {
15010 static_assert(not std::is_reference<ValueTypeCV>::value,
15011 "get() cannot be used with reference types, you might want to use get_ref()");
15012 return JSONSerializer<ValueTypeCV>::from_json(*this);
15013 }
15014
15048 template<typename ValueType,
15049 detail::enable_if_t <
15052 int> = 0>
15053 ValueType & get_to(ValueType& v) const noexcept(noexcept(
15054 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
15055 {
15056 JSONSerializer<ValueType>::from_json(*this, v);
15057 return v;
15058 }
15059
15060
15087 template<typename PointerType, typename std::enable_if<
15088 std::is_pointer<PointerType>::value, int>::type = 0>
15089 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
15090 {
15091 // delegate the call to get_impl_ptr<>()
15092 return get_impl_ptr(static_cast<PointerType>(nullptr));
15093 }
15094
15099 template<typename PointerType, typename std::enable_if<
15100 std::is_pointer<PointerType>::value and
15101 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
15102 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
15103 {
15104 // delegate the call to get_impl_ptr<>() const
15105 return get_impl_ptr(static_cast<PointerType>(nullptr));
15106 }
15107
15135 template<typename PointerType, typename std::enable_if<
15136 std::is_pointer<PointerType>::value, int>::type = 0>
15137 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
15138 {
15139 // delegate the call to get_ptr
15140 return get_ptr<PointerType>();
15141 }
15142
15147 template<typename PointerType, typename std::enable_if<
15148 std::is_pointer<PointerType>::value, int>::type = 0>
15149 constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
15150 {
15151 // delegate the call to get_ptr
15152 return get_ptr<PointerType>();
15153 }
15154
15181 template<typename ReferenceType, typename std::enable_if<
15182 std::is_reference<ReferenceType>::value, int>::type = 0>
15183 ReferenceType get_ref()
15184 {
15185 // delegate call to get_ref_impl
15186 return get_ref_impl<ReferenceType>(*this);
15187 }
15188
15193 template<typename ReferenceType, typename std::enable_if<
15194 std::is_reference<ReferenceType>::value and
15195 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int>::type = 0>
15196 ReferenceType get_ref() const
15197 {
15198 // delegate call to get_ref_impl
15199 return get_ref_impl<ReferenceType>(*this);
15200 }
15201
15231 template < typename ValueType, typename std::enable_if <
15232 not std::is_pointer<ValueType>::value and
15233 not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
15234 not std::is_same<ValueType, typename string_t::value_type>::value and
15236
15237#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
15238 and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
15239#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
15240 and not std::is_same<ValueType, typename std::string_view>::value
15241#endif
15242#endif
15243 and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
15244 , int >::type = 0 >
15245 operator ValueType() const
15246 {
15247 // delegate the call to get<>() const
15248 return get<ValueType>();
15249 }
15250
15252
15253
15255 // element access //
15257
15261
15289 {
15290 // at only works for arrays
15291 if (JSON_LIKELY(is_array()))
15292 {
15293 JSON_TRY
15294 {
15295 return m_value.array->at(idx);
15296 }
15297 JSON_CATCH (std::out_of_range&)
15298 {
15299 // create better exception explanation
15300 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
15301 }
15302 }
15303 else
15304 {
15305 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15306 }
15307 }
15308
15336 {
15337 // at only works for arrays
15338 if (JSON_LIKELY(is_array()))
15339 {
15340 JSON_TRY
15341 {
15342 return m_value.array->at(idx);
15343 }
15344 JSON_CATCH (std::out_of_range&)
15345 {
15346 // create better exception explanation
15347 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
15348 }
15349 }
15350 else
15351 {
15352 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15353 }
15354 }
15355
15386 reference at(const typename object_t::key_type& key)
15387 {
15388 // at only works for objects
15389 if (JSON_LIKELY(is_object()))
15390 {
15391 JSON_TRY
15392 {
15393 return m_value.object->at(key);
15394 }
15395 JSON_CATCH (std::out_of_range&)
15396 {
15397 // create better exception explanation
15398 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
15399 }
15400 }
15401 else
15402 {
15403 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15404 }
15405 }
15406
15437 const_reference at(const typename object_t::key_type& key) const
15438 {
15439 // at only works for objects
15440 if (JSON_LIKELY(is_object()))
15441 {
15442 JSON_TRY
15443 {
15444 return m_value.object->at(key);
15445 }
15446 JSON_CATCH (std::out_of_range&)
15447 {
15448 // create better exception explanation
15449 JSON_THROW(out_of_range::create(403, "key '" + key + "' not found"));
15450 }
15451 }
15452 else
15453 {
15454 JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
15455 }
15456 }
15457
15484 {
15485 // implicitly convert null value to an empty array
15486 if (is_null())
15487 {
15488 m_type = value_t::array;
15489 m_value.array = create<array_t>();
15490 assert_invariant();
15491 }
15492
15493 // operator[] only works for arrays
15494 if (JSON_LIKELY(is_array()))
15495 {
15496 // fill up array with null values if given idx is outside range
15497 if (idx >= m_value.array->size())
15498 {
15499 m_value.array->insert(m_value.array->end(),
15500 idx - m_value.array->size() + 1,
15501 basic_json());
15502 }
15503
15504 return m_value.array->operator[](idx);
15505 }
15506
15507 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
15508 }
15509
15530 {
15531 // const operator[] only works for arrays
15532 if (JSON_LIKELY(is_array()))
15533 {
15534 return m_value.array->operator[](idx);
15535 }
15536
15537 JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
15538 }
15539
15567 reference operator[](const typename object_t::key_type& key)
15568 {
15569 // implicitly convert null value to an empty object
15570 if (is_null())
15571 {
15572 m_type = value_t::object;
15573 m_value.object = create<object_t>();
15574 assert_invariant();
15575 }
15576
15577 // operator[] only works for objects
15578 if (JSON_LIKELY(is_object()))
15579 {
15580 return m_value.object->operator[](key);
15581 }
15582
15583 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15584 }
15585
15616 const_reference operator[](const typename object_t::key_type& key) const
15617 {
15618 // const operator[] only works for objects
15619 if (JSON_LIKELY(is_object()))
15620 {
15621 assert(m_value.object->find(key) != m_value.object->end());
15622 return m_value.object->find(key)->second;
15623 }
15624
15625 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15626 }
15627
15655 template<typename T>
15657 {
15658 // implicitly convert null to object
15659 if (is_null())
15660 {
15661 m_type = value_t::object;
15662 m_value = value_t::object;
15663 assert_invariant();
15664 }
15665
15666 // at only works for objects
15667 if (JSON_LIKELY(is_object()))
15668 {
15669 return m_value.object->operator[](key);
15670 }
15671
15672 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15673 }
15674
15705 template<typename T>
15707 {
15708 // at only works for objects
15709 if (JSON_LIKELY(is_object()))
15710 {
15711 assert(m_value.object->find(key) != m_value.object->end());
15712 return m_value.object->find(key)->second;
15713 }
15714
15715 JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
15716 }
15717
15766 template<class ValueType, typename std::enable_if<
15767 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
15768 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
15769 {
15770 // at only works for objects
15771 if (JSON_LIKELY(is_object()))
15772 {
15773 // if key is found, return value and given default value otherwise
15774 const auto it = find(key);
15775 if (it != end())
15776 {
15777 return *it;
15778 }
15779
15780 return default_value;
15781 }
15782
15783 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
15784 }
15785
15790 string_t value(const typename object_t::key_type& key, const char* default_value) const
15791 {
15792 return value(key, string_t(default_value));
15793 }
15794
15836 template<class ValueType, typename std::enable_if<
15837 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
15838 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
15839 {
15840 // at only works for objects
15841 if (JSON_LIKELY(is_object()))
15842 {
15843 // if pointer resolves a value, return it or use default value
15844 JSON_TRY
15845 {
15846 return ptr.get_checked(this);
15847 }
15848 JSON_INTERNAL_CATCH (out_of_range&)
15849 {
15850 return default_value;
15851 }
15852 }
15853
15854 JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
15855 }
15856
15861 string_t value(const json_pointer& ptr, const char* default_value) const
15862 {
15863 return value(ptr, string_t(default_value));
15864 }
15865
15892 {
15893 return *begin();
15894 }
15895
15900 {
15901 return *cbegin();
15902 }
15903
15936 {
15937 auto tmp = end();
15938 --tmp;
15939 return *tmp;
15940 }
15941
15946 {
15947 auto tmp = cend();
15948 --tmp;
15949 return *tmp;
15950 }
15951
15998 template<class IteratorType, typename std::enable_if<
15999 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
16000 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
16001 = 0>
16002 IteratorType erase(IteratorType pos)
16003 {
16004 // make sure iterator fits the current value
16005 if (JSON_UNLIKELY(this != pos.m_object))
16006 {
16007 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
16008 }
16009
16010 IteratorType result = end();
16011
16012 switch (m_type)
16013 {
16014 case value_t::boolean:
16015 case value_t::number_float:
16016 case value_t::number_integer:
16017 case value_t::number_unsigned:
16018 case value_t::string:
16019 {
16020 if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
16021 {
16022 JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
16023 }
16024
16025 if (is_string())
16026 {
16027 AllocatorType<string_t> alloc;
16028 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
16029 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
16030 m_value.string = nullptr;
16031 }
16032
16033 m_type = value_t::null;
16034 assert_invariant();
16035 break;
16036 }
16037
16038 case value_t::object:
16039 {
16040 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
16041 break;
16042 }
16043
16044 case value_t::array:
16045 {
16046 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
16047 break;
16048 }
16049
16050 default:
16051 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16052 }
16053
16054 return result;
16055 }
16056
16103 template<class IteratorType, typename std::enable_if<
16104 std::is_same<IteratorType, typename basic_json_t::iterator>::value or
16105 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int>::type
16106 = 0>
16107 IteratorType erase(IteratorType first, IteratorType last)
16108 {
16109 // make sure iterator fits the current value
16110 if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
16111 {
16112 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
16113 }
16114
16115 IteratorType result = end();
16116
16117 switch (m_type)
16118 {
16119 case value_t::boolean:
16120 case value_t::number_float:
16121 case value_t::number_integer:
16122 case value_t::number_unsigned:
16123 case value_t::string:
16124 {
16125 if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
16126 or not last.m_it.primitive_iterator.is_end()))
16127 {
16128 JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
16129 }
16130
16131 if (is_string())
16132 {
16133 AllocatorType<string_t> alloc;
16134 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
16135 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
16136 m_value.string = nullptr;
16137 }
16138
16139 m_type = value_t::null;
16140 assert_invariant();
16141 break;
16142 }
16143
16144 case value_t::object:
16145 {
16146 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
16147 last.m_it.object_iterator);
16148 break;
16149 }
16150
16151 case value_t::array:
16152 {
16153 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
16154 last.m_it.array_iterator);
16155 break;
16156 }
16157
16158 default:
16159 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16160 }
16161
16162 return result;
16163 }
16164
16194 size_type erase(const typename object_t::key_type& key)
16195 {
16196 // this erase only works for objects
16197 if (JSON_LIKELY(is_object()))
16198 {
16199 return m_value.object->erase(key);
16200 }
16201
16202 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16203 }
16204
16229 void erase(const size_type idx)
16230 {
16231 // this erase only works for arrays
16232 if (JSON_LIKELY(is_array()))
16233 {
16234 if (JSON_UNLIKELY(idx >= size()))
16235 {
16236 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
16237 }
16238
16239 m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
16240 }
16241 else
16242 {
16243 JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
16244 }
16245 }
16246
16248
16249
16251 // lookup //
16253
16256
16279 template<typename KeyT>
16280 iterator find(KeyT&& key)
16281 {
16282 auto result = end();
16283
16284 if (is_object())
16285 {
16286 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
16287 }
16288
16289 return result;
16290 }
16291
16296 template<typename KeyT>
16297 const_iterator find(KeyT&& key) const
16298 {
16299 auto result = cend();
16300
16301 if (is_object())
16302 {
16303 result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
16304 }
16305
16306 return result;
16307 }
16308
16330 template<typename KeyT>
16331 size_type count(KeyT&& key) const
16332 {
16333 // return 0 for all nonobject types
16334 return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
16335 }
16336
16338
16339
16341 // iterators //
16343
16346
16371 iterator begin() noexcept
16372 {
16373 iterator result(this);
16374 result.set_begin();
16375 return result;
16376 }
16377
16381 const_iterator begin() const noexcept
16382 {
16383 return cbegin();
16384 }
16385
16411 const_iterator cbegin() const noexcept
16412 {
16413 const_iterator result(this);
16414 result.set_begin();
16415 return result;
16416 }
16417
16442 iterator end() noexcept
16443 {
16444 iterator result(this);
16445 result.set_end();
16446 return result;
16447 }
16448
16452 const_iterator end() const noexcept
16453 {
16454 return cend();
16455 }
16456
16482 const_iterator cend() const noexcept
16483 {
16484 const_iterator result(this);
16485 result.set_end();
16486 return result;
16487 }
16488
16513 {
16514 return reverse_iterator(end());
16515 }
16516
16521 {
16522 return crbegin();
16523 }
16524
16550 {
16551 return reverse_iterator(begin());
16552 }
16553
16558 {
16559 return crend();
16560 }
16561
16587 {
16588 return const_reverse_iterator(cend());
16589 }
16590
16616 {
16617 return const_reverse_iterator(cbegin());
16618 }
16619
16620 public:
16678 JSON_DEPRECATED
16679 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
16680 {
16681 return ref.items();
16682 }
16683
16687 JSON_DEPRECATED
16688 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
16689 {
16690 return ref.items();
16691 }
16692
16756 iteration_proxy<iterator> items() noexcept
16757 {
16758 return iteration_proxy<iterator>(*this);
16759 }
16760
16764 iteration_proxy<const_iterator> items() const noexcept
16765 {
16766 return iteration_proxy<const_iterator>(*this);
16767 }
16768
16770
16771
16773 // capacity //
16775
16778
16820 bool empty() const noexcept
16821 {
16822 switch (m_type)
16823 {
16824 case value_t::null:
16825 {
16826 // null values are empty
16827 return true;
16828 }
16829
16830 case value_t::array:
16831 {
16832 // delegate call to array_t::empty()
16833 return m_value.array->empty();
16834 }
16835
16836 case value_t::object:
16837 {
16838 // delegate call to object_t::empty()
16839 return m_value.object->empty();
16840 }
16841
16842 default:
16843 {
16844 // all other types are nonempty
16845 return false;
16846 }
16847 }
16848 }
16849
16892 size_type size() const noexcept
16893 {
16894 switch (m_type)
16895 {
16896 case value_t::null:
16897 {
16898 // null values are empty
16899 return 0;
16900 }
16901
16902 case value_t::array:
16903 {
16904 // delegate call to array_t::size()
16905 return m_value.array->size();
16906 }
16907
16908 case value_t::object:
16909 {
16910 // delegate call to object_t::size()
16911 return m_value.object->size();
16912 }
16913
16914 default:
16915 {
16916 // all other types have size 1
16917 return 1;
16918 }
16919 }
16920 }
16921
16962 size_type max_size() const noexcept
16963 {
16964 switch (m_type)
16965 {
16966 case value_t::array:
16967 {
16968 // delegate call to array_t::max_size()
16969 return m_value.array->max_size();
16970 }
16971
16972 case value_t::object:
16973 {
16974 // delegate call to object_t::max_size()
16975 return m_value.object->max_size();
16976 }
16977
16978 default:
16979 {
16980 // all other types have max_size() == size()
16981 return size();
16982 }
16983 }
16984 }
16985
16987
16988
16990 // modifiers //
16992
16995
17032 void clear() noexcept
17033 {
17034 switch (m_type)
17035 {
17036 case value_t::number_integer:
17037 {
17038 m_value.number_integer = 0;
17039 break;
17040 }
17041
17042 case value_t::number_unsigned:
17043 {
17044 m_value.number_unsigned = 0;
17045 break;
17046 }
17047
17048 case value_t::number_float:
17049 {
17050 m_value.number_float = 0.0;
17051 break;
17052 }
17053
17054 case value_t::boolean:
17055 {
17056 m_value.boolean = false;
17057 break;
17058 }
17059
17060 case value_t::string:
17061 {
17062 m_value.string->clear();
17063 break;
17064 }
17065
17066 case value_t::array:
17067 {
17068 m_value.array->clear();
17069 break;
17070 }
17071
17072 case value_t::object:
17073 {
17074 m_value.object->clear();
17075 break;
17076 }
17077
17078 default:
17079 break;
17080 }
17081 }
17082
17104 {
17105 // push_back only works for null objects or arrays
17106 if (JSON_UNLIKELY(not(is_null() or is_array())))
17107 {
17108 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17109 }
17110
17111 // transform null object into an array
17112 if (is_null())
17113 {
17114 m_type = value_t::array;
17115 m_value = value_t::array;
17116 assert_invariant();
17117 }
17118
17119 // add element to array (move semantics)
17120 m_value.array->push_back(std::move(val));
17121 // invalidate object
17122 val.m_type = value_t::null;
17123 }
17124
17130 {
17131 push_back(std::move(val));
17132 return *this;
17133 }
17134
17139 void push_back(const basic_json& val)
17140 {
17141 // push_back only works for null objects or arrays
17142 if (JSON_UNLIKELY(not(is_null() or is_array())))
17143 {
17144 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17145 }
17146
17147 // transform null object into an array
17148 if (is_null())
17149 {
17150 m_type = value_t::array;
17151 m_value = value_t::array;
17152 assert_invariant();
17153 }
17154
17155 // add element to array
17156 m_value.array->push_back(val);
17157 }
17158
17164 {
17165 push_back(val);
17166 return *this;
17167 }
17168
17189 void push_back(const typename object_t::value_type& val)
17190 {
17191 // push_back only works for null objects or objects
17192 if (JSON_UNLIKELY(not(is_null() or is_object())))
17193 {
17194 JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
17195 }
17196
17197 // transform null object into an object
17198 if (is_null())
17199 {
17200 m_type = value_t::object;
17201 m_value = value_t::object;
17202 assert_invariant();
17203 }
17204
17205 // add element to array
17206 m_value.object->insert(val);
17207 }
17208
17213 reference operator+=(const typename object_t::value_type& val)
17214 {
17215 push_back(val);
17216 return *this;
17217 }
17218
17245 {
17246 if (is_object() and init.size() == 2 and (*init.begin())->is_string())
17247 {
17248 basic_json&& key = init.begin()->moved_or_copied();
17249 push_back(typename object_t::value_type(
17250 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
17251 }
17252 else
17253 {
17254 push_back(basic_json(init));
17255 }
17256 }
17257
17263 {
17264 push_back(init);
17265 return *this;
17266 }
17267
17289 template<class... Args>
17290 void emplace_back(Args&& ... args)
17291 {
17292 // emplace_back only works for null objects or arrays
17293 if (JSON_UNLIKELY(not(is_null() or is_array())))
17294 {
17295 JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
17296 }
17297
17298 // transform null object into an array
17299 if (is_null())
17300 {
17301 m_type = value_t::array;
17302 m_value = value_t::array;
17303 assert_invariant();
17304 }
17305
17306 // add element to array (perfect forwarding)
17307 m_value.array->emplace_back(std::forward<Args>(args)...);
17308 }
17309
17337 template<class... Args>
17338 std::pair<iterator, bool> emplace(Args&& ... args)
17339 {
17340 // emplace only works for null objects or arrays
17341 if (JSON_UNLIKELY(not(is_null() or is_object())))
17342 {
17343 JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
17344 }
17345
17346 // transform null object into an object
17347 if (is_null())
17348 {
17349 m_type = value_t::object;
17350 m_value = value_t::object;
17351 assert_invariant();
17352 }
17353
17354 // add element to array (perfect forwarding)
17355 auto res = m_value.object->emplace(std::forward<Args>(args)...);
17356 // create result iterator and set iterator to the result of emplace
17357 auto it = begin();
17358 it.m_it.object_iterator = res.first;
17359
17360 // return pair of iterator and boolean
17361 return {it, res.second};
17362 }
17363
17367 template<typename... Args>
17369 {
17370 iterator result(this);
17371 assert(m_value.array != nullptr);
17372
17373 auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
17374 m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
17375 result.m_it.array_iterator = m_value.array->begin() + insert_pos;
17376
17377 // This could have been written as:
17378 // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
17379 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
17380
17381 return result;
17382 }
17383
17407 {
17408 // insert only works for arrays
17409 if (JSON_LIKELY(is_array()))
17410 {
17411 // check if iterator pos fits to this JSON value
17412 if (JSON_UNLIKELY(pos.m_object != this))
17413 {
17414 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17415 }
17416
17417 // insert to array and return iterator
17418 return insert_iterator(pos, val);
17419 }
17420
17421 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17422 }
17423
17429 {
17430 return insert(pos, val);
17431 }
17432
17458 {
17459 // insert only works for arrays
17460 if (JSON_LIKELY(is_array()))
17461 {
17462 // check if iterator pos fits to this JSON value
17463 if (JSON_UNLIKELY(pos.m_object != this))
17464 {
17465 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17466 }
17467
17468 // insert to array and return iterator
17469 return insert_iterator(pos, cnt, val);
17470 }
17471
17472 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17473 }
17474
17506 {
17507 // insert only works for arrays
17508 if (JSON_UNLIKELY(not is_array()))
17509 {
17510 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17511 }
17512
17513 // check if iterator pos fits to this JSON value
17514 if (JSON_UNLIKELY(pos.m_object != this))
17515 {
17516 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17517 }
17518
17519 // check if range iterators belong to the same JSON object
17520 if (JSON_UNLIKELY(first.m_object != last.m_object))
17521 {
17522 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17523 }
17524
17525 if (JSON_UNLIKELY(first.m_object == this))
17526 {
17527 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
17528 }
17529
17530 // insert to array and return iterator
17531 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
17532 }
17533
17559 {
17560 // insert only works for arrays
17561 if (JSON_UNLIKELY(not is_array()))
17562 {
17563 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17564 }
17565
17566 // check if iterator pos fits to this JSON value
17567 if (JSON_UNLIKELY(pos.m_object != this))
17568 {
17569 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
17570 }
17571
17572 // insert to array and return iterator
17573 return insert_iterator(pos, ilist.begin(), ilist.end());
17574 }
17575
17600 {
17601 // insert only works for objects
17602 if (JSON_UNLIKELY(not is_object()))
17603 {
17604 JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
17605 }
17606
17607 // check if range iterators belong to the same JSON object
17608 if (JSON_UNLIKELY(first.m_object != last.m_object))
17609 {
17610 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17611 }
17612
17613 // passed iterators must belong to objects
17614 if (JSON_UNLIKELY(not first.m_object->is_object()))
17615 {
17616 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
17617 }
17618
17619 m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
17620 }
17621
17642 {
17643 // implicitly convert null value to an empty object
17644 if (is_null())
17645 {
17646 m_type = value_t::object;
17647 m_value.object = create<object_t>();
17648 assert_invariant();
17649 }
17650
17651 if (JSON_UNLIKELY(not is_object()))
17652 {
17653 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
17654 }
17655 if (JSON_UNLIKELY(not j.is_object()))
17656 {
17657 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name())));
17658 }
17659
17660 for (auto it = j.cbegin(); it != j.cend(); ++it)
17661 {
17662 m_value.object->operator[](it.key()) = it.value();
17663 }
17664 }
17665
17693 {
17694 // implicitly convert null value to an empty object
17695 if (is_null())
17696 {
17697 m_type = value_t::object;
17698 m_value.object = create<object_t>();
17699 assert_invariant();
17700 }
17701
17702 if (JSON_UNLIKELY(not is_object()))
17703 {
17704 JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name())));
17705 }
17706
17707 // check if range iterators belong to the same JSON object
17708 if (JSON_UNLIKELY(first.m_object != last.m_object))
17709 {
17710 JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
17711 }
17712
17713 // passed iterators must belong to objects
17714 if (JSON_UNLIKELY(not first.m_object->is_object()
17715 or not last.m_object->is_object()))
17716 {
17717 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
17718 }
17719
17720 for (auto it = first; it != last; ++it)
17721 {
17722 m_value.object->operator[](it.key()) = it.value();
17723 }
17724 }
17725
17743 void swap(reference other) noexcept (
17744 std::is_nothrow_move_constructible<value_t>::value and
17745 std::is_nothrow_move_assignable<value_t>::value and
17746 std::is_nothrow_move_constructible<json_value>::value and
17747 std::is_nothrow_move_assignable<json_value>::value
17748 )
17749 {
17750 std::swap(m_type, other.m_type);
17751 std::swap(m_value, other.m_value);
17752 assert_invariant();
17753 }
17754
17775 void swap(array_t& other)
17776 {
17777 // swap only works for arrays
17778 if (JSON_LIKELY(is_array()))
17779 {
17780 std::swap(*(m_value.array), other);
17781 }
17782 else
17783 {
17784 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
17785 }
17786 }
17787
17808 void swap(object_t& other)
17809 {
17810 // swap only works for objects
17811 if (JSON_LIKELY(is_object()))
17812 {
17813 std::swap(*(m_value.object), other);
17814 }
17815 else
17816 {
17817 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
17818 }
17819 }
17820
17841 void swap(string_t& other)
17842 {
17843 // swap only works for strings
17844 if (JSON_LIKELY(is_string()))
17845 {
17846 std::swap(*(m_value.string), other);
17847 }
17848 else
17849 {
17850 JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
17851 }
17852 }
17853
17855
17856 public:
17858 // lexicographical comparison operators //
17860
17863
17903 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
17904 {
17905 const auto lhs_type = lhs.type();
17906 const auto rhs_type = rhs.type();
17907
17908 if (lhs_type == rhs_type)
17909 {
17910 switch (lhs_type)
17911 {
17912 case value_t::array:
17913 return (*lhs.m_value.array == *rhs.m_value.array);
17914
17915 case value_t::object:
17916 return (*lhs.m_value.object == *rhs.m_value.object);
17917
17918 case value_t::null:
17919 return true;
17920
17921 case value_t::string:
17922 return (*lhs.m_value.string == *rhs.m_value.string);
17923
17924 case value_t::boolean:
17925 return (lhs.m_value.boolean == rhs.m_value.boolean);
17926
17927 case value_t::number_integer:
17928 return (lhs.m_value.number_integer == rhs.m_value.number_integer);
17929
17930 case value_t::number_unsigned:
17931 return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
17932
17933 case value_t::number_float:
17934 return (lhs.m_value.number_float == rhs.m_value.number_float);
17935
17936 default:
17937 return false;
17938 }
17939 }
17940 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
17941 {
17942 return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
17943 }
17944 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
17945 {
17946 return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
17947 }
17948 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
17949 {
17950 return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
17951 }
17952 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
17953 {
17954 return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
17955 }
17956 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
17957 {
17958 return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
17959 }
17960 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
17961 {
17962 return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
17963 }
17964
17965 return false;
17966 }
17967
17972 template<typename ScalarType, typename std::enable_if<
17973 std::is_scalar<ScalarType>::value, int>::type = 0>
17974 friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
17975 {
17976 return (lhs == basic_json(rhs));
17977 }
17978
17983 template<typename ScalarType, typename std::enable_if<
17984 std::is_scalar<ScalarType>::value, int>::type = 0>
17985 friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
17986 {
17987 return (basic_json(lhs) == rhs);
17988 }
17989
18008 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
18009 {
18010 return not (lhs == rhs);
18011 }
18012
18017 template<typename ScalarType, typename std::enable_if<
18018 std::is_scalar<ScalarType>::value, int>::type = 0>
18019 friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
18020 {
18021 return (lhs != basic_json(rhs));
18022 }
18023
18028 template<typename ScalarType, typename std::enable_if<
18029 std::is_scalar<ScalarType>::value, int>::type = 0>
18030 friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
18031 {
18032 return (basic_json(lhs) != rhs);
18033 }
18034
18061 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
18062 {
18063 const auto lhs_type = lhs.type();
18064 const auto rhs_type = rhs.type();
18065
18066 if (lhs_type == rhs_type)
18067 {
18068 switch (lhs_type)
18069 {
18070 case value_t::array:
18071 return (*lhs.m_value.array) < (*rhs.m_value.array);
18072
18073 case value_t::object:
18074 return *lhs.m_value.object < *rhs.m_value.object;
18075
18076 case value_t::null:
18077 return false;
18078
18079 case value_t::string:
18080 return *lhs.m_value.string < *rhs.m_value.string;
18081
18082 case value_t::boolean:
18083 return lhs.m_value.boolean < rhs.m_value.boolean;
18084
18085 case value_t::number_integer:
18086 return lhs.m_value.number_integer < rhs.m_value.number_integer;
18087
18088 case value_t::number_unsigned:
18089 return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
18090
18091 case value_t::number_float:
18092 return lhs.m_value.number_float < rhs.m_value.number_float;
18093
18094 default:
18095 return false;
18096 }
18097 }
18098 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
18099 {
18100 return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
18101 }
18102 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
18103 {
18104 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
18105 }
18106 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
18107 {
18108 return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
18109 }
18110 else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
18111 {
18112 return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
18113 }
18114 else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
18115 {
18116 return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
18117 }
18118 else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
18119 {
18120 return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
18121 }
18122
18123 // We only reach this line if we cannot compare values. In that case,
18124 // we compare types. Note we have to call the operator explicitly,
18125 // because MSVC has problems otherwise.
18126 return operator<(lhs_type, rhs_type);
18127 }
18128
18133 template<typename ScalarType, typename std::enable_if<
18134 std::is_scalar<ScalarType>::value, int>::type = 0>
18135 friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
18136 {
18137 return (lhs < basic_json(rhs));
18138 }
18139
18144 template<typename ScalarType, typename std::enable_if<
18145 std::is_scalar<ScalarType>::value, int>::type = 0>
18146 friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
18147 {
18148 return (basic_json(lhs) < rhs);
18149 }
18150
18170 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
18171 {
18172 return not (rhs < lhs);
18173 }
18174
18179 template<typename ScalarType, typename std::enable_if<
18180 std::is_scalar<ScalarType>::value, int>::type = 0>
18181 friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
18182 {
18183 return (lhs <= basic_json(rhs));
18184 }
18185
18190 template<typename ScalarType, typename std::enable_if<
18191 std::is_scalar<ScalarType>::value, int>::type = 0>
18192 friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
18193 {
18194 return (basic_json(lhs) <= rhs);
18195 }
18196
18216 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
18217 {
18218 return not (lhs <= rhs);
18219 }
18220
18225 template<typename ScalarType, typename std::enable_if<
18226 std::is_scalar<ScalarType>::value, int>::type = 0>
18227 friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
18228 {
18229 return (lhs > basic_json(rhs));
18230 }
18231
18236 template<typename ScalarType, typename std::enable_if<
18237 std::is_scalar<ScalarType>::value, int>::type = 0>
18238 friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
18239 {
18240 return (basic_json(lhs) > rhs);
18241 }
18242
18262 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
18263 {
18264 return not (lhs < rhs);
18265 }
18266
18271 template<typename ScalarType, typename std::enable_if<
18272 std::is_scalar<ScalarType>::value, int>::type = 0>
18273 friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
18274 {
18275 return (lhs >= basic_json(rhs));
18276 }
18277
18282 template<typename ScalarType, typename std::enable_if<
18283 std::is_scalar<ScalarType>::value, int>::type = 0>
18284 friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
18285 {
18286 return (basic_json(lhs) >= rhs);
18287 }
18288
18290
18292 // serialization //
18294
18297
18329 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
18330 {
18331 // read width member and use it as indentation parameter if nonzero
18332 const bool pretty_print = (o.width() > 0);
18333 const auto indentation = (pretty_print ? o.width() : 0);
18334
18335 // reset width to 0 for subsequent calls to this stream
18336 o.width(0);
18337
18338 // do the actual serialization
18340 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
18341 return o;
18342 }
18343
18352 JSON_DEPRECATED
18353 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
18354 {
18355 return o << j;
18356 }
18357
18359
18360
18362 // deserialization //
18364
18367
18433 const parser_callback_t cb = nullptr,
18434 const bool allow_exceptions = true)
18435 {
18436 basic_json result;
18437 parser(i, cb, allow_exceptions).parse(true, result);
18438 return result;
18439 }
18440
18441 static bool accept(detail::input_adapter&& i)
18442 {
18443 return parser(i).accept(true);
18444 }
18445
18502 template <typename SAX>
18503 static bool sax_parse(detail::input_adapter&& i, SAX* sax,
18504 input_format_t format = input_format_t::json,
18505 const bool strict = true)
18506 {
18507 assert(sax);
18508 switch (format)
18509 {
18510 case input_format_t::json:
18511 return parser(std::move(i)).sax_parse(sax, strict);
18512 default:
18513 return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
18514 }
18515 }
18516
18564 template<class IteratorType, typename std::enable_if<
18565 std::is_base_of<
18566 std::random_access_iterator_tag,
18567 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18568 static basic_json parse(IteratorType first, IteratorType last,
18569 const parser_callback_t cb = nullptr,
18570 const bool allow_exceptions = true)
18571 {
18572 basic_json result;
18573 parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result);
18574 return result;
18575 }
18576
18577 template<class IteratorType, typename std::enable_if<
18578 std::is_base_of<
18579 std::random_access_iterator_tag,
18580 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18581 static bool accept(IteratorType first, IteratorType last)
18582 {
18583 return parser(detail::input_adapter(first, last)).accept(true);
18584 }
18585
18586 template<class IteratorType, class SAX, typename std::enable_if<
18587 std::is_base_of<
18588 std::random_access_iterator_tag,
18589 typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
18590 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
18591 {
18592 return parser(detail::input_adapter(first, last)).sax_parse(sax);
18593 }
18594
18603 JSON_DEPRECATED
18604 friend std::istream& operator<<(basic_json& j, std::istream& i)
18605 {
18606 return operator>>(i, j);
18607 }
18608
18634 friend std::istream& operator>>(std::istream& i, basic_json& j)
18635 {
18636 parser(detail::input_adapter(i)).parse(false, j);
18637 return i;
18638 }
18639
18641
18643 // convenience functions //
18645
18676 const char* type_name() const noexcept
18677 {
18678 {
18679 switch (m_type)
18680 {
18681 case value_t::null:
18682 return "null";
18683 case value_t::object:
18684 return "object";
18685 case value_t::array:
18686 return "array";
18687 case value_t::string:
18688 return "string";
18689 case value_t::boolean:
18690 return "boolean";
18691 case value_t::discarded:
18692 return "discarded";
18693 default:
18694 return "number";
18695 }
18696 }
18697 }
18698
18699
18700 private:
18702 // member variables //
18704
18706 value_t m_type = value_t::null;
18707
18709 json_value m_value = {};
18710
18712 // binary serialization/deserialization //
18714
18717
18718 public:
18807 static std::vector<uint8_t> to_cbor(const basic_json& j)
18808 {
18809 std::vector<uint8_t> result;
18810 to_cbor(j, result);
18811 return result;
18812 }
18813
18814 static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
18815 {
18816 binary_writer<uint8_t>(o).write_cbor(j);
18817 }
18818
18819 static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
18820 {
18821 binary_writer<char>(o).write_cbor(j);
18822 }
18823
18903 static std::vector<uint8_t> to_msgpack(const basic_json& j)
18904 {
18905 std::vector<uint8_t> result;
18906 to_msgpack(j, result);
18907 return result;
18908 }
18909
18910 static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
18911 {
18912 binary_writer<uint8_t>(o).write_msgpack(j);
18913 }
18914
18915 static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
18916 {
18917 binary_writer<char>(o).write_msgpack(j);
18918 }
18919
19000 static std::vector<uint8_t> to_ubjson(const basic_json& j,
19001 const bool use_size = false,
19002 const bool use_type = false)
19003 {
19004 std::vector<uint8_t> result;
19005 to_ubjson(j, result, use_size, use_type);
19006 return result;
19007 }
19008
19009 static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
19010 const bool use_size = false, const bool use_type = false)
19011 {
19012 binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
19013 }
19014
19015 static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
19016 const bool use_size = false, const bool use_type = false)
19017 {
19018 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
19019 }
19020
19021
19077 static std::vector<uint8_t> to_bson(const basic_json& j)
19078 {
19079 std::vector<uint8_t> result;
19080 to_bson(j, result);
19081 return result;
19082 }
19083
19093 {
19094 binary_writer<uint8_t>(o).write_bson(j);
19095 }
19096
19101 {
19102 binary_writer<char>(o).write_bson(j);
19103 }
19104
19105
19204 const bool strict = true,
19205 const bool allow_exceptions = true)
19206 {
19207 basic_json result;
19208 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19209 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
19210 return res ? result : basic_json(value_t::discarded);
19211 }
19212
19216 template<typename A1, typename A2,
19217 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19218 static basic_json from_cbor(A1 && a1, A2 && a2,
19219 const bool strict = true,
19220 const bool allow_exceptions = true)
19221 {
19222 basic_json result;
19223 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19224 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
19225 return res ? result : basic_json(value_t::discarded);
19226 }
19227
19309 const bool strict = true,
19310 const bool allow_exceptions = true)
19311 {
19312 basic_json result;
19313 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19314 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
19315 return res ? result : basic_json(value_t::discarded);
19316 }
19317
19321 template<typename A1, typename A2,
19322 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19323 static basic_json from_msgpack(A1 && a1, A2 && a2,
19324 const bool strict = true,
19325 const bool allow_exceptions = true)
19326 {
19327 basic_json result;
19328 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19329 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
19330 return res ? result : basic_json(value_t::discarded);
19331 }
19332
19393 const bool strict = true,
19394 const bool allow_exceptions = true)
19395 {
19396 basic_json result;
19397 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19398 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
19399 return res ? result : basic_json(value_t::discarded);
19400 }
19401
19405 template<typename A1, typename A2,
19406 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19407 static basic_json from_ubjson(A1 && a1, A2 && a2,
19408 const bool strict = true,
19409 const bool allow_exceptions = true)
19410 {
19411 basic_json result;
19412 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19413 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
19414 return res ? result : basic_json(value_t::discarded);
19415 }
19416
19476 const bool strict = true,
19477 const bool allow_exceptions = true)
19478 {
19479 basic_json result;
19480 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19481 const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::bson, &sdp, strict);
19482 return res ? result : basic_json(value_t::discarded);
19483 }
19484
19488 template<typename A1, typename A2,
19489 detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
19490 static basic_json from_bson(A1 && a1, A2 && a2,
19491 const bool strict = true,
19492 const bool allow_exceptions = true)
19493 {
19494 basic_json result;
19495 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
19496 const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::bson, &sdp, strict);
19497 return res ? result : basic_json(value_t::discarded);
19498 }
19499
19500
19501
19503
19505 // JSON Pointer support //
19507
19510
19545 {
19546 return ptr.get_unchecked(this);
19547 }
19548
19573 {
19574 return ptr.get_unchecked(this);
19575 }
19576
19616 {
19617 return ptr.get_checked(this);
19618 }
19619
19659 {
19660 return ptr.get_checked(this);
19661 }
19662
19686 {
19687 basic_json result(value_t::object);
19688 json_pointer::flatten("", *this, result);
19689 return result;
19690 }
19691
19723 {
19724 return json_pointer::unflatten(*this);
19725 }
19726
19728
19730 // JSON Patch functions //
19732
19735
19783 basic_json patch(const basic_json& json_patch) const
19784 {
19785 // make a working copy to apply the patch to
19786 basic_json result = *this;
19787
19788 // the valid JSON Patch operations
19789 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
19790
19791 const auto get_op = [](const std::string & op)
19792 {
19793 if (op == "add")
19794 {
19795 return patch_operations::add;
19796 }
19797 if (op == "remove")
19798 {
19799 return patch_operations::remove;
19800 }
19801 if (op == "replace")
19802 {
19803 return patch_operations::replace;
19804 }
19805 if (op == "move")
19806 {
19807 return patch_operations::move;
19808 }
19809 if (op == "copy")
19810 {
19811 return patch_operations::copy;
19812 }
19813 if (op == "test")
19814 {
19815 return patch_operations::test;
19816 }
19817
19818 return patch_operations::invalid;
19819 };
19820
19821 // wrapper for "add" operation; add value at ptr
19822 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
19823 {
19824 // adding to the root of the target document means replacing it
19825 if (ptr.is_root())
19826 {
19827 result = val;
19828 }
19829 else
19830 {
19831 // make sure the top element of the pointer exists
19832 json_pointer top_pointer = ptr.top();
19833 if (top_pointer != ptr)
19834 {
19835 result.at(top_pointer);
19836 }
19837
19838 // get reference to parent of JSON pointer ptr
19839 const auto last_path = ptr.pop_back();
19840 basic_json& parent = result[ptr];
19841
19842 switch (parent.m_type)
19843 {
19844 case value_t::null:
19845 case value_t::object:
19846 {
19847 // use operator[] to add value
19848 parent[last_path] = val;
19849 break;
19850 }
19851
19852 case value_t::array:
19853 {
19854 if (last_path == "-")
19855 {
19856 // special case: append to back
19857 parent.push_back(val);
19858 }
19859 else
19860 {
19861 const auto idx = json_pointer::array_index(last_path);
19862 if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
19863 {
19864 // avoid undefined behavior
19865 JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
19866 }
19867
19868 // default case: insert add offset
19869 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
19870 }
19871 break;
19872 }
19873
19874 // LCOV_EXCL_START
19875 default:
19876 {
19877 // if there exists a parent it cannot be primitive
19878 assert(false);
19879 }
19880 // LCOV_EXCL_STOP
19881 }
19882 }
19883 };
19884
19885 // wrapper for "remove" operation; remove value at ptr
19886 const auto operation_remove = [&result](json_pointer & ptr)
19887 {
19888 // get reference to parent of JSON pointer ptr
19889 const auto last_path = ptr.pop_back();
19890 basic_json& parent = result.at(ptr);
19891
19892 // remove child
19893 if (parent.is_object())
19894 {
19895 // perform range check
19896 auto it = parent.find(last_path);
19897 if (JSON_LIKELY(it != parent.end()))
19898 {
19899 parent.erase(it);
19900 }
19901 else
19902 {
19903 JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found"));
19904 }
19905 }
19906 else if (parent.is_array())
19907 {
19908 // note erase performs range check
19909 parent.erase(static_cast<size_type>(json_pointer::array_index(last_path)));
19910 }
19911 };
19912
19913 // type check: top level value must be an array
19914 if (JSON_UNLIKELY(not json_patch.is_array()))
19915 {
19916 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
19917 }
19918
19919 // iterate and apply the operations
19920 for (const auto& val : json_patch)
19921 {
19922 // wrapper to get a value for an operation
19923 const auto get_value = [&val](const std::string & op,
19924 const std::string & member,
19925 bool string_type) -> basic_json &
19926 {
19927 // find value
19928 auto it = val.m_value.object->find(member);
19929
19930 // context-sensitive error message
19931 const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
19932
19933 // check if desired value is present
19934 if (JSON_UNLIKELY(it == val.m_value.object->end()))
19935 {
19936 JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
19937 }
19938
19939 // check if result is of type string
19940 if (JSON_UNLIKELY(string_type and not it->second.is_string()))
19941 {
19942 JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
19943 }
19944
19945 // no error: return value
19946 return it->second;
19947 };
19948
19949 // type check: every element of the array must be an object
19950 if (JSON_UNLIKELY(not val.is_object()))
19951 {
19952 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
19953 }
19954
19955 // collect mandatory members
19956 const std::string op = get_value("op", "op", true);
19957 const std::string path = get_value(op, "path", true);
19958 json_pointer ptr(path);
19959
19960 switch (get_op(op))
19961 {
19962 case patch_operations::add:
19963 {
19964 operation_add(ptr, get_value("add", "value", false));
19965 break;
19966 }
19967
19968 case patch_operations::remove:
19969 {
19970 operation_remove(ptr);
19971 break;
19972 }
19973
19974 case patch_operations::replace:
19975 {
19976 // the "path" location must exist - use at()
19977 result.at(ptr) = get_value("replace", "value", false);
19978 break;
19979 }
19980
19981 case patch_operations::move:
19982 {
19983 const std::string from_path = get_value("move", "from", true);
19984 json_pointer from_ptr(from_path);
19985
19986 // the "from" location must exist - use at()
19987 basic_json v = result.at(from_ptr);
19988
19989 // The move operation is functionally identical to a
19990 // "remove" operation on the "from" location, followed
19991 // immediately by an "add" operation at the target
19992 // location with the value that was just removed.
19993 operation_remove(from_ptr);
19994 operation_add(ptr, v);
19995 break;
19996 }
19997
19998 case patch_operations::copy:
19999 {
20000 const std::string from_path = get_value("copy", "from", true);
20001 const json_pointer from_ptr(from_path);
20002
20003 // the "from" location must exist - use at()
20004 basic_json v = result.at(from_ptr);
20005
20006 // The copy is functionally identical to an "add"
20007 // operation at the target location using the value
20008 // specified in the "from" member.
20009 operation_add(ptr, v);
20010 break;
20011 }
20012
20013 case patch_operations::test:
20014 {
20015 bool success = false;
20016 JSON_TRY
20017 {
20018 // check if "value" matches the one at "path"
20019 // the "path" location must exist - use at()
20020 success = (result.at(ptr) == get_value("test", "value", false));
20021 }
20022 JSON_INTERNAL_CATCH (out_of_range&)
20023 {
20024 // ignore out of range errors: success remains false
20025 }
20026
20027 // throw an exception if test fails
20028 if (JSON_UNLIKELY(not success))
20029 {
20030 JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
20031 }
20032
20033 break;
20034 }
20035
20036 case patch_operations::invalid:
20037 {
20038 // op must be "add", "remove", "replace", "move", "copy", or
20039 // "test"
20040 JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid"));
20041 }
20042 }
20043 }
20044
20045 return result;
20046 }
20047
20081 static basic_json diff(const basic_json& source, const basic_json& target,
20082 const std::string& path = "")
20083 {
20084 // the patch
20085 basic_json result(value_t::array);
20086
20087 // if the values are the same, return empty patch
20088 if (source == target)
20089 {
20090 return result;
20091 }
20092
20093 if (source.type() != target.type())
20094 {
20095 // different types: replace value
20096 result.push_back(
20097 {
20098 {"op", "replace"}, {"path", path}, {"value", target}
20099 });
20100 }
20101 else
20102 {
20103 switch (source.type())
20104 {
20105 case value_t::array:
20106 {
20107 // first pass: traverse common elements
20108 std::size_t i = 0;
20109 while (i < source.size() and i < target.size())
20110 {
20111 // recursive call to compare array values at index i
20112 auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
20113 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
20114 ++i;
20115 }
20116
20117 // i now reached the end of at least one array
20118 // in a second pass, traverse the remaining elements
20119
20120 // remove my remaining elements
20121 const auto end_index = static_cast<difference_type>(result.size());
20122 while (i < source.size())
20123 {
20124 // add operations in reverse order to avoid invalid
20125 // indices
20126 result.insert(result.begin() + end_index, object(
20127 {
20128 {"op", "remove"},
20129 {"path", path + "/" + std::to_string(i)}
20130 }));
20131 ++i;
20132 }
20133
20134 // add other remaining elements
20135 while (i < target.size())
20136 {
20137 result.push_back(
20138 {
20139 {"op", "add"},
20140 {"path", path + "/" + std::to_string(i)},
20141 {"value", target[i]}
20142 });
20143 ++i;
20144 }
20145
20146 break;
20147 }
20148
20149 case value_t::object:
20150 {
20151 // first pass: traverse this object's elements
20152 for (auto it = source.cbegin(); it != source.cend(); ++it)
20153 {
20154 // escape the key name to be used in a JSON patch
20155 const auto key = json_pointer::escape(it.key());
20156
20157 if (target.find(it.key()) != target.end())
20158 {
20159 // recursive call to compare object values at key it
20160 auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
20161 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
20162 }
20163 else
20164 {
20165 // found a key that is not in o -> remove it
20166 result.push_back(object(
20167 {
20168 {"op", "remove"}, {"path", path + "/" + key}
20169 }));
20170 }
20171 }
20172
20173 // second pass: traverse other object's elements
20174 for (auto it = target.cbegin(); it != target.cend(); ++it)
20175 {
20176 if (source.find(it.key()) == source.end())
20177 {
20178 // found a key that is not in this -> add it
20179 const auto key = json_pointer::escape(it.key());
20180 result.push_back(
20181 {
20182 {"op", "add"}, {"path", path + "/" + key},
20183 {"value", it.value()}
20184 });
20185 }
20186 }
20187
20188 break;
20189 }
20190
20191 default:
20192 {
20193 // both primitive type: replace value
20194 result.push_back(
20195 {
20196 {"op", "replace"}, {"path", path}, {"value", target}
20197 });
20198 break;
20199 }
20200 }
20201 }
20202
20203 return result;
20204 }
20205
20207
20209 // JSON Merge Patch functions //
20211
20214
20257 void merge_patch(const basic_json& apply_patch)
20258 {
20259 if (apply_patch.is_object())
20260 {
20261 if (not is_object())
20262 {
20263 *this = object();
20264 }
20265 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
20266 {
20267 if (it.value().is_null())
20268 {
20269 erase(it.key());
20270 }
20271 else
20272 {
20273 operator[](it.key()).merge_patch(it.value());
20274 }
20275 }
20276 }
20277 else
20278 {
20279 *this = apply_patch;
20280 }
20281 }
20282
20284};
20285} // namespace nlohmann
20286
20288// nonmember support //
20290
20291// specialization of std::swap, and std::hash
20292namespace std
20293{
20294
20296template<>
20297struct hash<nlohmann::json>
20298{
20304 std::size_t operator()(const nlohmann::json& j) const
20305 {
20306 // a naive hashing via the string representation
20307 const auto& h = hash<nlohmann::json::string_t>();
20308 return h(j.dump());
20309 }
20310};
20311
20315template<>
20316struct less< ::nlohmann::detail::value_t>
20317{
20322 bool operator()(nlohmann::detail::value_t lhs,
20323 nlohmann::detail::value_t rhs) const noexcept
20324 {
20325 return nlohmann::detail::operator<(lhs, rhs);
20326 }
20327};
20328
20334template<>
20335inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
20336 is_nothrow_move_constructible<nlohmann::json>::value and
20337 is_nothrow_move_assignable<nlohmann::json>::value
20338)
20339{
20340 j1.swap(j2);
20341}
20342
20343} // namespace std
20344
20358inline nlohmann::json operator "" _json(const char* s, std::size_t n)
20359{
20360 return nlohmann::json::parse(s, s + n);
20361}
20362
20376inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
20377{
20378 return nlohmann::json::json_pointer(std::string(s, n));
20379}
20380
20381// #include <nlohmann/detail/macro_unscope.hpp>
20382
20383
20384// restore GCC/clang diagnostic settings
20385#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
20386 #pragma GCC diagnostic pop
20387#endif
20388#if defined(__clang__)
20389 #pragma GCC diagnostic pop
20390#endif
20391
20392// clean up
20393#undef JSON_INTERNAL_CATCH
20394#undef JSON_CATCH
20395#undef JSON_THROW
20396#undef JSON_TRY
20397#undef JSON_LIKELY
20398#undef JSON_UNLIKELY
20399#undef JSON_DEPRECATED
20400#undef JSON_HAS_CPP_14
20401#undef JSON_HAS_CPP_17
20402#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
20403#undef NLOHMANN_BASIC_JSON_TPL
20404
20405
20406#endif
Definition format.h:4067
Definition base.h:1940
a class to store JSON values
Definition json.hpp:12544
reference back()
access the last element
Definition json.hpp:15935
iterator insert(const_iterator pos, const basic_json &val)
inserts element
Definition json.hpp:17406
static JSON_DEPRECATED iteration_proxy< const_iterator > iterator_wrapper(const_reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition json.hpp:16688
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:16002
size_type count(KeyT &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:16331
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:16371
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
comparison: equal
Definition json.hpp:17903
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than
Definition json.hpp:18238
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:16442
static JSON_DEPRECATED iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
wrapper to access iterator member functions in range-based for
Definition json.hpp:16679
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:16820
void insert(const_iterator first, const_iterator last)
inserts elements
Definition json.hpp:17599
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:17244
const_iterator end() const noexcept
returns a const iterator to one past the last element
Definition json.hpp:16452
void update(const_reference j)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:17641
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:16586
iterator insert(const_iterator pos, basic_json &&val)
inserts element
Definition json.hpp:17428
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:16512
reference operator[](const typename object_t::key_type &key)
access specified object element
Definition json.hpp:15567
size_type size() const noexcept
returns the number of elements
Definition json.hpp:16892
const_reference operator[](T *key) const
read-only access specified object element
Definition json.hpp:15706
void update(const_iterator first, const_iterator last)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:17692
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:14394
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:14525
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:16962
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:16194
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts elements
Definition json.hpp:17457
BasicJsonType get() const
get special-case overload
Definition json.hpp:14906
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:17368
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:14610
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.hpp:15053
std::size_t size_type
a type to represent container sizes
Definition json.hpp:12644
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:16764
reference front()
access the first element
Definition json.hpp:15891
static basic_json from_cbor(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in CBOR format
Definition json.hpp:19203
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts elements
Definition json.hpp:17505
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than
Definition json.hpp:18227
static std::vector< uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:19000
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:15137
const_reference front() const
access the first element
Definition json.hpp:15899
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:16107
BooleanType boolean_t
a type for a boolean
Definition json.hpp:12985
const_iterator begin() const noexcept
returns a const iterator to the first element
Definition json.hpp:16381
const_reverse_iterator rend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:16557
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.hpp:14342
const_reverse_iterator rbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:16520
static void to_bson(const basic_json &j, detail::output_adapter< uint8_t > o)
Serializes the given JSON object j to BSON and forwards the corresponding BSON-representation to the ...
Definition json.hpp:19092
const char * type_name() const noexcept
return the type as string
Definition json.hpp:18676
static basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition json.hpp:20081
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:17338
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:16615
static basic_json from_bson(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
Create a JSON value from an input in BSON format.
Definition json.hpp:19475
static basic_json parse(detail::input_adapter &&i, const parser_callback_t cb=nullptr, const bool allow_exceptions=true)
deserialize from a compatible input
Definition json.hpp:18432
ValueType get() const noexcept(noexcept(JSONSerializer< ValueTypeCV >::from_json(std::declval< const basic_json_t & >())))
get a value (explicit); special case
Definition json.hpp:15007
friend std::ostream & operator<<(std::ostream &o, const basic_json &j)
serialize to stream
Definition json.hpp:18329
JSON_DEPRECATED friend std::istream & operator<<(basic_json &j, std::istream &i)
deserialize from stream
Definition json.hpp:18604
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition json.hpp:18170
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
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition json.hpp:18284
StringType string_t
a type for a string
Definition json.hpp:12959
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:14424
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:15102
void swap(array_t &other)
exchanges the values
Definition json.hpp:17775
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:15838
::nlohmann::json_pointer< basic_json > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.hpp:12588
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
comparison: greater than or equal
Definition json.hpp:18273
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:14676
basic_json get() const
get special-case overload
Definition json.hpp:14883
static basic_json from_bson(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
Create a JSON value from an input in BSON format.
Definition json.hpp:19490
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
comparison: not equal
Definition json.hpp:18008
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:12661
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:15288
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:19658
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
comparison: greater than or equal
Definition json.hpp:18262
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:19722
static std::vector< uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:18903
basic_json(CompatibleType &&val) noexcept(noexcept(JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value
Definition json.hpp:13629
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than
Definition json.hpp:18135
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:20257
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
comparison: less than or equal
Definition json.hpp:18181
static basic_json from_msgpack(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:19308
basic_json patch(const basic_json &json_patch) const
applies a JSON patch
Definition json.hpp:19783
const_reference back() const
access the last element
Definition json.hpp:15945
static std::vector< uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:18807
string_t value(const json_pointer &ptr, const char *default_value) const
overload for a default value of type const char*
Definition json.hpp:15861
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:12647
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
comparison: greater than
Definition json.hpp:18216
JSON_DEPRECATED friend std::ostream & operator>>(const basic_json &j, std::ostream &o)
serialize to stream
Definition json.hpp:18353
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:16229
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:13196
iterator find(KeyT &&key)
find an element in a JSON object
Definition json.hpp:16280
static bool sax_parse(detail::input_adapter &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true)
generate SAX events
Definition json.hpp:18503
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:19615
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:17743
const_iterator cend() const noexcept
returns a const iterator to one past the last element
Definition json.hpp:16482
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:14473
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:15386
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:14495
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:13057
static basic_json from_ubjson(detail::input_adapter &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:19392
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value and std::is_nothrow_move_assignable< value_t >::value and std::is_nothrow_move_constructible< json_value >::value and std::is_nothrow_move_assignable< json_value >::value)
copy assignment
Definition json.hpp:14251
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:14214
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:15529
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:19572
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:14451
static basic_json from_cbor(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in CBOR format
Definition json.hpp:19218
static basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:13915
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:13666
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements
Definition json.hpp:17558
static basic_json from_msgpack(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:19323
ValueType get() const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), std::declval< ValueType & >())))
get a value (explicit)
Definition json.hpp:14956
static basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:13872
static basic_json from_ubjson(A1 &&a1, A2 &&a2, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:19407
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:14703
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
comparison: less than
Definition json.hpp:18061
typename parser::parse_event_t parse_event_t
parser event types
Definition json.hpp:13447
void emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:17290
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
comparison: not equal
Definition json.hpp:18030
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:15335
const_reference operator[](const typename object_t::key_type &key) const
read-only access specified object element
Definition json.hpp:15616
static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb=nullptr, const bool allow_exceptions=true)
deserialize from an iterator range with contiguous storage
Definition json.hpp:18568
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:17139
typename parser::parser_callback_t parser_callback_t
per-element parser callback type
Definition json.hpp:13498
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:13783
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:13942
basic_json flatten() const
return flattened JSON value
Definition json.hpp:19685
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:13128
~basic_json() noexcept
destructor
Definition json.hpp:14284
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
comparison: equal
Definition json.hpp:17974
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:14554
reference operator[](T *key)
access specified object element
Definition json.hpp:15656
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:14582
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:14007
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than
Definition json.hpp:18146
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:15089
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:17213
void clear() noexcept
clears the contents
Definition json.hpp:17032
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:12659
void swap(object_t &other)
exchanges the values
Definition json.hpp:17808
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:15196
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:19544
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:16549
reference operator[](size_type idx)
access specified array element
Definition json.hpp:15483
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:17103
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:15437
string_t value(const typename object_t::key_type &key, const char *default_value) const
overload for a default value of type const char*
Definition json.hpp:15790
constexpr auto get() const noexcept -> decltype(std::declval< const basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:15149
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.hpp:12594
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
comparison: less than or equal
Definition json.hpp:18192
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:16411
void swap(string_t &other)
exchanges the values
Definition json.hpp:17841
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:17163
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:15768
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:12906
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:17189
const_iterator find(KeyT &&key) const
find an element in a JSON object
Definition json.hpp:16297
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:13562
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:18634
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:17129
static std::vector< uint8_t > to_bson(const basic_json &j)
Serializes the given JSON object j to BSON and returns a vector containing the corresponding BSON-rep...
Definition json.hpp:19077
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
Serializes the given JSON object j to BSON and forwards the corresponding BSON-representation to the ...
Definition json.hpp:19100
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:13538
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
comparison: equal
Definition json.hpp:17985
static basic_json meta()
returns version information on the library
Definition json.hpp:12700
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:14654
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:12650
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:16756
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:17262
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:12669
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:14131
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:14632
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:15183
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:12642
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
comparison: not equal
Definition json.hpp:18019
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:12652
general exception of the basic_json class
Definition json.hpp:869
const int id
the id of the exception
Definition json.hpp:878
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:872
Definition json.hpp:2195
std::char_traits< char >::int_type get_character() noexcept override
get a character [0,255] or std::char_traits<char>::eof().
Definition json.hpp:2201
Definition json.hpp:2456
input_adapter(CharT b, std::size_t l)
input adapter for buffer
Definition json.hpp:2485
input_adapter(CharT b)
input adapter for string literal
Definition json.hpp:2497
input_adapter(const ContiguousContainer &c)
input adapter for contiguous container
Definition json.hpp:2549
input_adapter(T(&array)[N])
input adapter for array
Definition json.hpp:2541
input_adapter(IteratorType first, IteratorType last)
input adapter for iterator range with contiguous storage
Definition json.hpp:2506
input_adapter(std::istream &i)
input adapter for input stream
Definition json.hpp:2462
input_adapter(std::istream &&i)
input adapter for input stream
Definition json.hpp:2466
input adapter for buffer input
Definition json.hpp:2262
std::char_traits< char >::int_type get_character() noexcept override
get a character [0,255] or std::char_traits<char>::eof().
Definition json.hpp:2275
std::char_traits< char >::int_type get_character() override
get a character [0,255] or std::char_traits<char>::eof().
Definition json.hpp:2243
exception indicating errors with iterators
Definition json.hpp:1024
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:5630
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:5997
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:6111
iter_impl()=default
default constructor
Definition json.hpp:5632
iter_impl const operator--(int)
post-decrement (it–)
Definition json.hpp:5918
bool operator==(const iter_impl &other) const
comparison: equal
Definition json.hpp:5961
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:5655
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:5929
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:6122
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:5664
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:5804
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:6042
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:5659
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:5724
pointer operator->() const
dereference the iterator
Definition json.hpp:5841
iter_impl const operator++(int)
post-increment (it++)
Definition json.hpp:5875
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:5715
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition json.hpp:5675
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:6089
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:6100
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:6174
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:6033
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:5653
reference value() const
return the value of an iterator
Definition json.hpp:6190
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:5886
reference operator[](difference_type n) const
access to successor
Definition json.hpp:6143
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:6024
std::bidirectional_iterator_tag iterator_category
Definition json.hpp:5650
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:6051
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition json.hpp:5988
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:6080
Definition json.hpp:4870
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:4382
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition json.hpp:4394
exception indicating other library errors
Definition json.hpp:1160
exception indicating access out of the defined range
Definition json.hpp:1123
Definition json.hpp:6425
output adapter for output streams
Definition json.hpp:6380
output adapter for basic_string
Definition json.hpp:6403
output adapter for byte vectors
Definition json.hpp:6357
exception indicating a parse error
Definition json.hpp:938
static parse_error create(int id_, const position_t &pos, const std::string &what_arg)
create a parse error exception
Definition json.hpp:949
const std::size_t byte
byte index of the parse error
Definition json.hpp:973
syntax analysis
Definition json.hpp:4961
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:5009
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:4990
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:5070
parse_event_t
Definition json.hpp:4971
@ value
the parser finished reading a JSON value
@ key
the parser read a key of a value in an object
@ array_end
the parser read ] and finished processing a JSON array
@ array_start
the parser read [ and started to process a JSON array
@ object_start
the parser read { and started to process a JSON object
@ object_end
the parser read } and finished processing a JSON object
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:5488
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:5482
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:5470
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:5476
Definition json.hpp:10925
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:10974
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:10939
exception indicating executing a member function with a wrong type
Definition json.hpp:1077
std::char_traits< char >::int_type get_character() noexcept override
get a character [0,255] or std::char_traits<char>::eof().
Definition json.hpp:2416
JSON Pointer.
Definition json.hpp:11717
std::string to_string() const
return a string representation of the JSON pointer
Definition json.hpp:11763
json_pointer(const std::string &s="")
create JSON pointer
Definition json.hpp:11744
static int array_index(const std::string &s)
Definition json.hpp:11786
GLM_FUNC_QUALIFIER vec< L, T, Q > exp(vec< L, T, Q > const &x)
Definition func_exponential.inl:80
uint64 uint64_t
Definition fwd.hpp:145
int8 int8_t
Definition fwd.hpp:43
int64 int64_t
Definition fwd.hpp:85
uint32 uint32_t
Definition fwd.hpp:131
uint8 uint8_t
Definition fwd.hpp:103
int32 int32_t
Definition fwd.hpp:71
uint16 uint16_t
Definition fwd.hpp:117
int16 int16_t
Definition fwd.hpp:57
detail::uint8 byte
Definition raw_data.hpp:34
error_handler_t
how to treat decoding errors
Definition json.hpp:10917
@ strict
throw a type_error exception in case of invalid UTF-8
@ ignore
ignore invalid UTF-8 sequences
@ replace
replace invalid UTF-8 sequences with U+FFFD
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:6352
input_format_t
the supported input formats
Definition json.hpp:2163
std::shared_ptr< input_adapter_protocol > input_adapter_t
a type to simplify interfaces
Definition json.hpp:2188
namespace for Niels Lohmann
Definition json.hpp:65
Definition base.h:474
Definition PxMetaDataCompare.h:384
default JSONSerializer template argument
Definition json.hpp:12414
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:12442
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:12425
Definition json.hpp:423
Definition json.hpp:528
Definition json.hpp:559
Definition json.hpp:274
abstract input adapter interface
Definition json.hpp:2181
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:5573
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:5579
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:5577
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:5575
Definition json.hpp:484
Definition json.hpp:597
Definition json.hpp:4152
Definition json.hpp:374
Definition json.hpp:355
Definition json.hpp:340
Definition json.hpp:411
abstract output adapter interface
Definition json.hpp:6344
struct to capture the start position of the current token
Definition json.hpp:813
std::size_t lines_read
the number of lines read
Definition json.hpp:819
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:817
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:815
Definition json.hpp:302
Definition json.hpp:308
Definition json.hpp:2123
SAX interface.
Definition json.hpp:4261
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:4263
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:4265
typename BasicJsonType::number_float_t number_float_t
type for floating-point numbers
Definition json.hpp:4267
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:4269
virtual bool number_float(number_float_t val, const string_t &s)=0
an floating-point number was read
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:20304
bool operator()(nlohmann::detail::value_t lhs, nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:20322