#
tokens: 45302/50000 8/161 files (page 4/21)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 4 of 21. Use http://codebase.md/wasdubya/x64dbgmcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── build
│   ├── MCPx64dbg.dp32
│   └── MCPx64dbg.dp64
├── CMakeLists.txt
├── deps
│   ├── pluginsdk
│   │   ├── _dbgfunctions.h
│   │   ├── _plugin_types.h
│   │   ├── _plugins.h
│   │   ├── _scriptapi_argument.h
│   │   ├── _scriptapi_assembler.h
│   │   ├── _scriptapi_bookmark.h
│   │   ├── _scriptapi_comment.h
│   │   ├── _scriptapi_debug.h
│   │   ├── _scriptapi_flag.h
│   │   ├── _scriptapi_function.h
│   │   ├── _scriptapi_gui.h
│   │   ├── _scriptapi_label.h
│   │   ├── _scriptapi_memory.h
│   │   ├── _scriptapi_misc.h
│   │   ├── _scriptapi_module.h
│   │   ├── _scriptapi_pattern.h
│   │   ├── _scriptapi_register.h
│   │   ├── _scriptapi_stack.h
│   │   ├── _scriptapi_symbol.h
│   │   ├── _scriptapi.h
│   │   ├── bridgegraph.h
│   │   ├── bridgelist.h
│   │   ├── bridgemain.h
│   │   ├── dbghelp
│   │   │   ├── dbghelp_x64.a
│   │   │   ├── dbghelp_x64.lib
│   │   │   ├── dbghelp_x86.a
│   │   │   ├── dbghelp_x86.lib
│   │   │   └── dbghelp.h
│   │   ├── DeviceNameResolver
│   │   │   ├── DeviceNameResolver_x64.a
│   │   │   ├── DeviceNameResolver_x64.lib
│   │   │   ├── DeviceNameResolver_x86.a
│   │   │   ├── DeviceNameResolver_x86.lib
│   │   │   └── DeviceNameResolver.h
│   │   ├── jansson
│   │   │   ├── jansson_config.h
│   │   │   ├── jansson_x64.a
│   │   │   ├── jansson_x64.lib
│   │   │   ├── jansson_x64dbg.h
│   │   │   ├── jansson_x86.a
│   │   │   ├── jansson_x86.lib
│   │   │   └── jansson.h
│   │   ├── lz4
│   │   │   ├── lz4_x64.a
│   │   │   ├── lz4_x64.lib
│   │   │   ├── lz4_x86.a
│   │   │   ├── lz4_x86.lib
│   │   │   ├── lz4.h
│   │   │   ├── lz4file.h
│   │   │   └── lz4hc.h
│   │   ├── nlohmann
│   │   │   ├── adl_serializer.hpp
│   │   │   ├── byte_container_with_subtype.hpp
│   │   │   ├── detail
│   │   │   │   ├── abi_macros.hpp
│   │   │   │   ├── conversions
│   │   │   │   │   ├── from_json.hpp
│   │   │   │   │   ├── to_chars.hpp
│   │   │   │   │   └── to_json.hpp
│   │   │   │   ├── exceptions.hpp
│   │   │   │   ├── hash.hpp
│   │   │   │   ├── input
│   │   │   │   │   ├── binary_reader.hpp
│   │   │   │   │   ├── input_adapters.hpp
│   │   │   │   │   ├── json_sax.hpp
│   │   │   │   │   ├── lexer.hpp
│   │   │   │   │   ├── parser.hpp
│   │   │   │   │   └── position_t.hpp
│   │   │   │   ├── iterators
│   │   │   │   │   ├── internal_iterator.hpp
│   │   │   │   │   ├── iter_impl.hpp
│   │   │   │   │   ├── iteration_proxy.hpp
│   │   │   │   │   ├── iterator_traits.hpp
│   │   │   │   │   ├── json_reverse_iterator.hpp
│   │   │   │   │   └── primitive_iterator.hpp
│   │   │   │   ├── json_custom_base_class.hpp
│   │   │   │   ├── json_pointer.hpp
│   │   │   │   ├── json_ref.hpp
│   │   │   │   ├── macro_scope.hpp
│   │   │   │   ├── macro_unscope.hpp
│   │   │   │   ├── meta
│   │   │   │   │   ├── call_std
│   │   │   │   │   │   ├── begin.hpp
│   │   │   │   │   │   └── end.hpp
│   │   │   │   │   ├── cpp_future.hpp
│   │   │   │   │   ├── detected.hpp
│   │   │   │   │   ├── identity_tag.hpp
│   │   │   │   │   ├── is_sax.hpp
│   │   │   │   │   ├── std_fs.hpp
│   │   │   │   │   ├── type_traits.hpp
│   │   │   │   │   └── void_t.hpp
│   │   │   │   ├── output
│   │   │   │   │   ├── binary_writer.hpp
│   │   │   │   │   ├── output_adapters.hpp
│   │   │   │   │   └── serializer.hpp
│   │   │   │   ├── string_concat.hpp
│   │   │   │   ├── string_escape.hpp
│   │   │   │   └── value_t.hpp
│   │   │   ├── json_fwd.hpp
│   │   │   ├── json.hpp
│   │   │   ├── ordered_map.hpp
│   │   │   └── thirdparty
│   │   │       └── hedley
│   │   │           ├── hedley_undef.hpp
│   │   │           └── hedley.hpp
│   │   ├── TitanEngine
│   │   │   ├── TitanEngine_x64.a
│   │   │   ├── TitanEngine_x64.lib
│   │   │   ├── TitanEngine_x86.a
│   │   │   ├── TitanEngine_x86.lib
│   │   │   └── TitanEngine.h
│   │   ├── x32bridge.lib
│   │   ├── x32dbg.lib
│   │   ├── x64bridge.lib
│   │   ├── x64dbg.lib
│   │   └── XEDParse
│   │       ├── XEDParse_x64.a
│   │       ├── XEDParse_x64.lib
│   │       ├── XEDParse_x86.a
│   │       ├── XEDParse_x86.lib
│   │       └── XEDParse.h
│   └── x64dbg_sdk
│       └── pluginsdk
│           ├── _dbgfunctions.h
│           ├── _plugin_types.h
│           ├── _plugins.h
│           ├── _scriptapi_argument.h
│           ├── _scriptapi_assembler.h
│           ├── _scriptapi_bookmark.h
│           ├── _scriptapi_comment.h
│           ├── _scriptapi_debug.h
│           ├── _scriptapi_flag.h
│           ├── _scriptapi_function.h
│           ├── _scriptapi_gui.h
│           ├── _scriptapi_label.h
│           ├── _scriptapi_memory.h
│           ├── _scriptapi_misc.h
│           ├── _scriptapi_module.h
│           ├── _scriptapi_pattern.h
│           ├── _scriptapi_register.h
│           ├── _scriptapi_stack.h
│           ├── _scriptapi_symbol.h
│           ├── _scriptapi.h
│           ├── bridgegraph.h
│           ├── bridgelist.h
│           ├── bridgemain.h
│           ├── dbghelp
│           │   ├── dbghelp_x64.a
│           │   ├── dbghelp_x64.lib
│           │   ├── dbghelp_x86.a
│           │   ├── dbghelp_x86.lib
│           │   └── dbghelp.h
│           ├── DeviceNameResolver
│           │   ├── DeviceNameResolver_x64.a
│           │   ├── DeviceNameResolver_x64.lib
│           │   ├── DeviceNameResolver_x86.a
│           │   ├── DeviceNameResolver_x86.lib
│           │   └── DeviceNameResolver.h
│           ├── jansson
│           │   ├── jansson_config.h
│           │   ├── jansson_x64.a
│           │   ├── jansson_x64.lib
│           │   ├── jansson_x64dbg.h
│           │   ├── jansson_x86.a
│           │   ├── jansson_x86.lib
│           │   └── jansson.h
│           ├── lz4
│           │   ├── lz4_x64.a
│           │   ├── lz4_x64.lib
│           │   ├── lz4_x86.a
│           │   ├── lz4_x86.lib
│           │   ├── lz4.h
│           │   ├── lz4file.h
│           │   └── lz4hc.h
│           ├── TitanEngine
│           │   ├── TitanEngine_x64.a
│           │   ├── TitanEngine_x64.lib
│           │   ├── TitanEngine_x86.a
│           │   ├── TitanEngine_x86.lib
│           │   └── TitanEngine.h
│           ├── TitanEngine_x64.a
│           ├── TitanEngine_x64.lib
│           ├── TitanEngine_x86.a
│           ├── TitanEngine_x86.lib
│           ├── TitanEngine.h
│           ├── x32bridge.lib
│           ├── x32dbg.lib
│           ├── x64bridge.lib
│           ├── x64dbg.lib
│           └── XEDParse
│               ├── XEDParse_x64.a
│               ├── XEDParse_x64.lib
│               ├── XEDParse_x86.a
│               ├── XEDParse_x86.lib
│               └── XEDParse.h
├── include
│   └── nlohmann
│       ├── adl_serializer.hpp
│       ├── byte_container_with_subtype.hpp
│       ├── detail
│       │   ├── abi_macros.hpp
│       │   ├── conversions
│       │   │   ├── from_json.hpp
│       │   │   ├── to_chars.hpp
│       │   │   └── to_json.hpp
│       │   ├── exceptions.hpp
│       │   ├── hash.hpp
│       │   ├── input
│       │   │   ├── binary_reader.hpp
│       │   │   ├── input_adapters.hpp
│       │   │   ├── json_sax.hpp
│       │   │   ├── lexer.hpp
│       │   │   ├── parser.hpp
│       │   │   └── position_t.hpp
│       │   ├── iterators
│       │   │   ├── internal_iterator.hpp
│       │   │   ├── iter_impl.hpp
│       │   │   ├── iteration_proxy.hpp
│       │   │   ├── iterator_traits.hpp
│       │   │   ├── json_reverse_iterator.hpp
│       │   │   └── primitive_iterator.hpp
│       │   ├── json_custom_base_class.hpp
│       │   ├── json_pointer.hpp
│       │   ├── json_ref.hpp
│       │   ├── macro_scope.hpp
│       │   ├── macro_unscope.hpp
│       │   ├── meta
│       │   │   ├── call_std
│       │   │   │   ├── begin.hpp
│       │   │   │   └── end.hpp
│       │   │   ├── cpp_future.hpp
│       │   │   ├── detected.hpp
│       │   │   ├── identity_tag.hpp
│       │   │   ├── is_sax.hpp
│       │   │   ├── std_fs.hpp
│       │   │   ├── type_traits.hpp
│       │   │   └── void_t.hpp
│       │   ├── output
│       │   │   ├── binary_writer.hpp
│       │   │   ├── output_adapters.hpp
│       │   │   └── serializer.hpp
│       │   ├── string_concat.hpp
│       │   ├── string_escape.hpp
│       │   └── value_t.hpp
│       ├── json_fwd.hpp
│       ├── json.hpp
│       ├── ordered_map.hpp
│       └── thirdparty
│           └── hedley
│               ├── hedley_undef.hpp
│               └── hedley.hpp
├── README.md
├── Showcase.gif
├── side profile of a voxel spider walking.jpg
└── src
    ├── MCPx64dbg.cpp
    └── x64dbg.py
