This is page 3 of 17. Use http://codebase.md/wasdubya/x64dbgmcp?page={x} to view the full context. # Directory Structure ``` ├── build │ ├── MCPx64dbg.dp32 │ └── MCPx64dbg.dp64 ├── CMakeLists.txt ├── deps │ ├── pluginsdk │ │ ├── _dbgfunctions.h │ │ ├── _plugin_types.h │ │ ├── _plugins.h │ │ ├── _scriptapi_argument.h │ │ ├── _scriptapi_assembler.h │ │ ├── _scriptapi_bookmark.h │ │ ├── _scriptapi_comment.h │ │ ├── _scriptapi_debug.h │ │ ├── _scriptapi_flag.h │ │ ├── _scriptapi_function.h │ │ ├── _scriptapi_gui.h │ │ ├── _scriptapi_label.h │ │ ├── _scriptapi_memory.h │ │ ├── _scriptapi_misc.h │ │ ├── _scriptapi_module.h │ │ ├── _scriptapi_pattern.h │ │ ├── _scriptapi_register.h │ │ ├── _scriptapi_stack.h │ │ ├── _scriptapi_symbol.h │ │ ├── _scriptapi.h │ │ ├── bridgegraph.h │ │ ├── bridgelist.h │ │ ├── bridgemain.h │ │ ├── dbghelp │ │ │ ├── dbghelp_x64.a │ │ │ ├── dbghelp_x64.lib │ │ │ ├── dbghelp_x86.a │ │ │ ├── dbghelp_x86.lib │ │ │ └── dbghelp.h │ │ ├── DeviceNameResolver │ │ │ ├── DeviceNameResolver_x64.a │ │ │ ├── DeviceNameResolver_x64.lib │ │ │ ├── DeviceNameResolver_x86.a │ │ │ ├── DeviceNameResolver_x86.lib │ │ │ └── DeviceNameResolver.h │ │ ├── jansson │ │ │ ├── jansson_config.h │ │ │ ├── jansson_x64.a │ │ │ ├── jansson_x64.lib │ │ │ ├── jansson_x64dbg.h │ │ │ ├── jansson_x86.a │ │ │ ├── jansson_x86.lib │ │ │ └── jansson.h │ │ ├── lz4 │ │ │ ├── lz4_x64.a │ │ │ ├── lz4_x64.lib │ │ │ ├── lz4_x86.a │ │ │ ├── lz4_x86.lib │ │ │ ├── lz4.h │ │ │ ├── lz4file.h │ │ │ └── lz4hc.h │ │ ├── nlohmann │ │ │ ├── adl_serializer.hpp │ │ │ ├── byte_container_with_subtype.hpp │ │ │ ├── detail │ │ │ │ ├── abi_macros.hpp │ │ │ │ ├── conversions │ │ │ │ │ ├── from_json.hpp │ │ │ │ │ ├── to_chars.hpp │ │ │ │ │ └── to_json.hpp │ │ │ │ ├── exceptions.hpp │ │ │ │ ├── hash.hpp │ │ │ │ ├── input │ │ │ │ │ ├── binary_reader.hpp │ │ │ │ │ ├── input_adapters.hpp │ │ │ │ │ ├── json_sax.hpp │ │ │ │ │ ├── lexer.hpp │ │ │ │ │ ├── parser.hpp │ │ │ │ │ └── position_t.hpp │ │ │ │ ├── iterators │ │ │ │ │ ├── internal_iterator.hpp │ │ │ │ │ ├── iter_impl.hpp │ │ │ │ │ ├── iteration_proxy.hpp │ │ │ │ │ ├── iterator_traits.hpp │ │ │ │ │ ├── json_reverse_iterator.hpp │ │ │ │ │ └── primitive_iterator.hpp │ │ │ │ ├── json_custom_base_class.hpp │ │ │ │ ├── json_pointer.hpp │ │ │ │ ├── json_ref.hpp │ │ │ │ ├── macro_scope.hpp │ │ │ │ ├── macro_unscope.hpp │ │ │ │ ├── meta │ │ │ │ │ ├── call_std │ │ │ │ │ │ ├── begin.hpp │ │ │ │ │ │ └── end.hpp │ │ │ │ │ ├── cpp_future.hpp │ │ │ │ │ ├── detected.hpp │ │ │ │ │ ├── identity_tag.hpp │ │ │ │ │ ├── is_sax.hpp │ │ │ │ │ ├── std_fs.hpp │ │ │ │ │ ├── type_traits.hpp │ │ │ │ │ └── void_t.hpp │ │ │ │ ├── output │ │ │ │ │ ├── binary_writer.hpp │ │ │ │ │ ├── output_adapters.hpp │ │ │ │ │ └── serializer.hpp │ │ │ │ ├── string_concat.hpp │ │ │ │ ├── string_escape.hpp │ │ │ │ └── value_t.hpp │ │ │ ├── json_fwd.hpp │ │ │ ├── json.hpp │ │ │ ├── ordered_map.hpp │ │ │ └── thirdparty │ │ │ └── hedley │ │ │ ├── hedley_undef.hpp │ │ │ └── hedley.hpp │ │ ├── TitanEngine │ │ │ ├── TitanEngine_x64.a │ │ │ ├── TitanEngine_x64.lib │ │ │ ├── TitanEngine_x86.a │ │ │ ├── TitanEngine_x86.lib │ │ │ └── TitanEngine.h │ │ ├── x32bridge.lib │ │ ├── x32dbg.lib │ │ ├── x64bridge.lib │ │ ├── x64dbg.lib │ │ └── XEDParse │ │ ├── XEDParse_x64.a │ │ ├── XEDParse_x64.lib │ │ ├── XEDParse_x86.a │ │ ├── XEDParse_x86.lib │ │ └── XEDParse.h │ └── x64dbg_sdk │ └── pluginsdk │ ├── _dbgfunctions.h │ ├── _plugin_types.h │ ├── _plugins.h │ ├── _scriptapi_argument.h │ ├── _scriptapi_assembler.h │ ├── _scriptapi_bookmark.h │ ├── _scriptapi_comment.h │ ├── _scriptapi_debug.h │ ├── _scriptapi_flag.h │ ├── _scriptapi_function.h │ ├── _scriptapi_gui.h │ ├── _scriptapi_label.h │ ├── _scriptapi_memory.h │ ├── _scriptapi_misc.h │ ├── _scriptapi_module.h │ ├── _scriptapi_pattern.h │ ├── _scriptapi_register.h │ ├── _scriptapi_stack.h │ ├── _scriptapi_symbol.h │ ├── _scriptapi.h │ ├── bridgegraph.h │ ├── bridgelist.h │ ├── bridgemain.h │ ├── dbghelp │ │ ├── dbghelp_x64.a │ │ ├── dbghelp_x64.lib │ │ ├── dbghelp_x86.a │ │ ├── dbghelp_x86.lib │ │ └── dbghelp.h │ ├── DeviceNameResolver │ │ ├── DeviceNameResolver_x64.a │ │ ├── DeviceNameResolver_x64.lib │ │ ├── DeviceNameResolver_x86.a │ │ ├── DeviceNameResolver_x86.lib │ │ └── DeviceNameResolver.h │ ├── jansson │ │ ├── jansson_config.h │ │ ├── jansson_x64.a │ │ ├── jansson_x64.lib │ │ ├── jansson_x64dbg.h │ │ ├── jansson_x86.a │ │ ├── jansson_x86.lib │ │ └── jansson.h │ ├── lz4 │ │ ├── lz4_x64.a │ │ ├── lz4_x64.lib │ │ ├── lz4_x86.a │ │ ├── lz4_x86.lib │ │ ├── lz4.h │ │ ├── lz4file.h │ │ └── lz4hc.h │ ├── TitanEngine │ │ ├── TitanEngine_x64.a │ │ ├── TitanEngine_x64.lib │ │ ├── TitanEngine_x86.a │ │ ├── TitanEngine_x86.lib │ │ └── TitanEngine.h │ ├── TitanEngine_x64.a │ ├── TitanEngine_x64.lib │ ├── TitanEngine_x86.a │ ├── TitanEngine_x86.lib │ ├── TitanEngine.h │ ├── x32bridge.lib │ ├── x32dbg.lib │ ├── x64bridge.lib │ ├── x64dbg.lib │ └── XEDParse │ ├── XEDParse_x64.a │ ├── XEDParse_x64.lib │ ├── XEDParse_x86.a │ ├── XEDParse_x86.lib │ └── XEDParse.h ├── include │ └── nlohmann │ ├── adl_serializer.hpp │ ├── byte_container_with_subtype.hpp │ ├── detail │ │ ├── abi_macros.hpp │ │ ├── conversions │ │ │ ├── from_json.hpp │ │ │ ├── to_chars.hpp │ │ │ └── to_json.hpp │ │ ├── exceptions.hpp │ │ ├── hash.hpp │ │ ├── input │ │ │ ├── binary_reader.hpp │ │ │ ├── input_adapters.hpp │ │ │ ├── json_sax.hpp │ │ │ ├── lexer.hpp │ │ │ ├── parser.hpp │ │ │ └── position_t.hpp │ │ ├── iterators │ │ │ ├── internal_iterator.hpp │ │ │ ├── iter_impl.hpp │ │ │ ├── iteration_proxy.hpp │ │ │ ├── iterator_traits.hpp │ │ │ ├── json_reverse_iterator.hpp │ │ │ └── primitive_iterator.hpp │ │ ├── json_custom_base_class.hpp │ │ ├── json_pointer.hpp │ │ ├── json_ref.hpp │ │ ├── macro_scope.hpp │ │ ├── macro_unscope.hpp │ │ ├── meta │ │ │ ├── call_std │ │ │ │ ├── begin.hpp │ │ │ │ └── end.hpp │ │ │ ├── cpp_future.hpp │ │ │ ├── detected.hpp │ │ │ ├── identity_tag.hpp │ │ │ ├── is_sax.hpp │ │ │ ├── std_fs.hpp │ │ │ ├── type_traits.hpp │ │ │ └── void_t.hpp │ │ ├── output │ │ │ ├── binary_writer.hpp │ │ │ ├── output_adapters.hpp │ │ │ └── serializer.hpp │ │ ├── string_concat.hpp │ │ ├── string_escape.hpp │ │ └── value_t.hpp │ ├── json_fwd.hpp │ ├── json.hpp │ ├── ordered_map.hpp │ └── thirdparty │ └── hedley │ ├── hedley_undef.hpp │ └── hedley.hpp ├── README.md ├── Showcase.gif ├── side profile of a voxel spider walking.jpg └── src ├── MCPx64dbg.cpp └── x64dbg.py ``` # Files -------------------------------------------------------------------------------- /deps/pluginsdk/nlohmann/ordered_map.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <functional> // equal_to, less #include <initializer_list> // initializer_list #include <iterator> // input_iterator_tag, iterator_traits #include <memory> // allocator #include <stdexcept> // for out_of_range #include <type_traits> // enable_if, is_convertible #include <utility> // pair #include <vector> // vector #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/type_traits.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN /// ordered_map: a minimal map-like container that preserves insertion order /// for use within nlohmann::basic_json<ordered_map> template <class Key, class T, class IgnoredLess = std::less<Key>, class Allocator = std::allocator<std::pair<const Key, T>>> struct ordered_map : std::vector<std::pair<const Key, T>, Allocator> { using key_type = Key; using mapped_type = T; using Container = std::vector<std::pair<const Key, T>, Allocator>; using iterator = typename Container::iterator; using const_iterator = typename Container::const_iterator; using size_type = typename Container::size_type; using value_type = typename Container::value_type; #ifdef JSON_HAS_CPP_14 using key_compare = std::equal_to<>; #else using key_compare = std::equal_to<Key>; #endif // Explicit constructors instead of `using Container::Container` // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) ordered_map() noexcept(noexcept(Container())) : Container{} {} explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {} template <class It> ordered_map(It first, It last, const Allocator& alloc = Allocator()) : Container{first, last, alloc} {} ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() ) : Container{init, alloc} {} std::pair<iterator, bool> emplace(const key_type& key, T&& t) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return {it, false}; } } Container::emplace_back(key, std::forward<T>(t)); return {std::prev(this->end()), true}; } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> std::pair<iterator, bool> emplace(KeyType && key, T && t) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return {it, false}; } } Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t)); return {std::prev(this->end()), true}; } T& operator[](const key_type& key) { return emplace(key, T{}).first->second; } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> T & operator[](KeyType && key) { return emplace(std::forward<KeyType>(key), T{}).first->second; } const T& operator[](const key_type& key) const { return at(key); } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> const T & operator[](KeyType && key) const { return at(std::forward<KeyType>(key)); } T& at(const key_type& key) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it->second; } } JSON_THROW(std::out_of_range("key not found")); } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it->second; } } JSON_THROW(std::out_of_range("key not found")); } const T& at(const key_type& key) const { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it->second; } } JSON_THROW(std::out_of_range("key not found")); } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it->second; } } JSON_THROW(std::out_of_range("key not found")); } size_type erase(const key_type& key) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { // Since we cannot move const Keys, re-construct them in place for (auto next = it; ++next != this->end(); ++it) { it->~value_type(); // Destroy but keep allocation new (&*it) value_type{std::move(*next)}; } Container::pop_back(); return 1; } } return 0; } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { // Since we cannot move const Keys, re-construct them in place for (auto next = it; ++next != this->end(); ++it) { it->~value_type(); // Destroy but keep allocation new (&*it) value_type{std::move(*next)}; } Container::pop_back(); return 1; } } return 0; } iterator erase(iterator pos) { return erase(pos, std::next(pos)); } iterator erase(iterator first, iterator last) { if (first == last) { return first; } const auto elements_affected = std::distance(first, last); const auto offset = std::distance(Container::begin(), first); // This is the start situation. We need to delete elements_affected // elements (3 in this example: e, f, g), and need to return an // iterator past the last deleted element (h in this example). // Note that offset is the distance from the start of the vector // to first. We will need this later. // [ a, b, c, d, e, f, g, h, i, j ] // ^ ^ // first last // Since we cannot move const Keys, we re-construct them in place. // We start at first and re-construct (viz. copy) the elements from // the back of the vector. Example for first iteration: // ,--------. // v | destroy e and re-construct with h // [ a, b, c, d, e, f, g, h, i, j ] // ^ ^ // it it + elements_affected for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) { it->~value_type(); // destroy but keep allocation new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it } // [ a, b, c, d, h, i, j, h, i, j ] // ^ ^ // first last // remove the unneeded elements at the end of the vector Container::resize(this->size() - static_cast<size_type>(elements_affected)); // [ a, b, c, d, h, i, j ] // ^ ^ // first last // first is now pointing past the last deleted element, but we cannot // use this iterator, because it may have been invalidated by the // resize call. Instead, we can return begin() + offset. return Container::begin() + offset; } size_type count(const key_type& key) const { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return 1; } } return 0; } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return 1; } } return 0; } iterator find(const key_type& key) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it; } } return Container::end(); } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it; } } return Container::end(); } const_iterator find(const key_type& key) const { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it; } } return Container::end(); } std::pair<iterator, bool> insert( value_type&& value ) { return emplace(value.first, std::move(value.second)); } std::pair<iterator, bool> insert( const value_type& value ) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, value.first)) { return {it, false}; } } Container::push_back(value); return {--this->end(), true}; } template<typename InputIt> using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category, std::input_iterator_tag>::value>::type; template<typename InputIt, typename = require_input_iter<InputIt>> void insert(InputIt first, InputIt last) { for (auto it = first; it != last; ++it) { insert(*it); } } private: JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare(); }; NLOHMANN_JSON_NAMESPACE_END ``` -------------------------------------------------------------------------------- /include/nlohmann/ordered_map.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <functional> // equal_to, less #include <initializer_list> // initializer_list #include <iterator> // input_iterator_tag, iterator_traits #include <memory> // allocator #include <stdexcept> // for out_of_range #include <type_traits> // enable_if, is_convertible #include <utility> // pair #include <vector> // vector #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/type_traits.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN /// ordered_map: a minimal map-like container that preserves insertion order /// for use within nlohmann::basic_json<ordered_map> template <class Key, class T, class IgnoredLess = std::less<Key>, class Allocator = std::allocator<std::pair<const Key, T>>> struct ordered_map : std::vector<std::pair<const Key, T>, Allocator> { using key_type = Key; using mapped_type = T; using Container = std::vector<std::pair<const Key, T>, Allocator>; using iterator = typename Container::iterator; using const_iterator = typename Container::const_iterator; using size_type = typename Container::size_type; using value_type = typename Container::value_type; #ifdef JSON_HAS_CPP_14 using key_compare = std::equal_to<>; #else using key_compare = std::equal_to<Key>; #endif // Explicit constructors instead of `using Container::Container` // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) ordered_map() noexcept(noexcept(Container())) : Container{} {} explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {} template <class It> ordered_map(It first, It last, const Allocator& alloc = Allocator()) : Container{first, last, alloc} {} ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() ) : Container{init, alloc} {} std::pair<iterator, bool> emplace(const key_type& key, T&& t) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return {it, false}; } } Container::emplace_back(key, std::forward<T>(t)); return {std::prev(this->end()), true}; } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> std::pair<iterator, bool> emplace(KeyType && key, T && t) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return {it, false}; } } Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t)); return {std::prev(this->end()), true}; } T& operator[](const key_type& key) { return emplace(key, T{}).first->second; } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> T & operator[](KeyType && key) { return emplace(std::forward<KeyType>(key), T{}).first->second; } const T& operator[](const key_type& key) const { return at(key); } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> const T & operator[](KeyType && key) const { return at(std::forward<KeyType>(key)); } T& at(const key_type& key) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it->second; } } JSON_THROW(std::out_of_range("key not found")); } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it->second; } } JSON_THROW(std::out_of_range("key not found")); } const T& at(const key_type& key) const { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it->second; } } JSON_THROW(std::out_of_range("key not found")); } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it->second; } } JSON_THROW(std::out_of_range("key not found")); } size_type erase(const key_type& key) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { // Since we cannot move const Keys, re-construct them in place for (auto next = it; ++next != this->end(); ++it) { it->~value_type(); // Destroy but keep allocation new (&*it) value_type{std::move(*next)}; } Container::pop_back(); return 1; } } return 0; } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { // Since we cannot move const Keys, re-construct them in place for (auto next = it; ++next != this->end(); ++it) { it->~value_type(); // Destroy but keep allocation new (&*it) value_type{std::move(*next)}; } Container::pop_back(); return 1; } } return 0; } iterator erase(iterator pos) { return erase(pos, std::next(pos)); } iterator erase(iterator first, iterator last) { if (first == last) { return first; } const auto elements_affected = std::distance(first, last); const auto offset = std::distance(Container::begin(), first); // This is the start situation. We need to delete elements_affected // elements (3 in this example: e, f, g), and need to return an // iterator past the last deleted element (h in this example). // Note that offset is the distance from the start of the vector // to first. We will need this later. // [ a, b, c, d, e, f, g, h, i, j ] // ^ ^ // first last // Since we cannot move const Keys, we re-construct them in place. // We start at first and re-construct (viz. copy) the elements from // the back of the vector. Example for first iteration: // ,--------. // v | destroy e and re-construct with h // [ a, b, c, d, e, f, g, h, i, j ] // ^ ^ // it it + elements_affected for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it) { it->~value_type(); // destroy but keep allocation new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it } // [ a, b, c, d, h, i, j, h, i, j ] // ^ ^ // first last // remove the unneeded elements at the end of the vector Container::resize(this->size() - static_cast<size_type>(elements_affected)); // [ a, b, c, d, h, i, j ] // ^ ^ // first last // first is now pointing past the last deleted element, but we cannot // use this iterator, because it may have been invalidated by the // resize call. Instead, we can return begin() + offset. return Container::begin() + offset; } size_type count(const key_type& key) const { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return 1; } } return 0; } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return 1; } } return 0; } iterator find(const key_type& key) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it; } } return Container::end(); } template<class KeyType, detail::enable_if_t< detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0> iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it; } } return Container::end(); } const_iterator find(const key_type& key) const { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, key)) { return it; } } return Container::end(); } std::pair<iterator, bool> insert( value_type&& value ) { return emplace(value.first, std::move(value.second)); } std::pair<iterator, bool> insert( const value_type& value ) { for (auto it = this->begin(); it != this->end(); ++it) { if (m_compare(it->first, value.first)) { return {it, false}; } } Container::push_back(value); return {--this->end(), true}; } template<typename InputIt> using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category, std::input_iterator_tag>::value>::type; template<typename InputIt, typename = require_input_iter<InputIt>> void insert(InputIt first, InputIt last) { for (auto it = first; it != last; ++it) { insert(*it); } } private: JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare(); }; NLOHMANN_JSON_NAMESPACE_END ``` -------------------------------------------------------------------------------- /deps/pluginsdk/lz4/lz4.h: -------------------------------------------------------------------------------- ``` /* LZ4 - Fast LZ compression algorithm Header File Copyright (C) 2011-2014, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html - LZ4 source repository : http://code.google.com/p/lz4/ */ #ifndef _LZ4_H #define _LZ4_H #if defined (__cplusplus) extern "C" { #endif /************************************** Version **************************************/ #define LZ4_VERSION_MAJOR 1 /* for major interface/format changes */ #define LZ4_VERSION_MINOR 1 /* for minor interface/format changes */ #define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ /************************************** Compiler Options **************************************/ #if (defined(__GNUC__) && defined(__STRICT_ANSI__)) || (defined(_MSC_VER) && !defined(__cplusplus)) /* Visual Studio */ # define inline __inline /* Visual C is not C99, but supports some kind of inline */ #endif /************************************** Simple Functions **************************************/ __declspec(dllimport) int LZ4_compress(const char* source, char* dest, int inputSize); __declspec(dllimport) int LZ4_decompress_safe(const char* source, char* dest, int inputSize, int maxOutputSize); /* LZ4_compress() : Compresses 'inputSize' bytes from 'source' into 'dest'. Destination buffer must be already allocated, and must be sized to handle worst cases situations (input data not compressible) Worst case size evaluation is provided by function LZ4_compressBound() inputSize : Max supported value is LZ4_MAX_INPUT_VALUE return : the number of bytes written in buffer dest or 0 if the compression fails LZ4_decompress_safe() : maxOutputSize : is the size of the destination buffer (which must be already allocated) return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize) If the source stream is detected malformed, the function will stop decoding and return a negative result. This function is protected against buffer overflow exploits (never writes outside of output buffer, and never reads outside of input buffer). Therefore, it is protected against malicious data packets */ /************************************** Advanced Functions **************************************/ #define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ #define LZ4_COMPRESSBOUND(isize) ((unsigned int)(isize) > (unsigned int)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) /* LZ4_compressBound() : Provides the maximum size that LZ4 may output in a "worst case" scenario (input data not compressible) primarily useful for memory allocation of output buffer. inline function is recommended for the general case, macro is also provided when result needs to be evaluated at compilation (such as stack memory allocation). isize : is the input size. Max supported value is LZ4_MAX_INPUT_SIZE return : maximum output size in a "worst case" scenario or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) */ __declspec(dllimport) int LZ4_compressBound(int isize); /* LZ4_compress_limitedOutput() : Compress 'inputSize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'. If it cannot achieve it, compression will stop, and result of the function will be zero. This function never writes outside of provided output buffer. inputSize : Max supported value is LZ4_MAX_INPUT_VALUE maxOutputSize : is the size of the destination buffer (which must be already allocated) return : the number of bytes written in buffer 'dest' or 0 if the compression fails */ __declspec(dllimport) int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize); /* LZ4_decompress_fast() : originalSize : is the original and therefore uncompressed size return : the number of bytes read from the source buffer (in other words, the compressed size) If the source stream is malformed, the function will stop decoding and return a negative result. note : This function is a bit faster than LZ4_decompress_safe() This function never writes outside of output buffers, but may read beyond input buffer in case of malicious data packet. Use this function preferably into a trusted environment (data to decode comes from a trusted source). Destination buffer must be already allocated. Its size must be a minimum of 'outputSize' bytes. */ __declspec(dllimport) int LZ4_decompress_fast(const char* source, char* dest, int originalSize); /* LZ4_decompress_safe_partial() : This function decompress a compressed block of size 'inputSize' at position 'source' into output buffer 'dest' of size 'maxOutputSize'. The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached, reducing decompression time. return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize) Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller. Always control how many bytes were decoded. If the source stream is detected malformed, the function will stop decoding and return a negative result. This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets */ __declspec(dllimport) int LZ4_decompress_safe_partial(const char* source, char* dest, int inputSize, int targetOutputSize, int maxOutputSize); /* These functions are provided should you prefer to allocate memory for compression tables with your own allocation methods. To know how much memory must be allocated for the compression tables, use : int LZ4_sizeofState(); Note that tables must be aligned on 4-bytes boundaries, otherwise compression will fail (return code 0). The allocated memory can be provided to the compressions functions using 'void* state' parameter. LZ4_compress_withState() and LZ4_compress_limitedOutput_withState() are equivalent to previously described functions. They just use the externally allocated memory area instead of allocating their own (on stack, or on heap). */ __declspec(dllimport) int LZ4_sizeofState(void); __declspec(dllimport) int LZ4_compress_withState(void* state, const char* source, char* dest, int inputSize); __declspec(dllimport) int LZ4_compress_limitedOutput_withState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize); /************************************** Streaming Functions **************************************/ __declspec(dllimport) void* LZ4_create(const char* inputBuffer); __declspec(dllimport) int LZ4_compress_continue(void* LZ4_Data, const char* source, char* dest, int inputSize); __declspec(dllimport) int LZ4_compress_limitedOutput_continue(void* LZ4_Data, const char* source, char* dest, int inputSize, int maxOutputSize); __declspec(dllimport) char* LZ4_slideInputBuffer(void* LZ4_Data); __declspec(dllimport) int LZ4_free(void* LZ4_Data); /* These functions allow the compression of dependent blocks, where each block benefits from prior 64 KB within preceding blocks. In order to achieve this, it is necessary to start creating the LZ4 Data Structure, thanks to the function : void* LZ4_create (const char* inputBuffer); The result of the function is the (void*) pointer on the LZ4 Data Structure. This pointer will be needed in all other functions. If the pointer returned is NULL, then the allocation has failed, and compression must be aborted. The only parameter 'const char* inputBuffer' must, obviously, point at the beginning of input buffer. The input buffer must be already allocated, and size at least 192KB. 'inputBuffer' will also be the 'const char* source' of the first block. All blocks are expected to lay next to each other within the input buffer, starting from 'inputBuffer'. To compress each block, use either LZ4_compress_continue() or LZ4_compress_limitedOutput_continue(). Their behavior are identical to LZ4_compress() or LZ4_compress_limitedOutput(), but require the LZ4 Data Structure as their first argument, and check that each block starts right after the previous one. If next block does not begin immediately after the previous one, the compression will fail (return 0). When it's no longer possible to lay the next block after the previous one (not enough space left into input buffer), a call to : char* LZ4_slideInputBuffer(void* LZ4_Data); must be performed. It will typically copy the latest 64KB of input at the beginning of input buffer. Note that, for this function to work properly, minimum size of an input buffer must be 192KB. ==> The memory position where the next input data block must start is provided as the result of the function. Compression can then resume, using LZ4_compress_continue() or LZ4_compress_limitedOutput_continue(), as usual. When compression is completed, a call to LZ4_free() will release the memory used by the LZ4 Data Structure. */ __declspec(dllimport) int LZ4_sizeofStreamState(void); __declspec(dllimport) int LZ4_resetStreamState(void* state, const char* inputBuffer); /* These functions achieve the same result as : void* LZ4_create (const char* inputBuffer); They are provided here to allow the user program to allocate memory using its own routines. To know how much space must be allocated, use LZ4_sizeofStreamState(); Note also that space must be 4-bytes aligned. Once space is allocated, you must initialize it using : LZ4_resetStreamState(void* state, const char* inputBuffer); void* state is a pointer to the space allocated. It must be aligned on 4-bytes boundaries, and be large enough. The parameter 'const char* inputBuffer' must, obviously, point at the beginning of input buffer. The input buffer must be already allocated, and size at least 192KB. 'inputBuffer' will also be the 'const char* source' of the first block. The same space can be re-used multiple times, just by initializing it each time with LZ4_resetStreamState(). return value of LZ4_resetStreamState() must be 0 is OK. Any other value means there was an error (typically, pointer is not aligned on 4-bytes boundaries). */ __declspec(dllimport) int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int inputSize, int maxOutputSize); __declspec(dllimport) int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int outputSize); /* *_withPrefix64k() : These decoding functions work the same as their "normal name" versions, but can use up to 64KB of data in front of 'char* dest'. These functions are necessary to decode inter-dependant blocks. */ /************************************** Obsolete Functions **************************************/ /* These functions are deprecated and should no longer be used. They are provided here for compatibility with existing user programs. */ __declspec(dllimport) int LZ4_uncompress(const char* source, char* dest, int outputSize); __declspec(dllimport) int LZ4_uncompress_unknownOutputSize(const char* source, char* dest, int isize, int maxOutputSize); #if defined (__cplusplus) } #endif #endif //_LZ4_H ``` -------------------------------------------------------------------------------- /deps/x64dbg_sdk/pluginsdk/lz4/lz4.h: -------------------------------------------------------------------------------- ``` /* LZ4 - Fast LZ compression algorithm Header File Copyright (C) 2011-2014, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html - LZ4 source repository : http://code.google.com/p/lz4/ */ #ifndef _LZ4_H #define _LZ4_H #if defined (__cplusplus) extern "C" { #endif /************************************** Version **************************************/ #define LZ4_VERSION_MAJOR 1 /* for major interface/format changes */ #define LZ4_VERSION_MINOR 1 /* for minor interface/format changes */ #define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */ /************************************** Compiler Options **************************************/ #if (defined(__GNUC__) && defined(__STRICT_ANSI__)) || (defined(_MSC_VER) && !defined(__cplusplus)) /* Visual Studio */ # define inline __inline /* Visual C is not C99, but supports some kind of inline */ #endif /************************************** Simple Functions **************************************/ __declspec(dllimport) int LZ4_compress(const char* source, char* dest, int inputSize); __declspec(dllimport) int LZ4_decompress_safe(const char* source, char* dest, int inputSize, int maxOutputSize); /* LZ4_compress() : Compresses 'inputSize' bytes from 'source' into 'dest'. Destination buffer must be already allocated, and must be sized to handle worst cases situations (input data not compressible) Worst case size evaluation is provided by function LZ4_compressBound() inputSize : Max supported value is LZ4_MAX_INPUT_VALUE return : the number of bytes written in buffer dest or 0 if the compression fails LZ4_decompress_safe() : maxOutputSize : is the size of the destination buffer (which must be already allocated) return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize) If the source stream is detected malformed, the function will stop decoding and return a negative result. This function is protected against buffer overflow exploits (never writes outside of output buffer, and never reads outside of input buffer). Therefore, it is protected against malicious data packets */ /************************************** Advanced Functions **************************************/ #define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ #define LZ4_COMPRESSBOUND(isize) ((unsigned int)(isize) > (unsigned int)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) /* LZ4_compressBound() : Provides the maximum size that LZ4 may output in a "worst case" scenario (input data not compressible) primarily useful for memory allocation of output buffer. inline function is recommended for the general case, macro is also provided when result needs to be evaluated at compilation (such as stack memory allocation). isize : is the input size. Max supported value is LZ4_MAX_INPUT_SIZE return : maximum output size in a "worst case" scenario or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) */ __declspec(dllimport) int LZ4_compressBound(int isize); /* LZ4_compress_limitedOutput() : Compress 'inputSize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'. If it cannot achieve it, compression will stop, and result of the function will be zero. This function never writes outside of provided output buffer. inputSize : Max supported value is LZ4_MAX_INPUT_VALUE maxOutputSize : is the size of the destination buffer (which must be already allocated) return : the number of bytes written in buffer 'dest' or 0 if the compression fails */ __declspec(dllimport) int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize); /* LZ4_decompress_fast() : originalSize : is the original and therefore uncompressed size return : the number of bytes read from the source buffer (in other words, the compressed size) If the source stream is malformed, the function will stop decoding and return a negative result. note : This function is a bit faster than LZ4_decompress_safe() This function never writes outside of output buffers, but may read beyond input buffer in case of malicious data packet. Use this function preferably into a trusted environment (data to decode comes from a trusted source). Destination buffer must be already allocated. Its size must be a minimum of 'outputSize' bytes. */ __declspec(dllimport) int LZ4_decompress_fast(const char* source, char* dest, int originalSize); /* LZ4_decompress_safe_partial() : This function decompress a compressed block of size 'inputSize' at position 'source' into output buffer 'dest' of size 'maxOutputSize'. The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached, reducing decompression time. return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize) Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller. Always control how many bytes were decoded. If the source stream is detected malformed, the function will stop decoding and return a negative result. This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets */ __declspec(dllimport) int LZ4_decompress_safe_partial(const char* source, char* dest, int inputSize, int targetOutputSize, int maxOutputSize); /* These functions are provided should you prefer to allocate memory for compression tables with your own allocation methods. To know how much memory must be allocated for the compression tables, use : int LZ4_sizeofState(); Note that tables must be aligned on 4-bytes boundaries, otherwise compression will fail (return code 0). The allocated memory can be provided to the compressions functions using 'void* state' parameter. LZ4_compress_withState() and LZ4_compress_limitedOutput_withState() are equivalent to previously described functions. They just use the externally allocated memory area instead of allocating their own (on stack, or on heap). */ __declspec(dllimport) int LZ4_sizeofState(void); __declspec(dllimport) int LZ4_compress_withState(void* state, const char* source, char* dest, int inputSize); __declspec(dllimport) int LZ4_compress_limitedOutput_withState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize); /************************************** Streaming Functions **************************************/ __declspec(dllimport) void* LZ4_create(const char* inputBuffer); __declspec(dllimport) int LZ4_compress_continue(void* LZ4_Data, const char* source, char* dest, int inputSize); __declspec(dllimport) int LZ4_compress_limitedOutput_continue(void* LZ4_Data, const char* source, char* dest, int inputSize, int maxOutputSize); __declspec(dllimport) char* LZ4_slideInputBuffer(void* LZ4_Data); __declspec(dllimport) int LZ4_free(void* LZ4_Data); /* These functions allow the compression of dependent blocks, where each block benefits from prior 64 KB within preceding blocks. In order to achieve this, it is necessary to start creating the LZ4 Data Structure, thanks to the function : void* LZ4_create (const char* inputBuffer); The result of the function is the (void*) pointer on the LZ4 Data Structure. This pointer will be needed in all other functions. If the pointer returned is NULL, then the allocation has failed, and compression must be aborted. The only parameter 'const char* inputBuffer' must, obviously, point at the beginning of input buffer. The input buffer must be already allocated, and size at least 192KB. 'inputBuffer' will also be the 'const char* source' of the first block. All blocks are expected to lay next to each other within the input buffer, starting from 'inputBuffer'. To compress each block, use either LZ4_compress_continue() or LZ4_compress_limitedOutput_continue(). Their behavior are identical to LZ4_compress() or LZ4_compress_limitedOutput(), but require the LZ4 Data Structure as their first argument, and check that each block starts right after the previous one. If next block does not begin immediately after the previous one, the compression will fail (return 0). When it's no longer possible to lay the next block after the previous one (not enough space left into input buffer), a call to : char* LZ4_slideInputBuffer(void* LZ4_Data); must be performed. It will typically copy the latest 64KB of input at the beginning of input buffer. Note that, for this function to work properly, minimum size of an input buffer must be 192KB. ==> The memory position where the next input data block must start is provided as the result of the function. Compression can then resume, using LZ4_compress_continue() or LZ4_compress_limitedOutput_continue(), as usual. When compression is completed, a call to LZ4_free() will release the memory used by the LZ4 Data Structure. */ __declspec(dllimport) int LZ4_sizeofStreamState(void); __declspec(dllimport) int LZ4_resetStreamState(void* state, const char* inputBuffer); /* These functions achieve the same result as : void* LZ4_create (const char* inputBuffer); They are provided here to allow the user program to allocate memory using its own routines. To know how much space must be allocated, use LZ4_sizeofStreamState(); Note also that space must be 4-bytes aligned. Once space is allocated, you must initialize it using : LZ4_resetStreamState(void* state, const char* inputBuffer); void* state is a pointer to the space allocated. It must be aligned on 4-bytes boundaries, and be large enough. The parameter 'const char* inputBuffer' must, obviously, point at the beginning of input buffer. The input buffer must be already allocated, and size at least 192KB. 'inputBuffer' will also be the 'const char* source' of the first block. The same space can be re-used multiple times, just by initializing it each time with LZ4_resetStreamState(). return value of LZ4_resetStreamState() must be 0 is OK. Any other value means there was an error (typically, pointer is not aligned on 4-bytes boundaries). */ __declspec(dllimport) int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int inputSize, int maxOutputSize); __declspec(dllimport) int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int outputSize); /* *_withPrefix64k() : These decoding functions work the same as their "normal name" versions, but can use up to 64KB of data in front of 'char* dest'. These functions are necessary to decode inter-dependant blocks. */ /************************************** Obsolete Functions **************************************/ /* These functions are deprecated and should no longer be used. They are provided here for compatibility with existing user programs. */ __declspec(dllimport) int LZ4_uncompress(const char* source, char* dest, int outputSize); __declspec(dllimport) int LZ4_uncompress_unknownOutputSize(const char* source, char* dest, int isize, int maxOutputSize); #if defined (__cplusplus) } #endif #endif //_LZ4_H ``` -------------------------------------------------------------------------------- /deps/pluginsdk/nlohmann/detail/conversions/to_json.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <algorithm> // copy #include <iterator> // begin, end #include <string> // string #include <tuple> // tuple, get #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type #include <utility> // move, forward, declval, pair #include <valarray> // valarray #include <vector> // vector #include <nlohmann/detail/iterators/iteration_proxy.hpp> #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/cpp_future.hpp> #include <nlohmann/detail/meta/std_fs.hpp> #include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/value_t.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { ////////////////// // constructors // ////////////////// /* * Note all external_constructor<>::construct functions need to call * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an * allocated value (e.g., a string). See bug issue * https://github.com/nlohmann/json/issues/2865 for more information. */ template<value_t> struct external_constructor; template<> struct external_constructor<value_t::boolean> { template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::boolean; j.m_data.m_value = b; j.assert_invariant(); } }; template<> struct external_constructor<value_t::string> { template<typename BasicJsonType> static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::string; j.m_data.m_value = s; j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::string; j.m_data.m_value = std::move(s); j.assert_invariant(); } template < typename BasicJsonType, typename CompatibleStringType, enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value, int > = 0 > static void construct(BasicJsonType& j, const CompatibleStringType& str) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::string; j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str); j.assert_invariant(); } }; template<> struct external_constructor<value_t::binary> { template<typename BasicJsonType> static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::binary; j.m_data.m_value = typename BasicJsonType::binary_t(b); j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::binary; j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); j.assert_invariant(); } }; template<> struct external_constructor<value_t::number_float> { template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::number_float; j.m_data.m_value = val; j.assert_invariant(); } }; template<> struct external_constructor<value_t::number_unsigned> { template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::number_unsigned; j.m_data.m_value = val; j.assert_invariant(); } }; template<> struct external_constructor<value_t::number_integer> { template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::number_integer; j.m_data.m_value = val; j.assert_invariant(); } }; template<> struct external_constructor<value_t::array> { template<typename BasicJsonType> static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value = arr; j.set_parents(); j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value = std::move(arr); j.set_parents(); j.assert_invariant(); } template < typename BasicJsonType, typename CompatibleArrayType, enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, int > = 0 > static void construct(BasicJsonType& j, const CompatibleArrayType& arr) { using std::begin; using std::end; j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr)); j.set_parents(); j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, const std::vector<bool>& arr) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value = value_t::array; j.m_data.m_value.array->reserve(arr.size()); for (const bool x : arr) { j.m_data.m_value.array->push_back(x); j.set_parent(j.m_data.m_value.array->back()); } j.assert_invariant(); } template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> static void construct(BasicJsonType& j, const std::valarray<T>& arr) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value = value_t::array; j.m_data.m_value.array->resize(arr.size()); if (arr.size() > 0) { std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); } j.set_parents(); j.assert_invariant(); } }; template<> struct external_constructor<value_t::object> { template<typename BasicJsonType> static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::object; j.m_data.m_value = obj; j.set_parents(); j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::object; j.m_data.m_value = std::move(obj); j.set_parents(); j.assert_invariant(); } template < typename BasicJsonType, typename CompatibleObjectType, enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 > static void construct(BasicJsonType& j, const CompatibleObjectType& obj) { using std::begin; using std::end; j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::object; j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj)); j.set_parents(); j.assert_invariant(); } }; ///////////// // to_json // ///////////// template<typename BasicJsonType, typename T, enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0> inline void to_json(BasicJsonType& j, T b) noexcept { external_constructor<value_t::boolean>::construct(j, b); } template < typename BasicJsonType, typename BoolRef, enable_if_t < ((std::is_same<std::vector<bool>::reference, BoolRef>::value && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>, typename BasicJsonType::boolean_t >::value)) && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 > inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept { external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b)); } template<typename BasicJsonType, typename CompatibleString, enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0> inline void to_json(BasicJsonType& j, const CompatibleString& s) { external_constructor<value_t::string>::construct(j, s); } template<typename BasicJsonType> inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) { external_constructor<value_t::string>::construct(j, std::move(s)); } template<typename BasicJsonType, typename FloatType, enable_if_t<std::is_floating_point<FloatType>::value, int> = 0> inline void to_json(BasicJsonType& j, FloatType val) noexcept { external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val)); } template<typename BasicJsonType, typename CompatibleNumberUnsignedType, enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0> inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept { external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val)); } template<typename BasicJsonType, typename CompatibleNumberIntegerType, enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0> inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept { external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val)); } #if !JSON_DISABLE_ENUM_SERIALIZATION template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0> inline void to_json(BasicJsonType& j, EnumType e) noexcept { using underlying_type = typename std::underlying_type<EnumType>::type; external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e)); } #endif // JSON_DISABLE_ENUM_SERIALIZATION template<typename BasicJsonType> inline void to_json(BasicJsonType& j, const std::vector<bool>& e) { external_constructor<value_t::array>::construct(j, e); } template < typename BasicJsonType, typename CompatibleArrayType, enable_if_t < is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value&& !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&& !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&& !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&& !is_basic_json<CompatibleArrayType>::value, int > = 0 > inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { external_constructor<value_t::array>::construct(j, arr); } template<typename BasicJsonType> inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) { external_constructor<value_t::binary>::construct(j, bin); } template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> inline void to_json(BasicJsonType& j, const std::valarray<T>& arr) { external_constructor<value_t::array>::construct(j, std::move(arr)); } template<typename BasicJsonType> inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { external_constructor<value_t::array>::construct(j, std::move(arr)); } template < typename BasicJsonType, typename CompatibleObjectType, enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 > inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor<value_t::object>::construct(j, obj); } template<typename BasicJsonType> inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { external_constructor<value_t::object>::construct(j, std::move(obj)); } template < typename BasicJsonType, typename T, std::size_t N, enable_if_t < !std::is_constructible<typename BasicJsonType::string_t, const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) int > = 0 > inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { external_constructor<value_t::array>::construct(j, arr); } template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 > inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p) { j = { p.first, p.second }; } // for https://github.com/nlohmann/json/pull/1134 template<typename BasicJsonType, typename T, enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0> inline void to_json(BasicJsonType& j, const T& b) { j = { {b.key(), b.value()} }; } template<typename BasicJsonType, typename Tuple, std::size_t... Idx> inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/) { j = { std::get<Idx>(t)... }; } template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0> inline void to_json(BasicJsonType& j, const T& t) { to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {}); } #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM template<typename BasicJsonType> inline void to_json(BasicJsonType& j, const std_fs::path& p) { j = p.string(); } #endif struct to_json_fn { template<typename BasicJsonType, typename T> auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) -> decltype(to_json(j, std::forward<T>(val)), void()) { return to_json(j, std::forward<T>(val)); } }; } // namespace detail #ifndef JSON_HAS_CPP_17 /// namespace to hold default `to_json` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) { #endif JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) detail::static_const<detail::to_json_fn>::value; #ifndef JSON_HAS_CPP_17 } // namespace #endif NLOHMANN_JSON_NAMESPACE_END ``` -------------------------------------------------------------------------------- /include/nlohmann/detail/conversions/to_json.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <algorithm> // copy #include <iterator> // begin, end #include <string> // string #include <tuple> // tuple, get #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type #include <utility> // move, forward, declval, pair #include <valarray> // valarray #include <vector> // vector #include <nlohmann/detail/iterators/iteration_proxy.hpp> #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/cpp_future.hpp> #include <nlohmann/detail/meta/std_fs.hpp> #include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/value_t.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { ////////////////// // constructors // ////////////////// /* * Note all external_constructor<>::construct functions need to call * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an * allocated value (e.g., a string). See bug issue * https://github.com/nlohmann/json/issues/2865 for more information. */ template<value_t> struct external_constructor; template<> struct external_constructor<value_t::boolean> { template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::boolean; j.m_data.m_value = b; j.assert_invariant(); } }; template<> struct external_constructor<value_t::string> { template<typename BasicJsonType> static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::string; j.m_data.m_value = s; j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::string; j.m_data.m_value = std::move(s); j.assert_invariant(); } template < typename BasicJsonType, typename CompatibleStringType, enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value, int > = 0 > static void construct(BasicJsonType& j, const CompatibleStringType& str) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::string; j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str); j.assert_invariant(); } }; template<> struct external_constructor<value_t::binary> { template<typename BasicJsonType> static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::binary; j.m_data.m_value = typename BasicJsonType::binary_t(b); j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::binary; j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); j.assert_invariant(); } }; template<> struct external_constructor<value_t::number_float> { template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::number_float; j.m_data.m_value = val; j.assert_invariant(); } }; template<> struct external_constructor<value_t::number_unsigned> { template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::number_unsigned; j.m_data.m_value = val; j.assert_invariant(); } }; template<> struct external_constructor<value_t::number_integer> { template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::number_integer; j.m_data.m_value = val; j.assert_invariant(); } }; template<> struct external_constructor<value_t::array> { template<typename BasicJsonType> static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value = arr; j.set_parents(); j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value = std::move(arr); j.set_parents(); j.assert_invariant(); } template < typename BasicJsonType, typename CompatibleArrayType, enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, int > = 0 > static void construct(BasicJsonType& j, const CompatibleArrayType& arr) { using std::begin; using std::end; j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr)); j.set_parents(); j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, const std::vector<bool>& arr) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value = value_t::array; j.m_data.m_value.array->reserve(arr.size()); for (const bool x : arr) { j.m_data.m_value.array->push_back(x); j.set_parent(j.m_data.m_value.array->back()); } j.assert_invariant(); } template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> static void construct(BasicJsonType& j, const std::valarray<T>& arr) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::array; j.m_data.m_value = value_t::array; j.m_data.m_value.array->resize(arr.size()); if (arr.size() > 0) { std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); } j.set_parents(); j.assert_invariant(); } }; template<> struct external_constructor<value_t::object> { template<typename BasicJsonType> static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::object; j.m_data.m_value = obj; j.set_parents(); j.assert_invariant(); } template<typename BasicJsonType> static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::object; j.m_data.m_value = std::move(obj); j.set_parents(); j.assert_invariant(); } template < typename BasicJsonType, typename CompatibleObjectType, enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 > static void construct(BasicJsonType& j, const CompatibleObjectType& obj) { using std::begin; using std::end; j.m_data.m_value.destroy(j.m_data.m_type); j.m_data.m_type = value_t::object; j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj)); j.set_parents(); j.assert_invariant(); } }; ///////////// // to_json // ///////////// template<typename BasicJsonType, typename T, enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0> inline void to_json(BasicJsonType& j, T b) noexcept { external_constructor<value_t::boolean>::construct(j, b); } template < typename BasicJsonType, typename BoolRef, enable_if_t < ((std::is_same<std::vector<bool>::reference, BoolRef>::value && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>, typename BasicJsonType::boolean_t >::value)) && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 > inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept { external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b)); } template<typename BasicJsonType, typename CompatibleString, enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0> inline void to_json(BasicJsonType& j, const CompatibleString& s) { external_constructor<value_t::string>::construct(j, s); } template<typename BasicJsonType> inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) { external_constructor<value_t::string>::construct(j, std::move(s)); } template<typename BasicJsonType, typename FloatType, enable_if_t<std::is_floating_point<FloatType>::value, int> = 0> inline void to_json(BasicJsonType& j, FloatType val) noexcept { external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val)); } template<typename BasicJsonType, typename CompatibleNumberUnsignedType, enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0> inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept { external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val)); } template<typename BasicJsonType, typename CompatibleNumberIntegerType, enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0> inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept { external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val)); } #if !JSON_DISABLE_ENUM_SERIALIZATION template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0> inline void to_json(BasicJsonType& j, EnumType e) noexcept { using underlying_type = typename std::underlying_type<EnumType>::type; external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e)); } #endif // JSON_DISABLE_ENUM_SERIALIZATION template<typename BasicJsonType> inline void to_json(BasicJsonType& j, const std::vector<bool>& e) { external_constructor<value_t::array>::construct(j, e); } template < typename BasicJsonType, typename CompatibleArrayType, enable_if_t < is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value&& !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&& !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&& !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&& !is_basic_json<CompatibleArrayType>::value, int > = 0 > inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { external_constructor<value_t::array>::construct(j, arr); } template<typename BasicJsonType> inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) { external_constructor<value_t::binary>::construct(j, bin); } template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0> inline void to_json(BasicJsonType& j, const std::valarray<T>& arr) { external_constructor<value_t::array>::construct(j, std::move(arr)); } template<typename BasicJsonType> inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { external_constructor<value_t::array>::construct(j, std::move(arr)); } template < typename BasicJsonType, typename CompatibleObjectType, enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 > inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor<value_t::object>::construct(j, obj); } template<typename BasicJsonType> inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { external_constructor<value_t::object>::construct(j, std::move(obj)); } template < typename BasicJsonType, typename T, std::size_t N, enable_if_t < !std::is_constructible<typename BasicJsonType::string_t, const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) int > = 0 > inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { external_constructor<value_t::array>::construct(j, arr); } template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 > inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p) { j = { p.first, p.second }; } // for https://github.com/nlohmann/json/pull/1134 template<typename BasicJsonType, typename T, enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0> inline void to_json(BasicJsonType& j, const T& b) { j = { {b.key(), b.value()} }; } template<typename BasicJsonType, typename Tuple, std::size_t... Idx> inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/) { j = { std::get<Idx>(t)... }; } template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0> inline void to_json(BasicJsonType& j, const T& t) { to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {}); } #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM template<typename BasicJsonType> inline void to_json(BasicJsonType& j, const std_fs::path& p) { j = p.string(); } #endif struct to_json_fn { template<typename BasicJsonType, typename T> auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) -> decltype(to_json(j, std::forward<T>(val)), void()) { return to_json(j, std::forward<T>(val)); } }; } // namespace detail #ifndef JSON_HAS_CPP_17 /// namespace to hold default `to_json` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) { #endif JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) detail::static_const<detail::to_json_fn>::value; #ifndef JSON_HAS_CPP_17 } // namespace #endif NLOHMANN_JSON_NAMESPACE_END ``` -------------------------------------------------------------------------------- /deps/pluginsdk/nlohmann/detail/input/input_adapters.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <array> // array #include <cstddef> // size_t #include <cstring> // strlen #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next #include <memory> // shared_ptr, make_shared, addressof #include <numeric> // accumulate #include <string> // string, char_traits #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer #include <utility> // pair, declval #ifndef JSON_NO_IO #include <cstdio> // FILE * #include <istream> // istream #endif // JSON_NO_IO #include <nlohmann/detail/iterators/iterator_traits.hpp> #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/type_traits.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { /// the supported input formats enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; //////////////////// // input adapters // //////////////////// #ifndef JSON_NO_IO /*! Input adapter for stdio file access. This adapter read only 1 byte and do not use any buffer. This adapter is a very low level adapter. */ class file_input_adapter { public: using char_type = char; JSON_HEDLEY_NON_NULL(2) explicit file_input_adapter(std::FILE* f) noexcept : m_file(f) { JSON_ASSERT(m_file != nullptr); } // make class move-only file_input_adapter(const file_input_adapter&) = delete; file_input_adapter(file_input_adapter&&) noexcept = default; file_input_adapter& operator=(const file_input_adapter&) = delete; file_input_adapter& operator=(file_input_adapter&&) = delete; ~file_input_adapter() = default; std::char_traits<char>::int_type get_character() noexcept { return std::fgetc(m_file); } private: /// the file pointer to read from std::FILE* m_file; }; /*! Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at beginning of input. Does not support changing the underlying std::streambuf in mid-input. Maintains underlying std::istream and std::streambuf to support subsequent use of standard std::istream operations to process any input characters following those used in parsing the JSON input. Clears the std::istream flags; any input errors (e.g., EOF) will be detected by the first subsequent call for input from the std::istream. */ class input_stream_adapter { public: using char_type = char; ~input_stream_adapter() { // clear stream flags; we use underlying streambuf I/O, do not // maintain ifstream flags, except eof if (is != nullptr) { is->clear(is->rdstate() & std::ios::eofbit); } } explicit input_stream_adapter(std::istream& i) : is(&i), sb(i.rdbuf()) {} // delete because of pointer members input_stream_adapter(const input_stream_adapter&) = delete; input_stream_adapter& operator=(input_stream_adapter&) = delete; input_stream_adapter& operator=(input_stream_adapter&&) = delete; input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb) { rhs.is = nullptr; rhs.sb = nullptr; } // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to // ensure that std::char_traits<char>::eof() and the character 0xFF do not // end up as the same value, e.g. 0xFFFFFFFF. std::char_traits<char>::int_type get_character() { auto res = sb->sbumpc(); // set eof manually, as we don't use the istream interface. if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) { is->clear(is->rdstate() | std::ios::eofbit); } return res; } private: /// the associated input stream std::istream* is = nullptr; std::streambuf* sb = nullptr; }; #endif // JSON_NO_IO // General-purpose iterator-based adapter. It might not be as fast as // theoretically possible for some containers, but it is extremely versatile. template<typename IteratorType> class iterator_input_adapter { public: using char_type = typename std::iterator_traits<IteratorType>::value_type; iterator_input_adapter(IteratorType first, IteratorType last) : current(std::move(first)), end(std::move(last)) {} typename char_traits<char_type>::int_type get_character() { if (JSON_HEDLEY_LIKELY(current != end)) { auto result = char_traits<char_type>::to_int_type(*current); std::advance(current, 1); return result; } return char_traits<char_type>::eof(); } private: IteratorType current; IteratorType end; template<typename BaseInputAdapter, size_t T> friend struct wide_string_input_helper; bool empty() const { return current == end; } }; template<typename BaseInputAdapter, size_t T> struct wide_string_input_helper; template<typename BaseInputAdapter> struct wide_string_input_helper<BaseInputAdapter, 4> { // UTF-32 static void fill_buffer(BaseInputAdapter& input, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled) { utf8_bytes_index = 0; if (JSON_HEDLEY_UNLIKELY(input.empty())) { utf8_bytes[0] = std::char_traits<char>::eof(); utf8_bytes_filled = 1; } else { // get the current character const auto wc = input.get_character(); // UTF-32 to UTF-8 encoding if (wc < 0x80) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); utf8_bytes_filled = 1; } else if (wc <= 0x7FF) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu)); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 2; } else if (wc <= 0xFFFF) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu)); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 3; } else if (wc <= 0x10FFFF) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u)); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu)); utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 4; } else { // unknown character utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); utf8_bytes_filled = 1; } } } }; template<typename BaseInputAdapter> struct wide_string_input_helper<BaseInputAdapter, 2> { // UTF-16 static void fill_buffer(BaseInputAdapter& input, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled) { utf8_bytes_index = 0; if (JSON_HEDLEY_UNLIKELY(input.empty())) { utf8_bytes[0] = std::char_traits<char>::eof(); utf8_bytes_filled = 1; } else { // get the current character const auto wc = input.get_character(); // UTF-16 to UTF-8 encoding if (wc < 0x80) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); utf8_bytes_filled = 1; } else if (wc <= 0x7FF) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u))); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 2; } else if (0xD800 > wc || wc >= 0xE000) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u))); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 3; } else { if (JSON_HEDLEY_UNLIKELY(!input.empty())) { const auto wc2 = static_cast<unsigned int>(input.get_character()); const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u)); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu)); utf8_bytes_filled = 4; } else { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); utf8_bytes_filled = 1; } } } } }; // Wraps another input adapter to convert wide character types into individual bytes. template<typename BaseInputAdapter, typename WideCharType> class wide_string_input_adapter { public: using char_type = char; wide_string_input_adapter(BaseInputAdapter base) : base_adapter(base) {} typename std::char_traits<char>::int_type get_character() noexcept { // check if buffer needs to be filled if (utf8_bytes_index == utf8_bytes_filled) { fill_buffer<sizeof(WideCharType)>(); JSON_ASSERT(utf8_bytes_filled > 0); JSON_ASSERT(utf8_bytes_index == 0); } // use buffer JSON_ASSERT(utf8_bytes_filled > 0); JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); return utf8_bytes[utf8_bytes_index++]; } private: BaseInputAdapter base_adapter; template<size_t T> void fill_buffer() { wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); } /// a buffer for UTF-8 bytes std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; /// index to the utf8_codes array for the next valid byte std::size_t utf8_bytes_index = 0; /// number of valid bytes in the utf8_codes array std::size_t utf8_bytes_filled = 0; }; template<typename IteratorType, typename Enable = void> struct iterator_input_adapter_factory { using iterator_type = IteratorType; using char_type = typename std::iterator_traits<iterator_type>::value_type; using adapter_type = iterator_input_adapter<iterator_type>; static adapter_type create(IteratorType first, IteratorType last) { return adapter_type(std::move(first), std::move(last)); } }; template<typename T> struct is_iterator_of_multibyte { using value_type = typename std::iterator_traits<T>::value_type; enum { value = sizeof(value_type) > 1 }; }; template<typename IteratorType> struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>> { using iterator_type = IteratorType; using char_type = typename std::iterator_traits<iterator_type>::value_type; using base_adapter_type = iterator_input_adapter<iterator_type>; using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>; static adapter_type create(IteratorType first, IteratorType last) { return adapter_type(base_adapter_type(std::move(first), std::move(last))); } }; // General purpose iterator-based input template<typename IteratorType> typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last) { using factory_type = iterator_input_adapter_factory<IteratorType>; return factory_type::create(first, last); } // Convenience shorthand from container to iterator // Enables ADL on begin(container) and end(container) // Encloses the using declarations in namespace for not to leak them to outside scope namespace container_input_adapter_factory_impl { using std::begin; using std::end; template<typename ContainerType, typename Enable = void> struct container_input_adapter_factory {}; template<typename ContainerType> struct container_input_adapter_factory< ContainerType, void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>> { using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))); static adapter_type create(const ContainerType& container) { return input_adapter(begin(container), end(container)); } }; } // namespace container_input_adapter_factory_impl template<typename ContainerType> typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container) { return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container); } #ifndef JSON_NO_IO // Special cases with fast paths inline file_input_adapter input_adapter(std::FILE* file) { return file_input_adapter(file); } inline input_stream_adapter input_adapter(std::istream& stream) { return input_stream_adapter(stream); } inline input_stream_adapter input_adapter(std::istream&& stream) { return input_stream_adapter(stream); } #endif // JSON_NO_IO using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>())); // Null-delimited strings, and the like. template < typename CharT, typename std::enable_if < std::is_pointer<CharT>::value&& !std::is_array<CharT>::value&& std::is_integral<typename std::remove_pointer<CharT>::type>::value&& sizeof(typename std::remove_pointer<CharT>::type) == 1, int >::type = 0 > contiguous_bytes_input_adapter input_adapter(CharT b) { auto length = std::strlen(reinterpret_cast<const char*>(b)); const auto* ptr = reinterpret_cast<const char*>(b); return input_adapter(ptr, ptr + length); } template<typename T, std::size_t N> auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { return input_adapter(array, array + N); } // This class only handles inputs of input_buffer_adapter type. // It's required so that expressions like {ptr, len} can be implicitly cast // to the correct adapter. class span_input_adapter { public: template < typename CharT, typename std::enable_if < std::is_pointer<CharT>::value&& std::is_integral<typename std::remove_pointer<CharT>::type>::value&& sizeof(typename std::remove_pointer<CharT>::type) == 1, int >::type = 0 > span_input_adapter(CharT b, std::size_t l) : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {} template<class IteratorType, typename std::enable_if< std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, int>::type = 0> span_input_adapter(IteratorType first, IteratorType last) : ia(input_adapter(first, last)) {} contiguous_bytes_input_adapter&& get() { return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) } private: contiguous_bytes_input_adapter ia; }; } // namespace detail NLOHMANN_JSON_NAMESPACE_END ``` -------------------------------------------------------------------------------- /include/nlohmann/detail/input/input_adapters.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <array> // array #include <cstddef> // size_t #include <cstring> // strlen #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next #include <memory> // shared_ptr, make_shared, addressof #include <numeric> // accumulate #include <string> // string, char_traits #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer #include <utility> // pair, declval #ifndef JSON_NO_IO #include <cstdio> // FILE * #include <istream> // istream #endif // JSON_NO_IO #include <nlohmann/detail/iterators/iterator_traits.hpp> #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/type_traits.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { /// the supported input formats enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; //////////////////// // input adapters // //////////////////// #ifndef JSON_NO_IO /*! Input adapter for stdio file access. This adapter read only 1 byte and do not use any buffer. This adapter is a very low level adapter. */ class file_input_adapter { public: using char_type = char; JSON_HEDLEY_NON_NULL(2) explicit file_input_adapter(std::FILE* f) noexcept : m_file(f) { JSON_ASSERT(m_file != nullptr); } // make class move-only file_input_adapter(const file_input_adapter&) = delete; file_input_adapter(file_input_adapter&&) noexcept = default; file_input_adapter& operator=(const file_input_adapter&) = delete; file_input_adapter& operator=(file_input_adapter&&) = delete; ~file_input_adapter() = default; std::char_traits<char>::int_type get_character() noexcept { return std::fgetc(m_file); } private: /// the file pointer to read from std::FILE* m_file; }; /*! Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at beginning of input. Does not support changing the underlying std::streambuf in mid-input. Maintains underlying std::istream and std::streambuf to support subsequent use of standard std::istream operations to process any input characters following those used in parsing the JSON input. Clears the std::istream flags; any input errors (e.g., EOF) will be detected by the first subsequent call for input from the std::istream. */ class input_stream_adapter { public: using char_type = char; ~input_stream_adapter() { // clear stream flags; we use underlying streambuf I/O, do not // maintain ifstream flags, except eof if (is != nullptr) { is->clear(is->rdstate() & std::ios::eofbit); } } explicit input_stream_adapter(std::istream& i) : is(&i), sb(i.rdbuf()) {} // delete because of pointer members input_stream_adapter(const input_stream_adapter&) = delete; input_stream_adapter& operator=(input_stream_adapter&) = delete; input_stream_adapter& operator=(input_stream_adapter&&) = delete; input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb) { rhs.is = nullptr; rhs.sb = nullptr; } // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to // ensure that std::char_traits<char>::eof() and the character 0xFF do not // end up as the same value, e.g. 0xFFFFFFFF. std::char_traits<char>::int_type get_character() { auto res = sb->sbumpc(); // set eof manually, as we don't use the istream interface. if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof())) { is->clear(is->rdstate() | std::ios::eofbit); } return res; } private: /// the associated input stream std::istream* is = nullptr; std::streambuf* sb = nullptr; }; #endif // JSON_NO_IO // General-purpose iterator-based adapter. It might not be as fast as // theoretically possible for some containers, but it is extremely versatile. template<typename IteratorType> class iterator_input_adapter { public: using char_type = typename std::iterator_traits<IteratorType>::value_type; iterator_input_adapter(IteratorType first, IteratorType last) : current(std::move(first)), end(std::move(last)) {} typename char_traits<char_type>::int_type get_character() { if (JSON_HEDLEY_LIKELY(current != end)) { auto result = char_traits<char_type>::to_int_type(*current); std::advance(current, 1); return result; } return char_traits<char_type>::eof(); } private: IteratorType current; IteratorType end; template<typename BaseInputAdapter, size_t T> friend struct wide_string_input_helper; bool empty() const { return current == end; } }; template<typename BaseInputAdapter, size_t T> struct wide_string_input_helper; template<typename BaseInputAdapter> struct wide_string_input_helper<BaseInputAdapter, 4> { // UTF-32 static void fill_buffer(BaseInputAdapter& input, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled) { utf8_bytes_index = 0; if (JSON_HEDLEY_UNLIKELY(input.empty())) { utf8_bytes[0] = std::char_traits<char>::eof(); utf8_bytes_filled = 1; } else { // get the current character const auto wc = input.get_character(); // UTF-32 to UTF-8 encoding if (wc < 0x80) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); utf8_bytes_filled = 1; } else if (wc <= 0x7FF) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu)); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 2; } else if (wc <= 0xFFFF) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu)); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 3; } else if (wc <= 0x10FFFF) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u)); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu)); utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 4; } else { // unknown character utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); utf8_bytes_filled = 1; } } } }; template<typename BaseInputAdapter> struct wide_string_input_helper<BaseInputAdapter, 2> { // UTF-16 static void fill_buffer(BaseInputAdapter& input, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled) { utf8_bytes_index = 0; if (JSON_HEDLEY_UNLIKELY(input.empty())) { utf8_bytes[0] = std::char_traits<char>::eof(); utf8_bytes_filled = 1; } else { // get the current character const auto wc = input.get_character(); // UTF-16 to UTF-8 encoding if (wc < 0x80) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); utf8_bytes_filled = 1; } else if (wc <= 0x7FF) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u))); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 2; } else if (0xD800 > wc || wc >= 0xE000) { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u))); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu)); utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu)); utf8_bytes_filled = 3; } else { if (JSON_HEDLEY_UNLIKELY(!input.empty())) { const auto wc2 = static_cast<unsigned int>(input.get_character()); const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u)); utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu)); utf8_bytes_filled = 4; } else { utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc); utf8_bytes_filled = 1; } } } } }; // Wraps another input adapter to convert wide character types into individual bytes. template<typename BaseInputAdapter, typename WideCharType> class wide_string_input_adapter { public: using char_type = char; wide_string_input_adapter(BaseInputAdapter base) : base_adapter(base) {} typename std::char_traits<char>::int_type get_character() noexcept { // check if buffer needs to be filled if (utf8_bytes_index == utf8_bytes_filled) { fill_buffer<sizeof(WideCharType)>(); JSON_ASSERT(utf8_bytes_filled > 0); JSON_ASSERT(utf8_bytes_index == 0); } // use buffer JSON_ASSERT(utf8_bytes_filled > 0); JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); return utf8_bytes[utf8_bytes_index++]; } private: BaseInputAdapter base_adapter; template<size_t T> void fill_buffer() { wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); } /// a buffer for UTF-8 bytes std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; /// index to the utf8_codes array for the next valid byte std::size_t utf8_bytes_index = 0; /// number of valid bytes in the utf8_codes array std::size_t utf8_bytes_filled = 0; }; template<typename IteratorType, typename Enable = void> struct iterator_input_adapter_factory { using iterator_type = IteratorType; using char_type = typename std::iterator_traits<iterator_type>::value_type; using adapter_type = iterator_input_adapter<iterator_type>; static adapter_type create(IteratorType first, IteratorType last) { return adapter_type(std::move(first), std::move(last)); } }; template<typename T> struct is_iterator_of_multibyte { using value_type = typename std::iterator_traits<T>::value_type; enum { value = sizeof(value_type) > 1 }; }; template<typename IteratorType> struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>> { using iterator_type = IteratorType; using char_type = typename std::iterator_traits<iterator_type>::value_type; using base_adapter_type = iterator_input_adapter<iterator_type>; using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>; static adapter_type create(IteratorType first, IteratorType last) { return adapter_type(base_adapter_type(std::move(first), std::move(last))); } }; // General purpose iterator-based input template<typename IteratorType> typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last) { using factory_type = iterator_input_adapter_factory<IteratorType>; return factory_type::create(first, last); } // Convenience shorthand from container to iterator // Enables ADL on begin(container) and end(container) // Encloses the using declarations in namespace for not to leak them to outside scope namespace container_input_adapter_factory_impl { using std::begin; using std::end; template<typename ContainerType, typename Enable = void> struct container_input_adapter_factory {}; template<typename ContainerType> struct container_input_adapter_factory< ContainerType, void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>> { using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))); static adapter_type create(const ContainerType& container) { return input_adapter(begin(container), end(container)); } }; } // namespace container_input_adapter_factory_impl template<typename ContainerType> typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container) { return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container); } #ifndef JSON_NO_IO // Special cases with fast paths inline file_input_adapter input_adapter(std::FILE* file) { return file_input_adapter(file); } inline input_stream_adapter input_adapter(std::istream& stream) { return input_stream_adapter(stream); } inline input_stream_adapter input_adapter(std::istream&& stream) { return input_stream_adapter(stream); } #endif // JSON_NO_IO using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>())); // Null-delimited strings, and the like. template < typename CharT, typename std::enable_if < std::is_pointer<CharT>::value&& !std::is_array<CharT>::value&& std::is_integral<typename std::remove_pointer<CharT>::type>::value&& sizeof(typename std::remove_pointer<CharT>::type) == 1, int >::type = 0 > contiguous_bytes_input_adapter input_adapter(CharT b) { auto length = std::strlen(reinterpret_cast<const char*>(b)); const auto* ptr = reinterpret_cast<const char*>(b); return input_adapter(ptr, ptr + length); } template<typename T, std::size_t N> auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { return input_adapter(array, array + N); } // This class only handles inputs of input_buffer_adapter type. // It's required so that expressions like {ptr, len} can be implicitly cast // to the correct adapter. class span_input_adapter { public: template < typename CharT, typename std::enable_if < std::is_pointer<CharT>::value&& std::is_integral<typename std::remove_pointer<CharT>::type>::value&& sizeof(typename std::remove_pointer<CharT>::type) == 1, int >::type = 0 > span_input_adapter(CharT b, std::size_t l) : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {} template<class IteratorType, typename std::enable_if< std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, int>::type = 0> span_input_adapter(IteratorType first, IteratorType last) : ia(input_adapter(first, last)) {} contiguous_bytes_input_adapter&& get() { return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) } private: contiguous_bytes_input_adapter ia; }; } // namespace detail NLOHMANN_JSON_NAMESPACE_END ``` -------------------------------------------------------------------------------- /deps/pluginsdk/nlohmann/detail/conversions/from_json.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <algorithm> // transform #include <array> // array #include <forward_list> // forward_list #include <iterator> // inserter, front_inserter, end #include <map> // map #include <string> // string #include <tuple> // tuple, make_tuple #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible #include <unordered_map> // unordered_map #include <utility> // pair, declval #include <valarray> // valarray #include <nlohmann/detail/exceptions.hpp> #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/cpp_future.hpp> #include <nlohmann/detail/meta/identity_tag.hpp> #include <nlohmann/detail/meta/std_fs.hpp> #include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/string_concat.hpp> #include <nlohmann/detail/value_t.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) { if (JSON_HEDLEY_UNLIKELY(!j.is_null())) { JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); } n = nullptr; } // overloads for basic_json template parameters template < typename BasicJsonType, typename ArithmeticType, enable_if_t < std::is_arithmetic<ArithmeticType>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, int > = 0 > void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) { switch (static_cast<value_t>(j)) { case value_t::number_unsigned: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); break; } case value_t::number_integer: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); break; } case value_t::number_float: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); break; } case value_t::null: case value_t::object: case value_t::array: case value_t::string: case value_t::boolean: case value_t::binary: case value_t::discarded: default: JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); } } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) { if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) { JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); } b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); } template < typename BasicJsonType, typename StringType, enable_if_t < std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value && !std::is_same<typename BasicJsonType::string_t, StringType>::value && !is_json_ref<StringType>::value, int > = 0 > inline void from_json(const BasicJsonType& j, StringType& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) { get_arithmetic_value(j, val); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) { get_arithmetic_value(j, val); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) { get_arithmetic_value(j, val); } #if !JSON_DISABLE_ENUM_SERIALIZATION template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0> inline void from_json(const BasicJsonType& j, EnumType& e) { typename std::underlying_type<EnumType>::type val; get_arithmetic_value(j, val); e = static_cast<EnumType>(val); } #endif // JSON_DISABLE_ENUM_SERIALIZATION // forward_list doesn't have an insert method template<typename BasicJsonType, typename T, typename Allocator, enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } l.clear(); std::transform(j.rbegin(), j.rend(), std::front_inserter(l), [](const BasicJsonType & i) { return i.template get<T>(); }); } // valarray doesn't have an insert method template<typename BasicJsonType, typename T, enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> inline void from_json(const BasicJsonType& j, std::valarray<T>& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } l.resize(j.size()); std::transform(j.begin(), j.end(), std::begin(l), [](const BasicJsonType & elem) { return elem.template get<T>(); }); } template<typename BasicJsonType, typename T, std::size_t N> auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) -> decltype(j.template get<T>(), void()) { for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get<T>(); } } template<typename BasicJsonType> inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) { arr = *j.template get_ptr<const typename BasicJsonType::array_t*>(); } template<typename BasicJsonType, typename T, std::size_t N> auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/) -> decltype(j.template get<T>(), void()) { for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get<T>(); } } template<typename BasicJsonType, typename ConstructibleArrayType, enable_if_t< std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0> auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) -> decltype( arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()), j.template get<typename ConstructibleArrayType::value_type>(), void()) { using std::end; ConstructibleArrayType ret; ret.reserve(j.size()); std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType & i) { // get<BasicJsonType>() returns *this, this won't call a from_json // method when value_type is BasicJsonType return i.template get<typename ConstructibleArrayType::value_type>(); }); arr = std::move(ret); } template<typename BasicJsonType, typename ConstructibleArrayType, enable_if_t< std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0> inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<0> /*unused*/) { using std::end; ConstructibleArrayType ret; std::transform( j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType & i) { // get<BasicJsonType>() returns *this, this won't call a from_json // method when value_type is BasicJsonType return i.template get<typename ConstructibleArrayType::value_type>(); }); arr = std::move(ret); } template < typename BasicJsonType, typename ConstructibleArrayType, enable_if_t < is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&& !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&& !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&& !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&& !is_basic_json<ConstructibleArrayType>::value, int > = 0 > auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), j.template get<typename ConstructibleArrayType::value_type>(), void()) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } from_json_array_impl(j, arr, priority_tag<3> {}); } template < typename BasicJsonType, typename T, std::size_t... Idx > std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j, identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/) { return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } }; } template < typename BasicJsonType, typename T, std::size_t N > auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag) -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {})) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) { if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) { JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); } bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>(); } template<typename BasicJsonType, typename ConstructibleObjectType, enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0> inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) { if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); } ConstructibleObjectType ret; const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); using value_type = typename ConstructibleObjectType::value_type; std::transform( inner_object->begin(), inner_object->end(), std::inserter(ret, ret.begin()), [](typename BasicJsonType::object_t::value_type const & p) { return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>()); }); obj = std::move(ret); } // overload for arithmetic types, not chosen for basic_json template arguments // (BooleanType, etc..); note: Is it really necessary to provide explicit // overloads for boolean_t etc. in case of a custom BooleanType which is not // an arithmetic type? template < typename BasicJsonType, typename ArithmeticType, enable_if_t < std::is_arithmetic<ArithmeticType>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, int > = 0 > inline void from_json(const BasicJsonType& j, ArithmeticType& val) { switch (static_cast<value_t>(j)) { case value_t::number_unsigned: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); break; } case value_t::number_integer: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); break; } case value_t::number_float: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); break; } case value_t::boolean: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); break; } case value_t::null: case value_t::object: case value_t::array: case value_t::string: case value_t::binary: case value_t::discarded: default: JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); } } template<typename BasicJsonType, typename... Args, std::size_t... Idx> std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/) { return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...); } template < typename BasicJsonType, class A1, class A2 > std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/) { return {std::forward<BasicJsonType>(j).at(0).template get<A1>(), std::forward<BasicJsonType>(j).at(1).template get<A2>()}; } template<typename BasicJsonType, typename A1, typename A2> inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/) { p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {}); } template<typename BasicJsonType, typename... Args> std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/) { return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); } template<typename BasicJsonType, typename... Args> inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/) { t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); } template<typename BasicJsonType, typename TupleRelated> auto from_json(BasicJsonType&& j, TupleRelated&& t) -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {})) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}); } template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); } m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); } } template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); } m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); } } #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, std_fs::path& p) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); } #endif struct from_json_fn { template<typename BasicJsonType, typename T> auto operator()(const BasicJsonType& j, T&& val) const noexcept(noexcept(from_json(j, std::forward<T>(val)))) -> decltype(from_json(j, std::forward<T>(val))) { return from_json(j, std::forward<T>(val)); } }; } // namespace detail #ifndef JSON_HAS_CPP_17 /// namespace to hold default `from_json` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) { #endif JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) detail::static_const<detail::from_json_fn>::value; #ifndef JSON_HAS_CPP_17 } // namespace #endif NLOHMANN_JSON_NAMESPACE_END ``` -------------------------------------------------------------------------------- /include/nlohmann/detail/conversions/from_json.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <algorithm> // transform #include <array> // array #include <forward_list> // forward_list #include <iterator> // inserter, front_inserter, end #include <map> // map #include <string> // string #include <tuple> // tuple, make_tuple #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible #include <unordered_map> // unordered_map #include <utility> // pair, declval #include <valarray> // valarray #include <nlohmann/detail/exceptions.hpp> #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/cpp_future.hpp> #include <nlohmann/detail/meta/identity_tag.hpp> #include <nlohmann/detail/meta/std_fs.hpp> #include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/string_concat.hpp> #include <nlohmann/detail/value_t.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) { if (JSON_HEDLEY_UNLIKELY(!j.is_null())) { JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); } n = nullptr; } // overloads for basic_json template parameters template < typename BasicJsonType, typename ArithmeticType, enable_if_t < std::is_arithmetic<ArithmeticType>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, int > = 0 > void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) { switch (static_cast<value_t>(j)) { case value_t::number_unsigned: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); break; } case value_t::number_integer: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); break; } case value_t::number_float: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); break; } case value_t::null: case value_t::object: case value_t::array: case value_t::string: case value_t::boolean: case value_t::binary: case value_t::discarded: default: JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); } } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) { if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) { JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); } b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); } template < typename BasicJsonType, typename StringType, enable_if_t < std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value && !std::is_same<typename BasicJsonType::string_t, StringType>::value && !is_json_ref<StringType>::value, int > = 0 > inline void from_json(const BasicJsonType& j, StringType& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) { get_arithmetic_value(j, val); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) { get_arithmetic_value(j, val); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) { get_arithmetic_value(j, val); } #if !JSON_DISABLE_ENUM_SERIALIZATION template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0> inline void from_json(const BasicJsonType& j, EnumType& e) { typename std::underlying_type<EnumType>::type val; get_arithmetic_value(j, val); e = static_cast<EnumType>(val); } #endif // JSON_DISABLE_ENUM_SERIALIZATION // forward_list doesn't have an insert method template<typename BasicJsonType, typename T, typename Allocator, enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } l.clear(); std::transform(j.rbegin(), j.rend(), std::front_inserter(l), [](const BasicJsonType & i) { return i.template get<T>(); }); } // valarray doesn't have an insert method template<typename BasicJsonType, typename T, enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0> inline void from_json(const BasicJsonType& j, std::valarray<T>& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } l.resize(j.size()); std::transform(j.begin(), j.end(), std::begin(l), [](const BasicJsonType & elem) { return elem.template get<T>(); }); } template<typename BasicJsonType, typename T, std::size_t N> auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) -> decltype(j.template get<T>(), void()) { for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get<T>(); } } template<typename BasicJsonType> inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) { arr = *j.template get_ptr<const typename BasicJsonType::array_t*>(); } template<typename BasicJsonType, typename T, std::size_t N> auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/) -> decltype(j.template get<T>(), void()) { for (std::size_t i = 0; i < N; ++i) { arr[i] = j.at(i).template get<T>(); } } template<typename BasicJsonType, typename ConstructibleArrayType, enable_if_t< std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0> auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) -> decltype( arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()), j.template get<typename ConstructibleArrayType::value_type>(), void()) { using std::end; ConstructibleArrayType ret; ret.reserve(j.size()); std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType & i) { // get<BasicJsonType>() returns *this, this won't call a from_json // method when value_type is BasicJsonType return i.template get<typename ConstructibleArrayType::value_type>(); }); arr = std::move(ret); } template<typename BasicJsonType, typename ConstructibleArrayType, enable_if_t< std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0> inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<0> /*unused*/) { using std::end; ConstructibleArrayType ret; std::transform( j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType & i) { // get<BasicJsonType>() returns *this, this won't call a from_json // method when value_type is BasicJsonType return i.template get<typename ConstructibleArrayType::value_type>(); }); arr = std::move(ret); } template < typename BasicJsonType, typename ConstructibleArrayType, enable_if_t < is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&& !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&& !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&& !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&& !is_basic_json<ConstructibleArrayType>::value, int > = 0 > auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), j.template get<typename ConstructibleArrayType::value_type>(), void()) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } from_json_array_impl(j, arr, priority_tag<3> {}); } template < typename BasicJsonType, typename T, std::size_t... Idx > std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j, identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/) { return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } }; } template < typename BasicJsonType, typename T, std::size_t N > auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag) -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {})) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}); } template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) { if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) { JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); } bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>(); } template<typename BasicJsonType, typename ConstructibleObjectType, enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0> inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) { if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); } ConstructibleObjectType ret; const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); using value_type = typename ConstructibleObjectType::value_type; std::transform( inner_object->begin(), inner_object->end(), std::inserter(ret, ret.begin()), [](typename BasicJsonType::object_t::value_type const & p) { return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>()); }); obj = std::move(ret); } // overload for arithmetic types, not chosen for basic_json template arguments // (BooleanType, etc..); note: Is it really necessary to provide explicit // overloads for boolean_t etc. in case of a custom BooleanType which is not // an arithmetic type? template < typename BasicJsonType, typename ArithmeticType, enable_if_t < std::is_arithmetic<ArithmeticType>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&& !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, int > = 0 > inline void from_json(const BasicJsonType& j, ArithmeticType& val) { switch (static_cast<value_t>(j)) { case value_t::number_unsigned: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>()); break; } case value_t::number_integer: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>()); break; } case value_t::number_float: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); break; } case value_t::boolean: { val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); break; } case value_t::null: case value_t::object: case value_t::array: case value_t::string: case value_t::binary: case value_t::discarded: default: JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); } } template<typename BasicJsonType, typename... Args, std::size_t... Idx> std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/) { return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...); } template < typename BasicJsonType, class A1, class A2 > std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/) { return {std::forward<BasicJsonType>(j).at(0).template get<A1>(), std::forward<BasicJsonType>(j).at(1).template get<A2>()}; } template<typename BasicJsonType, typename A1, typename A2> inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/) { p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {}); } template<typename BasicJsonType, typename... Args> std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/) { return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); } template<typename BasicJsonType, typename... Args> inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/) { t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {}); } template<typename BasicJsonType, typename TupleRelated> auto from_json(BasicJsonType&& j, TupleRelated&& t) -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {})) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}); } template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); } m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); } } template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); } m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>()); } } #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM template<typename BasicJsonType> inline void from_json(const BasicJsonType& j, std_fs::path& p) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } p = *j.template get_ptr<const typename BasicJsonType::string_t*>(); } #endif struct from_json_fn { template<typename BasicJsonType, typename T> auto operator()(const BasicJsonType& j, T&& val) const noexcept(noexcept(from_json(j, std::forward<T>(val)))) -> decltype(from_json(j, std::forward<T>(val))) { return from_json(j, std::forward<T>(val)); } }; } // namespace detail #ifndef JSON_HAS_CPP_17 /// namespace to hold default `from_json` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) { #endif JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) detail::static_const<detail::from_json_fn>::value; #ifndef JSON_HAS_CPP_17 } // namespace #endif NLOHMANN_JSON_NAMESPACE_END ``` -------------------------------------------------------------------------------- /deps/pluginsdk/nlohmann/detail/input/parser.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <cmath> // isfinite #include <cstdint> // uint8_t #include <functional> // function #include <string> // string #include <utility> // move #include <vector> // vector #include <nlohmann/detail/exceptions.hpp> #include <nlohmann/detail/input/input_adapters.hpp> #include <nlohmann/detail/input/json_sax.hpp> #include <nlohmann/detail/input/lexer.hpp> #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/is_sax.hpp> #include <nlohmann/detail/string_concat.hpp> #include <nlohmann/detail/value_t.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { //////////// // parser // //////////// enum class parse_event_t : std::uint8_t { /// the parser read `{` and started to process a JSON object object_start, /// the parser read `}` and finished processing a JSON object object_end, /// the parser read `[` and started to process a JSON array array_start, /// the parser read `]` and finished processing a JSON array array_end, /// the parser read a key of a value in an object key, /// the parser finished reading a JSON value value }; template<typename BasicJsonType> using parser_callback_t = std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>; /*! @brief syntax analysis This class implements a recursive descent parser. */ template<typename BasicJsonType, typename InputAdapterType> class parser { using number_integer_t = typename BasicJsonType::number_integer_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t; using number_float_t = typename BasicJsonType::number_float_t; using string_t = typename BasicJsonType::string_t; using lexer_t = lexer<BasicJsonType, InputAdapterType>; using token_type = typename lexer_t::token_type; public: /// a parser reading from an input adapter explicit parser(InputAdapterType&& adapter, const parser_callback_t<BasicJsonType> cb = nullptr, const bool allow_exceptions_ = true, const bool skip_comments = false) : callback(cb) , m_lexer(std::move(adapter), skip_comments) , allow_exceptions(allow_exceptions_) { // read first token get_token(); } /*! @brief public parser interface @param[in] strict whether to expect the last token to be EOF @param[in,out] result parsed JSON value @throw parse_error.101 in case of an unexpected token @throw parse_error.102 if to_unicode fails or surrogate error @throw parse_error.103 if to_unicode fails */ void parse(const bool strict, BasicJsonType& result) { if (callback) { json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); sax_parse_internal(&sdp); // in strict mode, input must be completely read if (strict && (get_token() != token_type::end_of_input)) { sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); } // in case of an error, return discarded value if (sdp.is_errored()) { result = value_t::discarded; return; } // set top-level value to null if it was discarded by the callback // function if (result.is_discarded()) { result = nullptr; } } else { json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); sax_parse_internal(&sdp); // in strict mode, input must be completely read if (strict && (get_token() != token_type::end_of_input)) { sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); } // in case of an error, return discarded value if (sdp.is_errored()) { result = value_t::discarded; return; } } result.assert_invariant(); } /*! @brief public accept interface @param[in] strict whether to expect the last token to be EOF @return whether the input is a proper JSON text */ bool accept(const bool strict = true) { json_sax_acceptor<BasicJsonType> sax_acceptor; return sax_parse(&sax_acceptor, strict); } template<typename SAX> JSON_HEDLEY_NON_NULL(2) bool sax_parse(SAX* sax, const bool strict = true) { (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; const bool result = sax_parse_internal(sax); // strict mode: next byte must be EOF if (result && strict && (get_token() != token_type::end_of_input)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); } return result; } private: template<typename SAX> JSON_HEDLEY_NON_NULL(2) bool sax_parse_internal(SAX* sax) { // stack to remember the hierarchy of structured values we are parsing // true = array; false = object std::vector<bool> states; // value to avoid a goto (see comment where set to true) bool skip_to_state_evaluation = false; while (true) { if (!skip_to_state_evaluation) { // invariant: get_token() was called before each iteration switch (last_token) { case token_type::begin_object: { if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) { return false; } // closing } -> we are done if (get_token() == token_type::end_object) { if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) { return false; } break; } // parse key if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { return false; } // parse separator (:) if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); } // remember we are now inside an object states.push_back(false); // parse values get_token(); continue; } case token_type::begin_array: { if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) { return false; } // closing ] -> we are done if (get_token() == token_type::end_array) { if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) { return false; } break; } // remember we are now inside an array states.push_back(true); // parse values (no need to call get_token) continue; } case token_type::value_float: { const auto res = m_lexer.get_number_float(); if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) { return false; } break; } case token_type::literal_false: { if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) { return false; } break; } case token_type::literal_null: { if (JSON_HEDLEY_UNLIKELY(!sax->null())) { return false; } break; } case token_type::literal_true: { if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) { return false; } break; } case token_type::value_integer: { if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) { return false; } break; } case token_type::value_string: { if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) { return false; } break; } case token_type::value_unsigned: { if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) { return false; } break; } case token_type::parse_error: { // using "uninitialized" to avoid "expected" message return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); } case token_type::end_of_input: { if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); } return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); } case token_type::uninitialized: case token_type::end_array: case token_type::end_object: case token_type::name_separator: case token_type::value_separator: case token_type::literal_or_value: default: // the last token was unexpected { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); } } } else { skip_to_state_evaluation = false; } // we reached this line after we successfully parsed a value if (states.empty()) { // empty stack: we reached the end of the hierarchy: done return true; } if (states.back()) // array { // comma -> next value if (get_token() == token_type::value_separator) { // parse a new value get_token(); continue; } // closing ] if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) { if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) { return false; } // We are done with this array. Before we can parse a // new value, we need to evaluate the new state first. // By setting skip_to_state_evaluation to false, we // are effectively jumping to the beginning of this if. JSON_ASSERT(!states.empty()); states.pop_back(); skip_to_state_evaluation = true; continue; } return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); } // states.back() is false -> object // comma -> next value if (get_token() == token_type::value_separator) { // parse key if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { return false; } // parse separator (:) if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); } // parse values get_token(); continue; } // closing } if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) { if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) { return false; } // We are done with this object. Before we can parse a // new value, we need to evaluate the new state first. // By setting skip_to_state_evaluation to false, we // are effectively jumping to the beginning of this if. JSON_ASSERT(!states.empty()); states.pop_back(); skip_to_state_evaluation = true; continue; } return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); } } /// get next token from lexer token_type get_token() { return last_token = m_lexer.scan(); } std::string exception_message(const token_type expected, const std::string& context) { std::string error_msg = "syntax error "; if (!context.empty()) { error_msg += concat("while parsing ", context, ' '); } error_msg += "- "; if (last_token == token_type::parse_error) { error_msg += concat(m_lexer.get_error_message(), "; last read: '", m_lexer.get_token_string(), '\''); } else { error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); } if (expected != token_type::uninitialized) { error_msg += concat("; expected ", lexer_t::token_type_name(expected)); } return error_msg; } private: /// callback function const parser_callback_t<BasicJsonType> callback = nullptr; /// the type of the last read token token_type last_token = token_type::uninitialized; /// the lexer lexer_t m_lexer; /// whether to throw exceptions in case of errors const bool allow_exceptions = true; }; } // namespace detail NLOHMANN_JSON_NAMESPACE_END ``` -------------------------------------------------------------------------------- /include/nlohmann/detail/input/parser.hpp: -------------------------------------------------------------------------------- ``` // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me> // SPDX-License-Identifier: MIT #pragma once #include <cmath> // isfinite #include <cstdint> // uint8_t #include <functional> // function #include <string> // string #include <utility> // move #include <vector> // vector #include <nlohmann/detail/exceptions.hpp> #include <nlohmann/detail/input/input_adapters.hpp> #include <nlohmann/detail/input/json_sax.hpp> #include <nlohmann/detail/input/lexer.hpp> #include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/meta/is_sax.hpp> #include <nlohmann/detail/string_concat.hpp> #include <nlohmann/detail/value_t.hpp> NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { //////////// // parser // //////////// enum class parse_event_t : std::uint8_t { /// the parser read `{` and started to process a JSON object object_start, /// the parser read `}` and finished processing a JSON object object_end, /// the parser read `[` and started to process a JSON array array_start, /// the parser read `]` and finished processing a JSON array array_end, /// the parser read a key of a value in an object key, /// the parser finished reading a JSON value value }; template<typename BasicJsonType> using parser_callback_t = std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>; /*! @brief syntax analysis This class implements a recursive descent parser. */ template<typename BasicJsonType, typename InputAdapterType> class parser { using number_integer_t = typename BasicJsonType::number_integer_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t; using number_float_t = typename BasicJsonType::number_float_t; using string_t = typename BasicJsonType::string_t; using lexer_t = lexer<BasicJsonType, InputAdapterType>; using token_type = typename lexer_t::token_type; public: /// a parser reading from an input adapter explicit parser(InputAdapterType&& adapter, const parser_callback_t<BasicJsonType> cb = nullptr, const bool allow_exceptions_ = true, const bool skip_comments = false) : callback(cb) , m_lexer(std::move(adapter), skip_comments) , allow_exceptions(allow_exceptions_) { // read first token get_token(); } /*! @brief public parser interface @param[in] strict whether to expect the last token to be EOF @param[in,out] result parsed JSON value @throw parse_error.101 in case of an unexpected token @throw parse_error.102 if to_unicode fails or surrogate error @throw parse_error.103 if to_unicode fails */ void parse(const bool strict, BasicJsonType& result) { if (callback) { json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions); sax_parse_internal(&sdp); // in strict mode, input must be completely read if (strict && (get_token() != token_type::end_of_input)) { sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); } // in case of an error, return discarded value if (sdp.is_errored()) { result = value_t::discarded; return; } // set top-level value to null if it was discarded by the callback // function if (result.is_discarded()) { result = nullptr; } } else { json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions); sax_parse_internal(&sdp); // in strict mode, input must be completely read if (strict && (get_token() != token_type::end_of_input)) { sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); } // in case of an error, return discarded value if (sdp.is_errored()) { result = value_t::discarded; return; } } result.assert_invariant(); } /*! @brief public accept interface @param[in] strict whether to expect the last token to be EOF @return whether the input is a proper JSON text */ bool accept(const bool strict = true) { json_sax_acceptor<BasicJsonType> sax_acceptor; return sax_parse(&sax_acceptor, strict); } template<typename SAX> JSON_HEDLEY_NON_NULL(2) bool sax_parse(SAX* sax, const bool strict = true) { (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {}; const bool result = sax_parse_internal(sax); // strict mode: next byte must be EOF if (result && strict && (get_token() != token_type::end_of_input)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); } return result; } private: template<typename SAX> JSON_HEDLEY_NON_NULL(2) bool sax_parse_internal(SAX* sax) { // stack to remember the hierarchy of structured values we are parsing // true = array; false = object std::vector<bool> states; // value to avoid a goto (see comment where set to true) bool skip_to_state_evaluation = false; while (true) { if (!skip_to_state_evaluation) { // invariant: get_token() was called before each iteration switch (last_token) { case token_type::begin_object: { if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1)))) { return false; } // closing } -> we are done if (get_token() == token_type::end_object) { if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) { return false; } break; } // parse key if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { return false; } // parse separator (:) if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); } // remember we are now inside an object states.push_back(false); // parse values get_token(); continue; } case token_type::begin_array: { if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1)))) { return false; } // closing ] -> we are done if (get_token() == token_type::end_array) { if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) { return false; } break; } // remember we are now inside an array states.push_back(true); // parse values (no need to call get_token) continue; } case token_type::value_float: { const auto res = m_lexer.get_number_float(); if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) { return false; } break; } case token_type::literal_false: { if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) { return false; } break; } case token_type::literal_null: { if (JSON_HEDLEY_UNLIKELY(!sax->null())) { return false; } break; } case token_type::literal_true: { if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) { return false; } break; } case token_type::value_integer: { if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) { return false; } break; } case token_type::value_string: { if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) { return false; } break; } case token_type::value_unsigned: { if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) { return false; } break; } case token_type::parse_error: { // using "uninitialized" to avoid "expected" message return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); } case token_type::end_of_input: { if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); } return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); } case token_type::uninitialized: case token_type::end_array: case token_type::end_object: case token_type::name_separator: case token_type::value_separator: case token_type::literal_or_value: default: // the last token was unexpected { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); } } } else { skip_to_state_evaluation = false; } // we reached this line after we successfully parsed a value if (states.empty()) { // empty stack: we reached the end of the hierarchy: done return true; } if (states.back()) // array { // comma -> next value if (get_token() == token_type::value_separator) { // parse a new value get_token(); continue; } // closing ] if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) { if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) { return false; } // We are done with this array. Before we can parse a // new value, we need to evaluate the new state first. // By setting skip_to_state_evaluation to false, we // are effectively jumping to the beginning of this if. JSON_ASSERT(!states.empty()); states.pop_back(); skip_to_state_evaluation = true; continue; } return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); } // states.back() is false -> object // comma -> next value if (get_token() == token_type::value_separator) { // parse key if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { return false; } // parse separator (:) if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); } // parse values get_token(); continue; } // closing } if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) { if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) { return false; } // We are done with this object. Before we can parse a // new value, we need to evaluate the new state first. // By setting skip_to_state_evaluation to false, we // are effectively jumping to the beginning of this if. JSON_ASSERT(!states.empty()); states.pop_back(); skip_to_state_evaluation = true; continue; } return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); } } /// get next token from lexer token_type get_token() { return last_token = m_lexer.scan(); } std::string exception_message(const token_type expected, const std::string& context) { std::string error_msg = "syntax error "; if (!context.empty()) { error_msg += concat("while parsing ", context, ' '); } error_msg += "- "; if (last_token == token_type::parse_error) { error_msg += concat(m_lexer.get_error_message(), "; last read: '", m_lexer.get_token_string(), '\''); } else { error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); } if (expected != token_type::uninitialized) { error_msg += concat("; expected ", lexer_t::token_type_name(expected)); } return error_msg; } private: /// callback function const parser_callback_t<BasicJsonType> callback = nullptr; /// the type of the last read token token_type last_token = token_type::uninitialized; /// the lexer lexer_t m_lexer; /// whether to throw exceptions in case of errors const bool allow_exceptions = true; }; } // namespace detail NLOHMANN_JSON_NAMESPACE_END ```