File indexing completed on 2026-05-08 08:44:51
0001
0002
0003
0004
0005
0006
0007
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
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
0036 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
0037
0038
0039
0040
0041
0042 #ifndef JSON_NO_IO
0043
0044
0045
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
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
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
0080 std::FILE* m_file;
0081 };
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 class input_stream_adapter
0093 {
0094 public:
0095 using char_type = char;
0096
0097 ~input_stream_adapter()
0098 {
0099
0100
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
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
0124
0125
0126 std::char_traits<char>::int_type get_character()
0127 {
0128 auto res = sb->sbumpc();
0129
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
0150 std::istream* is = nullptr;
0151 std::streambuf* sb = nullptr;
0152 };
0153 #endif
0154
0155
0156
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
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
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
0234 const auto wc = input.get_character();
0235
0236
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
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
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
0292 const auto wc = input.get_character();
0293
0294
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
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
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
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
0363 template<class T>
0364 std::size_t get_elements(T* , std::size_t = 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
0379 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
0380
0381
0382 std::size_t utf8_bytes_index = 0;
0383
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
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
0433
0434
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 }
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
0466 using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
0467
0468 #ifndef JSON_NO_IO
0469
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
0489
0490 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
0491
0492
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);
0509 }
0510
0511 template<typename T, std::size_t N>
0512 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N))
0513 {
0514 return input_adapter(array, array + N);
0515 }
0516
0517
0518
0519
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);
0542 }
0543
0544 private:
0545 contiguous_bytes_input_adapter ia;
0546 };
0547
0548 }
0549 NLOHMANN_JSON_NAMESPACE_END