This is page 21 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 -------------------------------------------------------------------------------- /include/nlohmann/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 | /****************************************************************************\ 10 | * Note on documentation: The source files contain links to the online * 11 | * documentation of the public API at https://json.nlohmann.me. This URL * 12 | * contains the most recent documentation and should also be applicable to * 13 | * previous versions; documentation for deprecated functions is not * 14 | * removed, but marked deprecated. See "Generate documentation" section in * 15 | * file docs/README.md. * 16 | \****************************************************************************/ 17 | 18 | #ifndef INCLUDE_NLOHMANN_JSON_HPP_ 19 | #define INCLUDE_NLOHMANN_JSON_HPP_ 20 | 21 | #include <algorithm> // all_of, find, for_each 22 | #include <cstddef> // nullptr_t, ptrdiff_t, size_t 23 | #include <functional> // hash, less 24 | #include <initializer_list> // initializer_list 25 | #ifndef JSON_NO_IO 26 | #include <iosfwd> // istream, ostream 27 | #endif // JSON_NO_IO 28 | #include <iterator> // random_access_iterator_tag 29 | #include <memory> // unique_ptr 30 | #include <string> // string, stoi, to_string 31 | #include <utility> // declval, forward, move, pair, swap 32 | #include <vector> // vector 33 | 34 | #include <nlohmann/adl_serializer.hpp> 35 | #include <nlohmann/byte_container_with_subtype.hpp> 36 | #include <nlohmann/detail/conversions/from_json.hpp> 37 | #include <nlohmann/detail/conversions/to_json.hpp> 38 | #include <nlohmann/detail/exceptions.hpp> 39 | #include <nlohmann/detail/hash.hpp> 40 | #include <nlohmann/detail/input/binary_reader.hpp> 41 | #include <nlohmann/detail/input/input_adapters.hpp> 42 | #include <nlohmann/detail/input/lexer.hpp> 43 | #include <nlohmann/detail/input/parser.hpp> 44 | #include <nlohmann/detail/iterators/internal_iterator.hpp> 45 | #include <nlohmann/detail/iterators/iter_impl.hpp> 46 | #include <nlohmann/detail/iterators/iteration_proxy.hpp> 47 | #include <nlohmann/detail/iterators/json_reverse_iterator.hpp> 48 | #include <nlohmann/detail/iterators/primitive_iterator.hpp> 49 | #include <nlohmann/detail/json_custom_base_class.hpp> 50 | #include <nlohmann/detail/json_pointer.hpp> 51 | #include <nlohmann/detail/json_ref.hpp> 52 | #include <nlohmann/detail/macro_scope.hpp> 53 | #include <nlohmann/detail/string_concat.hpp> 54 | #include <nlohmann/detail/string_escape.hpp> 55 | #include <nlohmann/detail/meta/cpp_future.hpp> 56 | #include <nlohmann/detail/meta/type_traits.hpp> 57 | #include <nlohmann/detail/output/binary_writer.hpp> 58 | #include <nlohmann/detail/output/output_adapters.hpp> 59 | #include <nlohmann/detail/output/serializer.hpp> 60 | #include <nlohmann/detail/value_t.hpp> 61 | #include <nlohmann/json_fwd.hpp> 62 | #include <nlohmann/ordered_map.hpp> 63 | 64 | #if defined(JSON_HAS_CPP_17) 65 | #if JSON_HAS_STATIC_RTTI 66 | #include <any> 67 | #endif 68 | #include <string_view> 69 | #endif 70 | 71 | /*! 72 | @brief namespace for Niels Lohmann 73 | @see https://github.com/nlohmann 74 | @since version 1.0.0 75 | */ 76 | NLOHMANN_JSON_NAMESPACE_BEGIN 77 | 78 | /*! 79 | @brief a class to store JSON values 80 | 81 | @internal 82 | @invariant The member variables @a m_value and @a m_type have the following 83 | relationship: 84 | - If `m_type == value_t::object`, then `m_value.object != nullptr`. 85 | - If `m_type == value_t::array`, then `m_value.array != nullptr`. 86 | - If `m_type == value_t::string`, then `m_value.string != nullptr`. 87 | The invariants are checked by member function assert_invariant(). 88 | 89 | @note ObjectType trick from https://stackoverflow.com/a/9860911 90 | @endinternal 91 | 92 | @since version 1.0.0 93 | 94 | @nosubgrouping 95 | */ 96 | NLOHMANN_BASIC_JSON_TPL_DECLARATION 97 | class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 98 | : public ::nlohmann::detail::json_base_class<CustomBaseClass> 99 | { 100 | private: 101 | template<detail::value_t> friend struct detail::external_constructor; 102 | 103 | template<typename> 104 | friend class ::nlohmann::json_pointer; 105 | // can be restored when json_pointer backwards compatibility is removed 106 | // friend ::nlohmann::json_pointer<StringType>; 107 | 108 | template<typename BasicJsonType, typename InputType> 109 | friend class ::nlohmann::detail::parser; 110 | friend ::nlohmann::detail::serializer<basic_json>; 111 | template<typename BasicJsonType> 112 | friend class ::nlohmann::detail::iter_impl; 113 | template<typename BasicJsonType, typename CharType> 114 | friend class ::nlohmann::detail::binary_writer; 115 | template<typename BasicJsonType, typename InputType, typename SAX> 116 | friend class ::nlohmann::detail::binary_reader; 117 | template<typename BasicJsonType> 118 | friend class ::nlohmann::detail::json_sax_dom_parser; 119 | template<typename BasicJsonType> 120 | friend class ::nlohmann::detail::json_sax_dom_callback_parser; 121 | friend class ::nlohmann::detail::exception; 122 | 123 | /// workaround type for MSVC 124 | using basic_json_t = NLOHMANN_BASIC_JSON_TPL; 125 | using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>; 126 | 127 | JSON_PRIVATE_UNLESS_TESTED: 128 | // convenience aliases for types residing in namespace detail; 129 | using lexer = ::nlohmann::detail::lexer_base<basic_json>; 130 | 131 | template<typename InputAdapterType> 132 | static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser( 133 | InputAdapterType adapter, 134 | detail::parser_callback_t<basic_json>cb = nullptr, 135 | const bool allow_exceptions = true, 136 | const bool ignore_comments = false 137 | ) 138 | { 139 | return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter), 140 | std::move(cb), allow_exceptions, ignore_comments); 141 | } 142 | 143 | private: 144 | using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; 145 | template<typename BasicJsonType> 146 | using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>; 147 | template<typename BasicJsonType> 148 | using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>; 149 | template<typename Iterator> 150 | using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>; 151 | template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>; 152 | 153 | template<typename CharType> 154 | using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>; 155 | 156 | template<typename InputType> 157 | using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>; 158 | template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>; 159 | 160 | JSON_PRIVATE_UNLESS_TESTED: 161 | using serializer = ::nlohmann::detail::serializer<basic_json>; 162 | 163 | public: 164 | using value_t = detail::value_t; 165 | /// JSON Pointer, see @ref nlohmann::json_pointer 166 | using json_pointer = ::nlohmann::json_pointer<StringType>; 167 | template<typename T, typename SFINAE> 168 | using json_serializer = JSONSerializer<T, SFINAE>; 169 | /// how to treat decoding errors 170 | using error_handler_t = detail::error_handler_t; 171 | /// how to treat CBOR tags 172 | using cbor_tag_handler_t = detail::cbor_tag_handler_t; 173 | /// helper type for initializer lists of basic_json values 174 | using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; 175 | 176 | using input_format_t = detail::input_format_t; 177 | /// SAX interface type, see @ref nlohmann::json_sax 178 | using json_sax_t = json_sax<basic_json>; 179 | 180 | //////////////// 181 | // exceptions // 182 | //////////////// 183 | 184 | /// @name exceptions 185 | /// Classes to implement user-defined exceptions. 186 | /// @{ 187 | 188 | using exception = detail::exception; 189 | using parse_error = detail::parse_error; 190 | using invalid_iterator = detail::invalid_iterator; 191 | using type_error = detail::type_error; 192 | using out_of_range = detail::out_of_range; 193 | using other_error = detail::other_error; 194 | 195 | /// @} 196 | 197 | ///////////////////// 198 | // container types // 199 | ///////////////////// 200 | 201 | /// @name container types 202 | /// The canonic container types to use @ref basic_json like any other STL 203 | /// container. 204 | /// @{ 205 | 206 | /// the type of elements in a basic_json container 207 | using value_type = basic_json; 208 | 209 | /// the type of an element reference 210 | using reference = value_type&; 211 | /// the type of an element const reference 212 | using const_reference = const value_type&; 213 | 214 | /// a type to represent differences between iterators 215 | using difference_type = std::ptrdiff_t; 216 | /// a type to represent container sizes 217 | using size_type = std::size_t; 218 | 219 | /// the allocator type 220 | using allocator_type = AllocatorType<basic_json>; 221 | 222 | /// the type of an element pointer 223 | using pointer = typename std::allocator_traits<allocator_type>::pointer; 224 | /// the type of an element const pointer 225 | using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer; 226 | 227 | /// an iterator for a basic_json container 228 | using iterator = iter_impl<basic_json>; 229 | /// a const iterator for a basic_json container 230 | using const_iterator = iter_impl<const basic_json>; 231 | /// a reverse iterator for a basic_json container 232 | using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>; 233 | /// a const reverse iterator for a basic_json container 234 | using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>; 235 | 236 | /// @} 237 | 238 | /// @brief returns the allocator associated with the container 239 | /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ 240 | static allocator_type get_allocator() 241 | { 242 | return allocator_type(); 243 | } 244 | 245 | /// @brief returns version information on the library 246 | /// @sa https://json.nlohmann.me/api/basic_json/meta/ 247 | JSON_HEDLEY_WARN_UNUSED_RESULT 248 | static basic_json meta() 249 | { 250 | basic_json result; 251 | 252 | result["copyright"] = "(C) 2013-2023 Niels Lohmann"; 253 | result["name"] = "JSON for Modern C++"; 254 | result["url"] = "https://github.com/nlohmann/json"; 255 | result["version"]["string"] = 256 | detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.', 257 | std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.', 258 | std::to_string(NLOHMANN_JSON_VERSION_PATCH)); 259 | result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; 260 | result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; 261 | result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; 262 | 263 | #ifdef _WIN32 264 | result["platform"] = "win32"; 265 | #elif defined __linux__ 266 | result["platform"] = "linux"; 267 | #elif defined __APPLE__ 268 | result["platform"] = "apple"; 269 | #elif defined __unix__ 270 | result["platform"] = "unix"; 271 | #else 272 | result["platform"] = "unknown"; 273 | #endif 274 | 275 | #if defined(__ICC) || defined(__INTEL_COMPILER) 276 | result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; 277 | #elif defined(__clang__) 278 | result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; 279 | #elif defined(__GNUC__) || defined(__GNUG__) 280 | result["compiler"] = {{"family", "gcc"}, {"version", detail::concat( 281 | std::to_string(__GNUC__), '.', 282 | std::to_string(__GNUC_MINOR__), '.', 283 | std::to_string(__GNUC_PATCHLEVEL__)) 284 | } 285 | }; 286 | #elif defined(__HP_cc) || defined(__HP_aCC) 287 | result["compiler"] = "hp" 288 | #elif defined(__IBMCPP__) 289 | result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; 290 | #elif defined(_MSC_VER) 291 | result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; 292 | #elif defined(__PGI) 293 | result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; 294 | #elif defined(__SUNPRO_CC) 295 | result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; 296 | #else 297 | result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; 298 | #endif 299 | 300 | #if defined(_MSVC_LANG) 301 | result["compiler"]["c++"] = std::to_string(_MSVC_LANG); 302 | #elif defined(__cplusplus) 303 | result["compiler"]["c++"] = std::to_string(__cplusplus); 304 | #else 305 | result["compiler"]["c++"] = "unknown"; 306 | #endif 307 | return result; 308 | } 309 | 310 | /////////////////////////// 311 | // JSON value data types // 312 | /////////////////////////// 313 | 314 | /// @name JSON value data types 315 | /// The data types to store a JSON value. These types are derived from 316 | /// the template arguments passed to class @ref basic_json. 317 | /// @{ 318 | 319 | /// @brief default object key comparator type 320 | /// The actual object key comparator type (@ref object_comparator_t) may be 321 | /// different. 322 | /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/ 323 | #if defined(JSON_HAS_CPP_14) 324 | // use of transparent comparator avoids unnecessary repeated construction of temporaries 325 | // in functions involving lookup by key with types other than object_t::key_type (aka. StringType) 326 | using default_object_comparator_t = std::less<>; 327 | #else 328 | using default_object_comparator_t = std::less<StringType>; 329 | #endif 330 | 331 | /// @brief a type for an object 332 | /// @sa https://json.nlohmann.me/api/basic_json/object_t/ 333 | using object_t = ObjectType<StringType, 334 | basic_json, 335 | default_object_comparator_t, 336 | AllocatorType<std::pair<const StringType, 337 | basic_json>>>; 338 | 339 | /// @brief a type for an array 340 | /// @sa https://json.nlohmann.me/api/basic_json/array_t/ 341 | using array_t = ArrayType<basic_json, AllocatorType<basic_json>>; 342 | 343 | /// @brief a type for a string 344 | /// @sa https://json.nlohmann.me/api/basic_json/string_t/ 345 | using string_t = StringType; 346 | 347 | /// @brief a type for a boolean 348 | /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/ 349 | using boolean_t = BooleanType; 350 | 351 | /// @brief a type for a number (integer) 352 | /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/ 353 | using number_integer_t = NumberIntegerType; 354 | 355 | /// @brief a type for a number (unsigned) 356 | /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/ 357 | using number_unsigned_t = NumberUnsignedType; 358 | 359 | /// @brief a type for a number (floating-point) 360 | /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/ 361 | using number_float_t = NumberFloatType; 362 | 363 | /// @brief a type for a packed binary type 364 | /// @sa https://json.nlohmann.me/api/basic_json/binary_t/ 365 | using binary_t = nlohmann::byte_container_with_subtype<BinaryType>; 366 | 367 | /// @brief object key comparator type 368 | /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/ 369 | using object_comparator_t = detail::actual_object_comparator_t<basic_json>; 370 | 371 | /// @} 372 | 373 | private: 374 | 375 | /// helper for exception-safe object creation 376 | template<typename T, typename... Args> 377 | JSON_HEDLEY_RETURNS_NON_NULL 378 | static T* create(Args&& ... args) 379 | { 380 | AllocatorType<T> alloc; 381 | using AllocatorTraits = std::allocator_traits<AllocatorType<T>>; 382 | 383 | auto deleter = [&](T * obj) 384 | { 385 | AllocatorTraits::deallocate(alloc, obj, 1); 386 | }; 387 | std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter); 388 | AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...); 389 | JSON_ASSERT(obj != nullptr); 390 | return obj.release(); 391 | } 392 | 393 | //////////////////////// 394 | // JSON value storage // 395 | //////////////////////// 396 | 397 | JSON_PRIVATE_UNLESS_TESTED: 398 | /*! 399 | @brief a JSON value 400 | 401 | The actual storage for a JSON value of the @ref basic_json class. This 402 | union combines the different storage types for the JSON value types 403 | defined in @ref value_t. 404 | 405 | JSON type | value_t type | used type 406 | --------- | --------------- | ------------------------ 407 | object | object | pointer to @ref object_t 408 | array | array | pointer to @ref array_t 409 | string | string | pointer to @ref string_t 410 | boolean | boolean | @ref boolean_t 411 | number | number_integer | @ref number_integer_t 412 | number | number_unsigned | @ref number_unsigned_t 413 | number | number_float | @ref number_float_t 414 | binary | binary | pointer to @ref binary_t 415 | null | null | *no value is stored* 416 | 417 | @note Variable-length types (objects, arrays, and strings) are stored as 418 | pointers. The size of the union should not exceed 64 bits if the default 419 | value types are used. 420 | 421 | @since version 1.0.0 422 | */ 423 | union json_value 424 | { 425 | /// object (stored with pointer to save storage) 426 | object_t* object; 427 | /// array (stored with pointer to save storage) 428 | array_t* array; 429 | /// string (stored with pointer to save storage) 430 | string_t* string; 431 | /// binary (stored with pointer to save storage) 432 | binary_t* binary; 433 | /// boolean 434 | boolean_t boolean; 435 | /// number (integer) 436 | number_integer_t number_integer; 437 | /// number (unsigned integer) 438 | number_unsigned_t number_unsigned; 439 | /// number (floating-point) 440 | number_float_t number_float; 441 | 442 | /// default constructor (for null values) 443 | json_value() = default; 444 | /// constructor for booleans 445 | json_value(boolean_t v) noexcept : boolean(v) {} 446 | /// constructor for numbers (integer) 447 | json_value(number_integer_t v) noexcept : number_integer(v) {} 448 | /// constructor for numbers (unsigned) 449 | json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} 450 | /// constructor for numbers (floating-point) 451 | json_value(number_float_t v) noexcept : number_float(v) {} 452 | /// constructor for empty values of a given type 453 | json_value(value_t t) 454 | { 455 | switch (t) 456 | { 457 | case value_t::object: 458 | { 459 | object = create<object_t>(); 460 | break; 461 | } 462 | 463 | case value_t::array: 464 | { 465 | array = create<array_t>(); 466 | break; 467 | } 468 | 469 | case value_t::string: 470 | { 471 | string = create<string_t>(""); 472 | break; 473 | } 474 | 475 | case value_t::binary: 476 | { 477 | binary = create<binary_t>(); 478 | break; 479 | } 480 | 481 | case value_t::boolean: 482 | { 483 | boolean = static_cast<boolean_t>(false); 484 | break; 485 | } 486 | 487 | case value_t::number_integer: 488 | { 489 | number_integer = static_cast<number_integer_t>(0); 490 | break; 491 | } 492 | 493 | case value_t::number_unsigned: 494 | { 495 | number_unsigned = static_cast<number_unsigned_t>(0); 496 | break; 497 | } 498 | 499 | case value_t::number_float: 500 | { 501 | number_float = static_cast<number_float_t>(0.0); 502 | break; 503 | } 504 | 505 | case value_t::null: 506 | { 507 | object = nullptr; // silence warning, see #821 508 | break; 509 | } 510 | 511 | case value_t::discarded: 512 | default: 513 | { 514 | object = nullptr; // silence warning, see #821 515 | if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) 516 | { 517 | JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE 518 | } 519 | break; 520 | } 521 | } 522 | } 523 | 524 | /// constructor for strings 525 | json_value(const string_t& value) : string(create<string_t>(value)) {} 526 | 527 | /// constructor for rvalue strings 528 | json_value(string_t&& value) : string(create<string_t>(std::move(value))) {} 529 | 530 | /// constructor for objects 531 | json_value(const object_t& value) : object(create<object_t>(value)) {} 532 | 533 | /// constructor for rvalue objects 534 | json_value(object_t&& value) : object(create<object_t>(std::move(value))) {} 535 | 536 | /// constructor for arrays 537 | json_value(const array_t& value) : array(create<array_t>(value)) {} 538 | 539 | /// constructor for rvalue arrays 540 | json_value(array_t&& value) : array(create<array_t>(std::move(value))) {} 541 | 542 | /// constructor for binary arrays 543 | json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {} 544 | 545 | /// constructor for rvalue binary arrays 546 | json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {} 547 | 548 | /// constructor for binary arrays (internal type) 549 | json_value(const binary_t& value) : binary(create<binary_t>(value)) {} 550 | 551 | /// constructor for rvalue binary arrays (internal type) 552 | json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {} 553 | 554 | void destroy(value_t t) 555 | { 556 | if ( 557 | (t == value_t::object && object == nullptr) || 558 | (t == value_t::array && array == nullptr) || 559 | (t == value_t::string && string == nullptr) || 560 | (t == value_t::binary && binary == nullptr) 561 | ) 562 | { 563 | //not initialized (e.g. due to exception in the ctor) 564 | return; 565 | } 566 | if (t == value_t::array || t == value_t::object) 567 | { 568 | // flatten the current json_value to a heap-allocated stack 569 | std::vector<basic_json> stack; 570 | 571 | // move the top-level items to stack 572 | if (t == value_t::array) 573 | { 574 | stack.reserve(array->size()); 575 | std::move(array->begin(), array->end(), std::back_inserter(stack)); 576 | } 577 | else 578 | { 579 | stack.reserve(object->size()); 580 | for (auto&& it : *object) 581 | { 582 | stack.push_back(std::move(it.second)); 583 | } 584 | } 585 | 586 | while (!stack.empty()) 587 | { 588 | // move the last item to local variable to be processed 589 | basic_json current_item(std::move(stack.back())); 590 | stack.pop_back(); 591 | 592 | // if current_item is array/object, move 593 | // its children to the stack to be processed later 594 | if (current_item.is_array()) 595 | { 596 | std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); 597 | 598 | current_item.m_data.m_value.array->clear(); 599 | } 600 | else if (current_item.is_object()) 601 | { 602 | for (auto&& it : *current_item.m_data.m_value.object) 603 | { 604 | stack.push_back(std::move(it.second)); 605 | } 606 | 607 | current_item.m_data.m_value.object->clear(); 608 | } 609 | 610 | // it's now safe that current_item get destructed 611 | // since it doesn't have any children 612 | } 613 | } 614 | 615 | switch (t) 616 | { 617 | case value_t::object: 618 | { 619 | AllocatorType<object_t> alloc; 620 | std::allocator_traits<decltype(alloc)>::destroy(alloc, object); 621 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1); 622 | break; 623 | } 624 | 625 | case value_t::array: 626 | { 627 | AllocatorType<array_t> alloc; 628 | std::allocator_traits<decltype(alloc)>::destroy(alloc, array); 629 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1); 630 | break; 631 | } 632 | 633 | case value_t::string: 634 | { 635 | AllocatorType<string_t> alloc; 636 | std::allocator_traits<decltype(alloc)>::destroy(alloc, string); 637 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1); 638 | break; 639 | } 640 | 641 | case value_t::binary: 642 | { 643 | AllocatorType<binary_t> alloc; 644 | std::allocator_traits<decltype(alloc)>::destroy(alloc, binary); 645 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1); 646 | break; 647 | } 648 | 649 | case value_t::null: 650 | case value_t::boolean: 651 | case value_t::number_integer: 652 | case value_t::number_unsigned: 653 | case value_t::number_float: 654 | case value_t::discarded: 655 | default: 656 | { 657 | break; 658 | } 659 | } 660 | } 661 | }; 662 | 663 | private: 664 | /*! 665 | @brief checks the class invariants 666 | 667 | This function asserts the class invariants. It needs to be called at the 668 | end of every constructor to make sure that created objects respect the 669 | invariant. Furthermore, it has to be called each time the type of a JSON 670 | value is changed, because the invariant expresses a relationship between 671 | @a m_type and @a m_value. 672 | 673 | Furthermore, the parent relation is checked for arrays and objects: If 674 | @a check_parents true and the value is an array or object, then the 675 | container's elements must have the current value as parent. 676 | 677 | @param[in] check_parents whether the parent relation should be checked. 678 | The value is true by default and should only be set to false 679 | during destruction of objects when the invariant does not 680 | need to hold. 681 | */ 682 | void assert_invariant(bool check_parents = true) const noexcept 683 | { 684 | JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr); 685 | JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr); 686 | JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr); 687 | JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr); 688 | 689 | #if JSON_DIAGNOSTICS 690 | JSON_TRY 691 | { 692 | // cppcheck-suppress assertWithSideEffect 693 | JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j) 694 | { 695 | return j.m_parent == this; 696 | })); 697 | } 698 | JSON_CATCH(...) {} // LCOV_EXCL_LINE 699 | #endif 700 | static_cast<void>(check_parents); 701 | } 702 | 703 | void set_parents() 704 | { 705 | #if JSON_DIAGNOSTICS 706 | switch (m_data.m_type) 707 | { 708 | case value_t::array: 709 | { 710 | for (auto& element : *m_data.m_value.array) 711 | { 712 | element.m_parent = this; 713 | } 714 | break; 715 | } 716 | 717 | case value_t::object: 718 | { 719 | for (auto& element : *m_data.m_value.object) 720 | { 721 | element.second.m_parent = this; 722 | } 723 | break; 724 | } 725 | 726 | case value_t::null: 727 | case value_t::string: 728 | case value_t::boolean: 729 | case value_t::number_integer: 730 | case value_t::number_unsigned: 731 | case value_t::number_float: 732 | case value_t::binary: 733 | case value_t::discarded: 734 | default: 735 | break; 736 | } 737 | #endif 738 | } 739 | 740 | iterator set_parents(iterator it, typename iterator::difference_type count_set_parents) 741 | { 742 | #if JSON_DIAGNOSTICS 743 | for (typename iterator::difference_type i = 0; i < count_set_parents; ++i) 744 | { 745 | (it + i)->m_parent = this; 746 | } 747 | #else 748 | static_cast<void>(count_set_parents); 749 | #endif 750 | return it; 751 | } 752 | 753 | reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1)) 754 | { 755 | #if JSON_DIAGNOSTICS 756 | if (old_capacity != static_cast<std::size_t>(-1)) 757 | { 758 | // see https://github.com/nlohmann/json/issues/2838 759 | JSON_ASSERT(type() == value_t::array); 760 | if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) 761 | { 762 | // capacity has changed: update all parents 763 | set_parents(); 764 | return j; 765 | } 766 | } 767 | 768 | // ordered_json uses a vector internally, so pointers could have 769 | // been invalidated; see https://github.com/nlohmann/json/issues/2962 770 | #ifdef JSON_HEDLEY_MSVC_VERSION 771 | #pragma warning(push ) 772 | #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr 773 | #endif 774 | if (detail::is_ordered_map<object_t>::value) 775 | { 776 | set_parents(); 777 | return j; 778 | } 779 | #ifdef JSON_HEDLEY_MSVC_VERSION 780 | #pragma warning( pop ) 781 | #endif 782 | 783 | j.m_parent = this; 784 | #else 785 | static_cast<void>(j); 786 | static_cast<void>(old_capacity); 787 | #endif 788 | return j; 789 | } 790 | 791 | public: 792 | ////////////////////////// 793 | // JSON parser callback // 794 | ////////////////////////// 795 | 796 | /// @brief parser event types 797 | /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/ 798 | using parse_event_t = detail::parse_event_t; 799 | 800 | /// @brief per-element parser callback type 801 | /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/ 802 | using parser_callback_t = detail::parser_callback_t<basic_json>; 803 | 804 | ////////////////// 805 | // constructors // 806 | ////////////////// 807 | 808 | /// @name constructors and destructors 809 | /// Constructors of class @ref basic_json, copy/move constructor, copy 810 | /// assignment, static functions creating objects, and the destructor. 811 | /// @{ 812 | 813 | /// @brief create an empty value with a given type 814 | /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 815 | basic_json(const value_t v) 816 | : m_data(v) 817 | { 818 | assert_invariant(); 819 | } 820 | 821 | /// @brief create a null object 822 | /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 823 | basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape) 824 | : basic_json(value_t::null) 825 | { 826 | assert_invariant(); 827 | } 828 | 829 | /// @brief create a JSON value from compatible types 830 | /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 831 | template < typename CompatibleType, 832 | typename U = detail::uncvref_t<CompatibleType>, 833 | detail::enable_if_t < 834 | !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 > 835 | basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) 836 | JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), 837 | std::forward<CompatibleType>(val)))) 838 | { 839 | JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val)); 840 | set_parents(); 841 | assert_invariant(); 842 | } 843 | 844 | /// @brief create a JSON value from an existing one 845 | /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 846 | template < typename BasicJsonType, 847 | detail::enable_if_t < 848 | detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 > 849 | basic_json(const BasicJsonType& val) 850 | { 851 | using other_boolean_t = typename BasicJsonType::boolean_t; 852 | using other_number_float_t = typename BasicJsonType::number_float_t; 853 | using other_number_integer_t = typename BasicJsonType::number_integer_t; 854 | using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; 855 | using other_string_t = typename BasicJsonType::string_t; 856 | using other_object_t = typename BasicJsonType::object_t; 857 | using other_array_t = typename BasicJsonType::array_t; 858 | using other_binary_t = typename BasicJsonType::binary_t; 859 | 860 | switch (val.type()) 861 | { 862 | case value_t::boolean: 863 | JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>()); 864 | break; 865 | case value_t::number_float: 866 | JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>()); 867 | break; 868 | case value_t::number_integer: 869 | JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>()); 870 | break; 871 | case value_t::number_unsigned: 872 | JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>()); 873 | break; 874 | case value_t::string: 875 | JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>()); 876 | break; 877 | case value_t::object: 878 | JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>()); 879 | break; 880 | case value_t::array: 881 | JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>()); 882 | break; 883 | case value_t::binary: 884 | JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>()); 885 | break; 886 | case value_t::null: 887 | *this = nullptr; 888 | break; 889 | case value_t::discarded: 890 | m_data.m_type = value_t::discarded; 891 | break; 892 | default: // LCOV_EXCL_LINE 893 | JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 894 | } 895 | JSON_ASSERT(m_data.m_type == val.type()); 896 | set_parents(); 897 | assert_invariant(); 898 | } 899 | 900 | /// @brief create a container (array or object) from an initializer list 901 | /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 902 | basic_json(initializer_list_t init, 903 | bool type_deduction = true, 904 | value_t manual_type = value_t::array) 905 | { 906 | // check if each element is an array with two elements whose first 907 | // element is a string 908 | bool is_an_object = std::all_of(init.begin(), init.end(), 909 | [](const detail::json_ref<basic_json>& element_ref) 910 | { 911 | // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int; 912 | // (many string types can be constructed from 0 via its null-pointer guise, so we get a 913 | // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows) 914 | return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string(); 915 | }); 916 | 917 | // adjust type if type deduction is not wanted 918 | if (!type_deduction) 919 | { 920 | // if array is wanted, do not create an object though possible 921 | if (manual_type == value_t::array) 922 | { 923 | is_an_object = false; 924 | } 925 | 926 | // if object is wanted but impossible, throw an exception 927 | if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) 928 | { 929 | JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr)); 930 | } 931 | } 932 | 933 | if (is_an_object) 934 | { 935 | // the initializer list is a list of pairs -> create object 936 | m_data.m_type = value_t::object; 937 | m_data.m_value = value_t::object; 938 | 939 | for (auto& element_ref : init) 940 | { 941 | auto element = element_ref.moved_or_copied(); 942 | m_data.m_value.object->emplace( 943 | std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)), 944 | std::move((*element.m_data.m_value.array)[1])); 945 | } 946 | } 947 | else 948 | { 949 | // the initializer list describes an array -> create array 950 | m_data.m_type = value_t::array; 951 | m_data.m_value.array = create<array_t>(init.begin(), init.end()); 952 | } 953 | 954 | set_parents(); 955 | assert_invariant(); 956 | } 957 | 958 | /// @brief explicitly create a binary array (without subtype) 959 | /// @sa https://json.nlohmann.me/api/basic_json/binary/ 960 | JSON_HEDLEY_WARN_UNUSED_RESULT 961 | static basic_json binary(const typename binary_t::container_type& init) 962 | { 963 | auto res = basic_json(); 964 | res.m_data.m_type = value_t::binary; 965 | res.m_data.m_value = init; 966 | return res; 967 | } 968 | 969 | /// @brief explicitly create a binary array (with subtype) 970 | /// @sa https://json.nlohmann.me/api/basic_json/binary/ 971 | JSON_HEDLEY_WARN_UNUSED_RESULT 972 | static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) 973 | { 974 | auto res = basic_json(); 975 | res.m_data.m_type = value_t::binary; 976 | res.m_data.m_value = binary_t(init, subtype); 977 | return res; 978 | } 979 | 980 | /// @brief explicitly create a binary array 981 | /// @sa https://json.nlohmann.me/api/basic_json/binary/ 982 | JSON_HEDLEY_WARN_UNUSED_RESULT 983 | static basic_json binary(typename binary_t::container_type&& init) 984 | { 985 | auto res = basic_json(); 986 | res.m_data.m_type = value_t::binary; 987 | res.m_data.m_value = std::move(init); 988 | return res; 989 | } 990 | 991 | /// @brief explicitly create a binary array (with subtype) 992 | /// @sa https://json.nlohmann.me/api/basic_json/binary/ 993 | JSON_HEDLEY_WARN_UNUSED_RESULT 994 | static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) 995 | { 996 | auto res = basic_json(); 997 | res.m_data.m_type = value_t::binary; 998 | res.m_data.m_value = binary_t(std::move(init), subtype); 999 | return res; 1000 | } 1001 | 1002 | /// @brief explicitly create an array from an initializer list 1003 | /// @sa https://json.nlohmann.me/api/basic_json/array/ 1004 | JSON_HEDLEY_WARN_UNUSED_RESULT 1005 | static basic_json array(initializer_list_t init = {}) 1006 | { 1007 | return basic_json(init, false, value_t::array); 1008 | } 1009 | 1010 | /// @brief explicitly create an object from an initializer list 1011 | /// @sa https://json.nlohmann.me/api/basic_json/object/ 1012 | JSON_HEDLEY_WARN_UNUSED_RESULT 1013 | static basic_json object(initializer_list_t init = {}) 1014 | { 1015 | return basic_json(init, false, value_t::object); 1016 | } 1017 | 1018 | /// @brief construct an array with count copies of given value 1019 | /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 1020 | basic_json(size_type cnt, const basic_json& val): 1021 | m_data{cnt, val} 1022 | { 1023 | set_parents(); 1024 | assert_invariant(); 1025 | } 1026 | 1027 | /// @brief construct a JSON container given an iterator range 1028 | /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 1029 | template < class InputIT, typename std::enable_if < 1030 | std::is_same<InputIT, typename basic_json_t::iterator>::value || 1031 | std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 > 1032 | basic_json(InputIT first, InputIT last) 1033 | { 1034 | JSON_ASSERT(first.m_object != nullptr); 1035 | JSON_ASSERT(last.m_object != nullptr); 1036 | 1037 | // make sure iterator fits the current value 1038 | if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 1039 | { 1040 | JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr)); 1041 | } 1042 | 1043 | // copy type from first iterator 1044 | m_data.m_type = first.m_object->m_data.m_type; 1045 | 1046 | // check if iterator range is complete for primitive values 1047 | switch (m_data.m_type) 1048 | { 1049 | case value_t::boolean: 1050 | case value_t::number_float: 1051 | case value_t::number_integer: 1052 | case value_t::number_unsigned: 1053 | case value_t::string: 1054 | { 1055 | if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() 1056 | || !last.m_it.primitive_iterator.is_end())) 1057 | { 1058 | JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object)); 1059 | } 1060 | break; 1061 | } 1062 | 1063 | case value_t::null: 1064 | case value_t::object: 1065 | case value_t::array: 1066 | case value_t::binary: 1067 | case value_t::discarded: 1068 | default: 1069 | break; 1070 | } 1071 | 1072 | switch (m_data.m_type) 1073 | { 1074 | case value_t::number_integer: 1075 | { 1076 | m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer; 1077 | break; 1078 | } 1079 | 1080 | case value_t::number_unsigned: 1081 | { 1082 | m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned; 1083 | break; 1084 | } 1085 | 1086 | case value_t::number_float: 1087 | { 1088 | m_data.m_value.number_float = first.m_object->m_data.m_value.number_float; 1089 | break; 1090 | } 1091 | 1092 | case value_t::boolean: 1093 | { 1094 | m_data.m_value.boolean = first.m_object->m_data.m_value.boolean; 1095 | break; 1096 | } 1097 | 1098 | case value_t::string: 1099 | { 1100 | m_data.m_value = *first.m_object->m_data.m_value.string; 1101 | break; 1102 | } 1103 | 1104 | case value_t::object: 1105 | { 1106 | m_data.m_value.object = create<object_t>(first.m_it.object_iterator, 1107 | last.m_it.object_iterator); 1108 | break; 1109 | } 1110 | 1111 | case value_t::array: 1112 | { 1113 | m_data.m_value.array = create<array_t>(first.m_it.array_iterator, 1114 | last.m_it.array_iterator); 1115 | break; 1116 | } 1117 | 1118 | case value_t::binary: 1119 | { 1120 | m_data.m_value = *first.m_object->m_data.m_value.binary; 1121 | break; 1122 | } 1123 | 1124 | case value_t::null: 1125 | case value_t::discarded: 1126 | default: 1127 | JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object)); 1128 | } 1129 | 1130 | set_parents(); 1131 | assert_invariant(); 1132 | } 1133 | 1134 | /////////////////////////////////////// 1135 | // other constructors and destructor // 1136 | /////////////////////////////////////// 1137 | 1138 | template<typename JsonRef, 1139 | detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>, 1140 | std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 > 1141 | basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} 1142 | 1143 | /// @brief copy constructor 1144 | /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 1145 | basic_json(const basic_json& other) 1146 | : json_base_class_t(other) 1147 | { 1148 | m_data.m_type = other.m_data.m_type; 1149 | // check of passed value is valid 1150 | other.assert_invariant(); 1151 | 1152 | switch (m_data.m_type) 1153 | { 1154 | case value_t::object: 1155 | { 1156 | m_data.m_value = *other.m_data.m_value.object; 1157 | break; 1158 | } 1159 | 1160 | case value_t::array: 1161 | { 1162 | m_data.m_value = *other.m_data.m_value.array; 1163 | break; 1164 | } 1165 | 1166 | case value_t::string: 1167 | { 1168 | m_data.m_value = *other.m_data.m_value.string; 1169 | break; 1170 | } 1171 | 1172 | case value_t::boolean: 1173 | { 1174 | m_data.m_value = other.m_data.m_value.boolean; 1175 | break; 1176 | } 1177 | 1178 | case value_t::number_integer: 1179 | { 1180 | m_data.m_value = other.m_data.m_value.number_integer; 1181 | break; 1182 | } 1183 | 1184 | case value_t::number_unsigned: 1185 | { 1186 | m_data.m_value = other.m_data.m_value.number_unsigned; 1187 | break; 1188 | } 1189 | 1190 | case value_t::number_float: 1191 | { 1192 | m_data.m_value = other.m_data.m_value.number_float; 1193 | break; 1194 | } 1195 | 1196 | case value_t::binary: 1197 | { 1198 | m_data.m_value = *other.m_data.m_value.binary; 1199 | break; 1200 | } 1201 | 1202 | case value_t::null: 1203 | case value_t::discarded: 1204 | default: 1205 | break; 1206 | } 1207 | 1208 | set_parents(); 1209 | assert_invariant(); 1210 | } 1211 | 1212 | /// @brief move constructor 1213 | /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ 1214 | basic_json(basic_json&& other) noexcept 1215 | : json_base_class_t(std::forward<json_base_class_t>(other)), 1216 | m_data(std::move(other.m_data)) 1217 | { 1218 | // check that passed value is valid 1219 | other.assert_invariant(false); 1220 | 1221 | // invalidate payload 1222 | other.m_data.m_type = value_t::null; 1223 | other.m_data.m_value = {}; 1224 | 1225 | set_parents(); 1226 | assert_invariant(); 1227 | } 1228 | 1229 | /// @brief copy assignment 1230 | /// @sa https://json.nlohmann.me/api/basic_json/operator=/ 1231 | basic_json& operator=(basic_json other) noexcept ( 1232 | std::is_nothrow_move_constructible<value_t>::value&& 1233 | std::is_nothrow_move_assignable<value_t>::value&& 1234 | std::is_nothrow_move_constructible<json_value>::value&& 1235 | std::is_nothrow_move_assignable<json_value>::value&& 1236 | std::is_nothrow_move_assignable<json_base_class_t>::value 1237 | ) 1238 | { 1239 | // check that passed value is valid 1240 | other.assert_invariant(); 1241 | 1242 | using std::swap; 1243 | swap(m_data.m_type, other.m_data.m_type); 1244 | swap(m_data.m_value, other.m_data.m_value); 1245 | json_base_class_t::operator=(std::move(other)); 1246 | 1247 | set_parents(); 1248 | assert_invariant(); 1249 | return *this; 1250 | } 1251 | 1252 | /// @brief destructor 1253 | /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/ 1254 | ~basic_json() noexcept 1255 | { 1256 | assert_invariant(false); 1257 | } 1258 | 1259 | /// @} 1260 | 1261 | public: 1262 | /////////////////////// 1263 | // object inspection // 1264 | /////////////////////// 1265 | 1266 | /// @name object inspection 1267 | /// Functions to inspect the type of a JSON value. 1268 | /// @{ 1269 | 1270 | /// @brief serialization 1271 | /// @sa https://json.nlohmann.me/api/basic_json/dump/ 1272 | string_t dump(const int indent = -1, 1273 | const char indent_char = ' ', 1274 | const bool ensure_ascii = false, 1275 | const error_handler_t error_handler = error_handler_t::strict) const 1276 | { 1277 | string_t result; 1278 | serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler); 1279 | 1280 | if (indent >= 0) 1281 | { 1282 | s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent)); 1283 | } 1284 | else 1285 | { 1286 | s.dump(*this, false, ensure_ascii, 0); 1287 | } 1288 | 1289 | return result; 1290 | } 1291 | 1292 | /// @brief return the type of the JSON value (explicit) 1293 | /// @sa https://json.nlohmann.me/api/basic_json/type/ 1294 | constexpr value_t type() const noexcept 1295 | { 1296 | return m_data.m_type; 1297 | } 1298 | 1299 | /// @brief return whether type is primitive 1300 | /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/ 1301 | constexpr bool is_primitive() const noexcept 1302 | { 1303 | return is_null() || is_string() || is_boolean() || is_number() || is_binary(); 1304 | } 1305 | 1306 | /// @brief return whether type is structured 1307 | /// @sa https://json.nlohmann.me/api/basic_json/is_structured/ 1308 | constexpr bool is_structured() const noexcept 1309 | { 1310 | return is_array() || is_object(); 1311 | } 1312 | 1313 | /// @brief return whether value is null 1314 | /// @sa https://json.nlohmann.me/api/basic_json/is_null/ 1315 | constexpr bool is_null() const noexcept 1316 | { 1317 | return m_data.m_type == value_t::null; 1318 | } 1319 | 1320 | /// @brief return whether value is a boolean 1321 | /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ 1322 | constexpr bool is_boolean() const noexcept 1323 | { 1324 | return m_data.m_type == value_t::boolean; 1325 | } 1326 | 1327 | /// @brief return whether value is a number 1328 | /// @sa https://json.nlohmann.me/api/basic_json/is_number/ 1329 | constexpr bool is_number() const noexcept 1330 | { 1331 | return is_number_integer() || is_number_float(); 1332 | } 1333 | 1334 | /// @brief return whether value is an integer number 1335 | /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ 1336 | constexpr bool is_number_integer() const noexcept 1337 | { 1338 | return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned; 1339 | } 1340 | 1341 | /// @brief return whether value is an unsigned integer number 1342 | /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ 1343 | constexpr bool is_number_unsigned() const noexcept 1344 | { 1345 | return m_data.m_type == value_t::number_unsigned; 1346 | } 1347 | 1348 | /// @brief return whether value is a floating-point number 1349 | /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ 1350 | constexpr bool is_number_float() const noexcept 1351 | { 1352 | return m_data.m_type == value_t::number_float; 1353 | } 1354 | 1355 | /// @brief return whether value is an object 1356 | /// @sa https://json.nlohmann.me/api/basic_json/is_object/ 1357 | constexpr bool is_object() const noexcept 1358 | { 1359 | return m_data.m_type == value_t::object; 1360 | } 1361 | 1362 | /// @brief return whether value is an array 1363 | /// @sa https://json.nlohmann.me/api/basic_json/is_array/ 1364 | constexpr bool is_array() const noexcept 1365 | { 1366 | return m_data.m_type == value_t::array; 1367 | } 1368 | 1369 | /// @brief return whether value is a string 1370 | /// @sa https://json.nlohmann.me/api/basic_json/is_string/ 1371 | constexpr bool is_string() const noexcept 1372 | { 1373 | return m_data.m_type == value_t::string; 1374 | } 1375 | 1376 | /// @brief return whether value is a binary array 1377 | /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ 1378 | constexpr bool is_binary() const noexcept 1379 | { 1380 | return m_data.m_type == value_t::binary; 1381 | } 1382 | 1383 | /// @brief return whether value is discarded 1384 | /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ 1385 | constexpr bool is_discarded() const noexcept 1386 | { 1387 | return m_data.m_type == value_t::discarded; 1388 | } 1389 | 1390 | /// @brief return the type of the JSON value (implicit) 1391 | /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ 1392 | constexpr operator value_t() const noexcept 1393 | { 1394 | return m_data.m_type; 1395 | } 1396 | 1397 | /// @} 1398 | 1399 | private: 1400 | ////////////////// 1401 | // value access // 1402 | ////////////////// 1403 | 1404 | /// get a boolean (explicit) 1405 | boolean_t get_impl(boolean_t* /*unused*/) const 1406 | { 1407 | if (JSON_HEDLEY_LIKELY(is_boolean())) 1408 | { 1409 | return m_data.m_value.boolean; 1410 | } 1411 | 1412 | JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this)); 1413 | } 1414 | 1415 | /// get a pointer to the value (object) 1416 | object_t* get_impl_ptr(object_t* /*unused*/) noexcept 1417 | { 1418 | return is_object() ? m_data.m_value.object : nullptr; 1419 | } 1420 | 1421 | /// get a pointer to the value (object) 1422 | constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept 1423 | { 1424 | return is_object() ? m_data.m_value.object : nullptr; 1425 | } 1426 | 1427 | /// get a pointer to the value (array) 1428 | array_t* get_impl_ptr(array_t* /*unused*/) noexcept 1429 | { 1430 | return is_array() ? m_data.m_value.array : nullptr; 1431 | } 1432 | 1433 | /// get a pointer to the value (array) 1434 | constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept 1435 | { 1436 | return is_array() ? m_data.m_value.array : nullptr; 1437 | } 1438 | 1439 | /// get a pointer to the value (string) 1440 | string_t* get_impl_ptr(string_t* /*unused*/) noexcept 1441 | { 1442 | return is_string() ? m_data.m_value.string : nullptr; 1443 | } 1444 | 1445 | /// get a pointer to the value (string) 1446 | constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept 1447 | { 1448 | return is_string() ? m_data.m_value.string : nullptr; 1449 | } 1450 | 1451 | /// get a pointer to the value (boolean) 1452 | boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept 1453 | { 1454 | return is_boolean() ? &m_data.m_value.boolean : nullptr; 1455 | } 1456 | 1457 | /// get a pointer to the value (boolean) 1458 | constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept 1459 | { 1460 | return is_boolean() ? &m_data.m_value.boolean : nullptr; 1461 | } 1462 | 1463 | /// get a pointer to the value (integer number) 1464 | number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept 1465 | { 1466 | return is_number_integer() ? &m_data.m_value.number_integer : nullptr; 1467 | } 1468 | 1469 | /// get a pointer to the value (integer number) 1470 | constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept 1471 | { 1472 | return is_number_integer() ? &m_data.m_value.number_integer : nullptr; 1473 | } 1474 | 1475 | /// get a pointer to the value (unsigned number) 1476 | number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept 1477 | { 1478 | return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; 1479 | } 1480 | 1481 | /// get a pointer to the value (unsigned number) 1482 | constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept 1483 | { 1484 | return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; 1485 | } 1486 | 1487 | /// get a pointer to the value (floating-point number) 1488 | number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept 1489 | { 1490 | return is_number_float() ? &m_data.m_value.number_float : nullptr; 1491 | } 1492 | 1493 | /// get a pointer to the value (floating-point number) 1494 | constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept 1495 | { 1496 | return is_number_float() ? &m_data.m_value.number_float : nullptr; 1497 | } 1498 | 1499 | /// get a pointer to the value (binary) 1500 | binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept 1501 | { 1502 | return is_binary() ? m_data.m_value.binary : nullptr; 1503 | } 1504 | 1505 | /// get a pointer to the value (binary) 1506 | constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept 1507 | { 1508 | return is_binary() ? m_data.m_value.binary : nullptr; 1509 | } 1510 | 1511 | /*! 1512 | @brief helper function to implement get_ref() 1513 | 1514 | This function helps to implement get_ref() without code duplication for 1515 | const and non-const overloads 1516 | 1517 | @tparam ThisType will be deduced as `basic_json` or `const basic_json` 1518 | 1519 | @throw type_error.303 if ReferenceType does not match underlying value 1520 | type of the current JSON 1521 | */ 1522 | template<typename ReferenceType, typename ThisType> 1523 | static ReferenceType get_ref_impl(ThisType& obj) 1524 | { 1525 | // delegate the call to get_ptr<>() 1526 | auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>(); 1527 | 1528 | if (JSON_HEDLEY_LIKELY(ptr != nullptr)) 1529 | { 1530 | return *ptr; 1531 | } 1532 | 1533 | JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj)); 1534 | } 1535 | 1536 | public: 1537 | /// @name value access 1538 | /// Direct access to the stored value of a JSON value. 1539 | /// @{ 1540 | 1541 | /// @brief get a pointer value (implicit) 1542 | /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 1543 | template<typename PointerType, typename std::enable_if< 1544 | std::is_pointer<PointerType>::value, int>::type = 0> 1545 | auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) 1546 | { 1547 | // delegate the call to get_impl_ptr<>() 1548 | return get_impl_ptr(static_cast<PointerType>(nullptr)); 1549 | } 1550 | 1551 | /// @brief get a pointer value (implicit) 1552 | /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/ 1553 | template < typename PointerType, typename std::enable_if < 1554 | std::is_pointer<PointerType>::value&& 1555 | std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 > 1556 | constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) 1557 | { 1558 | // delegate the call to get_impl_ptr<>() const 1559 | return get_impl_ptr(static_cast<PointerType>(nullptr)); 1560 | } 1561 | 1562 | private: 1563 | /*! 1564 | @brief get a value (explicit) 1565 | 1566 | Explicit type conversion between the JSON value and a compatible value 1567 | which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 1568 | and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 1569 | The value is converted by calling the @ref json_serializer<ValueType> 1570 | `from_json()` method. 1571 | 1572 | The function is equivalent to executing 1573 | @code {.cpp} 1574 | ValueType ret; 1575 | JSONSerializer<ValueType>::from_json(*this, ret); 1576 | return ret; 1577 | @endcode 1578 | 1579 | This overloads is chosen if: 1580 | - @a ValueType is not @ref basic_json, 1581 | - @ref json_serializer<ValueType> has a `from_json()` method of the form 1582 | `void from_json(const basic_json&, ValueType&)`, and 1583 | - @ref json_serializer<ValueType> does not have a `from_json()` method of 1584 | the form `ValueType from_json(const basic_json&)` 1585 | 1586 | @tparam ValueType the returned value type 1587 | 1588 | @return copy of the JSON value, converted to @a ValueType 1589 | 1590 | @throw what @ref json_serializer<ValueType> `from_json()` method throws 1591 | 1592 | @liveexample{The example below shows several conversions from JSON values 1593 | to other types. There a few things to note: (1) Floating-point numbers can 1594 | be converted to integers\, (2) A JSON array can be converted to a standard 1595 | `std::vector<short>`\, (3) A JSON object can be converted to C++ 1596 | associative containers such as `std::unordered_map<std::string\, 1597 | json>`.,get__ValueType_const} 1598 | 1599 | @since version 2.1.0 1600 | */ 1601 | template < typename ValueType, 1602 | detail::enable_if_t < 1603 | detail::is_default_constructible<ValueType>::value&& 1604 | detail::has_from_json<basic_json_t, ValueType>::value, 1605 | int > = 0 > 1606 | ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( 1607 | JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) 1608 | { 1609 | auto ret = ValueType(); 1610 | JSONSerializer<ValueType>::from_json(*this, ret); 1611 | return ret; 1612 | } 1613 | 1614 | /*! 1615 | @brief get a value (explicit); special case 1616 | 1617 | Explicit type conversion between the JSON value and a compatible value 1618 | which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) 1619 | and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). 1620 | The value is converted by calling the @ref json_serializer<ValueType> 1621 | `from_json()` method. 1622 | 1623 | The function is equivalent to executing 1624 | @code {.cpp} 1625 | return JSONSerializer<ValueType>::from_json(*this); 1626 | @endcode 1627 | 1628 | This overloads is chosen if: 1629 | - @a ValueType is not @ref basic_json and 1630 | - @ref json_serializer<ValueType> has a `from_json()` method of the form 1631 | `ValueType from_json(const basic_json&)` 1632 | 1633 | @note If @ref json_serializer<ValueType> has both overloads of 1634 | `from_json()`, this one is chosen. 1635 | 1636 | @tparam ValueType the returned value type 1637 | 1638 | @return copy of the JSON value, converted to @a ValueType 1639 | 1640 | @throw what @ref json_serializer<ValueType> `from_json()` method throws 1641 | 1642 | @since version 2.1.0 1643 | */ 1644 | template < typename ValueType, 1645 | detail::enable_if_t < 1646 | detail::has_non_default_from_json<basic_json_t, ValueType>::value, 1647 | int > = 0 > 1648 | ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( 1649 | JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>()))) 1650 | { 1651 | return JSONSerializer<ValueType>::from_json(*this); 1652 | } 1653 | 1654 | /*! 1655 | @brief get special-case overload 1656 | 1657 | This overloads converts the current @ref basic_json in a different 1658 | @ref basic_json type 1659 | 1660 | @tparam BasicJsonType == @ref basic_json 1661 | 1662 | @return a copy of *this, converted into @a BasicJsonType 1663 | 1664 | @complexity Depending on the implementation of the called `from_json()` 1665 | method. 1666 | 1667 | @since version 3.2.0 1668 | */ 1669 | template < typename BasicJsonType, 1670 | detail::enable_if_t < 1671 | detail::is_basic_json<BasicJsonType>::value, 1672 | int > = 0 > 1673 | BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const 1674 | { 1675 | return *this; 1676 | } 1677 | 1678 | /*! 1679 | @brief get special-case overload 1680 | 1681 | This overloads avoids a lot of template boilerplate, it can be seen as the 1682 | identity method 1683 | 1684 | @tparam BasicJsonType == @ref basic_json 1685 | 1686 | @return a copy of *this 1687 | 1688 | @complexity Constant. 1689 | 1690 | @since version 2.1.0 1691 | */ 1692 | template<typename BasicJsonType, 1693 | detail::enable_if_t< 1694 | std::is_same<BasicJsonType, basic_json_t>::value, 1695 | int> = 0> 1696 | basic_json get_impl(detail::priority_tag<3> /*unused*/) const 1697 | { 1698 | return *this; 1699 | } 1700 | 1701 | /*! 1702 | @brief get a pointer value (explicit) 1703 | @copydoc get() 1704 | */ 1705 | template<typename PointerType, 1706 | detail::enable_if_t< 1707 | std::is_pointer<PointerType>::value, 1708 | int> = 0> 1709 | constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept 1710 | -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>()) 1711 | { 1712 | // delegate the call to get_ptr 1713 | return get_ptr<PointerType>(); 1714 | } 1715 | 1716 | public: 1717 | /*! 1718 | @brief get a (pointer) value (explicit) 1719 | 1720 | Performs explicit type conversion between the JSON value and a compatible value if required. 1721 | 1722 | - If the requested type is a pointer to the internally stored JSON value that pointer is returned. 1723 | No copies are made. 1724 | 1725 | - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible 1726 | from the current @ref basic_json. 1727 | 1728 | - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()` 1729 | method. 1730 | 1731 | @tparam ValueTypeCV the provided value type 1732 | @tparam ValueType the returned value type 1733 | 1734 | @return copy of the JSON value, converted to @tparam ValueType if necessary 1735 | 1736 | @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required 1737 | 1738 | @since version 2.1.0 1739 | */ 1740 | template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>> 1741 | #if defined(JSON_HAS_CPP_14) 1742 | constexpr 1743 | #endif 1744 | auto get() const noexcept( 1745 | noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))) 1746 | -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})) 1747 | { 1748 | // we cannot static_assert on ValueTypeCV being non-const, because 1749 | // there is support for get<const basic_json_t>(), which is why we 1750 | // still need the uncvref 1751 | static_assert(!std::is_reference<ValueTypeCV>::value, 1752 | "get() cannot be used with reference types, you might want to use get_ref()"); 1753 | return get_impl<ValueType>(detail::priority_tag<4> {}); 1754 | } 1755 | 1756 | /*! 1757 | @brief get a pointer value (explicit) 1758 | 1759 | Explicit pointer access to the internally stored JSON value. No copies are 1760 | made. 1761 | 1762 | @warning The pointer becomes invalid if the underlying JSON object 1763 | changes. 1764 | 1765 | @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref 1766 | object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, 1767 | @ref number_unsigned_t, or @ref number_float_t. 1768 | 1769 | @return pointer to the internally stored JSON value if the requested 1770 | pointer type @a PointerType fits to the JSON value; `nullptr` otherwise 1771 | 1772 | @complexity Constant. 1773 | 1774 | @liveexample{The example below shows how pointers to internal values of a 1775 | JSON value can be requested. Note that no type conversions are made and a 1776 | `nullptr` is returned if the value and the requested pointer type does not 1777 | match.,get__PointerType} 1778 | 1779 | @sa see @ref get_ptr() for explicit pointer-member access 1780 | 1781 | @since version 1.0.0 1782 | */ 1783 | template<typename PointerType, typename std::enable_if< 1784 | std::is_pointer<PointerType>::value, int>::type = 0> 1785 | auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>()) 1786 | { 1787 | // delegate the call to get_ptr 1788 | return get_ptr<PointerType>(); 1789 | } 1790 | 1791 | /// @brief get a value (explicit) 1792 | /// @sa https://json.nlohmann.me/api/basic_json/get_to/ 1793 | template < typename ValueType, 1794 | detail::enable_if_t < 1795 | !detail::is_basic_json<ValueType>::value&& 1796 | detail::has_from_json<basic_json_t, ValueType>::value, 1797 | int > = 0 > 1798 | ValueType & get_to(ValueType& v) const noexcept(noexcept( 1799 | JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v))) 1800 | { 1801 | JSONSerializer<ValueType>::from_json(*this, v); 1802 | return v; 1803 | } 1804 | 1805 | // specialization to allow calling get_to with a basic_json value 1806 | // see https://github.com/nlohmann/json/issues/2175 1807 | template<typename ValueType, 1808 | detail::enable_if_t < 1809 | detail::is_basic_json<ValueType>::value, 1810 | int> = 0> 1811 | ValueType & get_to(ValueType& v) const 1812 | { 1813 | v = *this; 1814 | return v; 1815 | } 1816 | 1817 | template < 1818 | typename T, std::size_t N, 1819 | typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 1820 | detail::enable_if_t < 1821 | detail::has_from_json<basic_json_t, Array>::value, int > = 0 > 1822 | Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 1823 | noexcept(noexcept(JSONSerializer<Array>::from_json( 1824 | std::declval<const basic_json_t&>(), v))) 1825 | { 1826 | JSONSerializer<Array>::from_json(*this, v); 1827 | return v; 1828 | } 1829 | 1830 | /// @brief get a reference value (implicit) 1831 | /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 1832 | template<typename ReferenceType, typename std::enable_if< 1833 | std::is_reference<ReferenceType>::value, int>::type = 0> 1834 | ReferenceType get_ref() 1835 | { 1836 | // delegate call to get_ref_impl 1837 | return get_ref_impl<ReferenceType>(*this); 1838 | } 1839 | 1840 | /// @brief get a reference value (implicit) 1841 | /// @sa https://json.nlohmann.me/api/basic_json/get_ref/ 1842 | template < typename ReferenceType, typename std::enable_if < 1843 | std::is_reference<ReferenceType>::value&& 1844 | std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 > 1845 | ReferenceType get_ref() const 1846 | { 1847 | // delegate call to get_ref_impl 1848 | return get_ref_impl<ReferenceType>(*this); 1849 | } 1850 | 1851 | /*! 1852 | @brief get a value (implicit) 1853 | 1854 | Implicit type conversion between the JSON value and a compatible value. 1855 | The call is realized by calling @ref get() const. 1856 | 1857 | @tparam ValueType non-pointer type compatible to the JSON value, for 1858 | instance `int` for JSON integer numbers, `bool` for JSON booleans, or 1859 | `std::vector` types for JSON arrays. The character type of @ref string_t 1860 | as well as an initializer list of this type is excluded to avoid 1861 | ambiguities as these types implicitly convert to `std::string`. 1862 | 1863 | @return copy of the JSON value, converted to type @a ValueType 1864 | 1865 | @throw type_error.302 in case passed type @a ValueType is incompatible 1866 | to the JSON value type (e.g., the JSON value is of type boolean, but a 1867 | string is requested); see example below 1868 | 1869 | @complexity Linear in the size of the JSON value. 1870 | 1871 | @liveexample{The example below shows several conversions from JSON values 1872 | to other types. There a few things to note: (1) Floating-point numbers can 1873 | be converted to integers\, (2) A JSON array can be converted to a standard 1874 | `std::vector<short>`\, (3) A JSON object can be converted to C++ 1875 | associative containers such as `std::unordered_map<std::string\, 1876 | json>`.,operator__ValueType} 1877 | 1878 | @since version 1.0.0 1879 | */ 1880 | template < typename ValueType, typename std::enable_if < 1881 | detail::conjunction < 1882 | detail::negation<std::is_pointer<ValueType>>, 1883 | detail::negation<std::is_same<ValueType, std::nullptr_t>>, 1884 | detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>, 1885 | detail::negation<std::is_same<ValueType, typename string_t::value_type>>, 1886 | detail::negation<detail::is_basic_json<ValueType>>, 1887 | detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>, 1888 | #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) 1889 | detail::negation<std::is_same<ValueType, std::string_view>>, 1890 | #endif 1891 | #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI 1892 | detail::negation<std::is_same<ValueType, std::any>>, 1893 | #endif 1894 | detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType> 1895 | >::value, int >::type = 0 > 1896 | JSON_EXPLICIT operator ValueType() const 1897 | { 1898 | // delegate the call to get<>() const 1899 | return get<ValueType>(); 1900 | } 1901 | 1902 | /// @brief get a binary value 1903 | /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 1904 | binary_t& get_binary() 1905 | { 1906 | if (!is_binary()) 1907 | { 1908 | JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); 1909 | } 1910 | 1911 | return *get_ptr<binary_t*>(); 1912 | } 1913 | 1914 | /// @brief get a binary value 1915 | /// @sa https://json.nlohmann.me/api/basic_json/get_binary/ 1916 | const binary_t& get_binary() const 1917 | { 1918 | if (!is_binary()) 1919 | { 1920 | JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this)); 1921 | } 1922 | 1923 | return *get_ptr<const binary_t*>(); 1924 | } 1925 | 1926 | /// @} 1927 | 1928 | //////////////////// 1929 | // element access // 1930 | //////////////////// 1931 | 1932 | /// @name element access 1933 | /// Access to the JSON value. 1934 | /// @{ 1935 | 1936 | /// @brief access specified array element with bounds checking 1937 | /// @sa https://json.nlohmann.me/api/basic_json/at/ 1938 | reference at(size_type idx) 1939 | { 1940 | // at only works for arrays 1941 | if (JSON_HEDLEY_LIKELY(is_array())) 1942 | { 1943 | JSON_TRY 1944 | { 1945 | return set_parent(m_data.m_value.array->at(idx)); 1946 | } 1947 | JSON_CATCH (std::out_of_range&) 1948 | { 1949 | // create better exception explanation 1950 | JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 1951 | } 1952 | } 1953 | else 1954 | { 1955 | JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 1956 | } 1957 | } 1958 | 1959 | /// @brief access specified array element with bounds checking 1960 | /// @sa https://json.nlohmann.me/api/basic_json/at/ 1961 | const_reference at(size_type idx) const 1962 | { 1963 | // at only works for arrays 1964 | if (JSON_HEDLEY_LIKELY(is_array())) 1965 | { 1966 | JSON_TRY 1967 | { 1968 | return m_data.m_value.array->at(idx); 1969 | } 1970 | JSON_CATCH (std::out_of_range&) 1971 | { 1972 | // create better exception explanation 1973 | JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 1974 | } 1975 | } 1976 | else 1977 | { 1978 | JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 1979 | } 1980 | } 1981 | 1982 | /// @brief access specified object element with bounds checking 1983 | /// @sa https://json.nlohmann.me/api/basic_json/at/ 1984 | reference at(const typename object_t::key_type& key) 1985 | { 1986 | // at only works for objects 1987 | if (JSON_HEDLEY_UNLIKELY(!is_object())) 1988 | { 1989 | JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 1990 | } 1991 | 1992 | auto it = m_data.m_value.object->find(key); 1993 | if (it == m_data.m_value.object->end()) 1994 | { 1995 | JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); 1996 | } 1997 | return set_parent(it->second); 1998 | } 1999 | 2000 | /// @brief access specified object element with bounds checking 2001 | /// @sa https://json.nlohmann.me/api/basic_json/at/ 2002 | template<class KeyType, detail::enable_if_t< 2003 | detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 2004 | reference at(KeyType && key) 2005 | { 2006 | // at only works for objects 2007 | if (JSON_HEDLEY_UNLIKELY(!is_object())) 2008 | { 2009 | JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 2010 | } 2011 | 2012 | auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 2013 | if (it == m_data.m_value.object->end()) 2014 | { 2015 | JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); 2016 | } 2017 | return set_parent(it->second); 2018 | } 2019 | 2020 | /// @brief access specified object element with bounds checking 2021 | /// @sa https://json.nlohmann.me/api/basic_json/at/ 2022 | const_reference at(const typename object_t::key_type& key) const 2023 | { 2024 | // at only works for objects 2025 | if (JSON_HEDLEY_UNLIKELY(!is_object())) 2026 | { 2027 | JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 2028 | } 2029 | 2030 | auto it = m_data.m_value.object->find(key); 2031 | if (it == m_data.m_value.object->end()) 2032 | { 2033 | JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); 2034 | } 2035 | return it->second; 2036 | } 2037 | 2038 | /// @brief access specified object element with bounds checking 2039 | /// @sa https://json.nlohmann.me/api/basic_json/at/ 2040 | template<class KeyType, detail::enable_if_t< 2041 | detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 2042 | const_reference at(KeyType && key) const 2043 | { 2044 | // at only works for objects 2045 | if (JSON_HEDLEY_UNLIKELY(!is_object())) 2046 | { 2047 | JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); 2048 | } 2049 | 2050 | auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 2051 | if (it == m_data.m_value.object->end()) 2052 | { 2053 | JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this)); 2054 | } 2055 | return it->second; 2056 | } 2057 | 2058 | /// @brief access specified array element 2059 | /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 2060 | reference operator[](size_type idx) 2061 | { 2062 | // implicitly convert null value to an empty array 2063 | if (is_null()) 2064 | { 2065 | m_data.m_type = value_t::array; 2066 | m_data.m_value.array = create<array_t>(); 2067 | assert_invariant(); 2068 | } 2069 | 2070 | // operator[] only works for arrays 2071 | if (JSON_HEDLEY_LIKELY(is_array())) 2072 | { 2073 | // fill up array with null values if given idx is outside range 2074 | if (idx >= m_data.m_value.array->size()) 2075 | { 2076 | #if JSON_DIAGNOSTICS 2077 | // remember array size & capacity before resizing 2078 | const auto old_size = m_data.m_value.array->size(); 2079 | const auto old_capacity = m_data.m_value.array->capacity(); 2080 | #endif 2081 | m_data.m_value.array->resize(idx + 1); 2082 | 2083 | #if JSON_DIAGNOSTICS 2084 | if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) 2085 | { 2086 | // capacity has changed: update all parents 2087 | set_parents(); 2088 | } 2089 | else 2090 | { 2091 | // set parent for values added above 2092 | set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size)); 2093 | } 2094 | #endif 2095 | assert_invariant(); 2096 | } 2097 | 2098 | return m_data.m_value.array->operator[](idx); 2099 | } 2100 | 2101 | JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); 2102 | } 2103 | 2104 | /// @brief access specified array element 2105 | /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 2106 | const_reference operator[](size_type idx) const 2107 | { 2108 | // const operator[] only works for arrays 2109 | if (JSON_HEDLEY_LIKELY(is_array())) 2110 | { 2111 | return m_data.m_value.array->operator[](idx); 2112 | } 2113 | 2114 | JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); 2115 | } 2116 | 2117 | /// @brief access specified object element 2118 | /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 2119 | reference operator[](typename object_t::key_type key) 2120 | { 2121 | // implicitly convert null value to an empty object 2122 | if (is_null()) 2123 | { 2124 | m_data.m_type = value_t::object; 2125 | m_data.m_value.object = create<object_t>(); 2126 | assert_invariant(); 2127 | } 2128 | 2129 | // operator[] only works for objects 2130 | if (JSON_HEDLEY_LIKELY(is_object())) 2131 | { 2132 | auto result = m_data.m_value.object->emplace(std::move(key), nullptr); 2133 | return set_parent(result.first->second); 2134 | } 2135 | 2136 | JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 2137 | } 2138 | 2139 | /// @brief access specified object element 2140 | /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 2141 | const_reference operator[](const typename object_t::key_type& key) const 2142 | { 2143 | // const operator[] only works for objects 2144 | if (JSON_HEDLEY_LIKELY(is_object())) 2145 | { 2146 | auto it = m_data.m_value.object->find(key); 2147 | JSON_ASSERT(it != m_data.m_value.object->end()); 2148 | return it->second; 2149 | } 2150 | 2151 | JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 2152 | } 2153 | 2154 | // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC 2155 | // (they seemingly cannot be constrained to resolve the ambiguity) 2156 | template<typename T> 2157 | reference operator[](T* key) 2158 | { 2159 | return operator[](typename object_t::key_type(key)); 2160 | } 2161 | 2162 | template<typename T> 2163 | const_reference operator[](T* key) const 2164 | { 2165 | return operator[](typename object_t::key_type(key)); 2166 | } 2167 | 2168 | /// @brief access specified object element 2169 | /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 2170 | template<class KeyType, detail::enable_if_t< 2171 | detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > 2172 | reference operator[](KeyType && key) 2173 | { 2174 | // implicitly convert null value to an empty object 2175 | if (is_null()) 2176 | { 2177 | m_data.m_type = value_t::object; 2178 | m_data.m_value.object = create<object_t>(); 2179 | assert_invariant(); 2180 | } 2181 | 2182 | // operator[] only works for objects 2183 | if (JSON_HEDLEY_LIKELY(is_object())) 2184 | { 2185 | auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr); 2186 | return set_parent(result.first->second); 2187 | } 2188 | 2189 | JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 2190 | } 2191 | 2192 | /// @brief access specified object element 2193 | /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 2194 | template<class KeyType, detail::enable_if_t< 2195 | detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 > 2196 | const_reference operator[](KeyType && key) const 2197 | { 2198 | // const operator[] only works for objects 2199 | if (JSON_HEDLEY_LIKELY(is_object())) 2200 | { 2201 | auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 2202 | JSON_ASSERT(it != m_data.m_value.object->end()); 2203 | return it->second; 2204 | } 2205 | 2206 | JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); 2207 | } 2208 | 2209 | private: 2210 | template<typename KeyType> 2211 | using is_comparable_with_object_key = detail::is_comparable < 2212 | object_comparator_t, const typename object_t::key_type&, KeyType >; 2213 | 2214 | template<typename ValueType> 2215 | using value_return_type = std::conditional < 2216 | detail::is_c_string_uncvref<ValueType>::value, 2217 | string_t, typename std::decay<ValueType>::type >; 2218 | 2219 | public: 2220 | /// @brief access specified object element with default value 2221 | /// @sa https://json.nlohmann.me/api/basic_json/value/ 2222 | template < class ValueType, detail::enable_if_t < 2223 | !detail::is_transparent<object_comparator_t>::value 2224 | && detail::is_getable<basic_json_t, ValueType>::value 2225 | && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 2226 | ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const 2227 | { 2228 | // value only works for objects 2229 | if (JSON_HEDLEY_LIKELY(is_object())) 2230 | { 2231 | // if key is found, return value and given default value otherwise 2232 | const auto it = find(key); 2233 | if (it != end()) 2234 | { 2235 | return it->template get<ValueType>(); 2236 | } 2237 | 2238 | return default_value; 2239 | } 2240 | 2241 | JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 2242 | } 2243 | 2244 | /// @brief access specified object element with default value 2245 | /// @sa https://json.nlohmann.me/api/basic_json/value/ 2246 | template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, 2247 | detail::enable_if_t < 2248 | !detail::is_transparent<object_comparator_t>::value 2249 | && detail::is_getable<basic_json_t, ReturnType>::value 2250 | && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 2251 | ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const 2252 | { 2253 | // value only works for objects 2254 | if (JSON_HEDLEY_LIKELY(is_object())) 2255 | { 2256 | // if key is found, return value and given default value otherwise 2257 | const auto it = find(key); 2258 | if (it != end()) 2259 | { 2260 | return it->template get<ReturnType>(); 2261 | } 2262 | 2263 | return std::forward<ValueType>(default_value); 2264 | } 2265 | 2266 | JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 2267 | } 2268 | 2269 | /// @brief access specified object element with default value 2270 | /// @sa https://json.nlohmann.me/api/basic_json/value/ 2271 | template < class ValueType, class KeyType, detail::enable_if_t < 2272 | detail::is_transparent<object_comparator_t>::value 2273 | && !detail::is_json_pointer<KeyType>::value 2274 | && is_comparable_with_object_key<KeyType>::value 2275 | && detail::is_getable<basic_json_t, ValueType>::value 2276 | && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 2277 | ValueType value(KeyType && key, const ValueType& default_value) const 2278 | { 2279 | // value only works for objects 2280 | if (JSON_HEDLEY_LIKELY(is_object())) 2281 | { 2282 | // if key is found, return value and given default value otherwise 2283 | const auto it = find(std::forward<KeyType>(key)); 2284 | if (it != end()) 2285 | { 2286 | return it->template get<ValueType>(); 2287 | } 2288 | 2289 | return default_value; 2290 | } 2291 | 2292 | JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 2293 | } 2294 | 2295 | /// @brief access specified object element via JSON Pointer with default value 2296 | /// @sa https://json.nlohmann.me/api/basic_json/value/ 2297 | template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type, 2298 | detail::enable_if_t < 2299 | detail::is_transparent<object_comparator_t>::value 2300 | && !detail::is_json_pointer<KeyType>::value 2301 | && is_comparable_with_object_key<KeyType>::value 2302 | && detail::is_getable<basic_json_t, ReturnType>::value 2303 | && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 2304 | ReturnType value(KeyType && key, ValueType && default_value) const 2305 | { 2306 | // value only works for objects 2307 | if (JSON_HEDLEY_LIKELY(is_object())) 2308 | { 2309 | // if key is found, return value and given default value otherwise 2310 | const auto it = find(std::forward<KeyType>(key)); 2311 | if (it != end()) 2312 | { 2313 | return it->template get<ReturnType>(); 2314 | } 2315 | 2316 | return std::forward<ValueType>(default_value); 2317 | } 2318 | 2319 | JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 2320 | } 2321 | 2322 | /// @brief access specified object element via JSON Pointer with default value 2323 | /// @sa https://json.nlohmann.me/api/basic_json/value/ 2324 | template < class ValueType, detail::enable_if_t < 2325 | detail::is_getable<basic_json_t, ValueType>::value 2326 | && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 2327 | ValueType value(const json_pointer& ptr, const ValueType& default_value) const 2328 | { 2329 | // value only works for objects 2330 | if (JSON_HEDLEY_LIKELY(is_object())) 2331 | { 2332 | // if pointer resolves a value, return it or use default value 2333 | JSON_TRY 2334 | { 2335 | return ptr.get_checked(this).template get<ValueType>(); 2336 | } 2337 | JSON_INTERNAL_CATCH (out_of_range&) 2338 | { 2339 | return default_value; 2340 | } 2341 | } 2342 | 2343 | JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 2344 | } 2345 | 2346 | /// @brief access specified object element via JSON Pointer with default value 2347 | /// @sa https://json.nlohmann.me/api/basic_json/value/ 2348 | template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type, 2349 | detail::enable_if_t < 2350 | detail::is_getable<basic_json_t, ReturnType>::value 2351 | && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 2352 | ReturnType value(const json_pointer& ptr, ValueType && default_value) const 2353 | { 2354 | // value only works for objects 2355 | if (JSON_HEDLEY_LIKELY(is_object())) 2356 | { 2357 | // if pointer resolves a value, return it or use default value 2358 | JSON_TRY 2359 | { 2360 | return ptr.get_checked(this).template get<ReturnType>(); 2361 | } 2362 | JSON_INTERNAL_CATCH (out_of_range&) 2363 | { 2364 | return std::forward<ValueType>(default_value); 2365 | } 2366 | } 2367 | 2368 | JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); 2369 | } 2370 | 2371 | template < class ValueType, class BasicJsonType, detail::enable_if_t < 2372 | detail::is_basic_json<BasicJsonType>::value 2373 | && detail::is_getable<basic_json_t, ValueType>::value 2374 | && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 2375 | JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 2376 | ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const 2377 | { 2378 | return value(ptr.convert(), default_value); 2379 | } 2380 | 2381 | template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type, 2382 | detail::enable_if_t < 2383 | detail::is_basic_json<BasicJsonType>::value 2384 | && detail::is_getable<basic_json_t, ReturnType>::value 2385 | && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 > 2386 | JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 2387 | ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const 2388 | { 2389 | return value(ptr.convert(), std::forward<ValueType>(default_value)); 2390 | } 2391 | 2392 | /// @brief access the first element 2393 | /// @sa https://json.nlohmann.me/api/basic_json/front/ 2394 | reference front() 2395 | { 2396 | return *begin(); 2397 | } 2398 | 2399 | /// @brief access the first element 2400 | /// @sa https://json.nlohmann.me/api/basic_json/front/ 2401 | const_reference front() const 2402 | { 2403 | return *cbegin(); 2404 | } 2405 | 2406 | /// @brief access the last element 2407 | /// @sa https://json.nlohmann.me/api/basic_json/back/ 2408 | reference back() 2409 | { 2410 | auto tmp = end(); 2411 | --tmp; 2412 | return *tmp; 2413 | } 2414 | 2415 | /// @brief access the last element 2416 | /// @sa https://json.nlohmann.me/api/basic_json/back/ 2417 | const_reference back() const 2418 | { 2419 | auto tmp = cend(); 2420 | --tmp; 2421 | return *tmp; 2422 | } 2423 | 2424 | /// @brief remove element given an iterator 2425 | /// @sa https://json.nlohmann.me/api/basic_json/erase/ 2426 | template < class IteratorType, detail::enable_if_t < 2427 | std::is_same<IteratorType, typename basic_json_t::iterator>::value || 2428 | std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > 2429 | IteratorType erase(IteratorType pos) 2430 | { 2431 | // make sure iterator fits the current value 2432 | if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) 2433 | { 2434 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 2435 | } 2436 | 2437 | IteratorType result = end(); 2438 | 2439 | switch (m_data.m_type) 2440 | { 2441 | case value_t::boolean: 2442 | case value_t::number_float: 2443 | case value_t::number_integer: 2444 | case value_t::number_unsigned: 2445 | case value_t::string: 2446 | case value_t::binary: 2447 | { 2448 | if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) 2449 | { 2450 | JSON_THROW(invalid_iterator::create(205, "iterator out of range", this)); 2451 | } 2452 | 2453 | if (is_string()) 2454 | { 2455 | AllocatorType<string_t> alloc; 2456 | std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string); 2457 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1); 2458 | m_data.m_value.string = nullptr; 2459 | } 2460 | else if (is_binary()) 2461 | { 2462 | AllocatorType<binary_t> alloc; 2463 | std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary); 2464 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1); 2465 | m_data.m_value.binary = nullptr; 2466 | } 2467 | 2468 | m_data.m_type = value_t::null; 2469 | assert_invariant(); 2470 | break; 2471 | } 2472 | 2473 | case value_t::object: 2474 | { 2475 | result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator); 2476 | break; 2477 | } 2478 | 2479 | case value_t::array: 2480 | { 2481 | result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator); 2482 | break; 2483 | } 2484 | 2485 | case value_t::null: 2486 | case value_t::discarded: 2487 | default: 2488 | JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 2489 | } 2490 | 2491 | return result; 2492 | } 2493 | 2494 | /// @brief remove elements given an iterator range 2495 | /// @sa https://json.nlohmann.me/api/basic_json/erase/ 2496 | template < class IteratorType, detail::enable_if_t < 2497 | std::is_same<IteratorType, typename basic_json_t::iterator>::value || 2498 | std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 > 2499 | IteratorType erase(IteratorType first, IteratorType last) 2500 | { 2501 | // make sure iterator fits the current value 2502 | if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) 2503 | { 2504 | JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this)); 2505 | } 2506 | 2507 | IteratorType result = end(); 2508 | 2509 | switch (m_data.m_type) 2510 | { 2511 | case value_t::boolean: 2512 | case value_t::number_float: 2513 | case value_t::number_integer: 2514 | case value_t::number_unsigned: 2515 | case value_t::string: 2516 | case value_t::binary: 2517 | { 2518 | if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() 2519 | || !last.m_it.primitive_iterator.is_end())) 2520 | { 2521 | JSON_THROW(invalid_iterator::create(204, "iterators out of range", this)); 2522 | } 2523 | 2524 | if (is_string()) 2525 | { 2526 | AllocatorType<string_t> alloc; 2527 | std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string); 2528 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1); 2529 | m_data.m_value.string = nullptr; 2530 | } 2531 | else if (is_binary()) 2532 | { 2533 | AllocatorType<binary_t> alloc; 2534 | std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary); 2535 | std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1); 2536 | m_data.m_value.binary = nullptr; 2537 | } 2538 | 2539 | m_data.m_type = value_t::null; 2540 | assert_invariant(); 2541 | break; 2542 | } 2543 | 2544 | case value_t::object: 2545 | { 2546 | result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator, 2547 | last.m_it.object_iterator); 2548 | break; 2549 | } 2550 | 2551 | case value_t::array: 2552 | { 2553 | result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator, 2554 | last.m_it.array_iterator); 2555 | break; 2556 | } 2557 | 2558 | case value_t::null: 2559 | case value_t::discarded: 2560 | default: 2561 | JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 2562 | } 2563 | 2564 | return result; 2565 | } 2566 | 2567 | private: 2568 | template < typename KeyType, detail::enable_if_t < 2569 | detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > 2570 | size_type erase_internal(KeyType && key) 2571 | { 2572 | // this erase only works for objects 2573 | if (JSON_HEDLEY_UNLIKELY(!is_object())) 2574 | { 2575 | JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 2576 | } 2577 | 2578 | return m_data.m_value.object->erase(std::forward<KeyType>(key)); 2579 | } 2580 | 2581 | template < typename KeyType, detail::enable_if_t < 2582 | !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 > 2583 | size_type erase_internal(KeyType && key) 2584 | { 2585 | // this erase only works for objects 2586 | if (JSON_HEDLEY_UNLIKELY(!is_object())) 2587 | { 2588 | JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 2589 | } 2590 | 2591 | const auto it = m_data.m_value.object->find(std::forward<KeyType>(key)); 2592 | if (it != m_data.m_value.object->end()) 2593 | { 2594 | m_data.m_value.object->erase(it); 2595 | return 1; 2596 | } 2597 | return 0; 2598 | } 2599 | 2600 | public: 2601 | 2602 | /// @brief remove element from a JSON object given a key 2603 | /// @sa https://json.nlohmann.me/api/basic_json/erase/ 2604 | size_type erase(const typename object_t::key_type& key) 2605 | { 2606 | // the indirection via erase_internal() is added to avoid making this 2607 | // function a template and thus de-rank it during overload resolution 2608 | return erase_internal(key); 2609 | } 2610 | 2611 | /// @brief remove element from a JSON object given a key 2612 | /// @sa https://json.nlohmann.me/api/basic_json/erase/ 2613 | template<class KeyType, detail::enable_if_t< 2614 | detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 2615 | size_type erase(KeyType && key) 2616 | { 2617 | return erase_internal(std::forward<KeyType>(key)); 2618 | } 2619 | 2620 | /// @brief remove element from a JSON array given an index 2621 | /// @sa https://json.nlohmann.me/api/basic_json/erase/ 2622 | void erase(const size_type idx) 2623 | { 2624 | // this erase only works for arrays 2625 | if (JSON_HEDLEY_LIKELY(is_array())) 2626 | { 2627 | if (JSON_HEDLEY_UNLIKELY(idx >= size())) 2628 | { 2629 | JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); 2630 | } 2631 | 2632 | m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx)); 2633 | } 2634 | else 2635 | { 2636 | JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); 2637 | } 2638 | } 2639 | 2640 | /// @} 2641 | 2642 | //////////// 2643 | // lookup // 2644 | //////////// 2645 | 2646 | /// @name lookup 2647 | /// @{ 2648 | 2649 | /// @brief find an element in a JSON object 2650 | /// @sa https://json.nlohmann.me/api/basic_json/find/ 2651 | iterator find(const typename object_t::key_type& key) 2652 | { 2653 | auto result = end(); 2654 | 2655 | if (is_object()) 2656 | { 2657 | result.m_it.object_iterator = m_data.m_value.object->find(key); 2658 | } 2659 | 2660 | return result; 2661 | } 2662 | 2663 | /// @brief find an element in a JSON object 2664 | /// @sa https://json.nlohmann.me/api/basic_json/find/ 2665 | const_iterator find(const typename object_t::key_type& key) const 2666 | { 2667 | auto result = cend(); 2668 | 2669 | if (is_object()) 2670 | { 2671 | result.m_it.object_iterator = m_data.m_value.object->find(key); 2672 | } 2673 | 2674 | return result; 2675 | } 2676 | 2677 | /// @brief find an element in a JSON object 2678 | /// @sa https://json.nlohmann.me/api/basic_json/find/ 2679 | template<class KeyType, detail::enable_if_t< 2680 | detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 2681 | iterator find(KeyType && key) 2682 | { 2683 | auto result = end(); 2684 | 2685 | if (is_object()) 2686 | { 2687 | result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key)); 2688 | } 2689 | 2690 | return result; 2691 | } 2692 | 2693 | /// @brief find an element in a JSON object 2694 | /// @sa https://json.nlohmann.me/api/basic_json/find/ 2695 | template<class KeyType, detail::enable_if_t< 2696 | detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 2697 | const_iterator find(KeyType && key) const 2698 | { 2699 | auto result = cend(); 2700 | 2701 | if (is_object()) 2702 | { 2703 | result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key)); 2704 | } 2705 | 2706 | return result; 2707 | } 2708 | 2709 | /// @brief returns the number of occurrences of a key in a JSON object 2710 | /// @sa https://json.nlohmann.me/api/basic_json/count/ 2711 | size_type count(const typename object_t::key_type& key) const 2712 | { 2713 | // return 0 for all nonobject types 2714 | return is_object() ? m_data.m_value.object->count(key) : 0; 2715 | } 2716 | 2717 | /// @brief returns the number of occurrences of a key in a JSON object 2718 | /// @sa https://json.nlohmann.me/api/basic_json/count/ 2719 | template<class KeyType, detail::enable_if_t< 2720 | detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 2721 | size_type count(KeyType && key) const 2722 | { 2723 | // return 0 for all nonobject types 2724 | return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0; 2725 | } 2726 | 2727 | /// @brief check the existence of an element in a JSON object 2728 | /// @sa https://json.nlohmann.me/api/basic_json/contains/ 2729 | bool contains(const typename object_t::key_type& key) const 2730 | { 2731 | return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end(); 2732 | } 2733 | 2734 | /// @brief check the existence of an element in a JSON object 2735 | /// @sa https://json.nlohmann.me/api/basic_json/contains/ 2736 | template<class KeyType, detail::enable_if_t< 2737 | detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0> 2738 | bool contains(KeyType && key) const 2739 | { 2740 | return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end(); 2741 | } 2742 | 2743 | /// @brief check the existence of an element in a JSON object given a JSON pointer 2744 | /// @sa https://json.nlohmann.me/api/basic_json/contains/ 2745 | bool contains(const json_pointer& ptr) const 2746 | { 2747 | return ptr.contains(this); 2748 | } 2749 | 2750 | template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 2751 | JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 2752 | bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const 2753 | { 2754 | return ptr.contains(this); 2755 | } 2756 | 2757 | /// @} 2758 | 2759 | /////////////// 2760 | // iterators // 2761 | /////////////// 2762 | 2763 | /// @name iterators 2764 | /// @{ 2765 | 2766 | /// @brief returns an iterator to the first element 2767 | /// @sa https://json.nlohmann.me/api/basic_json/begin/ 2768 | iterator begin() noexcept 2769 | { 2770 | iterator result(this); 2771 | result.set_begin(); 2772 | return result; 2773 | } 2774 | 2775 | /// @brief returns an iterator to the first element 2776 | /// @sa https://json.nlohmann.me/api/basic_json/begin/ 2777 | const_iterator begin() const noexcept 2778 | { 2779 | return cbegin(); 2780 | } 2781 | 2782 | /// @brief returns a const iterator to the first element 2783 | /// @sa https://json.nlohmann.me/api/basic_json/cbegin/ 2784 | const_iterator cbegin() const noexcept 2785 | { 2786 | const_iterator result(this); 2787 | result.set_begin(); 2788 | return result; 2789 | } 2790 | 2791 | /// @brief returns an iterator to one past the last element 2792 | /// @sa https://json.nlohmann.me/api/basic_json/end/ 2793 | iterator end() noexcept 2794 | { 2795 | iterator result(this); 2796 | result.set_end(); 2797 | return result; 2798 | } 2799 | 2800 | /// @brief returns an iterator to one past the last element 2801 | /// @sa https://json.nlohmann.me/api/basic_json/end/ 2802 | const_iterator end() const noexcept 2803 | { 2804 | return cend(); 2805 | } 2806 | 2807 | /// @brief returns an iterator to one past the last element 2808 | /// @sa https://json.nlohmann.me/api/basic_json/cend/ 2809 | const_iterator cend() const noexcept 2810 | { 2811 | const_iterator result(this); 2812 | result.set_end(); 2813 | return result; 2814 | } 2815 | 2816 | /// @brief returns an iterator to the reverse-beginning 2817 | /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 2818 | reverse_iterator rbegin() noexcept 2819 | { 2820 | return reverse_iterator(end()); 2821 | } 2822 | 2823 | /// @brief returns an iterator to the reverse-beginning 2824 | /// @sa https://json.nlohmann.me/api/basic_json/rbegin/ 2825 | const_reverse_iterator rbegin() const noexcept 2826 | { 2827 | return crbegin(); 2828 | } 2829 | 2830 | /// @brief returns an iterator to the reverse-end 2831 | /// @sa https://json.nlohmann.me/api/basic_json/rend/ 2832 | reverse_iterator rend() noexcept 2833 | { 2834 | return reverse_iterator(begin()); 2835 | } 2836 | 2837 | /// @brief returns an iterator to the reverse-end 2838 | /// @sa https://json.nlohmann.me/api/basic_json/rend/ 2839 | const_reverse_iterator rend() const noexcept 2840 | { 2841 | return crend(); 2842 | } 2843 | 2844 | /// @brief returns a const reverse iterator to the last element 2845 | /// @sa https://json.nlohmann.me/api/basic_json/crbegin/ 2846 | const_reverse_iterator crbegin() const noexcept 2847 | { 2848 | return const_reverse_iterator(cend()); 2849 | } 2850 | 2851 | /// @brief returns a const reverse iterator to one before the first 2852 | /// @sa https://json.nlohmann.me/api/basic_json/crend/ 2853 | const_reverse_iterator crend() const noexcept 2854 | { 2855 | return const_reverse_iterator(cbegin()); 2856 | } 2857 | 2858 | public: 2859 | /// @brief wrapper to access iterator member functions in range-based for 2860 | /// @sa https://json.nlohmann.me/api/basic_json/items/ 2861 | /// @deprecated This function is deprecated since 3.1.0 and will be removed in 2862 | /// version 4.0.0 of the library. Please use @ref items() instead; 2863 | /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 2864 | JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) 2865 | static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept 2866 | { 2867 | return ref.items(); 2868 | } 2869 | 2870 | /// @brief wrapper to access iterator member functions in range-based for 2871 | /// @sa https://json.nlohmann.me/api/basic_json/items/ 2872 | /// @deprecated This function is deprecated since 3.1.0 and will be removed in 2873 | /// version 4.0.0 of the library. Please use @ref items() instead; 2874 | /// that is, replace `json::iterator_wrapper(j)` with `j.items()`. 2875 | JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) 2876 | static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept 2877 | { 2878 | return ref.items(); 2879 | } 2880 | 2881 | /// @brief helper to access iterator member functions in range-based for 2882 | /// @sa https://json.nlohmann.me/api/basic_json/items/ 2883 | iteration_proxy<iterator> items() noexcept 2884 | { 2885 | return iteration_proxy<iterator>(*this); 2886 | } 2887 | 2888 | /// @brief helper to access iterator member functions in range-based for 2889 | /// @sa https://json.nlohmann.me/api/basic_json/items/ 2890 | iteration_proxy<const_iterator> items() const noexcept 2891 | { 2892 | return iteration_proxy<const_iterator>(*this); 2893 | } 2894 | 2895 | /// @} 2896 | 2897 | ////////////// 2898 | // capacity // 2899 | ////////////// 2900 | 2901 | /// @name capacity 2902 | /// @{ 2903 | 2904 | /// @brief checks whether the container is empty. 2905 | /// @sa https://json.nlohmann.me/api/basic_json/empty/ 2906 | bool empty() const noexcept 2907 | { 2908 | switch (m_data.m_type) 2909 | { 2910 | case value_t::null: 2911 | { 2912 | // null values are empty 2913 | return true; 2914 | } 2915 | 2916 | case value_t::array: 2917 | { 2918 | // delegate call to array_t::empty() 2919 | return m_data.m_value.array->empty(); 2920 | } 2921 | 2922 | case value_t::object: 2923 | { 2924 | // delegate call to object_t::empty() 2925 | return m_data.m_value.object->empty(); 2926 | } 2927 | 2928 | case value_t::string: 2929 | case value_t::boolean: 2930 | case value_t::number_integer: 2931 | case value_t::number_unsigned: 2932 | case value_t::number_float: 2933 | case value_t::binary: 2934 | case value_t::discarded: 2935 | default: 2936 | { 2937 | // all other types are nonempty 2938 | return false; 2939 | } 2940 | } 2941 | } 2942 | 2943 | /// @brief returns the number of elements 2944 | /// @sa https://json.nlohmann.me/api/basic_json/size/ 2945 | size_type size() const noexcept 2946 | { 2947 | switch (m_data.m_type) 2948 | { 2949 | case value_t::null: 2950 | { 2951 | // null values are empty 2952 | return 0; 2953 | } 2954 | 2955 | case value_t::array: 2956 | { 2957 | // delegate call to array_t::size() 2958 | return m_data.m_value.array->size(); 2959 | } 2960 | 2961 | case value_t::object: 2962 | { 2963 | // delegate call to object_t::size() 2964 | return m_data.m_value.object->size(); 2965 | } 2966 | 2967 | case value_t::string: 2968 | case value_t::boolean: 2969 | case value_t::number_integer: 2970 | case value_t::number_unsigned: 2971 | case value_t::number_float: 2972 | case value_t::binary: 2973 | case value_t::discarded: 2974 | default: 2975 | { 2976 | // all other types have size 1 2977 | return 1; 2978 | } 2979 | } 2980 | } 2981 | 2982 | /// @brief returns the maximum possible number of elements 2983 | /// @sa https://json.nlohmann.me/api/basic_json/max_size/ 2984 | size_type max_size() const noexcept 2985 | { 2986 | switch (m_data.m_type) 2987 | { 2988 | case value_t::array: 2989 | { 2990 | // delegate call to array_t::max_size() 2991 | return m_data.m_value.array->max_size(); 2992 | } 2993 | 2994 | case value_t::object: 2995 | { 2996 | // delegate call to object_t::max_size() 2997 | return m_data.m_value.object->max_size(); 2998 | } 2999 | 3000 | case value_t::null: 3001 | case value_t::string: 3002 | case value_t::boolean: 3003 | case value_t::number_integer: 3004 | case value_t::number_unsigned: 3005 | case value_t::number_float: 3006 | case value_t::binary: 3007 | case value_t::discarded: 3008 | default: 3009 | { 3010 | // all other types have max_size() == size() 3011 | return size(); 3012 | } 3013 | } 3014 | } 3015 | 3016 | /// @} 3017 | 3018 | /////////////// 3019 | // modifiers // 3020 | /////////////// 3021 | 3022 | /// @name modifiers 3023 | /// @{ 3024 | 3025 | /// @brief clears the contents 3026 | /// @sa https://json.nlohmann.me/api/basic_json/clear/ 3027 | void clear() noexcept 3028 | { 3029 | switch (m_data.m_type) 3030 | { 3031 | case value_t::number_integer: 3032 | { 3033 | m_data.m_value.number_integer = 0; 3034 | break; 3035 | } 3036 | 3037 | case value_t::number_unsigned: 3038 | { 3039 | m_data.m_value.number_unsigned = 0; 3040 | break; 3041 | } 3042 | 3043 | case value_t::number_float: 3044 | { 3045 | m_data.m_value.number_float = 0.0; 3046 | break; 3047 | } 3048 | 3049 | case value_t::boolean: 3050 | { 3051 | m_data.m_value.boolean = false; 3052 | break; 3053 | } 3054 | 3055 | case value_t::string: 3056 | { 3057 | m_data.m_value.string->clear(); 3058 | break; 3059 | } 3060 | 3061 | case value_t::binary: 3062 | { 3063 | m_data.m_value.binary->clear(); 3064 | break; 3065 | } 3066 | 3067 | case value_t::array: 3068 | { 3069 | m_data.m_value.array->clear(); 3070 | break; 3071 | } 3072 | 3073 | case value_t::object: 3074 | { 3075 | m_data.m_value.object->clear(); 3076 | break; 3077 | } 3078 | 3079 | case value_t::null: 3080 | case value_t::discarded: 3081 | default: 3082 | break; 3083 | } 3084 | } 3085 | 3086 | /// @brief add an object to an array 3087 | /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 3088 | void push_back(basic_json&& val) 3089 | { 3090 | // push_back only works for null objects or arrays 3091 | if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 3092 | { 3093 | JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 3094 | } 3095 | 3096 | // transform null object into an array 3097 | if (is_null()) 3098 | { 3099 | m_data.m_type = value_t::array; 3100 | m_data.m_value = value_t::array; 3101 | assert_invariant(); 3102 | } 3103 | 3104 | // add element to array (move semantics) 3105 | const auto old_capacity = m_data.m_value.array->capacity(); 3106 | m_data.m_value.array->push_back(std::move(val)); 3107 | set_parent(m_data.m_value.array->back(), old_capacity); 3108 | // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor 3109 | } 3110 | 3111 | /// @brief add an object to an array 3112 | /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 3113 | reference operator+=(basic_json&& val) 3114 | { 3115 | push_back(std::move(val)); 3116 | return *this; 3117 | } 3118 | 3119 | /// @brief add an object to an array 3120 | /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 3121 | void push_back(const basic_json& val) 3122 | { 3123 | // push_back only works for null objects or arrays 3124 | if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 3125 | { 3126 | JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 3127 | } 3128 | 3129 | // transform null object into an array 3130 | if (is_null()) 3131 | { 3132 | m_data.m_type = value_t::array; 3133 | m_data.m_value = value_t::array; 3134 | assert_invariant(); 3135 | } 3136 | 3137 | // add element to array 3138 | const auto old_capacity = m_data.m_value.array->capacity(); 3139 | m_data.m_value.array->push_back(val); 3140 | set_parent(m_data.m_value.array->back(), old_capacity); 3141 | } 3142 | 3143 | /// @brief add an object to an array 3144 | /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 3145 | reference operator+=(const basic_json& val) 3146 | { 3147 | push_back(val); 3148 | return *this; 3149 | } 3150 | 3151 | /// @brief add an object to an object 3152 | /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 3153 | void push_back(const typename object_t::value_type& val) 3154 | { 3155 | // push_back only works for null objects or objects 3156 | if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) 3157 | { 3158 | JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this)); 3159 | } 3160 | 3161 | // transform null object into an object 3162 | if (is_null()) 3163 | { 3164 | m_data.m_type = value_t::object; 3165 | m_data.m_value = value_t::object; 3166 | assert_invariant(); 3167 | } 3168 | 3169 | // add element to object 3170 | auto res = m_data.m_value.object->insert(val); 3171 | set_parent(res.first->second); 3172 | } 3173 | 3174 | /// @brief add an object to an object 3175 | /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 3176 | reference operator+=(const typename object_t::value_type& val) 3177 | { 3178 | push_back(val); 3179 | return *this; 3180 | } 3181 | 3182 | /// @brief add an object to an object 3183 | /// @sa https://json.nlohmann.me/api/basic_json/push_back/ 3184 | void push_back(initializer_list_t init) 3185 | { 3186 | if (is_object() && init.size() == 2 && (*init.begin())->is_string()) 3187 | { 3188 | basic_json&& key = init.begin()->moved_or_copied(); 3189 | push_back(typename object_t::value_type( 3190 | std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied())); 3191 | } 3192 | else 3193 | { 3194 | push_back(basic_json(init)); 3195 | } 3196 | } 3197 | 3198 | /// @brief add an object to an object 3199 | /// @sa https://json.nlohmann.me/api/basic_json/operator+=/ 3200 | reference operator+=(initializer_list_t init) 3201 | { 3202 | push_back(init); 3203 | return *this; 3204 | } 3205 | 3206 | /// @brief add an object to an array 3207 | /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/ 3208 | template<class... Args> 3209 | reference emplace_back(Args&& ... args) 3210 | { 3211 | // emplace_back only works for null objects or arrays 3212 | if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) 3213 | { 3214 | JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this)); 3215 | } 3216 | 3217 | // transform null object into an array 3218 | if (is_null()) 3219 | { 3220 | m_data.m_type = value_t::array; 3221 | m_data.m_value = value_t::array; 3222 | assert_invariant(); 3223 | } 3224 | 3225 | // add element to array (perfect forwarding) 3226 | const auto old_capacity = m_data.m_value.array->capacity(); 3227 | m_data.m_value.array->emplace_back(std::forward<Args>(args)...); 3228 | return set_parent(m_data.m_value.array->back(), old_capacity); 3229 | } 3230 | 3231 | /// @brief add an object to an object if key does not exist 3232 | /// @sa https://json.nlohmann.me/api/basic_json/emplace/ 3233 | template<class... Args> 3234 | std::pair<iterator, bool> emplace(Args&& ... args) 3235 | { 3236 | // emplace only works for null objects or arrays 3237 | if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) 3238 | { 3239 | JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this)); 3240 | } 3241 | 3242 | // transform null object into an object 3243 | if (is_null()) 3244 | { 3245 | m_data.m_type = value_t::object; 3246 | m_data.m_value = value_t::object; 3247 | assert_invariant(); 3248 | } 3249 | 3250 | // add element to array (perfect forwarding) 3251 | auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...); 3252 | set_parent(res.first->second); 3253 | 3254 | // create result iterator and set iterator to the result of emplace 3255 | auto it = begin(); 3256 | it.m_it.object_iterator = res.first; 3257 | 3258 | // return pair of iterator and boolean 3259 | return {it, res.second}; 3260 | } 3261 | 3262 | /// Helper for insertion of an iterator 3263 | /// @note: This uses std::distance to support GCC 4.8, 3264 | /// see https://github.com/nlohmann/json/pull/1257 3265 | template<typename... Args> 3266 | iterator insert_iterator(const_iterator pos, Args&& ... args) 3267 | { 3268 | iterator result(this); 3269 | JSON_ASSERT(m_data.m_value.array != nullptr); 3270 | 3271 | auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator); 3272 | m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...); 3273 | result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos; 3274 | 3275 | // This could have been written as: 3276 | // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); 3277 | // but the return value of insert is missing in GCC 4.8, so it is written this way instead. 3278 | 3279 | set_parents(); 3280 | return result; 3281 | } 3282 | 3283 | /// @brief inserts element into array 3284 | /// @sa https://json.nlohmann.me/api/basic_json/insert/ 3285 | iterator insert(const_iterator pos, const basic_json& val) 3286 | { 3287 | // insert only works for arrays 3288 | if (JSON_HEDLEY_LIKELY(is_array())) 3289 | { 3290 | // check if iterator pos fits to this JSON value 3291 | if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 3292 | { 3293 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 3294 | } 3295 | 3296 | // insert to array and return iterator 3297 | return insert_iterator(pos, val); 3298 | } 3299 | 3300 | JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 3301 | } 3302 | 3303 | /// @brief inserts element into array 3304 | /// @sa https://json.nlohmann.me/api/basic_json/insert/ 3305 | iterator insert(const_iterator pos, basic_json&& val) 3306 | { 3307 | return insert(pos, val); 3308 | } 3309 | 3310 | /// @brief inserts copies of element into array 3311 | /// @sa https://json.nlohmann.me/api/basic_json/insert/ 3312 | iterator insert(const_iterator pos, size_type cnt, const basic_json& val) 3313 | { 3314 | // insert only works for arrays 3315 | if (JSON_HEDLEY_LIKELY(is_array())) 3316 | { 3317 | // check if iterator pos fits to this JSON value 3318 | if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 3319 | { 3320 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 3321 | } 3322 | 3323 | // insert to array and return iterator 3324 | return insert_iterator(pos, cnt, val); 3325 | } 3326 | 3327 | JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 3328 | } 3329 | 3330 | /// @brief inserts range of elements into array 3331 | /// @sa https://json.nlohmann.me/api/basic_json/insert/ 3332 | iterator insert(const_iterator pos, const_iterator first, const_iterator last) 3333 | { 3334 | // insert only works for arrays 3335 | if (JSON_HEDLEY_UNLIKELY(!is_array())) 3336 | { 3337 | JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 3338 | } 3339 | 3340 | // check if iterator pos fits to this JSON value 3341 | if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 3342 | { 3343 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 3344 | } 3345 | 3346 | // check if range iterators belong to the same JSON object 3347 | if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 3348 | { 3349 | JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 3350 | } 3351 | 3352 | if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) 3353 | { 3354 | JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this)); 3355 | } 3356 | 3357 | // insert to array and return iterator 3358 | return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); 3359 | } 3360 | 3361 | /// @brief inserts elements from initializer list into array 3362 | /// @sa https://json.nlohmann.me/api/basic_json/insert/ 3363 | iterator insert(const_iterator pos, initializer_list_t ilist) 3364 | { 3365 | // insert only works for arrays 3366 | if (JSON_HEDLEY_UNLIKELY(!is_array())) 3367 | { 3368 | JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 3369 | } 3370 | 3371 | // check if iterator pos fits to this JSON value 3372 | if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) 3373 | { 3374 | JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this)); 3375 | } 3376 | 3377 | // insert to array and return iterator 3378 | return insert_iterator(pos, ilist.begin(), ilist.end()); 3379 | } 3380 | 3381 | /// @brief inserts range of elements into object 3382 | /// @sa https://json.nlohmann.me/api/basic_json/insert/ 3383 | void insert(const_iterator first, const_iterator last) 3384 | { 3385 | // insert only works for objects 3386 | if (JSON_HEDLEY_UNLIKELY(!is_object())) 3387 | { 3388 | JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this)); 3389 | } 3390 | 3391 | // check if range iterators belong to the same JSON object 3392 | if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 3393 | { 3394 | JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 3395 | } 3396 | 3397 | // passed iterators must belong to objects 3398 | if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) 3399 | { 3400 | JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this)); 3401 | } 3402 | 3403 | m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); 3404 | } 3405 | 3406 | /// @brief updates a JSON object from another object, overwriting existing keys 3407 | /// @sa https://json.nlohmann.me/api/basic_json/update/ 3408 | void update(const_reference j, bool merge_objects = false) 3409 | { 3410 | update(j.begin(), j.end(), merge_objects); 3411 | } 3412 | 3413 | /// @brief updates a JSON object from another object, overwriting existing keys 3414 | /// @sa https://json.nlohmann.me/api/basic_json/update/ 3415 | void update(const_iterator first, const_iterator last, bool merge_objects = false) 3416 | { 3417 | // implicitly convert null value to an empty object 3418 | if (is_null()) 3419 | { 3420 | m_data.m_type = value_t::object; 3421 | m_data.m_value.object = create<object_t>(); 3422 | assert_invariant(); 3423 | } 3424 | 3425 | if (JSON_HEDLEY_UNLIKELY(!is_object())) 3426 | { 3427 | JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this)); 3428 | } 3429 | 3430 | // check if range iterators belong to the same JSON object 3431 | if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) 3432 | { 3433 | JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this)); 3434 | } 3435 | 3436 | // passed iterators must belong to objects 3437 | if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) 3438 | { 3439 | JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object)); 3440 | } 3441 | 3442 | for (auto it = first; it != last; ++it) 3443 | { 3444 | if (merge_objects && it.value().is_object()) 3445 | { 3446 | auto it2 = m_data.m_value.object->find(it.key()); 3447 | if (it2 != m_data.m_value.object->end()) 3448 | { 3449 | it2->second.update(it.value(), true); 3450 | continue; 3451 | } 3452 | } 3453 | m_data.m_value.object->operator[](it.key()) = it.value(); 3454 | #if JSON_DIAGNOSTICS 3455 | m_data.m_value.object->operator[](it.key()).m_parent = this; 3456 | #endif 3457 | } 3458 | } 3459 | 3460 | /// @brief exchanges the values 3461 | /// @sa https://json.nlohmann.me/api/basic_json/swap/ 3462 | void swap(reference other) noexcept ( 3463 | std::is_nothrow_move_constructible<value_t>::value&& 3464 | std::is_nothrow_move_assignable<value_t>::value&& 3465 | std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 3466 | std::is_nothrow_move_assignable<json_value>::value 3467 | ) 3468 | { 3469 | std::swap(m_data.m_type, other.m_data.m_type); 3470 | std::swap(m_data.m_value, other.m_data.m_value); 3471 | 3472 | set_parents(); 3473 | other.set_parents(); 3474 | assert_invariant(); 3475 | } 3476 | 3477 | /// @brief exchanges the values 3478 | /// @sa https://json.nlohmann.me/api/basic_json/swap/ 3479 | friend void swap(reference left, reference right) noexcept ( 3480 | std::is_nothrow_move_constructible<value_t>::value&& 3481 | std::is_nothrow_move_assignable<value_t>::value&& 3482 | std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 3483 | std::is_nothrow_move_assignable<json_value>::value 3484 | ) 3485 | { 3486 | left.swap(right); 3487 | } 3488 | 3489 | /// @brief exchanges the values 3490 | /// @sa https://json.nlohmann.me/api/basic_json/swap/ 3491 | void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 3492 | { 3493 | // swap only works for arrays 3494 | if (JSON_HEDLEY_LIKELY(is_array())) 3495 | { 3496 | using std::swap; 3497 | swap(*(m_data.m_value.array), other); 3498 | } 3499 | else 3500 | { 3501 | JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this)); 3502 | } 3503 | } 3504 | 3505 | /// @brief exchanges the values 3506 | /// @sa https://json.nlohmann.me/api/basic_json/swap/ 3507 | void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 3508 | { 3509 | // swap only works for objects 3510 | if (JSON_HEDLEY_LIKELY(is_object())) 3511 | { 3512 | using std::swap; 3513 | swap(*(m_data.m_value.object), other); 3514 | } 3515 | else 3516 | { 3517 | JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this)); 3518 | } 3519 | } 3520 | 3521 | /// @brief exchanges the values 3522 | /// @sa https://json.nlohmann.me/api/basic_json/swap/ 3523 | void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 3524 | { 3525 | // swap only works for strings 3526 | if (JSON_HEDLEY_LIKELY(is_string())) 3527 | { 3528 | using std::swap; 3529 | swap(*(m_data.m_value.string), other); 3530 | } 3531 | else 3532 | { 3533 | JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this)); 3534 | } 3535 | } 3536 | 3537 | /// @brief exchanges the values 3538 | /// @sa https://json.nlohmann.me/api/basic_json/swap/ 3539 | void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 3540 | { 3541 | // swap only works for strings 3542 | if (JSON_HEDLEY_LIKELY(is_binary())) 3543 | { 3544 | using std::swap; 3545 | swap(*(m_data.m_value.binary), other); 3546 | } 3547 | else 3548 | { 3549 | JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this)); 3550 | } 3551 | } 3552 | 3553 | /// @brief exchanges the values 3554 | /// @sa https://json.nlohmann.me/api/basic_json/swap/ 3555 | void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape) 3556 | { 3557 | // swap only works for strings 3558 | if (JSON_HEDLEY_LIKELY(is_binary())) 3559 | { 3560 | using std::swap; 3561 | swap(*(m_data.m_value.binary), other); 3562 | } 3563 | else 3564 | { 3565 | JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this)); 3566 | } 3567 | } 3568 | 3569 | /// @} 3570 | 3571 | ////////////////////////////////////////// 3572 | // lexicographical comparison operators // 3573 | ////////////////////////////////////////// 3574 | 3575 | /// @name lexicographical comparison operators 3576 | /// @{ 3577 | 3578 | // note parentheses around operands are necessary; see 3579 | // https://github.com/nlohmann/json/issues/1530 3580 | #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \ 3581 | const auto lhs_type = lhs.type(); \ 3582 | const auto rhs_type = rhs.type(); \ 3583 | \ 3584 | if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \ 3585 | { \ 3586 | switch (lhs_type) \ 3587 | { \ 3588 | case value_t::array: \ 3589 | return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \ 3590 | \ 3591 | case value_t::object: \ 3592 | return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \ 3593 | \ 3594 | case value_t::null: \ 3595 | return (null_result); \ 3596 | \ 3597 | case value_t::string: \ 3598 | return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \ 3599 | \ 3600 | case value_t::boolean: \ 3601 | return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \ 3602 | \ 3603 | case value_t::number_integer: \ 3604 | return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \ 3605 | \ 3606 | case value_t::number_unsigned: \ 3607 | return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \ 3608 | \ 3609 | case value_t::number_float: \ 3610 | return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \ 3611 | \ 3612 | case value_t::binary: \ 3613 | return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \ 3614 | \ 3615 | case value_t::discarded: \ 3616 | default: \ 3617 | return (unordered_result); \ 3618 | } \ 3619 | } \ 3620 | else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \ 3621 | { \ 3622 | return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \ 3623 | } \ 3624 | else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \ 3625 | { \ 3626 | return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \ 3627 | } \ 3628 | else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \ 3629 | { \ 3630 | return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \ 3631 | } \ 3632 | else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \ 3633 | { \ 3634 | return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \ 3635 | } \ 3636 | else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \ 3637 | { \ 3638 | return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \ 3639 | } \ 3640 | else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \ 3641 | { \ 3642 | return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \ 3643 | } \ 3644 | else if(compares_unordered(lhs, rhs))\ 3645 | {\ 3646 | return (unordered_result);\ 3647 | }\ 3648 | \ 3649 | return (default_result); 3650 | 3651 | JSON_PRIVATE_UNLESS_TESTED: 3652 | // returns true if: 3653 | // - any operand is NaN and the other operand is of number type 3654 | // - any operand is discarded 3655 | // in legacy mode, discarded values are considered ordered if 3656 | // an operation is computed as an odd number of inverses of others 3657 | static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept 3658 | { 3659 | if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number()) 3660 | || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) 3661 | { 3662 | return true; 3663 | } 3664 | #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 3665 | return (lhs.is_discarded() || rhs.is_discarded()) && !inverse; 3666 | #else 3667 | static_cast<void>(inverse); 3668 | return lhs.is_discarded() || rhs.is_discarded(); 3669 | #endif 3670 | } 3671 | 3672 | private: 3673 | bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept 3674 | { 3675 | return compares_unordered(*this, rhs, inverse); 3676 | } 3677 | 3678 | public: 3679 | #if JSON_HAS_THREE_WAY_COMPARISON 3680 | /// @brief comparison: equal 3681 | /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 3682 | bool operator==(const_reference rhs) const noexcept 3683 | { 3684 | #ifdef __GNUC__ 3685 | #pragma GCC diagnostic push 3686 | #pragma GCC diagnostic ignored "-Wfloat-equal" 3687 | #endif 3688 | const_reference lhs = *this; 3689 | JSON_IMPLEMENT_OPERATOR( ==, true, false, false) 3690 | #ifdef __GNUC__ 3691 | #pragma GCC diagnostic pop 3692 | #endif 3693 | } 3694 | 3695 | /// @brief comparison: equal 3696 | /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 3697 | template<typename ScalarType> 3698 | requires std::is_scalar_v<ScalarType> 3699 | bool operator==(ScalarType rhs) const noexcept 3700 | { 3701 | return *this == basic_json(rhs); 3702 | } 3703 | 3704 | /// @brief comparison: not equal 3705 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 3706 | bool operator!=(const_reference rhs) const noexcept 3707 | { 3708 | if (compares_unordered(rhs, true)) 3709 | { 3710 | return false; 3711 | } 3712 | return !operator==(rhs); 3713 | } 3714 | 3715 | /// @brief comparison: 3-way 3716 | /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 3717 | std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD* 3718 | { 3719 | const_reference lhs = *this; 3720 | // default_result is used if we cannot compare values. In that case, 3721 | // we compare types. 3722 | JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD* 3723 | std::partial_ordering::equivalent, 3724 | std::partial_ordering::unordered, 3725 | lhs_type <=> rhs_type) // *NOPAD* 3726 | } 3727 | 3728 | /// @brief comparison: 3-way 3729 | /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/ 3730 | template<typename ScalarType> 3731 | requires std::is_scalar_v<ScalarType> 3732 | std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD* 3733 | { 3734 | return *this <=> basic_json(rhs); // *NOPAD* 3735 | } 3736 | 3737 | #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 3738 | // all operators that are computed as an odd number of inverses of others 3739 | // need to be overloaded to emulate the legacy comparison behavior 3740 | 3741 | /// @brief comparison: less than or equal 3742 | /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 3743 | JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) 3744 | bool operator<=(const_reference rhs) const noexcept 3745 | { 3746 | if (compares_unordered(rhs, true)) 3747 | { 3748 | return false; 3749 | } 3750 | return !(rhs < *this); 3751 | } 3752 | 3753 | /// @brief comparison: less than or equal 3754 | /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 3755 | template<typename ScalarType> 3756 | requires std::is_scalar_v<ScalarType> 3757 | bool operator<=(ScalarType rhs) const noexcept 3758 | { 3759 | return *this <= basic_json(rhs); 3760 | } 3761 | 3762 | /// @brief comparison: greater than or equal 3763 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 3764 | JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON) 3765 | bool operator>=(const_reference rhs) const noexcept 3766 | { 3767 | if (compares_unordered(rhs, true)) 3768 | { 3769 | return false; 3770 | } 3771 | return !(*this < rhs); 3772 | } 3773 | 3774 | /// @brief comparison: greater than or equal 3775 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 3776 | template<typename ScalarType> 3777 | requires std::is_scalar_v<ScalarType> 3778 | bool operator>=(ScalarType rhs) const noexcept 3779 | { 3780 | return *this >= basic_json(rhs); 3781 | } 3782 | #endif 3783 | #else 3784 | /// @brief comparison: equal 3785 | /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 3786 | friend bool operator==(const_reference lhs, const_reference rhs) noexcept 3787 | { 3788 | #ifdef __GNUC__ 3789 | #pragma GCC diagnostic push 3790 | #pragma GCC diagnostic ignored "-Wfloat-equal" 3791 | #endif 3792 | JSON_IMPLEMENT_OPERATOR( ==, true, false, false) 3793 | #ifdef __GNUC__ 3794 | #pragma GCC diagnostic pop 3795 | #endif 3796 | } 3797 | 3798 | /// @brief comparison: equal 3799 | /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 3800 | template<typename ScalarType, typename std::enable_if< 3801 | std::is_scalar<ScalarType>::value, int>::type = 0> 3802 | friend bool operator==(const_reference lhs, ScalarType rhs) noexcept 3803 | { 3804 | return lhs == basic_json(rhs); 3805 | } 3806 | 3807 | /// @brief comparison: equal 3808 | /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/ 3809 | template<typename ScalarType, typename std::enable_if< 3810 | std::is_scalar<ScalarType>::value, int>::type = 0> 3811 | friend bool operator==(ScalarType lhs, const_reference rhs) noexcept 3812 | { 3813 | return basic_json(lhs) == rhs; 3814 | } 3815 | 3816 | /// @brief comparison: not equal 3817 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 3818 | friend bool operator!=(const_reference lhs, const_reference rhs) noexcept 3819 | { 3820 | if (compares_unordered(lhs, rhs, true)) 3821 | { 3822 | return false; 3823 | } 3824 | return !(lhs == rhs); 3825 | } 3826 | 3827 | /// @brief comparison: not equal 3828 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 3829 | template<typename ScalarType, typename std::enable_if< 3830 | std::is_scalar<ScalarType>::value, int>::type = 0> 3831 | friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept 3832 | { 3833 | return lhs != basic_json(rhs); 3834 | } 3835 | 3836 | /// @brief comparison: not equal 3837 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/ 3838 | template<typename ScalarType, typename std::enable_if< 3839 | std::is_scalar<ScalarType>::value, int>::type = 0> 3840 | friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept 3841 | { 3842 | return basic_json(lhs) != rhs; 3843 | } 3844 | 3845 | /// @brief comparison: less than 3846 | /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 3847 | friend bool operator<(const_reference lhs, const_reference rhs) noexcept 3848 | { 3849 | // default_result is used if we cannot compare values. In that case, 3850 | // we compare types. Note we have to call the operator explicitly, 3851 | // because MSVC has problems otherwise. 3852 | JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type)) 3853 | } 3854 | 3855 | /// @brief comparison: less than 3856 | /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 3857 | template<typename ScalarType, typename std::enable_if< 3858 | std::is_scalar<ScalarType>::value, int>::type = 0> 3859 | friend bool operator<(const_reference lhs, ScalarType rhs) noexcept 3860 | { 3861 | return lhs < basic_json(rhs); 3862 | } 3863 | 3864 | /// @brief comparison: less than 3865 | /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/ 3866 | template<typename ScalarType, typename std::enable_if< 3867 | std::is_scalar<ScalarType>::value, int>::type = 0> 3868 | friend bool operator<(ScalarType lhs, const_reference rhs) noexcept 3869 | { 3870 | return basic_json(lhs) < rhs; 3871 | } 3872 | 3873 | /// @brief comparison: less than or equal 3874 | /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 3875 | friend bool operator<=(const_reference lhs, const_reference rhs) noexcept 3876 | { 3877 | if (compares_unordered(lhs, rhs, true)) 3878 | { 3879 | return false; 3880 | } 3881 | return !(rhs < lhs); 3882 | } 3883 | 3884 | /// @brief comparison: less than or equal 3885 | /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 3886 | template<typename ScalarType, typename std::enable_if< 3887 | std::is_scalar<ScalarType>::value, int>::type = 0> 3888 | friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept 3889 | { 3890 | return lhs <= basic_json(rhs); 3891 | } 3892 | 3893 | /// @brief comparison: less than or equal 3894 | /// @sa https://json.nlohmann.me/api/basic_json/operator_le/ 3895 | template<typename ScalarType, typename std::enable_if< 3896 | std::is_scalar<ScalarType>::value, int>::type = 0> 3897 | friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept 3898 | { 3899 | return basic_json(lhs) <= rhs; 3900 | } 3901 | 3902 | /// @brief comparison: greater than 3903 | /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 3904 | friend bool operator>(const_reference lhs, const_reference rhs) noexcept 3905 | { 3906 | // double inverse 3907 | if (compares_unordered(lhs, rhs)) 3908 | { 3909 | return false; 3910 | } 3911 | return !(lhs <= rhs); 3912 | } 3913 | 3914 | /// @brief comparison: greater than 3915 | /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 3916 | template<typename ScalarType, typename std::enable_if< 3917 | std::is_scalar<ScalarType>::value, int>::type = 0> 3918 | friend bool operator>(const_reference lhs, ScalarType rhs) noexcept 3919 | { 3920 | return lhs > basic_json(rhs); 3921 | } 3922 | 3923 | /// @brief comparison: greater than 3924 | /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/ 3925 | template<typename ScalarType, typename std::enable_if< 3926 | std::is_scalar<ScalarType>::value, int>::type = 0> 3927 | friend bool operator>(ScalarType lhs, const_reference rhs) noexcept 3928 | { 3929 | return basic_json(lhs) > rhs; 3930 | } 3931 | 3932 | /// @brief comparison: greater than or equal 3933 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 3934 | friend bool operator>=(const_reference lhs, const_reference rhs) noexcept 3935 | { 3936 | if (compares_unordered(lhs, rhs, true)) 3937 | { 3938 | return false; 3939 | } 3940 | return !(lhs < rhs); 3941 | } 3942 | 3943 | /// @brief comparison: greater than or equal 3944 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 3945 | template<typename ScalarType, typename std::enable_if< 3946 | std::is_scalar<ScalarType>::value, int>::type = 0> 3947 | friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept 3948 | { 3949 | return lhs >= basic_json(rhs); 3950 | } 3951 | 3952 | /// @brief comparison: greater than or equal 3953 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/ 3954 | template<typename ScalarType, typename std::enable_if< 3955 | std::is_scalar<ScalarType>::value, int>::type = 0> 3956 | friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept 3957 | { 3958 | return basic_json(lhs) >= rhs; 3959 | } 3960 | #endif 3961 | 3962 | #undef JSON_IMPLEMENT_OPERATOR 3963 | 3964 | /// @} 3965 | 3966 | /////////////////// 3967 | // serialization // 3968 | /////////////////// 3969 | 3970 | /// @name serialization 3971 | /// @{ 3972 | #ifndef JSON_NO_IO 3973 | /// @brief serialize to stream 3974 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 3975 | friend std::ostream& operator<<(std::ostream& o, const basic_json& j) 3976 | { 3977 | // read width member and use it as indentation parameter if nonzero 3978 | const bool pretty_print = o.width() > 0; 3979 | const auto indentation = pretty_print ? o.width() : 0; 3980 | 3981 | // reset width to 0 for subsequent calls to this stream 3982 | o.width(0); 3983 | 3984 | // do the actual serialization 3985 | serializer s(detail::output_adapter<char>(o), o.fill()); 3986 | s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation)); 3987 | return o; 3988 | } 3989 | 3990 | /// @brief serialize to stream 3991 | /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ 3992 | /// @deprecated This function is deprecated since 3.0.0 and will be removed in 3993 | /// version 4.0.0 of the library. Please use 3994 | /// operator<<(std::ostream&, const basic_json&) instead; that is, 3995 | /// replace calls like `j >> o;` with `o << j;`. 3996 | JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) 3997 | friend std::ostream& operator>>(const basic_json& j, std::ostream& o) 3998 | { 3999 | return o << j; 4000 | } 4001 | #endif // JSON_NO_IO 4002 | /// @} 4003 | 4004 | ///////////////////// 4005 | // deserialization // 4006 | ///////////////////// 4007 | 4008 | /// @name deserialization 4009 | /// @{ 4010 | 4011 | /// @brief deserialize from a compatible input 4012 | /// @sa https://json.nlohmann.me/api/basic_json/parse/ 4013 | template<typename InputType> 4014 | JSON_HEDLEY_WARN_UNUSED_RESULT 4015 | static basic_json parse(InputType&& i, 4016 | const parser_callback_t cb = nullptr, 4017 | const bool allow_exceptions = true, 4018 | const bool ignore_comments = false) 4019 | { 4020 | basic_json result; 4021 | parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result); 4022 | return result; 4023 | } 4024 | 4025 | /// @brief deserialize from a pair of character iterators 4026 | /// @sa https://json.nlohmann.me/api/basic_json/parse/ 4027 | template<typename IteratorType> 4028 | JSON_HEDLEY_WARN_UNUSED_RESULT 4029 | static basic_json parse(IteratorType first, 4030 | IteratorType last, 4031 | const parser_callback_t cb = nullptr, 4032 | const bool allow_exceptions = true, 4033 | const bool ignore_comments = false) 4034 | { 4035 | basic_json result; 4036 | parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); 4037 | return result; 4038 | } 4039 | 4040 | JSON_HEDLEY_WARN_UNUSED_RESULT 4041 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) 4042 | static basic_json parse(detail::span_input_adapter&& i, 4043 | const parser_callback_t cb = nullptr, 4044 | const bool allow_exceptions = true, 4045 | const bool ignore_comments = false) 4046 | { 4047 | basic_json result; 4048 | parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); 4049 | return result; 4050 | } 4051 | 4052 | /// @brief check if the input is valid JSON 4053 | /// @sa https://json.nlohmann.me/api/basic_json/accept/ 4054 | template<typename InputType> 4055 | static bool accept(InputType&& i, 4056 | const bool ignore_comments = false) 4057 | { 4058 | return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true); 4059 | } 4060 | 4061 | /// @brief check if the input is valid JSON 4062 | /// @sa https://json.nlohmann.me/api/basic_json/accept/ 4063 | template<typename IteratorType> 4064 | static bool accept(IteratorType first, IteratorType last, 4065 | const bool ignore_comments = false) 4066 | { 4067 | return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); 4068 | } 4069 | 4070 | JSON_HEDLEY_WARN_UNUSED_RESULT 4071 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) 4072 | static bool accept(detail::span_input_adapter&& i, 4073 | const bool ignore_comments = false) 4074 | { 4075 | return parser(i.get(), nullptr, false, ignore_comments).accept(true); 4076 | } 4077 | 4078 | /// @brief generate SAX events 4079 | /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 4080 | template <typename InputType, typename SAX> 4081 | JSON_HEDLEY_NON_NULL(2) 4082 | static bool sax_parse(InputType&& i, SAX* sax, 4083 | input_format_t format = input_format_t::json, 4084 | const bool strict = true, 4085 | const bool ignore_comments = false) 4086 | { 4087 | auto ia = detail::input_adapter(std::forward<InputType>(i)); 4088 | return format == input_format_t::json 4089 | ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 4090 | : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 4091 | } 4092 | 4093 | /// @brief generate SAX events 4094 | /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 4095 | template<class IteratorType, class SAX> 4096 | JSON_HEDLEY_NON_NULL(3) 4097 | static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, 4098 | input_format_t format = input_format_t::json, 4099 | const bool strict = true, 4100 | const bool ignore_comments = false) 4101 | { 4102 | auto ia = detail::input_adapter(std::move(first), std::move(last)); 4103 | return format == input_format_t::json 4104 | ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 4105 | : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 4106 | } 4107 | 4108 | /// @brief generate SAX events 4109 | /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ 4110 | /// @deprecated This function is deprecated since 3.8.0 and will be removed in 4111 | /// version 4.0.0 of the library. Please use 4112 | /// sax_parse(ptr, ptr + len) instead. 4113 | template <typename SAX> 4114 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) 4115 | JSON_HEDLEY_NON_NULL(2) 4116 | static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, 4117 | input_format_t format = input_format_t::json, 4118 | const bool strict = true, 4119 | const bool ignore_comments = false) 4120 | { 4121 | auto ia = i.get(); 4122 | return format == input_format_t::json 4123 | // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 4124 | ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) 4125 | // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 4126 | : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict); 4127 | } 4128 | #ifndef JSON_NO_IO 4129 | /// @brief deserialize from stream 4130 | /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 4131 | /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in 4132 | /// version 4.0.0 of the library. Please use 4133 | /// operator>>(std::istream&, basic_json&) instead; that is, 4134 | /// replace calls like `j << i;` with `i >> j;`. 4135 | JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) 4136 | friend std::istream& operator<<(basic_json& j, std::istream& i) 4137 | { 4138 | return operator>>(i, j); 4139 | } 4140 | 4141 | /// @brief deserialize from stream 4142 | /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/ 4143 | friend std::istream& operator>>(std::istream& i, basic_json& j) 4144 | { 4145 | parser(detail::input_adapter(i)).parse(false, j); 4146 | return i; 4147 | } 4148 | #endif // JSON_NO_IO 4149 | /// @} 4150 | 4151 | /////////////////////////// 4152 | // convenience functions // 4153 | /////////////////////////// 4154 | 4155 | /// @brief return the type as string 4156 | /// @sa https://json.nlohmann.me/api/basic_json/type_name/ 4157 | JSON_HEDLEY_RETURNS_NON_NULL 4158 | const char* type_name() const noexcept 4159 | { 4160 | switch (m_data.m_type) 4161 | { 4162 | case value_t::null: 4163 | return "null"; 4164 | case value_t::object: 4165 | return "object"; 4166 | case value_t::array: 4167 | return "array"; 4168 | case value_t::string: 4169 | return "string"; 4170 | case value_t::boolean: 4171 | return "boolean"; 4172 | case value_t::binary: 4173 | return "binary"; 4174 | case value_t::discarded: 4175 | return "discarded"; 4176 | case value_t::number_integer: 4177 | case value_t::number_unsigned: 4178 | case value_t::number_float: 4179 | default: 4180 | return "number"; 4181 | } 4182 | } 4183 | 4184 | JSON_PRIVATE_UNLESS_TESTED: 4185 | ////////////////////// 4186 | // member variables // 4187 | ////////////////////// 4188 | 4189 | struct data 4190 | { 4191 | /// the type of the current element 4192 | value_t m_type = value_t::null; 4193 | 4194 | /// the value of the current element 4195 | json_value m_value = {}; 4196 | 4197 | data(const value_t v) 4198 | : m_type(v), m_value(v) 4199 | { 4200 | } 4201 | 4202 | data(size_type cnt, const basic_json& val) 4203 | : m_type(value_t::array) 4204 | { 4205 | m_value.array = create<array_t>(cnt, val); 4206 | } 4207 | 4208 | data() noexcept = default; 4209 | data(data&&) noexcept = default; 4210 | data(const data&) noexcept = delete; 4211 | data& operator=(data&&) noexcept = delete; 4212 | data& operator=(const data&) noexcept = delete; 4213 | 4214 | ~data() noexcept 4215 | { 4216 | m_value.destroy(m_type); 4217 | } 4218 | }; 4219 | 4220 | data m_data = {}; 4221 | 4222 | #if JSON_DIAGNOSTICS 4223 | /// a pointer to a parent value (for debugging purposes) 4224 | basic_json* m_parent = nullptr; 4225 | #endif 4226 | 4227 | ////////////////////////////////////////// 4228 | // binary serialization/deserialization // 4229 | ////////////////////////////////////////// 4230 | 4231 | /// @name binary serialization/deserialization support 4232 | /// @{ 4233 | 4234 | public: 4235 | /// @brief create a CBOR serialization of a given JSON value 4236 | /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 4237 | static std::vector<std::uint8_t> to_cbor(const basic_json& j) 4238 | { 4239 | std::vector<std::uint8_t> result; 4240 | to_cbor(j, result); 4241 | return result; 4242 | } 4243 | 4244 | /// @brief create a CBOR serialization of a given JSON value 4245 | /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 4246 | static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o) 4247 | { 4248 | binary_writer<std::uint8_t>(o).write_cbor(j); 4249 | } 4250 | 4251 | /// @brief create a CBOR serialization of a given JSON value 4252 | /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/ 4253 | static void to_cbor(const basic_json& j, detail::output_adapter<char> o) 4254 | { 4255 | binary_writer<char>(o).write_cbor(j); 4256 | } 4257 | 4258 | /// @brief create a MessagePack serialization of a given JSON value 4259 | /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 4260 | static std::vector<std::uint8_t> to_msgpack(const basic_json& j) 4261 | { 4262 | std::vector<std::uint8_t> result; 4263 | to_msgpack(j, result); 4264 | return result; 4265 | } 4266 | 4267 | /// @brief create a MessagePack serialization of a given JSON value 4268 | /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 4269 | static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o) 4270 | { 4271 | binary_writer<std::uint8_t>(o).write_msgpack(j); 4272 | } 4273 | 4274 | /// @brief create a MessagePack serialization of a given JSON value 4275 | /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/ 4276 | static void to_msgpack(const basic_json& j, detail::output_adapter<char> o) 4277 | { 4278 | binary_writer<char>(o).write_msgpack(j); 4279 | } 4280 | 4281 | /// @brief create a UBJSON serialization of a given JSON value 4282 | /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 4283 | static std::vector<std::uint8_t> to_ubjson(const basic_json& j, 4284 | const bool use_size = false, 4285 | const bool use_type = false) 4286 | { 4287 | std::vector<std::uint8_t> result; 4288 | to_ubjson(j, result, use_size, use_type); 4289 | return result; 4290 | } 4291 | 4292 | /// @brief create a UBJSON serialization of a given JSON value 4293 | /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 4294 | static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o, 4295 | const bool use_size = false, const bool use_type = false) 4296 | { 4297 | binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type); 4298 | } 4299 | 4300 | /// @brief create a UBJSON serialization of a given JSON value 4301 | /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/ 4302 | static void to_ubjson(const basic_json& j, detail::output_adapter<char> o, 4303 | const bool use_size = false, const bool use_type = false) 4304 | { 4305 | binary_writer<char>(o).write_ubjson(j, use_size, use_type); 4306 | } 4307 | 4308 | /// @brief create a BJData serialization of a given JSON value 4309 | /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 4310 | static std::vector<std::uint8_t> to_bjdata(const basic_json& j, 4311 | const bool use_size = false, 4312 | const bool use_type = false) 4313 | { 4314 | std::vector<std::uint8_t> result; 4315 | to_bjdata(j, result, use_size, use_type); 4316 | return result; 4317 | } 4318 | 4319 | /// @brief create a BJData serialization of a given JSON value 4320 | /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 4321 | static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o, 4322 | const bool use_size = false, const bool use_type = false) 4323 | { 4324 | binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true); 4325 | } 4326 | 4327 | /// @brief create a BJData serialization of a given JSON value 4328 | /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/ 4329 | static void to_bjdata(const basic_json& j, detail::output_adapter<char> o, 4330 | const bool use_size = false, const bool use_type = false) 4331 | { 4332 | binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true); 4333 | } 4334 | 4335 | /// @brief create a BSON serialization of a given JSON value 4336 | /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 4337 | static std::vector<std::uint8_t> to_bson(const basic_json& j) 4338 | { 4339 | std::vector<std::uint8_t> result; 4340 | to_bson(j, result); 4341 | return result; 4342 | } 4343 | 4344 | /// @brief create a BSON serialization of a given JSON value 4345 | /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 4346 | static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o) 4347 | { 4348 | binary_writer<std::uint8_t>(o).write_bson(j); 4349 | } 4350 | 4351 | /// @brief create a BSON serialization of a given JSON value 4352 | /// @sa https://json.nlohmann.me/api/basic_json/to_bson/ 4353 | static void to_bson(const basic_json& j, detail::output_adapter<char> o) 4354 | { 4355 | binary_writer<char>(o).write_bson(j); 4356 | } 4357 | 4358 | /// @brief create a JSON value from an input in CBOR format 4359 | /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 4360 | template<typename InputType> 4361 | JSON_HEDLEY_WARN_UNUSED_RESULT 4362 | static basic_json from_cbor(InputType&& i, 4363 | const bool strict = true, 4364 | const bool allow_exceptions = true, 4365 | const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 4366 | { 4367 | basic_json result; 4368 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4369 | auto ia = detail::input_adapter(std::forward<InputType>(i)); 4370 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 4371 | return res ? result : basic_json(value_t::discarded); 4372 | } 4373 | 4374 | /// @brief create a JSON value from an input in CBOR format 4375 | /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/ 4376 | template<typename IteratorType> 4377 | JSON_HEDLEY_WARN_UNUSED_RESULT 4378 | static basic_json from_cbor(IteratorType first, IteratorType last, 4379 | const bool strict = true, 4380 | const bool allow_exceptions = true, 4381 | const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 4382 | { 4383 | basic_json result; 4384 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4385 | auto ia = detail::input_adapter(std::move(first), std::move(last)); 4386 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 4387 | return res ? result : basic_json(value_t::discarded); 4388 | } 4389 | 4390 | template<typename T> 4391 | JSON_HEDLEY_WARN_UNUSED_RESULT 4392 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) 4393 | static basic_json from_cbor(const T* ptr, std::size_t len, 4394 | const bool strict = true, 4395 | const bool allow_exceptions = true, 4396 | const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 4397 | { 4398 | return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); 4399 | } 4400 | 4401 | JSON_HEDLEY_WARN_UNUSED_RESULT 4402 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) 4403 | static basic_json from_cbor(detail::span_input_adapter&& i, 4404 | const bool strict = true, 4405 | const bool allow_exceptions = true, 4406 | const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) 4407 | { 4408 | basic_json result; 4409 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4410 | auto ia = i.get(); 4411 | // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 4412 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); 4413 | return res ? result : basic_json(value_t::discarded); 4414 | } 4415 | 4416 | /// @brief create a JSON value from an input in MessagePack format 4417 | /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 4418 | template<typename InputType> 4419 | JSON_HEDLEY_WARN_UNUSED_RESULT 4420 | static basic_json from_msgpack(InputType&& i, 4421 | const bool strict = true, 4422 | const bool allow_exceptions = true) 4423 | { 4424 | basic_json result; 4425 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4426 | auto ia = detail::input_adapter(std::forward<InputType>(i)); 4427 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 4428 | return res ? result : basic_json(value_t::discarded); 4429 | } 4430 | 4431 | /// @brief create a JSON value from an input in MessagePack format 4432 | /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/ 4433 | template<typename IteratorType> 4434 | JSON_HEDLEY_WARN_UNUSED_RESULT 4435 | static basic_json from_msgpack(IteratorType first, IteratorType last, 4436 | const bool strict = true, 4437 | const bool allow_exceptions = true) 4438 | { 4439 | basic_json result; 4440 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4441 | auto ia = detail::input_adapter(std::move(first), std::move(last)); 4442 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 4443 | return res ? result : basic_json(value_t::discarded); 4444 | } 4445 | 4446 | template<typename T> 4447 | JSON_HEDLEY_WARN_UNUSED_RESULT 4448 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) 4449 | static basic_json from_msgpack(const T* ptr, std::size_t len, 4450 | const bool strict = true, 4451 | const bool allow_exceptions = true) 4452 | { 4453 | return from_msgpack(ptr, ptr + len, strict, allow_exceptions); 4454 | } 4455 | 4456 | JSON_HEDLEY_WARN_UNUSED_RESULT 4457 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) 4458 | static basic_json from_msgpack(detail::span_input_adapter&& i, 4459 | const bool strict = true, 4460 | const bool allow_exceptions = true) 4461 | { 4462 | basic_json result; 4463 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4464 | auto ia = i.get(); 4465 | // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 4466 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); 4467 | return res ? result : basic_json(value_t::discarded); 4468 | } 4469 | 4470 | /// @brief create a JSON value from an input in UBJSON format 4471 | /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 4472 | template<typename InputType> 4473 | JSON_HEDLEY_WARN_UNUSED_RESULT 4474 | static basic_json from_ubjson(InputType&& i, 4475 | const bool strict = true, 4476 | const bool allow_exceptions = true) 4477 | { 4478 | basic_json result; 4479 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4480 | auto ia = detail::input_adapter(std::forward<InputType>(i)); 4481 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 4482 | return res ? result : basic_json(value_t::discarded); 4483 | } 4484 | 4485 | /// @brief create a JSON value from an input in UBJSON format 4486 | /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/ 4487 | template<typename IteratorType> 4488 | JSON_HEDLEY_WARN_UNUSED_RESULT 4489 | static basic_json from_ubjson(IteratorType first, IteratorType last, 4490 | const bool strict = true, 4491 | const bool allow_exceptions = true) 4492 | { 4493 | basic_json result; 4494 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4495 | auto ia = detail::input_adapter(std::move(first), std::move(last)); 4496 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 4497 | return res ? result : basic_json(value_t::discarded); 4498 | } 4499 | 4500 | template<typename T> 4501 | JSON_HEDLEY_WARN_UNUSED_RESULT 4502 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) 4503 | static basic_json from_ubjson(const T* ptr, std::size_t len, 4504 | const bool strict = true, 4505 | const bool allow_exceptions = true) 4506 | { 4507 | return from_ubjson(ptr, ptr + len, strict, allow_exceptions); 4508 | } 4509 | 4510 | JSON_HEDLEY_WARN_UNUSED_RESULT 4511 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) 4512 | static basic_json from_ubjson(detail::span_input_adapter&& i, 4513 | const bool strict = true, 4514 | const bool allow_exceptions = true) 4515 | { 4516 | basic_json result; 4517 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4518 | auto ia = i.get(); 4519 | // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 4520 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); 4521 | return res ? result : basic_json(value_t::discarded); 4522 | } 4523 | 4524 | /// @brief create a JSON value from an input in BJData format 4525 | /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 4526 | template<typename InputType> 4527 | JSON_HEDLEY_WARN_UNUSED_RESULT 4528 | static basic_json from_bjdata(InputType&& i, 4529 | const bool strict = true, 4530 | const bool allow_exceptions = true) 4531 | { 4532 | basic_json result; 4533 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4534 | auto ia = detail::input_adapter(std::forward<InputType>(i)); 4535 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); 4536 | return res ? result : basic_json(value_t::discarded); 4537 | } 4538 | 4539 | /// @brief create a JSON value from an input in BJData format 4540 | /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ 4541 | template<typename IteratorType> 4542 | JSON_HEDLEY_WARN_UNUSED_RESULT 4543 | static basic_json from_bjdata(IteratorType first, IteratorType last, 4544 | const bool strict = true, 4545 | const bool allow_exceptions = true) 4546 | { 4547 | basic_json result; 4548 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4549 | auto ia = detail::input_adapter(std::move(first), std::move(last)); 4550 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); 4551 | return res ? result : basic_json(value_t::discarded); 4552 | } 4553 | 4554 | /// @brief create a JSON value from an input in BSON format 4555 | /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 4556 | template<typename InputType> 4557 | JSON_HEDLEY_WARN_UNUSED_RESULT 4558 | static basic_json from_bson(InputType&& i, 4559 | const bool strict = true, 4560 | const bool allow_exceptions = true) 4561 | { 4562 | basic_json result; 4563 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4564 | auto ia = detail::input_adapter(std::forward<InputType>(i)); 4565 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 4566 | return res ? result : basic_json(value_t::discarded); 4567 | } 4568 | 4569 | /// @brief create a JSON value from an input in BSON format 4570 | /// @sa https://json.nlohmann.me/api/basic_json/from_bson/ 4571 | template<typename IteratorType> 4572 | JSON_HEDLEY_WARN_UNUSED_RESULT 4573 | static basic_json from_bson(IteratorType first, IteratorType last, 4574 | const bool strict = true, 4575 | const bool allow_exceptions = true) 4576 | { 4577 | basic_json result; 4578 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4579 | auto ia = detail::input_adapter(std::move(first), std::move(last)); 4580 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 4581 | return res ? result : basic_json(value_t::discarded); 4582 | } 4583 | 4584 | template<typename T> 4585 | JSON_HEDLEY_WARN_UNUSED_RESULT 4586 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) 4587 | static basic_json from_bson(const T* ptr, std::size_t len, 4588 | const bool strict = true, 4589 | const bool allow_exceptions = true) 4590 | { 4591 | return from_bson(ptr, ptr + len, strict, allow_exceptions); 4592 | } 4593 | 4594 | JSON_HEDLEY_WARN_UNUSED_RESULT 4595 | JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) 4596 | static basic_json from_bson(detail::span_input_adapter&& i, 4597 | const bool strict = true, 4598 | const bool allow_exceptions = true) 4599 | { 4600 | basic_json result; 4601 | detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); 4602 | auto ia = i.get(); 4603 | // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 4604 | const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); 4605 | return res ? result : basic_json(value_t::discarded); 4606 | } 4607 | /// @} 4608 | 4609 | ////////////////////////// 4610 | // JSON Pointer support // 4611 | ////////////////////////// 4612 | 4613 | /// @name JSON Pointer functions 4614 | /// @{ 4615 | 4616 | /// @brief access specified element via JSON Pointer 4617 | /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 4618 | reference operator[](const json_pointer& ptr) 4619 | { 4620 | return ptr.get_unchecked(this); 4621 | } 4622 | 4623 | template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 4624 | JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 4625 | reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) 4626 | { 4627 | return ptr.get_unchecked(this); 4628 | } 4629 | 4630 | /// @brief access specified element via JSON Pointer 4631 | /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ 4632 | const_reference operator[](const json_pointer& ptr) const 4633 | { 4634 | return ptr.get_unchecked(this); 4635 | } 4636 | 4637 | template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 4638 | JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 4639 | const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const 4640 | { 4641 | return ptr.get_unchecked(this); 4642 | } 4643 | 4644 | /// @brief access specified element via JSON Pointer 4645 | /// @sa https://json.nlohmann.me/api/basic_json/at/ 4646 | reference at(const json_pointer& ptr) 4647 | { 4648 | return ptr.get_checked(this); 4649 | } 4650 | 4651 | template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 4652 | JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 4653 | reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) 4654 | { 4655 | return ptr.get_checked(this); 4656 | } 4657 | 4658 | /// @brief access specified element via JSON Pointer 4659 | /// @sa https://json.nlohmann.me/api/basic_json/at/ 4660 | const_reference at(const json_pointer& ptr) const 4661 | { 4662 | return ptr.get_checked(this); 4663 | } 4664 | 4665 | template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0> 4666 | JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens) 4667 | const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const 4668 | { 4669 | return ptr.get_checked(this); 4670 | } 4671 | 4672 | /// @brief return flattened JSON value 4673 | /// @sa https://json.nlohmann.me/api/basic_json/flatten/ 4674 | basic_json flatten() const 4675 | { 4676 | basic_json result(value_t::object); 4677 | json_pointer::flatten("", *this, result); 4678 | return result; 4679 | } 4680 | 4681 | /// @brief unflatten a previously flattened JSON value 4682 | /// @sa https://json.nlohmann.me/api/basic_json/unflatten/ 4683 | basic_json unflatten() const 4684 | { 4685 | return json_pointer::unflatten(*this); 4686 | } 4687 | 4688 | /// @} 4689 | 4690 | ////////////////////////// 4691 | // JSON Patch functions // 4692 | ////////////////////////// 4693 | 4694 | /// @name JSON Patch functions 4695 | /// @{ 4696 | 4697 | /// @brief applies a JSON patch in-place without copying the object 4698 | /// @sa https://json.nlohmann.me/api/basic_json/patch/ 4699 | void patch_inplace(const basic_json& json_patch) 4700 | { 4701 | basic_json& result = *this; 4702 | // the valid JSON Patch operations 4703 | enum class patch_operations {add, remove, replace, move, copy, test, invalid}; 4704 | 4705 | const auto get_op = [](const std::string & op) 4706 | { 4707 | if (op == "add") 4708 | { 4709 | return patch_operations::add; 4710 | } 4711 | if (op == "remove") 4712 | { 4713 | return patch_operations::remove; 4714 | } 4715 | if (op == "replace") 4716 | { 4717 | return patch_operations::replace; 4718 | } 4719 | if (op == "move") 4720 | { 4721 | return patch_operations::move; 4722 | } 4723 | if (op == "copy") 4724 | { 4725 | return patch_operations::copy; 4726 | } 4727 | if (op == "test") 4728 | { 4729 | return patch_operations::test; 4730 | } 4731 | 4732 | return patch_operations::invalid; 4733 | }; 4734 | 4735 | // wrapper for "add" operation; add value at ptr 4736 | const auto operation_add = [&result](json_pointer & ptr, basic_json val) 4737 | { 4738 | // adding to the root of the target document means replacing it 4739 | if (ptr.empty()) 4740 | { 4741 | result = val; 4742 | return; 4743 | } 4744 | 4745 | // make sure the top element of the pointer exists 4746 | json_pointer const top_pointer = ptr.top(); 4747 | if (top_pointer != ptr) 4748 | { 4749 | result.at(top_pointer); 4750 | } 4751 | 4752 | // get reference to parent of JSON pointer ptr 4753 | const auto last_path = ptr.back(); 4754 | ptr.pop_back(); 4755 | // parent must exist when performing patch add per RFC6902 specs 4756 | basic_json& parent = result.at(ptr); 4757 | 4758 | switch (parent.m_data.m_type) 4759 | { 4760 | case value_t::null: 4761 | case value_t::object: 4762 | { 4763 | // use operator[] to add value 4764 | parent[last_path] = val; 4765 | break; 4766 | } 4767 | 4768 | case value_t::array: 4769 | { 4770 | if (last_path == "-") 4771 | { 4772 | // special case: append to back 4773 | parent.push_back(val); 4774 | } 4775 | else 4776 | { 4777 | const auto idx = json_pointer::template array_index<basic_json_t>(last_path); 4778 | if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) 4779 | { 4780 | // avoid undefined behavior 4781 | JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent)); 4782 | } 4783 | 4784 | // default case: insert add offset 4785 | parent.insert(parent.begin() + static_cast<difference_type>(idx), val); 4786 | } 4787 | break; 4788 | } 4789 | 4790 | // if there exists a parent it cannot be primitive 4791 | case value_t::string: // LCOV_EXCL_LINE 4792 | case value_t::boolean: // LCOV_EXCL_LINE 4793 | case value_t::number_integer: // LCOV_EXCL_LINE 4794 | case value_t::number_unsigned: // LCOV_EXCL_LINE 4795 | case value_t::number_float: // LCOV_EXCL_LINE 4796 | case value_t::binary: // LCOV_EXCL_LINE 4797 | case value_t::discarded: // LCOV_EXCL_LINE 4798 | default: // LCOV_EXCL_LINE 4799 | JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE 4800 | } 4801 | }; 4802 | 4803 | // wrapper for "remove" operation; remove value at ptr 4804 | const auto operation_remove = [this, & result](json_pointer & ptr) 4805 | { 4806 | // get reference to parent of JSON pointer ptr 4807 | const auto last_path = ptr.back(); 4808 | ptr.pop_back(); 4809 | basic_json& parent = result.at(ptr); 4810 | 4811 | // remove child 4812 | if (parent.is_object()) 4813 | { 4814 | // perform range check 4815 | auto it = parent.find(last_path); 4816 | if (JSON_HEDLEY_LIKELY(it != parent.end())) 4817 | { 4818 | parent.erase(it); 4819 | } 4820 | else 4821 | { 4822 | JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this)); 4823 | } 4824 | } 4825 | else if (parent.is_array()) 4826 | { 4827 | // note erase performs range check 4828 | parent.erase(json_pointer::template array_index<basic_json_t>(last_path)); 4829 | } 4830 | }; 4831 | 4832 | // type check: top level value must be an array 4833 | if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) 4834 | { 4835 | JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch)); 4836 | } 4837 | 4838 | // iterate and apply the operations 4839 | for (const auto& val : json_patch) 4840 | { 4841 | // wrapper to get a value for an operation 4842 | const auto get_value = [&val](const std::string & op, 4843 | const std::string & member, 4844 | bool string_type) -> basic_json & 4845 | { 4846 | // find value 4847 | auto it = val.m_data.m_value.object->find(member); 4848 | 4849 | // context-sensitive error message 4850 | const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); 4851 | 4852 | // check if desired value is present 4853 | if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) 4854 | { 4855 | // NOLINTNEXTLINE(performance-inefficient-string-concatenation) 4856 | JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val)); 4857 | } 4858 | 4859 | // check if result is of type string 4860 | if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) 4861 | { 4862 | // NOLINTNEXTLINE(performance-inefficient-string-concatenation) 4863 | JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val)); 4864 | } 4865 | 4866 | // no error: return value 4867 | return it->second; 4868 | }; 4869 | 4870 | // type check: every element of the array must be an object 4871 | if (JSON_HEDLEY_UNLIKELY(!val.is_object())) 4872 | { 4873 | JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val)); 4874 | } 4875 | 4876 | // collect mandatory members 4877 | const auto op = get_value("op", "op", true).template get<std::string>(); 4878 | const auto path = get_value(op, "path", true).template get<std::string>(); 4879 | json_pointer ptr(path); 4880 | 4881 | switch (get_op(op)) 4882 | { 4883 | case patch_operations::add: 4884 | { 4885 | operation_add(ptr, get_value("add", "value", false)); 4886 | break; 4887 | } 4888 | 4889 | case patch_operations::remove: 4890 | { 4891 | operation_remove(ptr); 4892 | break; 4893 | } 4894 | 4895 | case patch_operations::replace: 4896 | { 4897 | // the "path" location must exist - use at() 4898 | result.at(ptr) = get_value("replace", "value", false); 4899 | break; 4900 | } 4901 | 4902 | case patch_operations::move: 4903 | { 4904 | const auto from_path = get_value("move", "from", true).template get<std::string>(); 4905 | json_pointer from_ptr(from_path); 4906 | 4907 | // the "from" location must exist - use at() 4908 | basic_json const v = result.at(from_ptr); 4909 | 4910 | // The move operation is functionally identical to a 4911 | // "remove" operation on the "from" location, followed 4912 | // immediately by an "add" operation at the target 4913 | // location with the value that was just removed. 4914 | operation_remove(from_ptr); 4915 | operation_add(ptr, v); 4916 | break; 4917 | } 4918 | 4919 | case patch_operations::copy: 4920 | { 4921 | const auto from_path = get_value("copy", "from", true).template get<std::string>(); 4922 | const json_pointer from_ptr(from_path); 4923 | 4924 | // the "from" location must exist - use at() 4925 | basic_json const v = result.at(from_ptr); 4926 | 4927 | // The copy is functionally identical to an "add" 4928 | // operation at the target location using the value 4929 | // specified in the "from" member. 4930 | operation_add(ptr, v); 4931 | break; 4932 | } 4933 | 4934 | case patch_operations::test: 4935 | { 4936 | bool success = false; 4937 | JSON_TRY 4938 | { 4939 | // check if "value" matches the one at "path" 4940 | // the "path" location must exist - use at() 4941 | success = (result.at(ptr) == get_value("test", "value", false)); 4942 | } 4943 | JSON_INTERNAL_CATCH (out_of_range&) 4944 | { 4945 | // ignore out of range errors: success remains false 4946 | } 4947 | 4948 | // throw an exception if test fails 4949 | if (JSON_HEDLEY_UNLIKELY(!success)) 4950 | { 4951 | JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val)); 4952 | } 4953 | 4954 | break; 4955 | } 4956 | 4957 | case patch_operations::invalid: 4958 | default: 4959 | { 4960 | // op must be "add", "remove", "replace", "move", "copy", or 4961 | // "test" 4962 | JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val)); 4963 | } 4964 | } 4965 | } 4966 | } 4967 | 4968 | /// @brief applies a JSON patch to a copy of the current object 4969 | /// @sa https://json.nlohmann.me/api/basic_json/patch/ 4970 | basic_json patch(const basic_json& json_patch) const 4971 | { 4972 | basic_json result = *this; 4973 | result.patch_inplace(json_patch); 4974 | return result; 4975 | } 4976 | 4977 | /// @brief creates a diff as a JSON patch 4978 | /// @sa https://json.nlohmann.me/api/basic_json/diff/ 4979 | JSON_HEDLEY_WARN_UNUSED_RESULT 4980 | static basic_json diff(const basic_json& source, const basic_json& target, 4981 | const std::string& path = "") 4982 | { 4983 | // the patch 4984 | basic_json result(value_t::array); 4985 | 4986 | // if the values are the same, return empty patch 4987 | if (source == target) 4988 | { 4989 | return result; 4990 | } 4991 | 4992 | if (source.type() != target.type()) 4993 | { 4994 | // different types: replace value 4995 | result.push_back( 4996 | { 4997 | {"op", "replace"}, {"path", path}, {"value", target} 4998 | }); 4999 | return result; 5000 | } 5001 | 5002 | switch (source.type()) 5003 | { 5004 | case value_t::array: 5005 | { 5006 | // first pass: traverse common elements 5007 | std::size_t i = 0; 5008 | while (i < source.size() && i < target.size()) 5009 | { 5010 | // recursive call to compare array values at index i 5011 | auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i))); 5012 | result.insert(result.end(), temp_diff.begin(), temp_diff.end()); 5013 | ++i; 5014 | } 5015 | 5016 | // We now reached the end of at least one array 5017 | // in a second pass, traverse the remaining elements 5018 | 5019 | // remove my remaining elements 5020 | const auto end_index = static_cast<difference_type>(result.size()); 5021 | while (i < source.size()) 5022 | { 5023 | // add operations in reverse order to avoid invalid 5024 | // indices 5025 | result.insert(result.begin() + end_index, object( 5026 | { 5027 | {"op", "remove"}, 5028 | {"path", detail::concat(path, '/', std::to_string(i))} 5029 | })); 5030 | ++i; 5031 | } 5032 | 5033 | // add other remaining elements 5034 | while (i < target.size()) 5035 | { 5036 | result.push_back( 5037 | { 5038 | {"op", "add"}, 5039 | {"path", detail::concat(path, "/-")}, 5040 | {"value", target[i]} 5041 | }); 5042 | ++i; 5043 | } 5044 | 5045 | break; 5046 | } 5047 | 5048 | case value_t::object: 5049 | { 5050 | // first pass: traverse this object's elements 5051 | for (auto it = source.cbegin(); it != source.cend(); ++it) 5052 | { 5053 | // escape the key name to be used in a JSON patch 5054 | const auto path_key = detail::concat(path, '/', detail::escape(it.key())); 5055 | 5056 | if (target.find(it.key()) != target.end()) 5057 | { 5058 | // recursive call to compare object values at key it 5059 | auto temp_diff = diff(it.value(), target[it.key()], path_key); 5060 | result.insert(result.end(), temp_diff.begin(), temp_diff.end()); 5061 | } 5062 | else 5063 | { 5064 | // found a key that is not in o -> remove it 5065 | result.push_back(object( 5066 | { 5067 | {"op", "remove"}, {"path", path_key} 5068 | })); 5069 | } 5070 | } 5071 | 5072 | // second pass: traverse other object's elements 5073 | for (auto it = target.cbegin(); it != target.cend(); ++it) 5074 | { 5075 | if (source.find(it.key()) == source.end()) 5076 | { 5077 | // found a key that is not in this -> add it 5078 | const auto path_key = detail::concat(path, '/', detail::escape(it.key())); 5079 | result.push_back( 5080 | { 5081 | {"op", "add"}, {"path", path_key}, 5082 | {"value", it.value()} 5083 | }); 5084 | } 5085 | } 5086 | 5087 | break; 5088 | } 5089 | 5090 | case value_t::null: 5091 | case value_t::string: 5092 | case value_t::boolean: 5093 | case value_t::number_integer: 5094 | case value_t::number_unsigned: 5095 | case value_t::number_float: 5096 | case value_t::binary: 5097 | case value_t::discarded: 5098 | default: 5099 | { 5100 | // both primitive type: replace value 5101 | result.push_back( 5102 | { 5103 | {"op", "replace"}, {"path", path}, {"value", target} 5104 | }); 5105 | break; 5106 | } 5107 | } 5108 | 5109 | return result; 5110 | } 5111 | /// @} 5112 | 5113 | //////////////////////////////// 5114 | // JSON Merge Patch functions // 5115 | //////////////////////////////// 5116 | 5117 | /// @name JSON Merge Patch functions 5118 | /// @{ 5119 | 5120 | /// @brief applies a JSON Merge Patch 5121 | /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/ 5122 | void merge_patch(const basic_json& apply_patch) 5123 | { 5124 | if (apply_patch.is_object()) 5125 | { 5126 | if (!is_object()) 5127 | { 5128 | *this = object(); 5129 | } 5130 | for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) 5131 | { 5132 | if (it.value().is_null()) 5133 | { 5134 | erase(it.key()); 5135 | } 5136 | else 5137 | { 5138 | operator[](it.key()).merge_patch(it.value()); 5139 | } 5140 | } 5141 | } 5142 | else 5143 | { 5144 | *this = apply_patch; 5145 | } 5146 | } 5147 | 5148 | /// @} 5149 | }; 5150 | 5151 | /// @brief user-defined to_string function for JSON values 5152 | /// @sa https://json.nlohmann.me/api/basic_json/to_string/ 5153 | NLOHMANN_BASIC_JSON_TPL_DECLARATION 5154 | std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) 5155 | { 5156 | return j.dump(); 5157 | } 5158 | 5159 | inline namespace literals 5160 | { 5161 | inline namespace json_literals 5162 | { 5163 | 5164 | /// @brief user-defined string literal for JSON values 5165 | /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ 5166 | JSON_HEDLEY_NON_NULL(1) 5167 | #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) 5168 | inline nlohmann::json operator ""_json(const char* s, std::size_t n) 5169 | #else 5170 | inline nlohmann::json operator "" _json(const char* s, std::size_t n) 5171 | #endif 5172 | { 5173 | return nlohmann::json::parse(s, s + n); 5174 | } 5175 | 5176 | /// @brief user-defined string literal for JSON pointer 5177 | /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ 5178 | JSON_HEDLEY_NON_NULL(1) 5179 | #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) 5180 | inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n) 5181 | #else 5182 | inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) 5183 | #endif 5184 | { 5185 | return nlohmann::json::json_pointer(std::string(s, n)); 5186 | } 5187 | 5188 | } // namespace json_literals 5189 | } // namespace literals 5190 | NLOHMANN_JSON_NAMESPACE_END 5191 | 5192 | /////////////////////// 5193 | // nonmember support // 5194 | /////////////////////// 5195 | 5196 | namespace std // NOLINT(cert-dcl58-cpp) 5197 | { 5198 | 5199 | /// @brief hash value for JSON objects 5200 | /// @sa https://json.nlohmann.me/api/basic_json/std_hash/ 5201 | NLOHMANN_BASIC_JSON_TPL_DECLARATION 5202 | struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp) 5203 | { 5204 | std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const 5205 | { 5206 | return nlohmann::detail::hash(j); 5207 | } 5208 | }; 5209 | 5210 | // specialization for std::less<value_t> 5211 | template<> 5212 | struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679 5213 | { 5214 | /*! 5215 | @brief compare two value_t enum values 5216 | @since version 3.0.0 5217 | */ 5218 | bool operator()(::nlohmann::detail::value_t lhs, 5219 | ::nlohmann::detail::value_t rhs) const noexcept 5220 | { 5221 | #if JSON_HAS_THREE_WAY_COMPARISON 5222 | return std::is_lt(lhs <=> rhs); // *NOPAD* 5223 | #else 5224 | return ::nlohmann::detail::operator<(lhs, rhs); 5225 | #endif 5226 | } 5227 | }; 5228 | 5229 | // C++20 prohibit function specialization in the std namespace. 5230 | #ifndef JSON_HAS_CPP_20 5231 | 5232 | /// @brief exchanges the values of two JSON objects 5233 | /// @sa https://json.nlohmann.me/api/basic_json/std_swap/ 5234 | NLOHMANN_BASIC_JSON_TPL_DECLARATION 5235 | inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) 5236 | is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) 5237 | is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value) 5238 | { 5239 | j1.swap(j2); 5240 | } 5241 | 5242 | #endif 5243 | 5244 | } // namespace std 5245 | 5246 | #if JSON_USE_GLOBAL_UDLS 5247 | #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) 5248 | using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) 5249 | using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) 5250 | #else 5251 | using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) 5252 | using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) 5253 | #endif 5254 | #endif 5255 | 5256 | #include <nlohmann/detail/macro_unscope.hpp> 5257 | 5258 | #endif // INCLUDE_NLOHMANN_JSON_HPP_ 5259 | ```