File indexing completed on 2025-09-17 09:03:21
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/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
0035 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
0036
0037
0038
0039
0040
0041 #ifndef JSON_NO_IO
0042
0043
0044
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
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
0072 std::FILE* m_file;
0073 };
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 class input_stream_adapter
0085 {
0086 public:
0087 using char_type = char;
0088
0089 ~input_stream_adapter()
0090 {
0091
0092
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
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
0116
0117
0118 std::char_traits<char>::int_type get_character()
0119 {
0120 auto res = sb->sbumpc();
0121
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
0131 std::istream* is = nullptr;
0132 std::streambuf* sb = nullptr;
0133 };
0134 #endif
0135
0136
0137
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
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
0195 const auto wc = input.get_character();
0196
0197
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
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
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
0253 const auto wc = input.get_character();
0254
0255
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
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
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
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
0333 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
0334
0335
0336 std::size_t utf8_bytes_index = 0;
0337
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
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
0387
0388
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 }
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
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
0436
0437 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
0438
0439
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))
0456 {
0457 return input_adapter(array, array + N);
0458 }
0459
0460
0461
0462
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);
0485 }
0486
0487 private:
0488 contiguous_bytes_input_adapter ia;
0489 };
0490
0491 }
0492 NLOHMANN_JSON_NAMESPACE_END