```

# Files

--------------------------------------------------------------------------------
/deps/pluginsdk/nlohmann/detail/conversions/to_json.hpp:
--------------------------------------------------------------------------------

```
  1 | //     __ _____ _____ _____
  2 | //  __|  |   __|     |   | |  JSON for Modern C++
  3 | // |  |  |__   |  |  | | | |  version 3.11.3
  4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  5 | //
  6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7 | // SPDX-License-Identifier: MIT
  8 | 
  9 | #pragma once
 10 | 
 11 | #include <algorithm> // copy
 12 | #include <iterator> // begin, end
 13 | #include <string> // string
 14 | #include <tuple> // tuple, get
 15 | #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
 16 | #include <utility> // move, forward, declval, pair
 17 | #include <valarray> // valarray
 18 | #include <vector> // vector
 19 | 
 20 | #include <nlohmann/detail/iterators/iteration_proxy.hpp>
 21 | #include <nlohmann/detail/macro_scope.hpp>
 22 | #include <nlohmann/detail/meta/cpp_future.hpp>
 23 | #include <nlohmann/detail/meta/std_fs.hpp>
 24 | #include <nlohmann/detail/meta/type_traits.hpp>
 25 | #include <nlohmann/detail/value_t.hpp>
 26 | 
 27 | NLOHMANN_JSON_NAMESPACE_BEGIN
 28 | namespace detail
 29 | {
 30 | 
 31 | //////////////////
 32 | // constructors //
 33 | //////////////////
 34 | 
 35 | /*
 36 |  * Note all external_constructor<>::construct functions need to call
 37 |  * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
 38 |  * allocated value (e.g., a string). See bug issue
 39 |  * https://github.com/nlohmann/json/issues/2865 for more information.
 40 |  */
 41 | 
 42 | template<value_t> struct external_constructor;
 43 | 
 44 | template<>
 45 | struct external_constructor<value_t::boolean>
 46 | {
 47 |     template<typename BasicJsonType>
 48 |     static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
 49 |     {
 50 |         j.m_data.m_value.destroy(j.m_data.m_type);
 51 |         j.m_data.m_type = value_t::boolean;
 52 |         j.m_data.m_value = b;
 53 |         j.assert_invariant();
 54 |     }
 55 | };
 56 | 
 57 | template<>
 58 | struct external_constructor<value_t::string>
 59 | {
 60 |     template<typename BasicJsonType>
 61 |     static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
 62 |     {
 63 |         j.m_data.m_value.destroy(j.m_data.m_type);
 64 |         j.m_data.m_type = value_t::string;
 65 |         j.m_data.m_value = s;
 66 |         j.assert_invariant();
 67 |     }
 68 | 
 69 |     template<typename BasicJsonType>
 70 |     static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
 71 |     {
 72 |         j.m_data.m_value.destroy(j.m_data.m_type);
 73 |         j.m_data.m_type = value_t::string;
 74 |         j.m_data.m_value = std::move(s);
 75 |         j.assert_invariant();
 76 |     }
 77 | 
 78 |     template < typename BasicJsonType, typename CompatibleStringType,
 79 |                enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
 80 |                              int > = 0 >
 81 |     static void construct(BasicJsonType& j, const CompatibleStringType& str)
 82 |     {
 83 |         j.m_data.m_value.destroy(j.m_data.m_type);
 84 |         j.m_data.m_type = value_t::string;
 85 |         j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
 86 |         j.assert_invariant();
 87 |     }
 88 | };
 89 | 
 90 | template<>
 91 | struct external_constructor<value_t::binary>
 92 | {
 93 |     template<typename BasicJsonType>
 94 |     static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
 95 |     {
 96 |         j.m_data.m_value.destroy(j.m_data.m_type);
 97 |         j.m_data.m_type = value_t::binary;
 98 |         j.m_data.m_value = typename BasicJsonType::binary_t(b);
 99 |         j.assert_invariant();
100 |     }
101 | 
102 |     template<typename BasicJsonType>
103 |     static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
104 |     {
105 |         j.m_data.m_value.destroy(j.m_data.m_type);
106 |         j.m_data.m_type = value_t::binary;
107 |         j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
108 |         j.assert_invariant();
109 |     }
110 | };
111 | 
112 | template<>
113 | struct external_constructor<value_t::number_float>
114 | {
115 |     template<typename BasicJsonType>
116 |     static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
117 |     {
118 |         j.m_data.m_value.destroy(j.m_data.m_type);
119 |         j.m_data.m_type = value_t::number_float;
120 |         j.m_data.m_value = val;
121 |         j.assert_invariant();
122 |     }
123 | };
124 | 
125 | template<>
126 | struct external_constructor<value_t::number_unsigned>
127 | {
128 |     template<typename BasicJsonType>
129 |     static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
130 |     {
131 |         j.m_data.m_value.destroy(j.m_data.m_type);
132 |         j.m_data.m_type = value_t::number_unsigned;
133 |         j.m_data.m_value = val;
134 |         j.assert_invariant();
135 |     }
136 | };
137 | 
138 | template<>
139 | struct external_constructor<value_t::number_integer>
140 | {
141 |     template<typename BasicJsonType>
142 |     static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
143 |     {
144 |         j.m_data.m_value.destroy(j.m_data.m_type);
145 |         j.m_data.m_type = value_t::number_integer;
146 |         j.m_data.m_value = val;
147 |         j.assert_invariant();
148 |     }
149 | };
150 | 
151 | template<>
152 | struct external_constructor<value_t::array>
153 | {
154 |     template<typename BasicJsonType>
155 |     static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
156 |     {
157 |         j.m_data.m_value.destroy(j.m_data.m_type);
158 |         j.m_data.m_type = value_t::array;
159 |         j.m_data.m_value = arr;
160 |         j.set_parents();
161 |         j.assert_invariant();
162 |     }
163 | 
164 |     template<typename BasicJsonType>
165 |     static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
166 |     {
167 |         j.m_data.m_value.destroy(j.m_data.m_type);
168 |         j.m_data.m_type = value_t::array;
169 |         j.m_data.m_value = std::move(arr);
170 |         j.set_parents();
171 |         j.assert_invariant();
172 |     }
173 | 
174 |     template < typename BasicJsonType, typename CompatibleArrayType,
175 |                enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
176 |                              int > = 0 >
177 |     static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
178 |     {
179 |         using std::begin;
180 |         using std::end;
181 | 
182 |         j.m_data.m_value.destroy(j.m_data.m_type);
183 |         j.m_data.m_type = value_t::array;
184 |         j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
185 |         j.set_parents();
186 |         j.assert_invariant();
187 |     }
188 | 
189 |     template<typename BasicJsonType>
190 |     static void construct(BasicJsonType& j, const std::vector<bool>& arr)
191 |     {
192 |         j.m_data.m_value.destroy(j.m_data.m_type);
193 |         j.m_data.m_type = value_t::array;
194 |         j.m_data.m_value = value_t::array;
195 |         j.m_data.m_value.array->reserve(arr.size());
196 |         for (const bool x : arr)
197 |         {
198 |             j.m_data.m_value.array->push_back(x);
199 |             j.set_parent(j.m_data.m_value.array->back());
200 |         }
201 |         j.assert_invariant();
202 |     }
203 | 
204 |     template<typename BasicJsonType, typename T,
205 |              enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
206 |     static void construct(BasicJsonType& j, const std::valarray<T>& arr)
207 |     {
208 |         j.m_data.m_value.destroy(j.m_data.m_type);
209 |         j.m_data.m_type = value_t::array;
210 |         j.m_data.m_value = value_t::array;
211 |         j.m_data.m_value.array->resize(arr.size());
212 |         if (arr.size() > 0)
213 |         {
214 |             std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
215 |         }
216 |         j.set_parents();
217 |         j.assert_invariant();
218 |     }
219 | };
220 | 
221 | template<>
222 | struct external_constructor<value_t::object>
223 | {
224 |     template<typename BasicJsonType>
225 |     static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
226 |     {
227 |         j.m_data.m_value.destroy(j.m_data.m_type);
228 |         j.m_data.m_type = value_t::object;
229 |         j.m_data.m_value = obj;
230 |         j.set_parents();
231 |         j.assert_invariant();
232 |     }
233 | 
234 |     template<typename BasicJsonType>
235 |     static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
236 |     {
237 |         j.m_data.m_value.destroy(j.m_data.m_type);
238 |         j.m_data.m_type = value_t::object;
239 |         j.m_data.m_value = std::move(obj);
240 |         j.set_parents();
241 |         j.assert_invariant();
242 |     }
243 | 
244 |     template < typename BasicJsonType, typename CompatibleObjectType,
245 |                enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
246 |     static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
247 |     {
248 |         using std::begin;
249 |         using std::end;
250 | 
251 |         j.m_data.m_value.destroy(j.m_data.m_type);
252 |         j.m_data.m_type = value_t::object;
253 |         j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
254 |         j.set_parents();
255 |         j.assert_invariant();
256 |     }
257 | };
258 | 
259 | /////////////
260 | // to_json //
261 | /////////////
262 | 
263 | template<typename BasicJsonType, typename T,
264 |          enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
265 | inline void to_json(BasicJsonType& j, T b) noexcept
266 | {
267 |     external_constructor<value_t::boolean>::construct(j, b);
268 | }
269 | 
270 | template < typename BasicJsonType, typename BoolRef,
271 |            enable_if_t <
272 |                ((std::is_same<std::vector<bool>::reference, BoolRef>::value
273 |                  && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
274 |                 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
275 |                     && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
276 |                                       typename BasicJsonType::boolean_t >::value))
277 |                && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
278 | inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
279 | {
280 |     external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
281 | }
282 | 
283 | template<typename BasicJsonType, typename CompatibleString,
284 |          enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
285 | inline void to_json(BasicJsonType& j, const CompatibleString& s)
286 | {
287 |     external_constructor<value_t::string>::construct(j, s);
288 | }
289 | 
290 | template<typename BasicJsonType>
291 | inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
292 | {
293 |     external_constructor<value_t::string>::construct(j, std::move(s));
294 | }
295 | 
296 | template<typename BasicJsonType, typename FloatType,
297 |          enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
298 | inline void to_json(BasicJsonType& j, FloatType val) noexcept
299 | {
300 |     external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
301 | }
302 | 
303 | template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
304 |          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
305 | inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
306 | {
307 |     external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
308 | }
309 | 
310 | template<typename BasicJsonType, typename CompatibleNumberIntegerType,
311 |          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
312 | inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
313 | {
314 |     external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
315 | }
316 | 
317 | #if !JSON_DISABLE_ENUM_SERIALIZATION
318 | template<typename BasicJsonType, typename EnumType,
319 |          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
320 | inline void to_json(BasicJsonType& j, EnumType e) noexcept
321 | {
322 |     using underlying_type = typename std::underlying_type<EnumType>::type;
323 |     external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
324 | }
325 | #endif  // JSON_DISABLE_ENUM_SERIALIZATION
326 | 
327 | template<typename BasicJsonType>
328 | inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
329 | {
330 |     external_constructor<value_t::array>::construct(j, e);
331 | }
332 | 
333 | template < typename BasicJsonType, typename CompatibleArrayType,
334 |            enable_if_t < is_compatible_array_type<BasicJsonType,
335 |                          CompatibleArrayType>::value&&
336 |                          !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
337 |                          !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
338 |                          !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
339 |                          !is_basic_json<CompatibleArrayType>::value,
340 |                          int > = 0 >
341 | inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
342 | {
343 |     external_constructor<value_t::array>::construct(j, arr);
344 | }
345 | 
346 | template<typename BasicJsonType>
347 | inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
348 | {
349 |     external_constructor<value_t::binary>::construct(j, bin);
350 | }
351 | 
352 | template<typename BasicJsonType, typename T,
353 |          enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
354 | inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
355 | {
356 |     external_constructor<value_t::array>::construct(j, std::move(arr));
357 | }
358 | 
359 | template<typename BasicJsonType>
360 | inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
361 | {
362 |     external_constructor<value_t::array>::construct(j, std::move(arr));
363 | }
364 | 
365 | template < typename BasicJsonType, typename CompatibleObjectType,
366 |            enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
367 | inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
368 | {
369 |     external_constructor<value_t::object>::construct(j, obj);
370 | }
371 | 
372 | template<typename BasicJsonType>
373 | inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
374 | {
375 |     external_constructor<value_t::object>::construct(j, std::move(obj));
376 | }
377 | 
378 | template <
379 |     typename BasicJsonType, typename T, std::size_t N,
380 |     enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
381 |                   const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
382 |                   int > = 0 >
383 | inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
384 | {
385 |     external_constructor<value_t::array>::construct(j, arr);
386 | }
387 | 
388 | template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
389 | inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
390 | {
391 |     j = { p.first, p.second };
392 | }
393 | 
394 | // for https://github.com/nlohmann/json/pull/1134
395 | template<typename BasicJsonType, typename T,
396 |          enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
397 | inline void to_json(BasicJsonType& j, const T& b)
398 | {
399 |     j = { {b.key(), b.value()} };
400 | }
401 | 
402 | template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
403 | inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
404 | {
405 |     j = { std::get<Idx>(t)... };
406 | }
407 | 
408 | template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
409 | inline void to_json(BasicJsonType& j, const T& t)
410 | {
411 |     to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
412 | }
413 | 
414 | #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
415 | template<typename BasicJsonType>
416 | inline void to_json(BasicJsonType& j, const std_fs::path& p)
417 | {
418 |     j = p.string();
419 | }
420 | #endif
421 | 
422 | struct to_json_fn
423 | {
424 |     template<typename BasicJsonType, typename T>
425 |     auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
426 |     -> decltype(to_json(j, std::forward<T>(val)), void())
427 |     {
428 |         return to_json(j, std::forward<T>(val));
429 |     }
430 | };
431 | }  // namespace detail
432 | 
433 | #ifndef JSON_HAS_CPP_17
434 | /// namespace to hold default `to_json` function
435 | /// to see why this is required:
436 | /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
437 | namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
438 | {
439 | #endif
440 | JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
441 |     detail::static_const<detail::to_json_fn>::value;
442 | #ifndef JSON_HAS_CPP_17
443 | }  // namespace
444 | #endif
445 | 
446 | NLOHMANN_JSON_NAMESPACE_END
447 | 
```

--------------------------------------------------------------------------------
/include/nlohmann/detail/conversions/to_json.hpp:
--------------------------------------------------------------------------------

```
  1 | //     __ _____ _____ _____
  2 | //  __|  |   __|     |   | |  JSON for Modern C++
  3 | // |  |  |__   |  |  | | | |  version 3.11.3
  4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  5 | //
  6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7 | // SPDX-License-Identifier: MIT
  8 | 
  9 | #pragma once
 10 | 
 11 | #include <algorithm> // copy
 12 | #include <iterator> // begin, end
 13 | #include <string> // string
 14 | #include <tuple> // tuple, get
 15 | #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
 16 | #include <utility> // move, forward, declval, pair
 17 | #include <valarray> // valarray
 18 | #include <vector> // vector
 19 | 
 20 | #include <nlohmann/detail/iterators/iteration_proxy.hpp>
 21 | #include <nlohmann/detail/macro_scope.hpp>
 22 | #include <nlohmann/detail/meta/cpp_future.hpp>
 23 | #include <nlohmann/detail/meta/std_fs.hpp>
 24 | #include <nlohmann/detail/meta/type_traits.hpp>
 25 | #include <nlohmann/detail/value_t.hpp>
 26 | 
 27 | NLOHMANN_JSON_NAMESPACE_BEGIN
 28 | namespace detail
 29 | {
 30 | 
 31 | //////////////////
 32 | // constructors //
 33 | //////////////////
 34 | 
 35 | /*
 36 |  * Note all external_constructor<>::construct functions need to call
 37 |  * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
 38 |  * allocated value (e.g., a string). See bug issue
 39 |  * https://github.com/nlohmann/json/issues/2865 for more information.
 40 |  */
 41 | 
 42 | template<value_t> struct external_constructor;
 43 | 
 44 | template<>
 45 | struct external_constructor<value_t::boolean>
 46 | {
 47 |     template<typename BasicJsonType>
 48 |     static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
 49 |     {
 50 |         j.m_data.m_value.destroy(j.m_data.m_type);
 51 |         j.m_data.m_type = value_t::boolean;
 52 |         j.m_data.m_value = b;
 53 |         j.assert_invariant();
 54 |     }
 55 | };
 56 | 
 57 | template<>
 58 | struct external_constructor<value_t::string>
 59 | {
 60 |     template<typename BasicJsonType>
 61 |     static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
 62 |     {
 63 |         j.m_data.m_value.destroy(j.m_data.m_type);
 64 |         j.m_data.m_type = value_t::string;
 65 |         j.m_data.m_value = s;
 66 |         j.assert_invariant();
 67 |     }
 68 | 
 69 |     template<typename BasicJsonType>
 70 |     static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
 71 |     {
 72 |         j.m_data.m_value.destroy(j.m_data.m_type);
 73 |         j.m_data.m_type = value_t::string;
 74 |         j.m_data.m_value = std::move(s);
 75 |         j.assert_invariant();
 76 |     }
 77 | 
 78 |     template < typename BasicJsonType, typename CompatibleStringType,
 79 |                enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
 80 |                              int > = 0 >
 81 |     static void construct(BasicJsonType& j, const CompatibleStringType& str)
 82 |     {
 83 |         j.m_data.m_value.destroy(j.m_data.m_type);
 84 |         j.m_data.m_type = value_t::string;
 85 |         j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
 86 |         j.assert_invariant();
 87 |     }
 88 | };
 89 | 
 90 | template<>
 91 | struct external_constructor<value_t::binary>
 92 | {
 93 |     template<typename BasicJsonType>
 94 |     static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
 95 |     {
 96 |         j.m_data.m_value.destroy(j.m_data.m_type);
 97 |         j.m_data.m_type = value_t::binary;
 98 |         j.m_data.m_value = typename BasicJsonType::binary_t(b);
 99 |         j.assert_invariant();
100 |     }
101 | 
102 |     template<typename BasicJsonType>
103 |     static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
104 |     {
105 |         j.m_data.m_value.destroy(j.m_data.m_type);
106 |         j.m_data.m_type = value_t::binary;
107 |         j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
108 |         j.assert_invariant();
109 |     }
110 | };
111 | 
112 | template<>
113 | struct external_constructor<value_t::number_float>
114 | {
115 |     template<typename BasicJsonType>
116 |     static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
117 |     {
118 |         j.m_data.m_value.destroy(j.m_data.m_type);
119 |         j.m_data.m_type = value_t::number_float;
120 |         j.m_data.m_value = val;
121 |         j.assert_invariant();
122 |     }
123 | };
124 | 
125 | template<>
126 | struct external_constructor<value_t::number_unsigned>
127 | {
128 |     template<typename BasicJsonType>
129 |     static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
130 |     {
131 |         j.m_data.m_value.destroy(j.m_data.m_type);
132 |         j.m_data.m_type = value_t::number_unsigned;
133 |         j.m_data.m_value = val;
134 |         j.assert_invariant();
135 |     }
136 | };
137 | 
138 | template<>
139 | struct external_constructor<value_t::number_integer>
140 | {
141 |     template<typename BasicJsonType>
142 |     static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
143 |     {
144 |         j.m_data.m_value.destroy(j.m_data.m_type);
145 |         j.m_data.m_type = value_t::number_integer;
146 |         j.m_data.m_value = val;
147 |         j.assert_invariant();
148 |     }
149 | };
150 | 
151 | template<>
152 | struct external_constructor<value_t::array>
153 | {
154 |     template<typename BasicJsonType>
155 |     static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
156 |     {
157 |         j.m_data.m_value.destroy(j.m_data.m_type);
158 |         j.m_data.m_type = value_t::array;
159 |         j.m_data.m_value = arr;
160 |         j.set_parents();
161 |         j.assert_invariant();
162 |     }
163 | 
164 |     template<typename BasicJsonType>
165 |     static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
166 |     {
167 |         j.m_data.m_value.destroy(j.m_data.m_type);
168 |         j.m_data.m_type = value_t::array;
169 |         j.m_data.m_value = std::move(arr);
170 |         j.set_parents();
171 |         j.assert_invariant();
172 |     }
173 | 
174 |     template < typename BasicJsonType, typename CompatibleArrayType,
175 |                enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
176 |                              int > = 0 >
177 |     static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
178 |     {
179 |         using std::begin;
180 |         using std::end;
181 | 
182 |         j.m_data.m_value.destroy(j.m_data.m_type);
183 |         j.m_data.m_type = value_t::array;
184 |         j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
185 |         j.set_parents();
186 |         j.assert_invariant();
187 |     }
188 | 
189 |     template<typename BasicJsonType>
190 |     static void construct(BasicJsonType& j, const std::vector<bool>& arr)
191 |     {
192 |         j.m_data.m_value.destroy(j.m_data.m_type);
193 |         j.m_data.m_type = value_t::array;
194 |         j.m_data.m_value = value_t::array;
195 |         j.m_data.m_value.array->reserve(arr.size());
196 |         for (const bool x : arr)
197 |         {
198 |             j.m_data.m_value.array->push_back(x);
199 |             j.set_parent(j.m_data.m_value.array->back());
200 |         }
201 |         j.assert_invariant();
202 |     }
203 | 
204 |     template<typename BasicJsonType, typename T,
205 |              enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
206 |     static void construct(BasicJsonType& j, const std::valarray<T>& arr)
207 |     {
208 |         j.m_data.m_value.destroy(j.m_data.m_type);
209 |         j.m_data.m_type = value_t::array;
210 |         j.m_data.m_value = value_t::array;
211 |         j.m_data.m_value.array->resize(arr.size());
212 |         if (arr.size() > 0)
213 |         {
214 |             std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
215 |         }
216 |         j.set_parents();
217 |         j.assert_invariant();
218 |     }
219 | };
220 | 
221 | template<>
222 | struct external_constructor<value_t::object>
223 | {
224 |     template<typename BasicJsonType>
225 |     static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
226 |     {
227 |         j.m_data.m_value.destroy(j.m_data.m_type);
228 |         j.m_data.m_type = value_t::object;
229 |         j.m_data.m_value = obj;
230 |         j.set_parents();
231 |         j.assert_invariant();
232 |     }
233 | 
234 |     template<typename BasicJsonType>
235 |     static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
236 |     {
237 |         j.m_data.m_value.destroy(j.m_data.m_type);
238 |         j.m_data.m_type = value_t::object;
239 |         j.m_data.m_value = std::move(obj);
240 |         j.set_parents();
241 |         j.assert_invariant();
242 |     }
243 | 
244 |     template < typename BasicJsonType, typename CompatibleObjectType,
245 |                enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
246 |     static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
247 |     {
248 |         using std::begin;
249 |         using std::end;
250 | 
251 |         j.m_data.m_value.destroy(j.m_data.m_type);
252 |         j.m_data.m_type = value_t::object;
253 |         j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
254 |         j.set_parents();
255 |         j.assert_invariant();
256 |     }
257 | };
258 | 
259 | /////////////
260 | // to_json //
261 | /////////////
262 | 
263 | template<typename BasicJsonType, typename T,
264 |          enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
265 | inline void to_json(BasicJsonType& j, T b) noexcept
266 | {
267 |     external_constructor<value_t::boolean>::construct(j, b);
268 | }
269 | 
270 | template < typename BasicJsonType, typename BoolRef,
271 |            enable_if_t <
272 |                ((std::is_same<std::vector<bool>::reference, BoolRef>::value
273 |                  && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
274 |                 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
275 |                     && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
276 |                                       typename BasicJsonType::boolean_t >::value))
277 |                && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
278 | inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
279 | {
280 |     external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
281 | }
282 | 
283 | template<typename BasicJsonType, typename CompatibleString,
284 |          enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
285 | inline void to_json(BasicJsonType& j, const CompatibleString& s)
286 | {
287 |     external_constructor<value_t::string>::construct(j, s);
288 | }
289 | 
290 | template<typename BasicJsonType>
291 | inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
292 | {
293 |     external_constructor<value_t::string>::construct(j, std::move(s));
294 | }
295 | 
296 | template<typename BasicJsonType, typename FloatType,
297 |          enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
298 | inline void to_json(BasicJsonType& j, FloatType val) noexcept
299 | {
300 |     external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
301 | }
302 | 
303 | template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
304 |          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
305 | inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
306 | {
307 |     external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
308 | }
309 | 
310 | template<typename BasicJsonType, typename CompatibleNumberIntegerType,
311 |          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
312 | inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
313 | {
314 |     external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
315 | }
316 | 
317 | #if !JSON_DISABLE_ENUM_SERIALIZATION
318 | template<typename BasicJsonType, typename EnumType,
319 |          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
320 | inline void to_json(BasicJsonType& j, EnumType e) noexcept
321 | {
322 |     using underlying_type = typename std::underlying_type<EnumType>::type;
323 |     external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
324 | }
325 | #endif  // JSON_DISABLE_ENUM_SERIALIZATION
326 | 
327 | template<typename BasicJsonType>
328 | inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
329 | {
330 |     external_constructor<value_t::array>::construct(j, e);
331 | }
332 | 
333 | template < typename BasicJsonType, typename CompatibleArrayType,
334 |            enable_if_t < is_compatible_array_type<BasicJsonType,
335 |                          CompatibleArrayType>::value&&
336 |                          !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
337 |                          !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
338 |                          !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
339 |                          !is_basic_json<CompatibleArrayType>::value,
340 |                          int > = 0 >
341 | inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
342 | {
343 |     external_constructor<value_t::array>::construct(j, arr);
344 | }
345 | 
346 | template<typename BasicJsonType>
347 | inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
348 | {
349 |     external_constructor<value_t::binary>::construct(j, bin);
350 | }
351 | 
352 | template<typename BasicJsonType, typename T,
353 |          enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
354 | inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
355 | {
356 |     external_constructor<value_t::array>::construct(j, std::move(arr));
357 | }
358 | 
359 | template<typename BasicJsonType>
360 | inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
361 | {
362 |     external_constructor<value_t::array>::construct(j, std::move(arr));
363 | }
364 | 
365 | template < typename BasicJsonType, typename CompatibleObjectType,
366 |            enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
367 | inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
368 | {
369 |     external_constructor<value_t::object>::construct(j, obj);
370 | }
371 | 
372 | template<typename BasicJsonType>
373 | inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
374 | {
375 |     external_constructor<value_t::object>::construct(j, std::move(obj));
376 | }
377 | 
378 | template <
379 |     typename BasicJsonType, typename T, std::size_t N,
380 |     enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
381 |                   const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
382 |                   int > = 0 >
383 | inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
384 | {
385 |     external_constructor<value_t::array>::construct(j, arr);
386 | }
387 | 
388 | template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
389 | inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
390 | {
391 |     j = { p.first, p.second };
392 | }
393 | 
394 | // for https://github.com/nlohmann/json/pull/1134
395 | template<typename BasicJsonType, typename T,
396 |          enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
397 | inline void to_json(BasicJsonType& j, const T& b)
398 | {
399 |     j = { {b.key(), b.value()} };
400 | }
401 | 
402 | template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
403 | inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
404 | {
405 |     j = { std::get<Idx>(t)... };
406 | }
407 | 
408 | template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
409 | inline void to_json(BasicJsonType& j, const T& t)
410 | {
411 |     to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
412 | }
413 | 
414 | #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
415 | template<typename BasicJsonType>
416 | inline void to_json(BasicJsonType& j, const std_fs::path& p)
417 | {
418 |     j = p.string();
419 | }
420 | #endif
421 | 
422 | struct to_json_fn
423 | {
424 |     template<typename BasicJsonType, typename T>
425 |     auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
426 |     -> decltype(to_json(j, std::forward<T>(val)), void())
427 |     {
428 |         return to_json(j, std::forward<T>(val));
429 |     }
430 | };
431 | }  // namespace detail
432 | 
433 | #ifndef JSON_HAS_CPP_17
434 | /// namespace to hold default `to_json` function
435 | /// to see why this is required:
436 | /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
437 | namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
438 | {
439 | #endif
440 | JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
441 |     detail::static_const<detail::to_json_fn>::value;
442 | #ifndef JSON_HAS_CPP_17
443 | }  // namespace
444 | #endif
445 | 
446 | NLOHMANN_JSON_NAMESPACE_END
447 | 
```

--------------------------------------------------------------------------------
/deps/pluginsdk/nlohmann/detail/input/input_adapters.hpp:
--------------------------------------------------------------------------------

```
  1 | //     __ _____ _____ _____
  2 | //  __|  |   __|     |   | |  JSON for Modern C++
  3 | // |  |  |__   |  |  | | | |  version 3.11.3
  4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  5 | //
  6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7 | // SPDX-License-Identifier: MIT
  8 | 
  9 | #pragma once
 10 | 
 11 | #include <array> // array
 12 | #include <cstddef> // size_t
 13 | #include <cstring> // strlen
 14 | #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
 15 | #include <memory> // shared_ptr, make_shared, addressof
 16 | #include <numeric> // accumulate
 17 | #include <string> // string, char_traits
 18 | #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
 19 | #include <utility> // pair, declval
 20 | 
 21 | #ifndef JSON_NO_IO
 22 |     #include <cstdio>   // FILE *
 23 |     #include <istream>  // istream
 24 | #endif                  // JSON_NO_IO
 25 | 
 26 | #include <nlohmann/detail/iterators/iterator_traits.hpp>
 27 | #include <nlohmann/detail/macro_scope.hpp>
 28 | #include <nlohmann/detail/meta/type_traits.hpp>
 29 | 
 30 | NLOHMANN_JSON_NAMESPACE_BEGIN
 31 | namespace detail
 32 | {
 33 | 
 34 | /// the supported input formats
 35 | enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
 36 | 
 37 | ////////////////////
 38 | // input adapters //
 39 | ////////////////////
 40 | 
 41 | #ifndef JSON_NO_IO
 42 | /*!
 43 | Input adapter for stdio file access. This adapter read only 1 byte and do not use any
 44 |  buffer. This adapter is a very low level adapter.
 45 | */
 46 | class file_input_adapter
 47 | {
 48 |   public:
 49 |     using char_type = char;
 50 | 
 51 |     JSON_HEDLEY_NON_NULL(2)
 52 |     explicit file_input_adapter(std::FILE* f) noexcept
 53 |         : m_file(f)
 54 |     {
 55 |         JSON_ASSERT(m_file != nullptr);
 56 |     }
 57 | 
 58 |     // make class move-only
 59 |     file_input_adapter(const file_input_adapter&) = delete;
 60 |     file_input_adapter(file_input_adapter&&) noexcept = default;
 61 |     file_input_adapter& operator=(const file_input_adapter&) = delete;
 62 |     file_input_adapter& operator=(file_input_adapter&&) = delete;
 63 |     ~file_input_adapter() = default;
 64 | 
 65 |     std::char_traits<char>::int_type get_character() noexcept
 66 |     {
 67 |         return std::fgetc(m_file);
 68 |     }
 69 | 
 70 |   private:
 71 |     /// the file pointer to read from
 72 |     std::FILE* m_file;
 73 | };
 74 | 
 75 | /*!
 76 | Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
 77 | beginning of input. Does not support changing the underlying std::streambuf
 78 | in mid-input. Maintains underlying std::istream and std::streambuf to support
 79 | subsequent use of standard std::istream operations to process any input
 80 | characters following those used in parsing the JSON input.  Clears the
 81 | std::istream flags; any input errors (e.g., EOF) will be detected by the first
 82 | subsequent call for input from the std::istream.
 83 | */
 84 | class input_stream_adapter
 85 | {
 86 |   public:
 87 |     using char_type = char;
 88 | 
 89 |     ~input_stream_adapter()
 90 |     {
 91 |         // clear stream flags; we use underlying streambuf I/O, do not
 92 |         // maintain ifstream flags, except eof
 93 |         if (is != nullptr)
 94 |         {
 95 |             is->clear(is->rdstate() & std::ios::eofbit);
 96 |         }
 97 |     }
 98 | 
 99 |     explicit input_stream_adapter(std::istream& i)
100 |         : is(&i), sb(i.rdbuf())
101 |     {}
102 | 
103 |     // delete because of pointer members
104 |     input_stream_adapter(const input_stream_adapter&) = delete;
105 |     input_stream_adapter& operator=(input_stream_adapter&) = delete;
106 |     input_stream_adapter& operator=(input_stream_adapter&&) = delete;
107 | 
108 |     input_stream_adapter(input_stream_adapter&& rhs) noexcept
109 |         : is(rhs.is), sb(rhs.sb)
110 |     {
111 |         rhs.is = nullptr;
112 |         rhs.sb = nullptr;
113 |     }
114 | 
115 |     // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
116 |     // ensure that std::char_traits<char>::eof() and the character 0xFF do not
117 |     // end up as the same value, e.g. 0xFFFFFFFF.
118 |     std::char_traits<char>::int_type get_character()
119 |     {
120 |         auto res = sb->sbumpc();
121 |         // set eof manually, as we don't use the istream interface.
122 |         if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
123 |         {
124 |             is->clear(is->rdstate() | std::ios::eofbit);
125 |         }
126 |         return res;
127 |     }
128 | 
129 |   private:
130 |     /// the associated input stream
131 |     std::istream* is = nullptr;
132 |     std::streambuf* sb = nullptr;
133 | };
134 | #endif  // JSON_NO_IO
135 | 
136 | // General-purpose iterator-based adapter. It might not be as fast as
137 | // theoretically possible for some containers, but it is extremely versatile.
138 | template<typename IteratorType>
139 | class iterator_input_adapter
140 | {
141 |   public:
142 |     using char_type = typename std::iterator_traits<IteratorType>::value_type;
143 | 
144 |     iterator_input_adapter(IteratorType first, IteratorType last)
145 |         : current(std::move(first)), end(std::move(last))
146 |     {}
147 | 
148 |     typename char_traits<char_type>::int_type get_character()
149 |     {
150 |         if (JSON_HEDLEY_LIKELY(current != end))
151 |         {
152 |             auto result = char_traits<char_type>::to_int_type(*current);
153 |             std::advance(current, 1);
154 |             return result;
155 |         }
156 | 
157 |         return char_traits<char_type>::eof();
158 |     }
159 | 
160 |   private:
161 |     IteratorType current;
162 |     IteratorType end;
163 | 
164 |     template<typename BaseInputAdapter, size_t T>
165 |     friend struct wide_string_input_helper;
166 | 
167 |     bool empty() const
168 |     {
169 |         return current == end;
170 |     }
171 | };
172 | 
173 | template<typename BaseInputAdapter, size_t T>
174 | struct wide_string_input_helper;
175 | 
176 | template<typename BaseInputAdapter>
177 | struct wide_string_input_helper<BaseInputAdapter, 4>
178 | {
179 |     // UTF-32
180 |     static void fill_buffer(BaseInputAdapter& input,
181 |                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
182 |                             size_t& utf8_bytes_index,
183 |                             size_t& utf8_bytes_filled)
184 |     {
185 |         utf8_bytes_index = 0;
186 | 
187 |         if (JSON_HEDLEY_UNLIKELY(input.empty()))
188 |         {
189 |             utf8_bytes[0] = std::char_traits<char>::eof();
190 |             utf8_bytes_filled = 1;
191 |         }
192 |         else
193 |         {
194 |             // get the current character
195 |             const auto wc = input.get_character();
196 | 
197 |             // UTF-32 to UTF-8 encoding
198 |             if (wc < 0x80)
199 |             {
200 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
201 |                 utf8_bytes_filled = 1;
202 |             }
203 |             else if (wc <= 0x7FF)
204 |             {
205 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
206 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
207 |                 utf8_bytes_filled = 2;
208 |             }
209 |             else if (wc <= 0xFFFF)
210 |             {
211 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
212 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
213 |                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
214 |                 utf8_bytes_filled = 3;
215 |             }
216 |             else if (wc <= 0x10FFFF)
217 |             {
218 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
219 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
220 |                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
221 |                 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
222 |                 utf8_bytes_filled = 4;
223 |             }
224 |             else
225 |             {
226 |                 // unknown character
227 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
228 |                 utf8_bytes_filled = 1;
229 |             }
230 |         }
231 |     }
232 | };
233 | 
234 | template<typename BaseInputAdapter>
235 | struct wide_string_input_helper<BaseInputAdapter, 2>
236 | {
237 |     // UTF-16
238 |     static void fill_buffer(BaseInputAdapter& input,
239 |                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
240 |                             size_t& utf8_bytes_index,
241 |                             size_t& utf8_bytes_filled)
242 |     {
243 |         utf8_bytes_index = 0;
244 | 
245 |         if (JSON_HEDLEY_UNLIKELY(input.empty()))
246 |         {
247 |             utf8_bytes[0] = std::char_traits<char>::eof();
248 |             utf8_bytes_filled = 1;
249 |         }
250 |         else
251 |         {
252 |             // get the current character
253 |             const auto wc = input.get_character();
254 | 
255 |             // UTF-16 to UTF-8 encoding
256 |             if (wc < 0x80)
257 |             {
258 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
259 |                 utf8_bytes_filled = 1;
260 |             }
261 |             else if (wc <= 0x7FF)
262 |             {
263 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
264 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
265 |                 utf8_bytes_filled = 2;
266 |             }
267 |             else if (0xD800 > wc || wc >= 0xE000)
268 |             {
269 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
270 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
271 |                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
272 |                 utf8_bytes_filled = 3;
273 |             }
274 |             else
275 |             {
276 |                 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
277 |                 {
278 |                     const auto wc2 = static_cast<unsigned int>(input.get_character());
279 |                     const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
280 |                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
281 |                     utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
282 |                     utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
283 |                     utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
284 |                     utf8_bytes_filled = 4;
285 |                 }
286 |                 else
287 |                 {
288 |                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
289 |                     utf8_bytes_filled = 1;
290 |                 }
291 |             }
292 |         }
293 |     }
294 | };
295 | 
296 | // Wraps another input adapter to convert wide character types into individual bytes.
297 | template<typename BaseInputAdapter, typename WideCharType>
298 | class wide_string_input_adapter
299 | {
300 |   public:
301 |     using char_type = char;
302 | 
303 |     wide_string_input_adapter(BaseInputAdapter base)
304 |         : base_adapter(base) {}
305 | 
306 |     typename std::char_traits<char>::int_type get_character() noexcept
307 |     {
308 |         // check if buffer needs to be filled
309 |         if (utf8_bytes_index == utf8_bytes_filled)
310 |         {
311 |             fill_buffer<sizeof(WideCharType)>();
312 | 
313 |             JSON_ASSERT(utf8_bytes_filled > 0);
314 |             JSON_ASSERT(utf8_bytes_index == 0);
315 |         }
316 | 
317 |         // use buffer
318 |         JSON_ASSERT(utf8_bytes_filled > 0);
319 |         JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
320 |         return utf8_bytes[utf8_bytes_index++];
321 |     }
322 | 
323 |   private:
324 |     BaseInputAdapter base_adapter;
325 | 
326 |     template<size_t T>
327 |     void fill_buffer()
328 |     {
329 |         wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
330 |     }
331 | 
332 |     /// a buffer for UTF-8 bytes
333 |     std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
334 | 
335 |     /// index to the utf8_codes array for the next valid byte
336 |     std::size_t utf8_bytes_index = 0;
337 |     /// number of valid bytes in the utf8_codes array
338 |     std::size_t utf8_bytes_filled = 0;
339 | };
340 | 
341 | template<typename IteratorType, typename Enable = void>
342 | struct iterator_input_adapter_factory
343 | {
344 |     using iterator_type = IteratorType;
345 |     using char_type = typename std::iterator_traits<iterator_type>::value_type;
346 |     using adapter_type = iterator_input_adapter<iterator_type>;
347 | 
348 |     static adapter_type create(IteratorType first, IteratorType last)
349 |     {
350 |         return adapter_type(std::move(first), std::move(last));
351 |     }
352 | };
353 | 
354 | template<typename T>
355 | struct is_iterator_of_multibyte
356 | {
357 |     using value_type = typename std::iterator_traits<T>::value_type;
358 |     enum
359 |     {
360 |         value = sizeof(value_type) > 1
361 |     };
362 | };
363 | 
364 | template<typename IteratorType>
365 | struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
366 | {
367 |     using iterator_type = IteratorType;
368 |     using char_type = typename std::iterator_traits<iterator_type>::value_type;
369 |     using base_adapter_type = iterator_input_adapter<iterator_type>;
370 |     using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
371 | 
372 |     static adapter_type create(IteratorType first, IteratorType last)
373 |     {
374 |         return adapter_type(base_adapter_type(std::move(first), std::move(last)));
375 |     }
376 | };
377 | 
378 | // General purpose iterator-based input
379 | template<typename IteratorType>
380 | typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
381 | {
382 |     using factory_type = iterator_input_adapter_factory<IteratorType>;
383 |     return factory_type::create(first, last);
384 | }
385 | 
386 | // Convenience shorthand from container to iterator
387 | // Enables ADL on begin(container) and end(container)
388 | // Encloses the using declarations in namespace for not to leak them to outside scope
389 | 
390 | namespace container_input_adapter_factory_impl
391 | {
392 | 
393 | using std::begin;
394 | using std::end;
395 | 
396 | template<typename ContainerType, typename Enable = void>
397 | struct container_input_adapter_factory {};
398 | 
399 | template<typename ContainerType>
400 | struct container_input_adapter_factory< ContainerType,
401 |        void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
402 |        {
403 |            using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
404 | 
405 |            static adapter_type create(const ContainerType& container)
406 | {
407 |     return input_adapter(begin(container), end(container));
408 | }
409 |        };
410 | 
411 | }  // namespace container_input_adapter_factory_impl
412 | 
413 | template<typename ContainerType>
414 | typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
415 | {
416 |     return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
417 | }
418 | 
419 | #ifndef JSON_NO_IO
420 | // Special cases with fast paths
421 | inline file_input_adapter input_adapter(std::FILE* file)
422 | {
423 |     return file_input_adapter(file);
424 | }
425 | 
426 | inline input_stream_adapter input_adapter(std::istream& stream)
427 | {
428 |     return input_stream_adapter(stream);
429 | }
430 | 
431 | inline input_stream_adapter input_adapter(std::istream&& stream)
432 | {
433 |     return input_stream_adapter(stream);
434 | }
435 | #endif  // JSON_NO_IO
436 | 
437 | using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
438 | 
439 | // Null-delimited strings, and the like.
440 | template < typename CharT,
441 |            typename std::enable_if <
442 |                std::is_pointer<CharT>::value&&
443 |                !std::is_array<CharT>::value&&
444 |                std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
445 |                sizeof(typename std::remove_pointer<CharT>::type) == 1,
446 |                int >::type = 0 >
447 | contiguous_bytes_input_adapter input_adapter(CharT b)
448 | {
449 |     auto length = std::strlen(reinterpret_cast<const char*>(b));
450 |     const auto* ptr = reinterpret_cast<const char*>(b);
451 |     return input_adapter(ptr, ptr + length);
452 | }
453 | 
454 | template<typename T, std::size_t N>
455 | auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
456 | {
457 |     return input_adapter(array, array + N);
458 | }
459 | 
460 | // This class only handles inputs of input_buffer_adapter type.
461 | // It's required so that expressions like {ptr, len} can be implicitly cast
462 | // to the correct adapter.
463 | class span_input_adapter
464 | {
465 |   public:
466 |     template < typename CharT,
467 |                typename std::enable_if <
468 |                    std::is_pointer<CharT>::value&&
469 |                    std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
470 |                    sizeof(typename std::remove_pointer<CharT>::type) == 1,
471 |                    int >::type = 0 >
472 |     span_input_adapter(CharT b, std::size_t l)
473 |         : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
474 | 
475 |     template<class IteratorType,
476 |              typename std::enable_if<
477 |                  std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
478 |                  int>::type = 0>
479 |     span_input_adapter(IteratorType first, IteratorType last)
480 |         : ia(input_adapter(first, last)) {}
481 | 
482 |     contiguous_bytes_input_adapter&& get()
483 |     {
484 |         return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
485 |     }
486 | 
487 |   private:
488 |     contiguous_bytes_input_adapter ia;
489 | };
490 | 
491 | }  // namespace detail
492 | NLOHMANN_JSON_NAMESPACE_END
493 | 
```

--------------------------------------------------------------------------------
/include/nlohmann/detail/input/input_adapters.hpp:
--------------------------------------------------------------------------------

```
  1 | //     __ _____ _____ _____
  2 | //  __|  |   __|     |   | |  JSON for Modern C++
  3 | // |  |  |__   |  |  | | | |  version 3.11.3
  4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  5 | //
  6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7 | // SPDX-License-Identifier: MIT
  8 | 
  9 | #pragma once
 10 | 
 11 | #include <array> // array
 12 | #include <cstddef> // size_t
 13 | #include <cstring> // strlen
 14 | #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
 15 | #include <memory> // shared_ptr, make_shared, addressof
 16 | #include <numeric> // accumulate
 17 | #include <string> // string, char_traits
 18 | #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
 19 | #include <utility> // pair, declval
 20 | 
 21 | #ifndef JSON_NO_IO
 22 |     #include <cstdio>   // FILE *
 23 |     #include <istream>  // istream
 24 | #endif                  // JSON_NO_IO
 25 | 
 26 | #include <nlohmann/detail/iterators/iterator_traits.hpp>
 27 | #include <nlohmann/detail/macro_scope.hpp>
 28 | #include <nlohmann/detail/meta/type_traits.hpp>
 29 | 
 30 | NLOHMANN_JSON_NAMESPACE_BEGIN
 31 | namespace detail
 32 | {
 33 | 
 34 | /// the supported input formats
 35 | enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
 36 | 
 37 | ////////////////////
 38 | // input adapters //
 39 | ////////////////////
 40 | 
 41 | #ifndef JSON_NO_IO
 42 | /*!
 43 | Input adapter for stdio file access. This adapter read only 1 byte and do not use any
 44 |  buffer. This adapter is a very low level adapter.
 45 | */
 46 | class file_input_adapter
 47 | {
 48 |   public:
 49 |     using char_type = char;
 50 | 
 51 |     JSON_HEDLEY_NON_NULL(2)
 52 |     explicit file_input_adapter(std::FILE* f) noexcept
 53 |         : m_file(f)
 54 |     {
 55 |         JSON_ASSERT(m_file != nullptr);
 56 |     }
 57 | 
 58 |     // make class move-only
 59 |     file_input_adapter(const file_input_adapter&) = delete;
 60 |     file_input_adapter(file_input_adapter&&) noexcept = default;
 61 |     file_input_adapter& operator=(const file_input_adapter&) = delete;
 62 |     file_input_adapter& operator=(file_input_adapter&&) = delete;
 63 |     ~file_input_adapter() = default;
 64 | 
 65 |     std::char_traits<char>::int_type get_character() noexcept
 66 |     {
 67 |         return std::fgetc(m_file);
 68 |     }
 69 | 
 70 |   private:
 71 |     /// the file pointer to read from
 72 |     std::FILE* m_file;
 73 | };
 74 | 
 75 | /*!
 76 | Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
 77 | beginning of input. Does not support changing the underlying std::streambuf
 78 | in mid-input. Maintains underlying std::istream and std::streambuf to support
 79 | subsequent use of standard std::istream operations to process any input
 80 | characters following those used in parsing the JSON input.  Clears the
 81 | std::istream flags; any input errors (e.g., EOF) will be detected by the first
 82 | subsequent call for input from the std::istream.
 83 | */
 84 | class input_stream_adapter
 85 | {
 86 |   public:
 87 |     using char_type = char;
 88 | 
 89 |     ~input_stream_adapter()
 90 |     {
 91 |         // clear stream flags; we use underlying streambuf I/O, do not
 92 |         // maintain ifstream flags, except eof
 93 |         if (is != nullptr)
 94 |         {
 95 |             is->clear(is->rdstate() & std::ios::eofbit);
 96 |         }
 97 |     }
 98 | 
 99 |     explicit input_stream_adapter(std::istream& i)
100 |         : is(&i), sb(i.rdbuf())
101 |     {}
102 | 
103 |     // delete because of pointer members
104 |     input_stream_adapter(const input_stream_adapter&) = delete;
105 |     input_stream_adapter& operator=(input_stream_adapter&) = delete;
106 |     input_stream_adapter& operator=(input_stream_adapter&&) = delete;
107 | 
108 |     input_stream_adapter(input_stream_adapter&& rhs) noexcept
109 |         : is(rhs.is), sb(rhs.sb)
110 |     {
111 |         rhs.is = nullptr;
112 |         rhs.sb = nullptr;
113 |     }
114 | 
115 |     // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
116 |     // ensure that std::char_traits<char>::eof() and the character 0xFF do not
117 |     // end up as the same value, e.g. 0xFFFFFFFF.
118 |     std::char_traits<char>::int_type get_character()
119 |     {
120 |         auto res = sb->sbumpc();
121 |         // set eof manually, as we don't use the istream interface.
122 |         if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
123 |         {
124 |             is->clear(is->rdstate() | std::ios::eofbit);
125 |         }
126 |         return res;
127 |     }
128 | 
129 |   private:
130 |     /// the associated input stream
131 |     std::istream* is = nullptr;
132 |     std::streambuf* sb = nullptr;
133 | };
134 | #endif  // JSON_NO_IO
135 | 
136 | // General-purpose iterator-based adapter. It might not be as fast as
137 | // theoretically possible for some containers, but it is extremely versatile.
138 | template<typename IteratorType>
139 | class iterator_input_adapter
140 | {
141 |   public:
142 |     using char_type = typename std::iterator_traits<IteratorType>::value_type;
143 | 
144 |     iterator_input_adapter(IteratorType first, IteratorType last)
145 |         : current(std::move(first)), end(std::move(last))
146 |     {}
147 | 
148 |     typename char_traits<char_type>::int_type get_character()
149 |     {
150 |         if (JSON_HEDLEY_LIKELY(current != end))
151 |         {
152 |             auto result = char_traits<char_type>::to_int_type(*current);
153 |             std::advance(current, 1);
154 |             return result;
155 |         }
156 | 
157 |         return char_traits<char_type>::eof();
158 |     }
159 | 
160 |   private:
161 |     IteratorType current;
162 |     IteratorType end;
163 | 
164 |     template<typename BaseInputAdapter, size_t T>
165 |     friend struct wide_string_input_helper;
166 | 
167 |     bool empty() const
168 |     {
169 |         return current == end;
170 |     }
171 | };
172 | 
173 | template<typename BaseInputAdapter, size_t T>
174 | struct wide_string_input_helper;
175 | 
176 | template<typename BaseInputAdapter>
177 | struct wide_string_input_helper<BaseInputAdapter, 4>
178 | {
179 |     // UTF-32
180 |     static void fill_buffer(BaseInputAdapter& input,
181 |                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
182 |                             size_t& utf8_bytes_index,
183 |                             size_t& utf8_bytes_filled)
184 |     {
185 |         utf8_bytes_index = 0;
186 | 
187 |         if (JSON_HEDLEY_UNLIKELY(input.empty()))
188 |         {
189 |             utf8_bytes[0] = std::char_traits<char>::eof();
190 |             utf8_bytes_filled = 1;
191 |         }
192 |         else
193 |         {
194 |             // get the current character
195 |             const auto wc = input.get_character();
196 | 
197 |             // UTF-32 to UTF-8 encoding
198 |             if (wc < 0x80)
199 |             {
200 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
201 |                 utf8_bytes_filled = 1;
202 |             }
203 |             else if (wc <= 0x7FF)
204 |             {
205 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
206 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
207 |                 utf8_bytes_filled = 2;
208 |             }
209 |             else if (wc <= 0xFFFF)
210 |             {
211 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
212 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
213 |                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
214 |                 utf8_bytes_filled = 3;
215 |             }
216 |             else if (wc <= 0x10FFFF)
217 |             {
218 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
219 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
220 |                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
221 |                 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
222 |                 utf8_bytes_filled = 4;
223 |             }
224 |             else
225 |             {
226 |                 // unknown character
227 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
228 |                 utf8_bytes_filled = 1;
229 |             }
230 |         }
231 |     }
232 | };
233 | 
234 | template<typename BaseInputAdapter>
235 | struct wide_string_input_helper<BaseInputAdapter, 2>
236 | {
237 |     // UTF-16
238 |     static void fill_buffer(BaseInputAdapter& input,
239 |                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
240 |                             size_t& utf8_bytes_index,
241 |                             size_t& utf8_bytes_filled)
242 |     {
243 |         utf8_bytes_index = 0;
244 | 
245 |         if (JSON_HEDLEY_UNLIKELY(input.empty()))
246 |         {
247 |             utf8_bytes[0] = std::char_traits<char>::eof();
248 |             utf8_bytes_filled = 1;
249 |         }
250 |         else
251 |         {
252 |             // get the current character
253 |             const auto wc = input.get_character();
254 | 
255 |             // UTF-16 to UTF-8 encoding
256 |             if (wc < 0x80)
257 |             {
258 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
259 |                 utf8_bytes_filled = 1;
260 |             }
261 |             else if (wc <= 0x7FF)
262 |             {
263 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
264 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
265 |                 utf8_bytes_filled = 2;
266 |             }
267 |             else if (0xD800 > wc || wc >= 0xE000)
268 |             {
269 |                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
270 |                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
271 |                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
272 |                 utf8_bytes_filled = 3;
273 |             }
274 |             else
275 |             {
276 |                 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
277 |                 {
278 |                     const auto wc2 = static_cast<unsigned int>(input.get_character());
279 |                     const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
280 |                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
281 |                     utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
282 |                     utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
283 |                     utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
284 |                     utf8_bytes_filled = 4;
285 |                 }
286 |                 else
287 |                 {
288 |                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
289 |                     utf8_bytes_filled = 1;
290 |                 }
291 |             }
292 |         }
293 |     }
294 | };
295 | 
296 | // Wraps another input adapter to convert wide character types into individual bytes.
297 | template<typename BaseInputAdapter, typename WideCharType>
298 | class wide_string_input_adapter
299 | {
300 |   public:
301 |     using char_type = char;
302 | 
303 |     wide_string_input_adapter(BaseInputAdapter base)
304 |         : base_adapter(base) {}
305 | 
306 |     typename std::char_traits<char>::int_type get_character() noexcept
307 |     {
308 |         // check if buffer needs to be filled
309 |         if (utf8_bytes_index == utf8_bytes_filled)
310 |         {
311 |             fill_buffer<sizeof(WideCharType)>();
312 | 
313 |             JSON_ASSERT(utf8_bytes_filled > 0);
314 |             JSON_ASSERT(utf8_bytes_index == 0);
315 |         }
316 | 
317 |         // use buffer
318 |         JSON_ASSERT(utf8_bytes_filled > 0);
319 |         JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
320 |         return utf8_bytes[utf8_bytes_index++];
321 |     }
322 | 
323 |   private:
324 |     BaseInputAdapter base_adapter;
325 | 
326 |     template<size_t T>
327 |     void fill_buffer()
328 |     {
329 |         wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
330 |     }
331 | 
332 |     /// a buffer for UTF-8 bytes
333 |     std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
334 | 
335 |     /// index to the utf8_codes array for the next valid byte
336 |     std::size_t utf8_bytes_index = 0;
337 |     /// number of valid bytes in the utf8_codes array
338 |     std::size_t utf8_bytes_filled = 0;
339 | };
340 | 
341 | template<typename IteratorType, typename Enable = void>
342 | struct iterator_input_adapter_factory
343 | {
344 |     using iterator_type = IteratorType;
345 |     using char_type = typename std::iterator_traits<iterator_type>::value_type;
346 |     using adapter_type = iterator_input_adapter<iterator_type>;
347 | 
348 |     static adapter_type create(IteratorType first, IteratorType last)
349 |     {
350 |         return adapter_type(std::move(first), std::move(last));
351 |     }
352 | };
353 | 
354 | template<typename T>
355 | struct is_iterator_of_multibyte
356 | {
357 |     using value_type = typename std::iterator_traits<T>::value_type;
358 |     enum
359 |     {
360 |         value = sizeof(value_type) > 1
361 |     };
362 | };
363 | 
364 | template<typename IteratorType>
365 | struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
366 | {
367 |     using iterator_type = IteratorType;
368 |     using char_type = typename std::iterator_traits<iterator_type>::value_type;
369 |     using base_adapter_type = iterator_input_adapter<iterator_type>;
370 |     using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
371 | 
372 |     static adapter_type create(IteratorType first, IteratorType last)
373 |     {
374 |         return adapter_type(base_adapter_type(std::move(first), std::move(last)));
375 |     }
376 | };
377 | 
378 | // General purpose iterator-based input
379 | template<typename IteratorType>
380 | typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
381 | {
382 |     using factory_type = iterator_input_adapter_factory<IteratorType>;
383 |     return factory_type::create(first, last);
384 | }
385 | 
386 | // Convenience shorthand from container to iterator
387 | // Enables ADL on begin(container) and end(container)
388 | // Encloses the using declarations in namespace for not to leak them to outside scope
389 | 
390 | namespace container_input_adapter_factory_impl
391 | {
392 | 
393 | using std::begin;
394 | using std::end;
395 | 
396 | template<typename ContainerType, typename Enable = void>
397 | struct container_input_adapter_factory {};
398 | 
399 | template<typename ContainerType>
400 | struct container_input_adapter_factory< ContainerType,
401 |        void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
402 |        {
403 |            using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
404 | 
405 |            static adapter_type create(const ContainerType& container)
406 | {
407 |     return input_adapter(begin(container), end(container));
408 | }
409 |        };
410 | 
411 | }  // namespace container_input_adapter_factory_impl
412 | 
413 | template<typename ContainerType>
414 | typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
415 | {
416 |     return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
417 | }
418 | 
419 | #ifndef JSON_NO_IO
420 | // Special cases with fast paths
421 | inline file_input_adapter input_adapter(std::FILE* file)
422 | {
423 |     return file_input_adapter(file);
424 | }
425 | 
426 | inline input_stream_adapter input_adapter(std::istream& stream)
427 | {
428 |     return input_stream_adapter(stream);
429 | }
430 | 
431 | inline input_stream_adapter input_adapter(std::istream&& stream)
432 | {
433 |     return input_stream_adapter(stream);
434 | }
435 | #endif  // JSON_NO_IO
436 | 
437 | using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
438 | 
439 | // Null-delimited strings, and the like.
440 | template < typename CharT,
441 |            typename std::enable_if <
442 |                std::is_pointer<CharT>::value&&
443 |                !std::is_array<CharT>::value&&
444 |                std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
445 |                sizeof(typename std::remove_pointer<CharT>::type) == 1,
446 |                int >::type = 0 >
447 | contiguous_bytes_input_adapter input_adapter(CharT b)
448 | {
449 |     auto length = std::strlen(reinterpret_cast<const char*>(b));
450 |     const auto* ptr = reinterpret_cast<const char*>(b);
451 |     return input_adapter(ptr, ptr + length);
452 | }
453 | 
454 | template<typename T, std::size_t N>
455 | auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
456 | {
457 |     return input_adapter(array, array + N);
458 | }
459 | 
460 | // This class only handles inputs of input_buffer_adapter type.
461 | // It's required so that expressions like {ptr, len} can be implicitly cast
462 | // to the correct adapter.
463 | class span_input_adapter
464 | {
465 |   public:
466 |     template < typename CharT,
467 |                typename std::enable_if <
468 |                    std::is_pointer<CharT>::value&&
469 |                    std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
470 |                    sizeof(typename std::remove_pointer<CharT>::type) == 1,
471 |                    int >::type = 0 >
472 |     span_input_adapter(CharT b, std::size_t l)
473 |         : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
474 | 
475 |     template<class IteratorType,
476 |              typename std::enable_if<
477 |                  std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
478 |                  int>::type = 0>
479 |     span_input_adapter(IteratorType first, IteratorType last)
480 |         : ia(input_adapter(first, last)) {}
481 | 
482 |     contiguous_bytes_input_adapter&& get()
483 |     {
484 |         return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
485 |     }
486 | 
487 |   private:
488 |     contiguous_bytes_input_adapter ia;
489 | };
490 | 
491 | }  // namespace detail
492 | NLOHMANN_JSON_NAMESPACE_END
493 | 
```

--------------------------------------------------------------------------------
/deps/pluginsdk/nlohmann/detail/conversions/from_json.hpp:
--------------------------------------------------------------------------------

```
  1 | //     __ _____ _____ _____
  2 | //  __|  |   __|     |   | |  JSON for Modern C++
  3 | // |  |  |__   |  |  | | | |  version 3.11.3
  4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  5 | //
  6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7 | // SPDX-License-Identifier: MIT
  8 | 
  9 | #pragma once
 10 | 
 11 | #include <algorithm> // transform
 12 | #include <array> // array
 13 | #include <forward_list> // forward_list
 14 | #include <iterator> // inserter, front_inserter, end
 15 | #include <map> // map
 16 | #include <string> // string
 17 | #include <tuple> // tuple, make_tuple
 18 | #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
 19 | #include <unordered_map> // unordered_map
 20 | #include <utility> // pair, declval
 21 | #include <valarray> // valarray
 22 | 
 23 | #include <nlohmann/detail/exceptions.hpp>
 24 | #include <nlohmann/detail/macro_scope.hpp>
 25 | #include <nlohmann/detail/meta/cpp_future.hpp>
 26 | #include <nlohmann/detail/meta/identity_tag.hpp>
 27 | #include <nlohmann/detail/meta/std_fs.hpp>
 28 | #include <nlohmann/detail/meta/type_traits.hpp>
 29 | #include <nlohmann/detail/string_concat.hpp>
 30 | #include <nlohmann/detail/value_t.hpp>
 31 | 
 32 | NLOHMANN_JSON_NAMESPACE_BEGIN
 33 | namespace detail
 34 | {
 35 | 
 36 | template<typename BasicJsonType>
 37 | inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
 38 | {
 39 |     if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
 40 |     {
 41 |         JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
 42 |     }
 43 |     n = nullptr;
 44 | }
 45 | 
 46 | // overloads for basic_json template parameters
 47 | template < typename BasicJsonType, typename ArithmeticType,
 48 |            enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
 49 |                          !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
 50 |                          int > = 0 >
 51 | void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
 52 | {
 53 |     switch (static_cast<value_t>(j))
 54 |     {
 55 |         case value_t::number_unsigned:
 56 |         {
 57 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
 58 |             break;
 59 |         }
 60 |         case value_t::number_integer:
 61 |         {
 62 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
 63 |             break;
 64 |         }
 65 |         case value_t::number_float:
 66 |         {
 67 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
 68 |             break;
 69 |         }
 70 | 
 71 |         case value_t::null:
 72 |         case value_t::object:
 73 |         case value_t::array:
 74 |         case value_t::string:
 75 |         case value_t::boolean:
 76 |         case value_t::binary:
 77 |         case value_t::discarded:
 78 |         default:
 79 |             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
 80 |     }
 81 | }
 82 | 
 83 | template<typename BasicJsonType>
 84 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
 85 | {
 86 |     if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
 87 |     {
 88 |         JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
 89 |     }
 90 |     b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
 91 | }
 92 | 
 93 | template<typename BasicJsonType>
 94 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
 95 | {
 96 |     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
 97 |     {
 98 |         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
 99 |     }
100 |     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
101 | }
102 | 
103 | template <
104 |     typename BasicJsonType, typename StringType,
105 |     enable_if_t <
106 |         std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
107 |         && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
108 |         && !std::is_same<typename BasicJsonType::string_t, StringType>::value
109 |         && !is_json_ref<StringType>::value, int > = 0 >
110 | inline void from_json(const BasicJsonType& j, StringType& s)
111 | {
112 |     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
113 |     {
114 |         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
115 |     }
116 | 
117 |     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
118 | }
119 | 
120 | template<typename BasicJsonType>
121 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
122 | {
123 |     get_arithmetic_value(j, val);
124 | }
125 | 
126 | template<typename BasicJsonType>
127 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
128 | {
129 |     get_arithmetic_value(j, val);
130 | }
131 | 
132 | template<typename BasicJsonType>
133 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
134 | {
135 |     get_arithmetic_value(j, val);
136 | }
137 | 
138 | #if !JSON_DISABLE_ENUM_SERIALIZATION
139 | template<typename BasicJsonType, typename EnumType,
140 |          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
141 | inline void from_json(const BasicJsonType& j, EnumType& e)
142 | {
143 |     typename std::underlying_type<EnumType>::type val;
144 |     get_arithmetic_value(j, val);
145 |     e = static_cast<EnumType>(val);
146 | }
147 | #endif  // JSON_DISABLE_ENUM_SERIALIZATION
148 | 
149 | // forward_list doesn't have an insert method
150 | template<typename BasicJsonType, typename T, typename Allocator,
151 |          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
152 | inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
153 | {
154 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
155 |     {
156 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
157 |     }
158 |     l.clear();
159 |     std::transform(j.rbegin(), j.rend(),
160 |                    std::front_inserter(l), [](const BasicJsonType & i)
161 |     {
162 |         return i.template get<T>();
163 |     });
164 | }
165 | 
166 | // valarray doesn't have an insert method
167 | template<typename BasicJsonType, typename T,
168 |          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
169 | inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
170 | {
171 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
172 |     {
173 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
174 |     }
175 |     l.resize(j.size());
176 |     std::transform(j.begin(), j.end(), std::begin(l),
177 |                    [](const BasicJsonType & elem)
178 |     {
179 |         return elem.template get<T>();
180 |     });
181 | }
182 | 
183 | template<typename BasicJsonType, typename T, std::size_t N>
184 | auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
185 | -> decltype(j.template get<T>(), void())
186 | {
187 |     for (std::size_t i = 0; i < N; ++i)
188 |     {
189 |         arr[i] = j.at(i).template get<T>();
190 |     }
191 | }
192 | 
193 | template<typename BasicJsonType>
194 | inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
195 | {
196 |     arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
197 | }
198 | 
199 | template<typename BasicJsonType, typename T, std::size_t N>
200 | auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
201 |                           priority_tag<2> /*unused*/)
202 | -> decltype(j.template get<T>(), void())
203 | {
204 |     for (std::size_t i = 0; i < N; ++i)
205 |     {
206 |         arr[i] = j.at(i).template get<T>();
207 |     }
208 | }
209 | 
210 | template<typename BasicJsonType, typename ConstructibleArrayType,
211 |          enable_if_t<
212 |              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
213 |              int> = 0>
214 | auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
215 | -> decltype(
216 |     arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
217 |     j.template get<typename ConstructibleArrayType::value_type>(),
218 |     void())
219 | {
220 |     using std::end;
221 | 
222 |     ConstructibleArrayType ret;
223 |     ret.reserve(j.size());
224 |     std::transform(j.begin(), j.end(),
225 |                    std::inserter(ret, end(ret)), [](const BasicJsonType & i)
226 |     {
227 |         // get<BasicJsonType>() returns *this, this won't call a from_json
228 |         // method when value_type is BasicJsonType
229 |         return i.template get<typename ConstructibleArrayType::value_type>();
230 |     });
231 |     arr = std::move(ret);
232 | }
233 | 
234 | template<typename BasicJsonType, typename ConstructibleArrayType,
235 |          enable_if_t<
236 |              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
237 |              int> = 0>
238 | inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
239 |                                  priority_tag<0> /*unused*/)
240 | {
241 |     using std::end;
242 | 
243 |     ConstructibleArrayType ret;
244 |     std::transform(
245 |         j.begin(), j.end(), std::inserter(ret, end(ret)),
246 |         [](const BasicJsonType & i)
247 |     {
248 |         // get<BasicJsonType>() returns *this, this won't call a from_json
249 |         // method when value_type is BasicJsonType
250 |         return i.template get<typename ConstructibleArrayType::value_type>();
251 |     });
252 |     arr = std::move(ret);
253 | }
254 | 
255 | template < typename BasicJsonType, typename ConstructibleArrayType,
256 |            enable_if_t <
257 |                is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
258 |                !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
259 |                !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
260 |                !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
261 |                !is_basic_json<ConstructibleArrayType>::value,
262 |                int > = 0 >
263 | auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
264 | -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
265 | j.template get<typename ConstructibleArrayType::value_type>(),
266 | void())
267 | {
268 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
269 |     {
270 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
271 |     }
272 | 
273 |     from_json_array_impl(j, arr, priority_tag<3> {});
274 | }
275 | 
276 | template < typename BasicJsonType, typename T, std::size_t... Idx >
277 | std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
278 |         identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
279 | {
280 |     return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
281 | }
282 | 
283 | template < typename BasicJsonType, typename T, std::size_t N >
284 | auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
285 | -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
286 | {
287 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
288 |     {
289 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
290 |     }
291 | 
292 |     return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
293 | }
294 | 
295 | template<typename BasicJsonType>
296 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
297 | {
298 |     if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
299 |     {
300 |         JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
301 |     }
302 | 
303 |     bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
304 | }
305 | 
306 | template<typename BasicJsonType, typename ConstructibleObjectType,
307 |          enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
308 | inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
309 | {
310 |     if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
311 |     {
312 |         JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
313 |     }
314 | 
315 |     ConstructibleObjectType ret;
316 |     const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
317 |     using value_type = typename ConstructibleObjectType::value_type;
318 |     std::transform(
319 |         inner_object->begin(), inner_object->end(),
320 |         std::inserter(ret, ret.begin()),
321 |         [](typename BasicJsonType::object_t::value_type const & p)
322 |     {
323 |         return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
324 |     });
325 |     obj = std::move(ret);
326 | }
327 | 
328 | // overload for arithmetic types, not chosen for basic_json template arguments
329 | // (BooleanType, etc..); note: Is it really necessary to provide explicit
330 | // overloads for boolean_t etc. in case of a custom BooleanType which is not
331 | // an arithmetic type?
332 | template < typename BasicJsonType, typename ArithmeticType,
333 |            enable_if_t <
334 |                std::is_arithmetic<ArithmeticType>::value&&
335 |                !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
336 |                !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
337 |                !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
338 |                !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
339 |                int > = 0 >
340 | inline void from_json(const BasicJsonType& j, ArithmeticType& val)
341 | {
342 |     switch (static_cast<value_t>(j))
343 |     {
344 |         case value_t::number_unsigned:
345 |         {
346 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
347 |             break;
348 |         }
349 |         case value_t::number_integer:
350 |         {
351 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
352 |             break;
353 |         }
354 |         case value_t::number_float:
355 |         {
356 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
357 |             break;
358 |         }
359 |         case value_t::boolean:
360 |         {
361 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
362 |             break;
363 |         }
364 | 
365 |         case value_t::null:
366 |         case value_t::object:
367 |         case value_t::array:
368 |         case value_t::string:
369 |         case value_t::binary:
370 |         case value_t::discarded:
371 |         default:
372 |             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
373 |     }
374 | }
375 | 
376 | template<typename BasicJsonType, typename... Args, std::size_t... Idx>
377 | std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
378 | {
379 |     return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
380 | }
381 | 
382 | template < typename BasicJsonType, class A1, class A2 >
383 | std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
384 | {
385 |     return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
386 |             std::forward<BasicJsonType>(j).at(1).template get<A2>()};
387 | }
388 | 
389 | template<typename BasicJsonType, typename A1, typename A2>
390 | inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
391 | {
392 |     p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
393 | }
394 | 
395 | template<typename BasicJsonType, typename... Args>
396 | std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
397 | {
398 |     return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
399 | }
400 | 
401 | template<typename BasicJsonType, typename... Args>
402 | inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
403 | {
404 |     t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
405 | }
406 | 
407 | template<typename BasicJsonType, typename TupleRelated>
408 | auto from_json(BasicJsonType&& j, TupleRelated&& t)
409 | -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
410 | {
411 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
412 |     {
413 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
414 |     }
415 | 
416 |     return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
417 | }
418 | 
419 | template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
420 |            typename = enable_if_t < !std::is_constructible <
421 |                                         typename BasicJsonType::string_t, Key >::value >>
422 | inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
423 | {
424 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
425 |     {
426 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
427 |     }
428 |     m.clear();
429 |     for (const auto& p : j)
430 |     {
431 |         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
432 |         {
433 |             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
434 |         }
435 |         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
436 |     }
437 | }
438 | 
439 | template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
440 |            typename = enable_if_t < !std::is_constructible <
441 |                                         typename BasicJsonType::string_t, Key >::value >>
442 | inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
443 | {
444 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
445 |     {
446 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
447 |     }
448 |     m.clear();
449 |     for (const auto& p : j)
450 |     {
451 |         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
452 |         {
453 |             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
454 |         }
455 |         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
456 |     }
457 | }
458 | 
459 | #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
460 | template<typename BasicJsonType>
461 | inline void from_json(const BasicJsonType& j, std_fs::path& p)
462 | {
463 |     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
464 |     {
465 |         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
466 |     }
467 |     p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
468 | }
469 | #endif
470 | 
471 | struct from_json_fn
472 | {
473 |     template<typename BasicJsonType, typename T>
474 |     auto operator()(const BasicJsonType& j, T&& val) const
475 |     noexcept(noexcept(from_json(j, std::forward<T>(val))))
476 |     -> decltype(from_json(j, std::forward<T>(val)))
477 |     {
478 |         return from_json(j, std::forward<T>(val));
479 |     }
480 | };
481 | 
482 | }  // namespace detail
483 | 
484 | #ifndef JSON_HAS_CPP_17
485 | /// namespace to hold default `from_json` function
486 | /// to see why this is required:
487 | /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
488 | namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
489 | {
490 | #endif
491 | JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
492 |     detail::static_const<detail::from_json_fn>::value;
493 | #ifndef JSON_HAS_CPP_17
494 | }  // namespace
495 | #endif
496 | 
497 | NLOHMANN_JSON_NAMESPACE_END
498 | 
```

--------------------------------------------------------------------------------
/include/nlohmann/detail/conversions/from_json.hpp:
--------------------------------------------------------------------------------

```
  1 | //     __ _____ _____ _____
  2 | //  __|  |   __|     |   | |  JSON for Modern C++
  3 | // |  |  |__   |  |  | | | |  version 3.11.3
  4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  5 | //
  6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7 | // SPDX-License-Identifier: MIT
  8 | 
  9 | #pragma once
 10 | 
 11 | #include <algorithm> // transform
 12 | #include <array> // array
 13 | #include <forward_list> // forward_list
 14 | #include <iterator> // inserter, front_inserter, end
 15 | #include <map> // map
 16 | #include <string> // string
 17 | #include <tuple> // tuple, make_tuple
 18 | #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
 19 | #include <unordered_map> // unordered_map
 20 | #include <utility> // pair, declval
 21 | #include <valarray> // valarray
 22 | 
 23 | #include <nlohmann/detail/exceptions.hpp>
 24 | #include <nlohmann/detail/macro_scope.hpp>
 25 | #include <nlohmann/detail/meta/cpp_future.hpp>
 26 | #include <nlohmann/detail/meta/identity_tag.hpp>
 27 | #include <nlohmann/detail/meta/std_fs.hpp>
 28 | #include <nlohmann/detail/meta/type_traits.hpp>
 29 | #include <nlohmann/detail/string_concat.hpp>
 30 | #include <nlohmann/detail/value_t.hpp>
 31 | 
 32 | NLOHMANN_JSON_NAMESPACE_BEGIN
 33 | namespace detail
 34 | {
 35 | 
 36 | template<typename BasicJsonType>
 37 | inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
 38 | {
 39 |     if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
 40 |     {
 41 |         JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
 42 |     }
 43 |     n = nullptr;
 44 | }
 45 | 
 46 | // overloads for basic_json template parameters
 47 | template < typename BasicJsonType, typename ArithmeticType,
 48 |            enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
 49 |                          !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
 50 |                          int > = 0 >
 51 | void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
 52 | {
 53 |     switch (static_cast<value_t>(j))
 54 |     {
 55 |         case value_t::number_unsigned:
 56 |         {
 57 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
 58 |             break;
 59 |         }
 60 |         case value_t::number_integer:
 61 |         {
 62 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
 63 |             break;
 64 |         }
 65 |         case value_t::number_float:
 66 |         {
 67 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
 68 |             break;
 69 |         }
 70 | 
 71 |         case value_t::null:
 72 |         case value_t::object:
 73 |         case value_t::array:
 74 |         case value_t::string:
 75 |         case value_t::boolean:
 76 |         case value_t::binary:
 77 |         case value_t::discarded:
 78 |         default:
 79 |             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
 80 |     }
 81 | }
 82 | 
 83 | template<typename BasicJsonType>
 84 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
 85 | {
 86 |     if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
 87 |     {
 88 |         JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
 89 |     }
 90 |     b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
 91 | }
 92 | 
 93 | template<typename BasicJsonType>
 94 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
 95 | {
 96 |     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
 97 |     {
 98 |         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
 99 |     }
100 |     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
101 | }
102 | 
103 | template <
104 |     typename BasicJsonType, typename StringType,
105 |     enable_if_t <
106 |         std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
107 |         && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
108 |         && !std::is_same<typename BasicJsonType::string_t, StringType>::value
109 |         && !is_json_ref<StringType>::value, int > = 0 >
110 | inline void from_json(const BasicJsonType& j, StringType& s)
111 | {
112 |     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
113 |     {
114 |         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
115 |     }
116 | 
117 |     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
118 | }
119 | 
120 | template<typename BasicJsonType>
121 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
122 | {
123 |     get_arithmetic_value(j, val);
124 | }
125 | 
126 | template<typename BasicJsonType>
127 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
128 | {
129 |     get_arithmetic_value(j, val);
130 | }
131 | 
132 | template<typename BasicJsonType>
133 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
134 | {
135 |     get_arithmetic_value(j, val);
136 | }
137 | 
138 | #if !JSON_DISABLE_ENUM_SERIALIZATION
139 | template<typename BasicJsonType, typename EnumType,
140 |          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
141 | inline void from_json(const BasicJsonType& j, EnumType& e)
142 | {
143 |     typename std::underlying_type<EnumType>::type val;
144 |     get_arithmetic_value(j, val);
145 |     e = static_cast<EnumType>(val);
146 | }
147 | #endif  // JSON_DISABLE_ENUM_SERIALIZATION
148 | 
149 | // forward_list doesn't have an insert method
150 | template<typename BasicJsonType, typename T, typename Allocator,
151 |          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
152 | inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
153 | {
154 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
155 |     {
156 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
157 |     }
158 |     l.clear();
159 |     std::transform(j.rbegin(), j.rend(),
160 |                    std::front_inserter(l), [](const BasicJsonType & i)
161 |     {
162 |         return i.template get<T>();
163 |     });
164 | }
165 | 
166 | // valarray doesn't have an insert method
167 | template<typename BasicJsonType, typename T,
168 |          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
169 | inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
170 | {
171 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
172 |     {
173 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
174 |     }
175 |     l.resize(j.size());
176 |     std::transform(j.begin(), j.end(), std::begin(l),
177 |                    [](const BasicJsonType & elem)
178 |     {
179 |         return elem.template get<T>();
180 |     });
181 | }
182 | 
183 | template<typename BasicJsonType, typename T, std::size_t N>
184 | auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
185 | -> decltype(j.template get<T>(), void())
186 | {
187 |     for (std::size_t i = 0; i < N; ++i)
188 |     {
189 |         arr[i] = j.at(i).template get<T>();
190 |     }
191 | }
192 | 
193 | template<typename BasicJsonType>
194 | inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
195 | {
196 |     arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
197 | }
198 | 
199 | template<typename BasicJsonType, typename T, std::size_t N>
200 | auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
201 |                           priority_tag<2> /*unused*/)
202 | -> decltype(j.template get<T>(), void())
203 | {
204 |     for (std::size_t i = 0; i < N; ++i)
205 |     {
206 |         arr[i] = j.at(i).template get<T>();
207 |     }
208 | }
209 | 
210 | template<typename BasicJsonType, typename ConstructibleArrayType,
211 |          enable_if_t<
212 |              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
213 |              int> = 0>
214 | auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
215 | -> decltype(
216 |     arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
217 |     j.template get<typename ConstructibleArrayType::value_type>(),
218 |     void())
219 | {
220 |     using std::end;
221 | 
222 |     ConstructibleArrayType ret;
223 |     ret.reserve(j.size());
224 |     std::transform(j.begin(), j.end(),
225 |                    std::inserter(ret, end(ret)), [](const BasicJsonType & i)
226 |     {
227 |         // get<BasicJsonType>() returns *this, this won't call a from_json
228 |         // method when value_type is BasicJsonType
229 |         return i.template get<typename ConstructibleArrayType::value_type>();
230 |     });
231 |     arr = std::move(ret);
232 | }
233 | 
234 | template<typename BasicJsonType, typename ConstructibleArrayType,
235 |          enable_if_t<
236 |              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
237 |              int> = 0>
238 | inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
239 |                                  priority_tag<0> /*unused*/)
240 | {
241 |     using std::end;
242 | 
243 |     ConstructibleArrayType ret;
244 |     std::transform(
245 |         j.begin(), j.end(), std::inserter(ret, end(ret)),
246 |         [](const BasicJsonType & i)
247 |     {
248 |         // get<BasicJsonType>() returns *this, this won't call a from_json
249 |         // method when value_type is BasicJsonType
250 |         return i.template get<typename ConstructibleArrayType::value_type>();
251 |     });
252 |     arr = std::move(ret);
253 | }
254 | 
255 | template < typename BasicJsonType, typename ConstructibleArrayType,
256 |            enable_if_t <
257 |                is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
258 |                !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
259 |                !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
260 |                !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
261 |                !is_basic_json<ConstructibleArrayType>::value,
262 |                int > = 0 >
263 | auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
264 | -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
265 | j.template get<typename ConstructibleArrayType::value_type>(),
266 | void())
267 | {
268 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
269 |     {
270 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
271 |     }
272 | 
273 |     from_json_array_impl(j, arr, priority_tag<3> {});
274 | }
275 | 
276 | template < typename BasicJsonType, typename T, std::size_t... Idx >
277 | std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
278 |         identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
279 | {
280 |     return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
281 | }
282 | 
283 | template < typename BasicJsonType, typename T, std::size_t N >
284 | auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
285 | -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
286 | {
287 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
288 |     {
289 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
290 |     }
291 | 
292 |     return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
293 | }
294 | 
295 | template<typename BasicJsonType>
296 | inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
297 | {
298 |     if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
299 |     {
300 |         JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
301 |     }
302 | 
303 |     bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
304 | }
305 | 
306 | template<typename BasicJsonType, typename ConstructibleObjectType,
307 |          enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
308 | inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
309 | {
310 |     if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
311 |     {
312 |         JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
313 |     }
314 | 
315 |     ConstructibleObjectType ret;
316 |     const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
317 |     using value_type = typename ConstructibleObjectType::value_type;
318 |     std::transform(
319 |         inner_object->begin(), inner_object->end(),
320 |         std::inserter(ret, ret.begin()),
321 |         [](typename BasicJsonType::object_t::value_type const & p)
322 |     {
323 |         return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
324 |     });
325 |     obj = std::move(ret);
326 | }
327 | 
328 | // overload for arithmetic types, not chosen for basic_json template arguments
329 | // (BooleanType, etc..); note: Is it really necessary to provide explicit
330 | // overloads for boolean_t etc. in case of a custom BooleanType which is not
331 | // an arithmetic type?
332 | template < typename BasicJsonType, typename ArithmeticType,
333 |            enable_if_t <
334 |                std::is_arithmetic<ArithmeticType>::value&&
335 |                !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
336 |                !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
337 |                !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
338 |                !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
339 |                int > = 0 >
340 | inline void from_json(const BasicJsonType& j, ArithmeticType& val)
341 | {
342 |     switch (static_cast<value_t>(j))
343 |     {
344 |         case value_t::number_unsigned:
345 |         {
346 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
347 |             break;
348 |         }
349 |         case value_t::number_integer:
350 |         {
351 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
352 |             break;
353 |         }
354 |         case value_t::number_float:
355 |         {
356 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
357 |             break;
358 |         }
359 |         case value_t::boolean:
360 |         {
361 |             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
362 |             break;
363 |         }
364 | 
365 |         case value_t::null:
366 |         case value_t::object:
367 |         case value_t::array:
368 |         case value_t::string:
369 |         case value_t::binary:
370 |         case value_t::discarded:
371 |         default:
372 |             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
373 |     }
374 | }
375 | 
376 | template<typename BasicJsonType, typename... Args, std::size_t... Idx>
377 | std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
378 | {
379 |     return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
380 | }
381 | 
382 | template < typename BasicJsonType, class A1, class A2 >
383 | std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
384 | {
385 |     return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
386 |             std::forward<BasicJsonType>(j).at(1).template get<A2>()};
387 | }
388 | 
389 | template<typename BasicJsonType, typename A1, typename A2>
390 | inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
391 | {
392 |     p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
393 | }
394 | 
395 | template<typename BasicJsonType, typename... Args>
396 | std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
397 | {
398 |     return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
399 | }
400 | 
401 | template<typename BasicJsonType, typename... Args>
402 | inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
403 | {
404 |     t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
405 | }
406 | 
407 | template<typename BasicJsonType, typename TupleRelated>
408 | auto from_json(BasicJsonType&& j, TupleRelated&& t)
409 | -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
410 | {
411 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
412 |     {
413 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
414 |     }
415 | 
416 |     return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
417 | }
418 | 
419 | template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
420 |            typename = enable_if_t < !std::is_constructible <
421 |                                         typename BasicJsonType::string_t, Key >::value >>
422 | inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
423 | {
424 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
425 |     {
426 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
427 |     }
428 |     m.clear();
429 |     for (const auto& p : j)
430 |     {
431 |         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
432 |         {
433 |             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
434 |         }
435 |         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
436 |     }
437 | }
438 | 
439 | template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
440 |            typename = enable_if_t < !std::is_constructible <
441 |                                         typename BasicJsonType::string_t, Key >::value >>
442 | inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
443 | {
444 |     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
445 |     {
446 |         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
447 |     }
448 |     m.clear();
449 |     for (const auto& p : j)
450 |     {
451 |         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
452 |         {
453 |             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
454 |         }
455 |         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
456 |     }
457 | }
458 | 
459 | #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
460 | template<typename BasicJsonType>
461 | inline void from_json(const BasicJsonType& j, std_fs::path& p)
462 | {
463 |     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
464 |     {
465 |         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
466 |     }
467 |     p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
468 | }
469 | #endif
470 | 
471 | struct from_json_fn
472 | {
473 |     template<typename BasicJsonType, typename T>
474 |     auto operator()(const BasicJsonType& j, T&& val) const
475 |     noexcept(noexcept(from_json(j, std::forward<T>(val))))
476 |     -> decltype(from_json(j, std::forward<T>(val)))
477 |     {
478 |         return from_json(j, std::forward<T>(val));
479 |     }
480 | };
481 | 
482 | }  // namespace detail
483 | 
484 | #ifndef JSON_HAS_CPP_17
485 | /// namespace to hold default `from_json` function
486 | /// to see why this is required:
487 | /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
488 | namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
489 | {
490 | #endif
491 | JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
492 |     detail::static_const<detail::from_json_fn>::value;
493 | #ifndef JSON_HAS_CPP_17
494 | }  // namespace
495 | #endif
496 | 
497 | NLOHMANN_JSON_NAMESPACE_END
498 | 
```

--------------------------------------------------------------------------------
/deps/pluginsdk/nlohmann/detail/input/parser.hpp:
--------------------------------------------------------------------------------

```
  1 | //     __ _____ _____ _____
  2 | //  __|  |   __|     |   | |  JSON for Modern C++
  3 | // |  |  |__   |  |  | | | |  version 3.11.3
  4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  5 | //
  6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7 | // SPDX-License-Identifier: MIT
  8 | 
  9 | #pragma once
 10 | 
 11 | #include <cmath> // isfinite
 12 | #include <cstdint> // uint8_t
 13 | #include <functional> // function
 14 | #include <string> // string
 15 | #include <utility> // move
 16 | #include <vector> // vector
 17 | 
 18 | #include <nlohmann/detail/exceptions.hpp>
 19 | #include <nlohmann/detail/input/input_adapters.hpp>
 20 | #include <nlohmann/detail/input/json_sax.hpp>
 21 | #include <nlohmann/detail/input/lexer.hpp>
 22 | #include <nlohmann/detail/macro_scope.hpp>
 23 | #include <nlohmann/detail/meta/is_sax.hpp>
 24 | #include <nlohmann/detail/string_concat.hpp>
 25 | #include <nlohmann/detail/value_t.hpp>
 26 | 
 27 | NLOHMANN_JSON_NAMESPACE_BEGIN
 28 | namespace detail
 29 | {
 30 | ////////////
 31 | // parser //
 32 | ////////////
 33 | 
 34 | enum class parse_event_t : std::uint8_t
 35 | {
 36 |     /// the parser read `{` and started to process a JSON object
 37 |     object_start,
 38 |     /// the parser read `}` and finished processing a JSON object
 39 |     object_end,
 40 |     /// the parser read `[` and started to process a JSON array
 41 |     array_start,
 42 |     /// the parser read `]` and finished processing a JSON array
 43 |     array_end,
 44 |     /// the parser read a key of a value in an object
 45 |     key,
 46 |     /// the parser finished reading a JSON value
 47 |     value
 48 | };
 49 | 
 50 | template<typename BasicJsonType>
 51 | using parser_callback_t =
 52 |     std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
 53 | 
 54 | /*!
 55 | @brief syntax analysis
 56 | 
 57 | This class implements a recursive descent parser.
 58 | */
 59 | template<typename BasicJsonType, typename InputAdapterType>
 60 | class parser
 61 | {
 62 |     using number_integer_t = typename BasicJsonType::number_integer_t;
 63 |     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 64 |     using number_float_t = typename BasicJsonType::number_float_t;
 65 |     using string_t = typename BasicJsonType::string_t;
 66 |     using lexer_t = lexer<BasicJsonType, InputAdapterType>;
 67 |     using token_type = typename lexer_t::token_type;
 68 | 
 69 |   public:
 70 |     /// a parser reading from an input adapter
 71 |     explicit parser(InputAdapterType&& adapter,
 72 |                     const parser_callback_t<BasicJsonType> cb = nullptr,
 73 |                     const bool allow_exceptions_ = true,
 74 |                     const bool skip_comments = false)
 75 |         : callback(cb)
 76 |         , m_lexer(std::move(adapter), skip_comments)
 77 |         , allow_exceptions(allow_exceptions_)
 78 |     {
 79 |         // read first token
 80 |         get_token();
 81 |     }
 82 | 
 83 |     /*!
 84 |     @brief public parser interface
 85 | 
 86 |     @param[in] strict      whether to expect the last token to be EOF
 87 |     @param[in,out] result  parsed JSON value
 88 | 
 89 |     @throw parse_error.101 in case of an unexpected token
 90 |     @throw parse_error.102 if to_unicode fails or surrogate error
 91 |     @throw parse_error.103 if to_unicode fails
 92 |     */
 93 |     void parse(const bool strict, BasicJsonType& result)
 94 |     {
 95 |         if (callback)
 96 |         {
 97 |             json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
 98 |             sax_parse_internal(&sdp);
 99 | 
100 |             // in strict mode, input must be completely read
101 |             if (strict && (get_token() != token_type::end_of_input))
102 |             {
103 |                 sdp.parse_error(m_lexer.get_position(),
104 |                                 m_lexer.get_token_string(),
105 |                                 parse_error::create(101, m_lexer.get_position(),
106 |                                                     exception_message(token_type::end_of_input, "value"), nullptr));
107 |             }
108 | 
109 |             // in case of an error, return discarded value
110 |             if (sdp.is_errored())
111 |             {
112 |                 result = value_t::discarded;
113 |                 return;
114 |             }
115 | 
116 |             // set top-level value to null if it was discarded by the callback
117 |             // function
118 |             if (result.is_discarded())
119 |             {
120 |                 result = nullptr;
121 |             }
122 |         }
123 |         else
124 |         {
125 |             json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
126 |             sax_parse_internal(&sdp);
127 | 
128 |             // in strict mode, input must be completely read
129 |             if (strict && (get_token() != token_type::end_of_input))
130 |             {
131 |                 sdp.parse_error(m_lexer.get_position(),
132 |                                 m_lexer.get_token_string(),
133 |                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
134 |             }
135 | 
136 |             // in case of an error, return discarded value
137 |             if (sdp.is_errored())
138 |             {
139 |                 result = value_t::discarded;
140 |                 return;
141 |             }
142 |         }
143 | 
144 |         result.assert_invariant();
145 |     }
146 | 
147 |     /*!
148 |     @brief public accept interface
149 | 
150 |     @param[in] strict  whether to expect the last token to be EOF
151 |     @return whether the input is a proper JSON text
152 |     */
153 |     bool accept(const bool strict = true)
154 |     {
155 |         json_sax_acceptor<BasicJsonType> sax_acceptor;
156 |         return sax_parse(&sax_acceptor, strict);
157 |     }
158 | 
159 |     template<typename SAX>
160 |     JSON_HEDLEY_NON_NULL(2)
161 |     bool sax_parse(SAX* sax, const bool strict = true)
162 |     {
163 |         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
164 |         const bool result = sax_parse_internal(sax);
165 | 
166 |         // strict mode: next byte must be EOF
167 |         if (result && strict && (get_token() != token_type::end_of_input))
168 |         {
169 |             return sax->parse_error(m_lexer.get_position(),
170 |                                     m_lexer.get_token_string(),
171 |                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
172 |         }
173 | 
174 |         return result;
175 |     }
176 | 
177 |   private:
178 |     template<typename SAX>
179 |     JSON_HEDLEY_NON_NULL(2)
180 |     bool sax_parse_internal(SAX* sax)
181 |     {
182 |         // stack to remember the hierarchy of structured values we are parsing
183 |         // true = array; false = object
184 |         std::vector<bool> states;
185 |         // value to avoid a goto (see comment where set to true)
186 |         bool skip_to_state_evaluation = false;
187 | 
188 |         while (true)
189 |         {
190 |             if (!skip_to_state_evaluation)
191 |             {
192 |                 // invariant: get_token() was called before each iteration
193 |                 switch (last_token)
194 |                 {
195 |                     case token_type::begin_object:
196 |                     {
197 |                         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
198 |                         {
199 |                             return false;
200 |                         }
201 | 
202 |                         // closing } -> we are done
203 |                         if (get_token() == token_type::end_object)
204 |                         {
205 |                             if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
206 |                             {
207 |                                 return false;
208 |                             }
209 |                             break;
210 |                         }
211 | 
212 |                         // parse key
213 |                         if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
214 |                         {
215 |                             return sax->parse_error(m_lexer.get_position(),
216 |                                                     m_lexer.get_token_string(),
217 |                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
218 |                         }
219 |                         if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
220 |                         {
221 |                             return false;
222 |                         }
223 | 
224 |                         // parse separator (:)
225 |                         if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
226 |                         {
227 |                             return sax->parse_error(m_lexer.get_position(),
228 |                                                     m_lexer.get_token_string(),
229 |                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
230 |                         }
231 | 
232 |                         // remember we are now inside an object
233 |                         states.push_back(false);
234 | 
235 |                         // parse values
236 |                         get_token();
237 |                         continue;
238 |                     }
239 | 
240 |                     case token_type::begin_array:
241 |                     {
242 |                         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
243 |                         {
244 |                             return false;
245 |                         }
246 | 
247 |                         // closing ] -> we are done
248 |                         if (get_token() == token_type::end_array)
249 |                         {
250 |                             if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
251 |                             {
252 |                                 return false;
253 |                             }
254 |                             break;
255 |                         }
256 | 
257 |                         // remember we are now inside an array
258 |                         states.push_back(true);
259 | 
260 |                         // parse values (no need to call get_token)
261 |                         continue;
262 |                     }
263 | 
264 |                     case token_type::value_float:
265 |                     {
266 |                         const auto res = m_lexer.get_number_float();
267 | 
268 |                         if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
269 |                         {
270 |                             return sax->parse_error(m_lexer.get_position(),
271 |                                                     m_lexer.get_token_string(),
272 |                                                     out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
273 |                         }
274 | 
275 |                         if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
276 |                         {
277 |                             return false;
278 |                         }
279 | 
280 |                         break;
281 |                     }
282 | 
283 |                     case token_type::literal_false:
284 |                     {
285 |                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
286 |                         {
287 |                             return false;
288 |                         }
289 |                         break;
290 |                     }
291 | 
292 |                     case token_type::literal_null:
293 |                     {
294 |                         if (JSON_HEDLEY_UNLIKELY(!sax->null()))
295 |                         {
296 |                             return false;
297 |                         }
298 |                         break;
299 |                     }
300 | 
301 |                     case token_type::literal_true:
302 |                     {
303 |                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
304 |                         {
305 |                             return false;
306 |                         }
307 |                         break;
308 |                     }
309 | 
310 |                     case token_type::value_integer:
311 |                     {
312 |                         if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
313 |                         {
314 |                             return false;
315 |                         }
316 |                         break;
317 |                     }
318 | 
319 |                     case token_type::value_string:
320 |                     {
321 |                         if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
322 |                         {
323 |                             return false;
324 |                         }
325 |                         break;
326 |                     }
327 | 
328 |                     case token_type::value_unsigned:
329 |                     {
330 |                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
331 |                         {
332 |                             return false;
333 |                         }
334 |                         break;
335 |                     }
336 | 
337 |                     case token_type::parse_error:
338 |                     {
339 |                         // using "uninitialized" to avoid "expected" message
340 |                         return sax->parse_error(m_lexer.get_position(),
341 |                                                 m_lexer.get_token_string(),
342 |                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
343 |                     }
344 |                     case token_type::end_of_input:
345 |                     {
346 |                         if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
347 |                         {
348 |                             return sax->parse_error(m_lexer.get_position(),
349 |                                                     m_lexer.get_token_string(),
350 |                                                     parse_error::create(101, m_lexer.get_position(),
351 |                                                             "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
352 |                         }
353 | 
354 |                         return sax->parse_error(m_lexer.get_position(),
355 |                                                 m_lexer.get_token_string(),
356 |                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
357 |                     }
358 |                     case token_type::uninitialized:
359 |                     case token_type::end_array:
360 |                     case token_type::end_object:
361 |                     case token_type::name_separator:
362 |                     case token_type::value_separator:
363 |                     case token_type::literal_or_value:
364 |                     default: // the last token was unexpected
365 |                     {
366 |                         return sax->parse_error(m_lexer.get_position(),
367 |                                                 m_lexer.get_token_string(),
368 |                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
369 |                     }
370 |                 }
371 |             }
372 |             else
373 |             {
374 |                 skip_to_state_evaluation = false;
375 |             }
376 | 
377 |             // we reached this line after we successfully parsed a value
378 |             if (states.empty())
379 |             {
380 |                 // empty stack: we reached the end of the hierarchy: done
381 |                 return true;
382 |             }
383 | 
384 |             if (states.back())  // array
385 |             {
386 |                 // comma -> next value
387 |                 if (get_token() == token_type::value_separator)
388 |                 {
389 |                     // parse a new value
390 |                     get_token();
391 |                     continue;
392 |                 }
393 | 
394 |                 // closing ]
395 |                 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
396 |                 {
397 |                     if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
398 |                     {
399 |                         return false;
400 |                     }
401 | 
402 |                     // We are done with this array. Before we can parse a
403 |                     // new value, we need to evaluate the new state first.
404 |                     // By setting skip_to_state_evaluation to false, we
405 |                     // are effectively jumping to the beginning of this if.
406 |                     JSON_ASSERT(!states.empty());
407 |                     states.pop_back();
408 |                     skip_to_state_evaluation = true;
409 |                     continue;
410 |                 }
411 | 
412 |                 return sax->parse_error(m_lexer.get_position(),
413 |                                         m_lexer.get_token_string(),
414 |                                         parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
415 |             }
416 | 
417 |             // states.back() is false -> object
418 | 
419 |             // comma -> next value
420 |             if (get_token() == token_type::value_separator)
421 |             {
422 |                 // parse key
423 |                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
424 |                 {
425 |                     return sax->parse_error(m_lexer.get_position(),
426 |                                             m_lexer.get_token_string(),
427 |                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
428 |                 }
429 | 
430 |                 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
431 |                 {
432 |                     return false;
433 |                 }
434 | 
435 |                 // parse separator (:)
436 |                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
437 |                 {
438 |                     return sax->parse_error(m_lexer.get_position(),
439 |                                             m_lexer.get_token_string(),
440 |                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
441 |                 }
442 | 
443 |                 // parse values
444 |                 get_token();
445 |                 continue;
446 |             }
447 | 
448 |             // closing }
449 |             if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
450 |             {
451 |                 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
452 |                 {
453 |                     return false;
454 |                 }
455 | 
456 |                 // We are done with this object. Before we can parse a
457 |                 // new value, we need to evaluate the new state first.
458 |                 // By setting skip_to_state_evaluation to false, we
459 |                 // are effectively jumping to the beginning of this if.
460 |                 JSON_ASSERT(!states.empty());
461 |                 states.pop_back();
462 |                 skip_to_state_evaluation = true;
463 |                 continue;
464 |             }
465 | 
466 |             return sax->parse_error(m_lexer.get_position(),
467 |                                     m_lexer.get_token_string(),
468 |                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
469 |         }
470 |     }
471 | 
472 |     /// get next token from lexer
473 |     token_type get_token()
474 |     {
475 |         return last_token = m_lexer.scan();
476 |     }
477 | 
478 |     std::string exception_message(const token_type expected, const std::string& context)
479 |     {
480 |         std::string error_msg = "syntax error ";
481 | 
482 |         if (!context.empty())
483 |         {
484 |             error_msg += concat("while parsing ", context, ' ');
485 |         }
486 | 
487 |         error_msg += "- ";
488 | 
489 |         if (last_token == token_type::parse_error)
490 |         {
491 |             error_msg += concat(m_lexer.get_error_message(), "; last read: '",
492 |                                 m_lexer.get_token_string(), '\'');
493 |         }
494 |         else
495 |         {
496 |             error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
497 |         }
498 | 
499 |         if (expected != token_type::uninitialized)
500 |         {
501 |             error_msg += concat("; expected ", lexer_t::token_type_name(expected));
502 |         }
503 | 
504 |         return error_msg;
505 |     }
506 | 
507 |   private:
508 |     /// callback function
509 |     const parser_callback_t<BasicJsonType> callback = nullptr;
510 |     /// the type of the last read token
511 |     token_type last_token = token_type::uninitialized;
512 |     /// the lexer
513 |     lexer_t m_lexer;
514 |     /// whether to throw exceptions in case of errors
515 |     const bool allow_exceptions = true;
516 | };
517 | 
518 | }  // namespace detail
519 | NLOHMANN_JSON_NAMESPACE_END
520 | 
```

--------------------------------------------------------------------------------
/include/nlohmann/detail/input/parser.hpp:
--------------------------------------------------------------------------------

```
  1 | //     __ _____ _____ _____
  2 | //  __|  |   __|     |   | |  JSON for Modern C++
  3 | // |  |  |__   |  |  | | | |  version 3.11.3
  4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  5 | //
  6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  7 | // SPDX-License-Identifier: MIT
  8 | 
  9 | #pragma once
 10 | 
 11 | #include <cmath> // isfinite
 12 | #include <cstdint> // uint8_t
 13 | #include <functional> // function
 14 | #include <string> // string
 15 | #include <utility> // move
 16 | #include <vector> // vector
 17 | 
 18 | #include <nlohmann/detail/exceptions.hpp>
 19 | #include <nlohmann/detail/input/input_adapters.hpp>
 20 | #include <nlohmann/detail/input/json_sax.hpp>
 21 | #include <nlohmann/detail/input/lexer.hpp>
 22 | #include <nlohmann/detail/macro_scope.hpp>
 23 | #include <nlohmann/detail/meta/is_sax.hpp>
 24 | #include <nlohmann/detail/string_concat.hpp>
 25 | #include <nlohmann/detail/value_t.hpp>
 26 | 
 27 | NLOHMANN_JSON_NAMESPACE_BEGIN
 28 | namespace detail
 29 | {
 30 | ////////////
 31 | // parser //
 32 | ////////////
 33 | 
 34 | enum class parse_event_t : std::uint8_t
 35 | {
 36 |     /// the parser read `{` and started to process a JSON object
 37 |     object_start,
 38 |     /// the parser read `}` and finished processing a JSON object
 39 |     object_end,
 40 |     /// the parser read `[` and started to process a JSON array
 41 |     array_start,
 42 |     /// the parser read `]` and finished processing a JSON array
 43 |     array_end,
 44 |     /// the parser read a key of a value in an object
 45 |     key,
 46 |     /// the parser finished reading a JSON value
 47 |     value
 48 | };
 49 | 
 50 | template<typename BasicJsonType>
 51 | using parser_callback_t =
 52 |     std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
 53 | 
 54 | /*!
 55 | @brief syntax analysis
 56 | 
 57 | This class implements a recursive descent parser.
 58 | */
 59 | template<typename BasicJsonType, typename InputAdapterType>
 60 | class parser
 61 | {
 62 |     using number_integer_t = typename BasicJsonType::number_integer_t;
 63 |     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 64 |     using number_float_t = typename BasicJsonType::number_float_t;
 65 |     using string_t = typename BasicJsonType::string_t;
 66 |     using lexer_t = lexer<BasicJsonType, InputAdapterType>;
 67 |     using token_type = typename lexer_t::token_type;
 68 | 
 69 |   public:
 70 |     /// a parser reading from an input adapter
 71 |     explicit parser(InputAdapterType&& adapter,
 72 |                     const parser_callback_t<BasicJsonType> cb = nullptr,
 73 |                     const bool allow_exceptions_ = true,
 74 |                     const bool skip_comments = false)
 75 |         : callback(cb)
 76 |         , m_lexer(std::move(adapter), skip_comments)
 77 |         , allow_exceptions(allow_exceptions_)
 78 |     {
 79 |         // read first token
 80 |         get_token();
 81 |     }
 82 | 
 83 |     /*!
 84 |     @brief public parser interface
 85 | 
 86 |     @param[in] strict      whether to expect the last token to be EOF
 87 |     @param[in,out] result  parsed JSON value
 88 | 
 89 |     @throw parse_error.101 in case of an unexpected token
 90 |     @throw parse_error.102 if to_unicode fails or surrogate error
 91 |     @throw parse_error.103 if to_unicode fails
 92 |     */
 93 |     void parse(const bool strict, BasicJsonType& result)
 94 |     {
 95 |         if (callback)
 96 |         {
 97 |             json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
 98 |             sax_parse_internal(&sdp);
 99 | 
100 |             // in strict mode, input must be completely read
101 |             if (strict && (get_token() != token_type::end_of_input))
102 |             {
103 |                 sdp.parse_error(m_lexer.get_position(),
104 |                                 m_lexer.get_token_string(),
105 |                                 parse_error::create(101, m_lexer.get_position(),
106 |                                                     exception_message(token_type::end_of_input, "value"), nullptr));
107 |             }
108 | 
109 |             // in case of an error, return discarded value
110 |             if (sdp.is_errored())
111 |             {
112 |                 result = value_t::discarded;
113 |                 return;
114 |             }
115 | 
116 |             // set top-level value to null if it was discarded by the callback
117 |             // function
118 |             if (result.is_discarded())
119 |             {
120 |                 result = nullptr;
121 |             }
122 |         }
123 |         else
124 |         {
125 |             json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
126 |             sax_parse_internal(&sdp);
127 | 
128 |             // in strict mode, input must be completely read
129 |             if (strict && (get_token() != token_type::end_of_input))
130 |             {
131 |                 sdp.parse_error(m_lexer.get_position(),
132 |                                 m_lexer.get_token_string(),
133 |                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
134 |             }
135 | 
136 |             // in case of an error, return discarded value
137 |             if (sdp.is_errored())
138 |             {
139 |                 result = value_t::discarded;
140 |                 return;
141 |             }
142 |         }
143 | 
144 |         result.assert_invariant();
145 |     }
146 | 
147 |     /*!
148 |     @brief public accept interface
149 | 
150 |     @param[in] strict  whether to expect the last token to be EOF
151 |     @return whether the input is a proper JSON text
152 |     */
153 |     bool accept(const bool strict = true)
154 |     {
155 |         json_sax_acceptor<BasicJsonType> sax_acceptor;
156 |         return sax_parse(&sax_acceptor, strict);
157 |     }
158 | 
159 |     template<typename SAX>
160 |     JSON_HEDLEY_NON_NULL(2)
161 |     bool sax_parse(SAX* sax, const bool strict = true)
162 |     {
163 |         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
164 |         const bool result = sax_parse_internal(sax);
165 | 
166 |         // strict mode: next byte must be EOF
167 |         if (result && strict && (get_token() != token_type::end_of_input))
168 |         {
169 |             return sax->parse_error(m_lexer.get_position(),
170 |                                     m_lexer.get_token_string(),
171 |                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
172 |         }
173 | 
174 |         return result;
175 |     }
176 | 
177 |   private:
178 |     template<typename SAX>
179 |     JSON_HEDLEY_NON_NULL(2)
180 |     bool sax_parse_internal(SAX* sax)
181 |     {
182 |         // stack to remember the hierarchy of structured values we are parsing
183 |         // true = array; false = object
184 |         std::vector<bool> states;
185 |         // value to avoid a goto (see comment where set to true)
186 |         bool skip_to_state_evaluation = false;
187 | 
188 |         while (true)
189 |         {
190 |             if (!skip_to_state_evaluation)
191 |             {
192 |                 // invariant: get_token() was called before each iteration
193 |                 switch (last_token)
194 |                 {
195 |                     case token_type::begin_object:
196 |                     {
197 |                         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
198 |                         {
199 |                             return false;
200 |                         }
201 | 
202 |                         // closing } -> we are done
203 |                         if (get_token() == token_type::end_object)
204 |                         {
205 |                             if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
206 |                             {
207 |                                 return false;
208 |                             }
209 |                             break;
210 |                         }
211 | 
212 |                         // parse key
213 |                         if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
214 |                         {
215 |                             return sax->parse_error(m_lexer.get_position(),
216 |                                                     m_lexer.get_token_string(),
217 |                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
218 |                         }
219 |                         if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
220 |                         {
221 |                             return false;
222 |                         }
223 | 
224 |                         // parse separator (:)
225 |                         if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
226 |                         {
227 |                             return sax->parse_error(m_lexer.get_position(),
228 |                                                     m_lexer.get_token_string(),
229 |                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
230 |                         }
231 | 
232 |                         // remember we are now inside an object
233 |                         states.push_back(false);
234 | 
235 |                         // parse values
236 |                         get_token();
237 |                         continue;
238 |                     }
239 | 
240 |                     case token_type::begin_array:
241 |                     {
242 |                         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
243 |                         {
244 |                             return false;
245 |                         }
246 | 
247 |                         // closing ] -> we are done
248 |                         if (get_token() == token_type::end_array)
249 |                         {
250 |                             if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
251 |                             {
252 |                                 return false;
253 |                             }
254 |                             break;
255 |                         }
256 | 
257 |                         // remember we are now inside an array
258 |                         states.push_back(true);
259 | 
260 |                         // parse values (no need to call get_token)
261 |                         continue;
262 |                     }
263 | 
264 |                     case token_type::value_float:
265 |                     {
266 |                         const auto res = m_lexer.get_number_float();
267 | 
268 |                         if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
269 |                         {
270 |                             return sax->parse_error(m_lexer.get_position(),
271 |                                                     m_lexer.get_token_string(),
272 |                                                     out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
273 |                         }
274 | 
275 |                         if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
276 |                         {
277 |                             return false;
278 |                         }
279 | 
280 |                         break;
281 |                     }
282 | 
283 |                     case token_type::literal_false:
284 |                     {
285 |                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
286 |                         {
287 |                             return false;
288 |                         }
289 |                         break;
290 |                     }
291 | 
292 |                     case token_type::literal_null:
293 |                     {
294 |                         if (JSON_HEDLEY_UNLIKELY(!sax->null()))
295 |                         {
296 |                             return false;
297 |                         }
298 |                         break;
299 |                     }
300 | 
301 |                     case token_type::literal_true:
302 |                     {
303 |                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
304 |                         {
305 |                             return false;
306 |                         }
307 |                         break;
308 |                     }
309 | 
310 |                     case token_type::value_integer:
311 |                     {
312 |                         if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
313 |                         {
314 |                             return false;
315 |                         }
316 |                         break;
317 |                     }
318 | 
319 |                     case token_type::value_string:
320 |                     {
321 |                         if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
322 |                         {
323 |                             return false;
324 |                         }
325 |                         break;
326 |                     }
327 | 
328 |                     case token_type::value_unsigned:
329 |                     {
330 |                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
331 |                         {
332 |                             return false;
333 |                         }
334 |                         break;
335 |                     }
336 | 
337 |                     case token_type::parse_error:
338 |                     {
339 |                         // using "uninitialized" to avoid "expected" message
340 |                         return sax->parse_error(m_lexer.get_position(),
341 |                                                 m_lexer.get_token_string(),
342 |                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
343 |                     }
344 |                     case token_type::end_of_input:
345 |                     {
346 |                         if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
347 |                         {
348 |                             return sax->parse_error(m_lexer.get_position(),
349 |                                                     m_lexer.get_token_string(),
350 |                                                     parse_error::create(101, m_lexer.get_position(),
351 |                                                             "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
352 |                         }
353 | 
354 |                         return sax->parse_error(m_lexer.get_position(),
355 |                                                 m_lexer.get_token_string(),
356 |                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
357 |                     }
358 |                     case token_type::uninitialized:
359 |                     case token_type::end_array:
360 |                     case token_type::end_object:
361 |                     case token_type::name_separator:
362 |                     case token_type::value_separator:
363 |                     case token_type::literal_or_value:
364 |                     default: // the last token was unexpected
365 |                     {
366 |                         return sax->parse_error(m_lexer.get_position(),
367 |                                                 m_lexer.get_token_string(),
368 |                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
369 |                     }
370 |                 }
371 |             }
372 |             else
373 |             {
374 |                 skip_to_state_evaluation = false;
375 |             }
376 | 
377 |             // we reached this line after we successfully parsed a value
378 |             if (states.empty())
379 |             {
380 |                 // empty stack: we reached the end of the hierarchy: done
381 |                 return true;
382 |             }
383 | 
384 |             if (states.back())  // array
385 |             {
386 |                 // comma -> next value
387 |                 if (get_token() == token_type::value_separator)
388 |                 {
389 |                     // parse a new value
390 |                     get_token();
391 |                     continue;
392 |                 }
393 | 
394 |                 // closing ]
395 |                 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
396 |                 {
397 |                     if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
398 |                     {
399 |                         return false;
400 |                     }
401 | 
402 |                     // We are done with this array. Before we can parse a
403 |                     // new value, we need to evaluate the new state first.
404 |                     // By setting skip_to_state_evaluation to false, we
405 |                     // are effectively jumping to the beginning of this if.
406 |                     JSON_ASSERT(!states.empty());
407 |                     states.pop_back();
408 |                     skip_to_state_evaluation = true;
409 |                     continue;
410 |                 }
411 | 
412 |                 return sax->parse_error(m_lexer.get_position(),
413 |                                         m_lexer.get_token_string(),
414 |                                         parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
415 |             }
416 | 
417 |             // states.back() is false -> object
418 | 
419 |             // comma -> next value
420 |             if (get_token() == token_type::value_separator)
421 |             {
422 |                 // parse key
423 |                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
424 |                 {
425 |                     return sax->parse_error(m_lexer.get_position(),
426 |                                             m_lexer.get_token_string(),
427 |                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
428 |                 }
429 | 
430 |                 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
431 |                 {
432 |                     return false;
433 |                 }
434 | 
435 |                 // parse separator (:)
436 |                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
437 |                 {
438 |                     return sax->parse_error(m_lexer.get_position(),
439 |                                             m_lexer.get_token_string(),
440 |                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
441 |                 }
442 | 
443 |                 // parse values
444 |                 get_token();
445 |                 continue;
446 |             }
447 | 
448 |             // closing }
449 |             if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
450 |             {
451 |                 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
452 |                 {
453 |                     return false;
454 |                 }
455 | 
456 |                 // We are done with this object. Before we can parse a
457 |                 // new value, we need to evaluate the new state first.
458 |                 // By setting skip_to_state_evaluation to false, we
459 |                 // are effectively jumping to the beginning of this if.
460 |                 JSON_ASSERT(!states.empty());
461 |                 states.pop_back();
462 |                 skip_to_state_evaluation = true;
463 |                 continue;
464 |             }
465 | 
466 |             return sax->parse_error(m_lexer.get_position(),
467 |                                     m_lexer.get_token_string(),
468 |                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
469 |         }
470 |     }
471 | 
472 |     /// get next token from lexer
473 |     token_type get_token()
474 |     {
475 |         return last_token = m_lexer.scan();
476 |     }
477 | 
478 |     std::string exception_message(const token_type expected, const std::string& context)
479 |     {
480 |         std::string error_msg = "syntax error ";
481 | 
482 |         if (!context.empty())
483 |         {
484 |             error_msg += concat("while parsing ", context, ' ');
485 |         }
486 | 
487 |         error_msg += "- ";
488 | 
489 |         if (last_token == token_type::parse_error)
490 |         {
491 |             error_msg += concat(m_lexer.get_error_message(), "; last read: '",
492 |                                 m_lexer.get_token_string(), '\'');
493 |         }
494 |         else
495 |         {
496 |             error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
497 |         }
498 | 
499 |         if (expected != token_type::uninitialized)
500 |         {
501 |             error_msg += concat("; expected ", lexer_t::token_type_name(expected));
502 |         }
503 | 
504 |         return error_msg;
505 |     }
506 | 
507 |   private:
508 |     /// callback function
509 |     const parser_callback_t<BasicJsonType> callback = nullptr;
510 |     /// the type of the last read token
511 |     token_type last_token = token_type::uninitialized;
512 |     /// the lexer
513 |     lexer_t m_lexer;
514 |     /// whether to throw exceptions in case of errors
515 |     const bool allow_exceptions = true;
516 | };
517 | 
518 | }  // namespace detail
519 | NLOHMANN_JSON_NAMESPACE_END
520 | 
```
Page 4/21FirstPrevNextLast