243 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			243 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //     __ _____ _____ _____
 | ||
|  | //  __|  |   __|     |   | |  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 <cstddef> // size_t
 | ||
|  | #include <iterator> // input_iterator_tag
 | ||
|  | #include <string> // string, to_string
 | ||
|  | #include <tuple> // tuple_size, get, tuple_element
 | ||
|  | #include <utility> // move
 | ||
|  | 
 | ||
|  | #if JSON_HAS_RANGES
 | ||
|  |     #include <ranges> // enable_borrowed_range
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #include <nlohmann/detail/abi_macros.hpp>
 | ||
|  | #include <nlohmann/detail/meta/type_traits.hpp>
 | ||
|  | #include <nlohmann/detail/value_t.hpp>
 | ||
|  | 
 | ||
|  | NLOHMANN_JSON_NAMESPACE_BEGIN | ||
|  | namespace detail | ||
|  | { | ||
|  | 
 | ||
|  | template<typename string_type> | ||
|  | void int_to_string( string_type& target, std::size_t value ) | ||
|  | { | ||
|  |     // For ADL
 | ||
|  |     using std::to_string; | ||
|  |     target = to_string(value); | ||
|  | } | ||
|  | template<typename IteratorType> class iteration_proxy_value | ||
|  | { | ||
|  |   public: | ||
|  |     using difference_type = std::ptrdiff_t; | ||
|  |     using value_type = iteration_proxy_value; | ||
|  |     using pointer = value_type *; | ||
|  |     using reference = value_type &; | ||
|  |     using iterator_category = std::input_iterator_tag; | ||
|  |     using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type; | ||
|  | 
 | ||
|  |   private: | ||
|  |     /// the iterator
 | ||
|  |     IteratorType anchor{}; | ||
|  |     /// an index for arrays (used to create key names)
 | ||
|  |     std::size_t array_index = 0; | ||
|  |     /// last stringified array index
 | ||
|  |     mutable std::size_t array_index_last = 0; | ||
|  |     /// a string representation of the array index
 | ||
|  |     mutable string_type array_index_str = "0"; | ||
|  |     /// an empty string (to return a reference for primitive values)
 | ||
|  |     string_type empty_str{}; | ||
|  | 
 | ||
|  |   public: | ||
|  |     explicit iteration_proxy_value() = default; | ||
|  |     explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) | ||
|  |     noexcept(std::is_nothrow_move_constructible<IteratorType>::value | ||
|  |              && std::is_nothrow_default_constructible<string_type>::value) | ||
|  |         : anchor(std::move(it)) | ||
|  |         , array_index(array_index_) | ||
|  |     {} | ||
|  | 
 | ||
|  |     iteration_proxy_value(iteration_proxy_value const&) = default; | ||
|  |     iteration_proxy_value& operator=(iteration_proxy_value const&) = default; | ||
|  |     // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
 | ||
|  |     iteration_proxy_value(iteration_proxy_value&&) | ||
|  |     noexcept(std::is_nothrow_move_constructible<IteratorType>::value | ||
|  |              && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
 | ||
|  |     iteration_proxy_value& operator=(iteration_proxy_value&&) | ||
|  |     noexcept(std::is_nothrow_move_assignable<IteratorType>::value | ||
|  |              && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
 | ||
|  |     ~iteration_proxy_value() = default; | ||
|  | 
 | ||
|  |     /// dereference operator (needed for range-based for)
 | ||
|  |     const iteration_proxy_value& operator*() const | ||
|  |     { | ||
|  |         return *this; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// increment operator (needed for range-based for)
 | ||
|  |     iteration_proxy_value& operator++() | ||
|  |     { | ||
|  |         ++anchor; | ||
|  |         ++array_index; | ||
|  | 
 | ||
|  |         return *this; | ||
|  |     } | ||
|  | 
 | ||
|  |     iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
 | ||
|  |     { | ||
|  |         auto tmp = iteration_proxy_value(anchor, array_index); | ||
|  |         ++anchor; | ||
|  |         ++array_index; | ||
|  |         return tmp; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// equality operator (needed for InputIterator)
 | ||
|  |     bool operator==(const iteration_proxy_value& o) const | ||
|  |     { | ||
|  |         return anchor == o.anchor; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// inequality operator (needed for range-based for)
 | ||
|  |     bool operator!=(const iteration_proxy_value& o) const | ||
|  |     { | ||
|  |         return anchor != o.anchor; | ||
|  |     } | ||
|  | 
 | ||
|  |     /// return key of the iterator
 | ||
|  |     const string_type& key() const | ||
|  |     { | ||
|  |         JSON_ASSERT(anchor.m_object != nullptr); | ||
|  | 
 | ||
|  |         switch (anchor.m_object->type()) | ||
|  |         { | ||
|  |             // use integer array index as key
 | ||
|  |             case value_t::array: | ||
|  |             { | ||
|  |                 if (array_index != array_index_last) | ||
|  |                 { | ||
|  |                     int_to_string( array_index_str, array_index ); | ||
|  |                     array_index_last = array_index; | ||
|  |                 } | ||
|  |                 return array_index_str; | ||
|  |             } | ||
|  | 
 | ||
|  |             // use key from the object
 | ||
|  |             case value_t::object: | ||
|  |                 return anchor.key(); | ||
|  | 
 | ||
|  |             // use an empty key for all primitive types
 | ||
|  |             case value_t::null: | ||
|  |             case value_t::string: | ||
|  |             case value_t::boolean: | ||
|  |             case value_t::number_integer: | ||
|  |             case value_t::number_unsigned: | ||
|  |             case value_t::number_float: | ||
|  |             case value_t::binary: | ||
|  |             case value_t::discarded: | ||
|  |             default: | ||
|  |                 return empty_str; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     /// return value of the iterator
 | ||
|  |     typename IteratorType::reference value() const | ||
|  |     { | ||
|  |         return anchor.value(); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | /// proxy class for the items() function
 | ||
|  | template<typename IteratorType> class iteration_proxy | ||
|  | { | ||
|  |   private: | ||
|  |     /// the container to iterate
 | ||
|  |     typename IteratorType::pointer container = nullptr; | ||
|  | 
 | ||
|  |   public: | ||
|  |     explicit iteration_proxy() = default; | ||
|  | 
 | ||
|  |     /// construct iteration proxy from a container
 | ||
|  |     explicit iteration_proxy(typename IteratorType::reference cont) noexcept | ||
|  |         : container(&cont) {} | ||
|  | 
 | ||
|  |     iteration_proxy(iteration_proxy const&) = default; | ||
|  |     iteration_proxy& operator=(iteration_proxy const&) = default; | ||
|  |     iteration_proxy(iteration_proxy&&) noexcept = default; | ||
|  |     iteration_proxy& operator=(iteration_proxy&&) noexcept = default; | ||
|  |     ~iteration_proxy() = default; | ||
|  | 
 | ||
|  |     /// return iterator begin (needed for range-based for)
 | ||
|  |     iteration_proxy_value<IteratorType> begin() const noexcept | ||
|  |     { | ||
|  |         return iteration_proxy_value<IteratorType>(container->begin()); | ||
|  |     } | ||
|  | 
 | ||
|  |     /// return iterator end (needed for range-based for)
 | ||
|  |     iteration_proxy_value<IteratorType> end() const noexcept | ||
|  |     { | ||
|  |         return iteration_proxy_value<IteratorType>(container->end()); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | // Structured Bindings Support
 | ||
|  | // For further reference see https://blog.tartanllama.xyz/structured-bindings/
 | ||
|  | // And see https://github.com/nlohmann/json/pull/1391
 | ||
|  | template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0> | ||
|  | auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key()) | ||
|  | { | ||
|  |     return i.key(); | ||
|  | } | ||
|  | // Structured Bindings Support
 | ||
|  | // For further reference see https://blog.tartanllama.xyz/structured-bindings/
 | ||
|  | // And see https://github.com/nlohmann/json/pull/1391
 | ||
|  | template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0> | ||
|  | auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value()) | ||
|  | { | ||
|  |     return i.value(); | ||
|  | } | ||
|  | 
 | ||
|  | }  // namespace detail
 | ||
|  | NLOHMANN_JSON_NAMESPACE_END | ||
|  | 
 | ||
|  | // The Addition to the STD Namespace is required to add
 | ||
|  | // Structured Bindings Support to the iteration_proxy_value class
 | ||
|  | // For further reference see https://blog.tartanllama.xyz/structured-bindings/
 | ||
|  | // And see https://github.com/nlohmann/json/pull/1391
 | ||
|  | namespace std | ||
|  | { | ||
|  | 
 | ||
|  | #if defined(__clang__)
 | ||
|  |     // Fix: https://github.com/nlohmann/json/issues/1401
 | ||
|  |     #pragma clang diagnostic push
 | ||
|  |     #pragma clang diagnostic ignored "-Wmismatched-tags"
 | ||
|  | #endif
 | ||
|  | template<typename IteratorType> | ||
|  | class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
 | ||
|  |             : public std::integral_constant<std::size_t, 2> {}; | ||
|  | 
 | ||
|  | template<std::size_t N, typename IteratorType> | ||
|  | class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
 | ||
|  | { | ||
|  |   public: | ||
|  |     using type = decltype( | ||
|  |                      get<N>(std::declval < | ||
|  |                             ::nlohmann::detail::iteration_proxy_value<IteratorType >> ())); | ||
|  | }; | ||
|  | #if defined(__clang__)
 | ||
|  |     #pragma clang diagnostic pop
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | }  // namespace std
 | ||
|  | 
 | ||
|  | #if JSON_HAS_RANGES
 | ||
|  |     template <typename IteratorType> | ||
|  |     inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true; | ||
|  | #endif
 |