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 | ```