Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:03:21

0001 //     __ _____ _____ _____
0002 //  __|  |   __|     |   | |  JSON for Modern C++
0003 // |  |  |__   |  |  | | | |  version 3.11.3
0004 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
0005 //
0006 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
0007 // SPDX-License-Identifier: MIT
0008 
0009 #pragma once
0010 
0011 #include <array> // array
0012 #include <cstddef> // size_t
0013 #include <cstring> // strlen
0014 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
0015 #include <memory> // shared_ptr, make_shared, addressof
0016 #include <numeric> // accumulate
0017 #include <string> // string, char_traits
0018 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
0019 #include <utility> // pair, declval
0020 
0021 #ifndef JSON_NO_IO
0022     #include <cstdio>   // FILE *
0023     #include <istream>  // istream
0024 #endif                  // JSON_NO_IO
0025 
0026 #include <nlohmann/detail/iterators/iterator_traits.hpp>
0027 #include <nlohmann/detail/macro_scope.hpp>
0028 #include <nlohmann/detail/meta/type_traits.hpp>
0029 
0030 NLOHMANN_JSON_NAMESPACE_BEGIN
0031 namespace detail
0032 {
0033 
0034 /// the supported input formats
0035 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
0036 
0037 ////////////////////
0038 // input adapters //
0039 ////////////////////
0040 
0041 #ifndef JSON_NO_IO
0042 /*!
0043 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
0044  buffer. This adapter is a very low level adapter.
0045 */
0046 class file_input_adapter
0047 {
0048   public:
0049     using char_type = char;
0050 
0051     JSON_HEDLEY_NON_NULL(2)
0052     explicit file_input_adapter(std::FILE* f) noexcept
0053         : m_file(f)
0054     {
0055         JSON_ASSERT(m_file != nullptr);
0056     }
0057 
0058     // make class move-only
0059     file_input_adapter(const file_input_adapter&) = delete;
0060     file_input_adapter(file_input_adapter&&) noexcept = default;
0061     file_input_adapter& operator=(const file_input_adapter&) = delete;
0062     file_input_adapter& operator=(file_input_adapter&&) = delete;
0063     ~file_input_adapter() = default;
0064 
0065     std::char_traits<char>::int_type get_character() noexcept
0066     {
0067         return std::fgetc(m_file);
0068     }
0069 
0070   private:
0071     /// the file pointer to read from
0072     std::FILE* m_file;
0073 };
0074 
0075 /*!
0076 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
0077 beginning of input. Does not support changing the underlying std::streambuf
0078 in mid-input. Maintains underlying std::istream and std::streambuf to support
0079 subsequent use of standard std::istream operations to process any input
0080 characters following those used in parsing the JSON input.  Clears the
0081 std::istream flags; any input errors (e.g., EOF) will be detected by the first
0082 subsequent call for input from the std::istream.
0083 */
0084 class input_stream_adapter
0085 {
0086   public:
0087     using char_type = char;
0088 
0089     ~input_stream_adapter()
0090     {
0091         // clear stream flags; we use underlying streambuf I/O, do not
0092         // maintain ifstream flags, except eof
0093         if (is != nullptr)
0094         {
0095             is->clear(is->rdstate() & std::ios::eofbit);
0096         }
0097     }
0098 
0099     explicit input_stream_adapter(std::istream& i)
0100         : is(&i), sb(i.rdbuf())
0101     {}
0102 
0103     // delete because of pointer members
0104     input_stream_adapter(const input_stream_adapter&) = delete;
0105     input_stream_adapter& operator=(input_stream_adapter&) = delete;
0106     input_stream_adapter& operator=(input_stream_adapter&&) = delete;
0107 
0108     input_stream_adapter(input_stream_adapter&& rhs) noexcept
0109         : is(rhs.is), sb(rhs.sb)
0110     {
0111         rhs.is = nullptr;
0112         rhs.sb = nullptr;
0113     }
0114 
0115     // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
0116     // ensure that std::char_traits<char>::eof() and the character 0xFF do not
0117     // end up as the same value, e.g. 0xFFFFFFFF.
0118     std::char_traits<char>::int_type get_character()
0119     {
0120         auto res = sb->sbumpc();
0121         // set eof manually, as we don't use the istream interface.
0122         if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
0123         {
0124             is->clear(is->rdstate() | std::ios::eofbit);
0125         }
0126         return res;
0127     }
0128 
0129   private:
0130     /// the associated input stream
0131     std::istream* is = nullptr;
0132     std::streambuf* sb = nullptr;
0133 };
0134 #endif  // JSON_NO_IO
0135 
0136 // General-purpose iterator-based adapter. It might not be as fast as
0137 // theoretically possible for some containers, but it is extremely versatile.
0138 template<typename IteratorType>
0139 class iterator_input_adapter
0140 {
0141   public:
0142     using char_type = typename std::iterator_traits<IteratorType>::value_type;
0143 
0144     iterator_input_adapter(IteratorType first, IteratorType last)
0145         : current(std::move(first)), end(std::move(last))
0146     {}
0147 
0148     typename char_traits<char_type>::int_type get_character()
0149     {
0150         if (JSON_HEDLEY_LIKELY(current != end))
0151         {
0152             auto result = char_traits<char_type>::to_int_type(*current);
0153             std::advance(current, 1);
0154             return result;
0155         }
0156 
0157         return char_traits<char_type>::eof();
0158     }
0159 
0160   private:
0161     IteratorType current;
0162     IteratorType end;
0163 
0164     template<typename BaseInputAdapter, size_t T>
0165     friend struct wide_string_input_helper;
0166 
0167     bool empty() const
0168     {
0169         return current == end;
0170     }
0171 };
0172 
0173 template<typename BaseInputAdapter, size_t T>
0174 struct wide_string_input_helper;
0175 
0176 template<typename BaseInputAdapter>
0177 struct wide_string_input_helper<BaseInputAdapter, 4>
0178 {
0179     // UTF-32
0180     static void fill_buffer(BaseInputAdapter& input,
0181                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
0182                             size_t& utf8_bytes_index,
0183                             size_t& utf8_bytes_filled)
0184     {
0185         utf8_bytes_index = 0;
0186 
0187         if (JSON_HEDLEY_UNLIKELY(input.empty()))
0188         {
0189             utf8_bytes[0] = std::char_traits<char>::eof();
0190             utf8_bytes_filled = 1;
0191         }
0192         else
0193         {
0194             // get the current character
0195             const auto wc = input.get_character();
0196 
0197             // UTF-32 to UTF-8 encoding
0198             if (wc < 0x80)
0199             {
0200                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
0201                 utf8_bytes_filled = 1;
0202             }
0203             else if (wc <= 0x7FF)
0204             {
0205                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
0206                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
0207                 utf8_bytes_filled = 2;
0208             }
0209             else if (wc <= 0xFFFF)
0210             {
0211                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
0212                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
0213                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
0214                 utf8_bytes_filled = 3;
0215             }
0216             else if (wc <= 0x10FFFF)
0217             {
0218                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
0219                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
0220                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
0221                 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
0222                 utf8_bytes_filled = 4;
0223             }
0224             else
0225             {
0226                 // unknown character
0227                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
0228                 utf8_bytes_filled = 1;
0229             }
0230         }
0231     }
0232 };
0233 
0234 template<typename BaseInputAdapter>
0235 struct wide_string_input_helper<BaseInputAdapter, 2>
0236 {
0237     // UTF-16
0238     static void fill_buffer(BaseInputAdapter& input,
0239                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
0240                             size_t& utf8_bytes_index,
0241                             size_t& utf8_bytes_filled)
0242     {
0243         utf8_bytes_index = 0;
0244 
0245         if (JSON_HEDLEY_UNLIKELY(input.empty()))
0246         {
0247             utf8_bytes[0] = std::char_traits<char>::eof();
0248             utf8_bytes_filled = 1;
0249         }
0250         else
0251         {
0252             // get the current character
0253             const auto wc = input.get_character();
0254 
0255             // UTF-16 to UTF-8 encoding
0256             if (wc < 0x80)
0257             {
0258                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
0259                 utf8_bytes_filled = 1;
0260             }
0261             else if (wc <= 0x7FF)
0262             {
0263                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
0264                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
0265                 utf8_bytes_filled = 2;
0266             }
0267             else if (0xD800 > wc || wc >= 0xE000)
0268             {
0269                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
0270                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
0271                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
0272                 utf8_bytes_filled = 3;
0273             }
0274             else
0275             {
0276                 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
0277                 {
0278                     const auto wc2 = static_cast<unsigned int>(input.get_character());
0279                     const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
0280                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
0281                     utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
0282                     utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
0283                     utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
0284                     utf8_bytes_filled = 4;
0285                 }
0286                 else
0287                 {
0288                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
0289                     utf8_bytes_filled = 1;
0290                 }
0291             }
0292         }
0293     }
0294 };
0295 
0296 // Wraps another input adapter to convert wide character types into individual bytes.
0297 template<typename BaseInputAdapter, typename WideCharType>
0298 class wide_string_input_adapter
0299 {
0300   public:
0301     using char_type = char;
0302 
0303     wide_string_input_adapter(BaseInputAdapter base)
0304         : base_adapter(base) {}
0305 
0306     typename std::char_traits<char>::int_type get_character() noexcept
0307     {
0308         // check if buffer needs to be filled
0309         if (utf8_bytes_index == utf8_bytes_filled)
0310         {
0311             fill_buffer<sizeof(WideCharType)>();
0312 
0313             JSON_ASSERT(utf8_bytes_filled > 0);
0314             JSON_ASSERT(utf8_bytes_index == 0);
0315         }
0316 
0317         // use buffer
0318         JSON_ASSERT(utf8_bytes_filled > 0);
0319         JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
0320         return utf8_bytes[utf8_bytes_index++];
0321     }
0322 
0323   private:
0324     BaseInputAdapter base_adapter;
0325 
0326     template<size_t T>
0327     void fill_buffer()
0328     {
0329         wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
0330     }
0331 
0332     /// a buffer for UTF-8 bytes
0333     std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
0334 
0335     /// index to the utf8_codes array for the next valid byte
0336     std::size_t utf8_bytes_index = 0;
0337     /// number of valid bytes in the utf8_codes array
0338     std::size_t utf8_bytes_filled = 0;
0339 };
0340 
0341 template<typename IteratorType, typename Enable = void>
0342 struct iterator_input_adapter_factory
0343 {
0344     using iterator_type = IteratorType;
0345     using char_type = typename std::iterator_traits<iterator_type>::value_type;
0346     using adapter_type = iterator_input_adapter<iterator_type>;
0347 
0348     static adapter_type create(IteratorType first, IteratorType last)
0349     {
0350         return adapter_type(std::move(first), std::move(last));
0351     }
0352 };
0353 
0354 template<typename T>
0355 struct is_iterator_of_multibyte
0356 {
0357     using value_type = typename std::iterator_traits<T>::value_type;
0358     enum
0359     {
0360         value = sizeof(value_type) > 1
0361     };
0362 };
0363 
0364 template<typename IteratorType>
0365 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
0366 {
0367     using iterator_type = IteratorType;
0368     using char_type = typename std::iterator_traits<iterator_type>::value_type;
0369     using base_adapter_type = iterator_input_adapter<iterator_type>;
0370     using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
0371 
0372     static adapter_type create(IteratorType first, IteratorType last)
0373     {
0374         return adapter_type(base_adapter_type(std::move(first), std::move(last)));
0375     }
0376 };
0377 
0378 // General purpose iterator-based input
0379 template<typename IteratorType>
0380 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
0381 {
0382     using factory_type = iterator_input_adapter_factory<IteratorType>;
0383     return factory_type::create(first, last);
0384 }
0385 
0386 // Convenience shorthand from container to iterator
0387 // Enables ADL on begin(container) and end(container)
0388 // Encloses the using declarations in namespace for not to leak them to outside scope
0389 
0390 namespace container_input_adapter_factory_impl
0391 {
0392 
0393 using std::begin;
0394 using std::end;
0395 
0396 template<typename ContainerType, typename Enable = void>
0397 struct container_input_adapter_factory {};
0398 
0399 template<typename ContainerType>
0400 struct container_input_adapter_factory< ContainerType,
0401        void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
0402        {
0403            using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
0404 
0405            static adapter_type create(const ContainerType& container)
0406 {
0407     return input_adapter(begin(container), end(container));
0408 }
0409        };
0410 
0411 }  // namespace container_input_adapter_factory_impl
0412 
0413 template<typename ContainerType>
0414 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
0415 {
0416     return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
0417 }
0418 
0419 #ifndef JSON_NO_IO
0420 // Special cases with fast paths
0421 inline file_input_adapter input_adapter(std::FILE* file)
0422 {
0423     return file_input_adapter(file);
0424 }
0425 
0426 inline input_stream_adapter input_adapter(std::istream& stream)
0427 {
0428     return input_stream_adapter(stream);
0429 }
0430 
0431 inline input_stream_adapter input_adapter(std::istream&& stream)
0432 {
0433     return input_stream_adapter(stream);
0434 }
0435 #endif  // JSON_NO_IO
0436 
0437 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
0438 
0439 // Null-delimited strings, and the like.
0440 template < typename CharT,
0441            typename std::enable_if <
0442                std::is_pointer<CharT>::value&&
0443                !std::is_array<CharT>::value&&
0444                std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
0445                sizeof(typename std::remove_pointer<CharT>::type) == 1,
0446                int >::type = 0 >
0447 contiguous_bytes_input_adapter input_adapter(CharT b)
0448 {
0449     auto length = std::strlen(reinterpret_cast<const char*>(b));
0450     const auto* ptr = reinterpret_cast<const char*>(b);
0451     return input_adapter(ptr, ptr + length);
0452 }
0453 
0454 template<typename T, std::size_t N>
0455 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)
0456 {
0457     return input_adapter(array, array + N);
0458 }
0459 
0460 // This class only handles inputs of input_buffer_adapter type.
0461 // It's required so that expressions like {ptr, len} can be implicitly cast
0462 // to the correct adapter.
0463 class span_input_adapter
0464 {
0465   public:
0466     template < typename CharT,
0467                typename std::enable_if <
0468                    std::is_pointer<CharT>::value&&
0469                    std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
0470                    sizeof(typename std::remove_pointer<CharT>::type) == 1,
0471                    int >::type = 0 >
0472     span_input_adapter(CharT b, std::size_t l)
0473         : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
0474 
0475     template<class IteratorType,
0476              typename std::enable_if<
0477                  std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
0478                  int>::type = 0>
0479     span_input_adapter(IteratorType first, IteratorType last)
0480         : ia(input_adapter(first, last)) {}
0481 
0482     contiguous_bytes_input_adapter&& get()
0483     {
0484         return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
0485     }
0486 
0487   private:
0488     contiguous_bytes_input_adapter ia;
0489 };
0490 
0491 }  // namespace detail
0492 NLOHMANN_JSON_NAMESPACE_END