Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-08 08:44:51

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