RflySimSDK v4.10
RflySimSDK说明文档
载入中...
搜索中...
未找到
input_adapters.hpp
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.12.0
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9#pragma once
10
11#include <array> // array
12#include <cstddef> // size_t
13#include <cstring> // strlen
14#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
15#include <memory> // shared_ptr, make_shared, addressof
16#include <numeric> // accumulate
17#include <streambuf> // streambuf
18#include <string> // string, char_traits
19#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
20#include <utility> // pair, declval
21
22#ifndef JSON_NO_IO
23 #include <cstdio> // FILE *
24 #include <istream> // istream
25#endif // JSON_NO_IO
26
27#include <nlohmann/detail/exceptions.hpp>
28#include <nlohmann/detail/iterators/iterator_traits.hpp>
29#include <nlohmann/detail/macro_scope.hpp>
30#include <nlohmann/detail/meta/type_traits.hpp>
31
32NLOHMANN_JSON_NAMESPACE_BEGIN
33namespace detail
34{
35
36/// the supported input formats
37enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
38
39////////////////////
40// input adapters //
41////////////////////
42
43#ifndef JSON_NO_IO
44/*!
45Input adapter for stdio file access. This adapter read only 1 byte and do not use any
46 buffer. This adapter is a very low level adapter.
47*/
48class file_input_adapter
49{
50 public:
51 using char_type = char;
52
53 JSON_HEDLEY_NON_NULL(2)
54 explicit file_input_adapter(std::FILE* f) noexcept
55 : m_file(f)
56 {
57 JSON_ASSERT(m_file != nullptr);
58 }
59
60 // make class move-only
61 file_input_adapter(const file_input_adapter&) = delete;
62 file_input_adapter(file_input_adapter&&) noexcept = default;
63 file_input_adapter& operator=(const file_input_adapter&) = delete;
64 file_input_adapter& operator=(file_input_adapter&&) = delete;
65 ~file_input_adapter() = default;
66
67 std::char_traits<char>::int_type get_character() noexcept
68 {
69 return std::fgetc(m_file);
70 }
71
72 // returns the number of characters successfully read
73 template<class T>
74 std::size_t get_elements(T* dest, std::size_t count = 1)
75 {
76 return fread(dest, 1, sizeof(T) * count, m_file);
77 }
78
79 private:
80 /// the file pointer to read from
81 std::FILE* m_file;
82};
83
84/*!
85Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
86beginning of input. Does not support changing the underlying std::streambuf
87in mid-input. Maintains underlying std::istream and std::streambuf to support
88subsequent use of standard std::istream operations to process any input
89characters following those used in parsing the JSON input. Clears the
90std::istream flags; any input errors (e.g., EOF) will be detected by the first
91subsequent call for input from the std::istream.
92*/
93class input_stream_adapter
94{
95 public:
96 using char_type = char;
97
98 ~input_stream_adapter()
99 {
100 // clear stream flags; we use underlying streambuf I/O, do not
101 // maintain ifstream flags, except eof
102 if (is != nullptr)
103 {
104 is->clear(is->rdstate() & std::ios::eofbit);
105 }
106 }
107
108 explicit input_stream_adapter(std::istream& i)
109 : is(&i), sb(i.rdbuf())
110 {}
111
112 // deleted because of pointer members
113 input_stream_adapter(const input_stream_adapter&) = delete;
114 input_stream_adapter& operator=(input_stream_adapter&) = delete;
115 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
116
117 input_stream_adapter(input_stream_adapter&& rhs) noexcept
118 : is(rhs.is), sb(rhs.sb)
119 {
120 rhs.is = nullptr;
121 rhs.sb = nullptr;
122 }
123
124 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
125 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
126 // end up as the same value, e.g., 0xFFFFFFFF.
127 std::char_traits<char>::int_type get_character()
128 {
129 auto res = sb->sbumpc();
130 // set eof manually, as we don't use the istream interface.
131 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
132 {
133 is->clear(is->rdstate() | std::ios::eofbit);
134 }
135 return res;
136 }
137
138 template<class T>
139 std::size_t get_elements(T* dest, std::size_t count = 1)
140 {
141 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
142 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
143 {
144 is->clear(is->rdstate() | std::ios::eofbit);
145 }
146 return res;
147 }
148
149 private:
150 /// the associated input stream
151 std::istream* is = nullptr;
152 std::streambuf* sb = nullptr;
153};
154#endif // JSON_NO_IO
155
156// General-purpose iterator-based adapter. It might not be as fast as
157// theoretically possible for some containers, but it is extremely versatile.
158template<typename IteratorType>
159class iterator_input_adapter
160{
161 public:
162 using char_type = typename std::iterator_traits<IteratorType>::value_type;
163
164 iterator_input_adapter(IteratorType first, IteratorType last)
165 : current(std::move(first)), end(std::move(last))
166 {}
167
168 typename char_traits<char_type>::int_type get_character()
169 {
170 if (JSON_HEDLEY_LIKELY(current != end))
171 {
172 auto result = char_traits<char_type>::to_int_type(*current);
173 std::advance(current, 1);
174 return result;
175 }
176
178 }
179
180 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
181 template<class T>
182 std::size_t get_elements(T* dest, std::size_t count = 1)
183 {
184 auto* ptr = reinterpret_cast<char*>(dest);
185 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
186 {
187 if (JSON_HEDLEY_LIKELY(current != end))
188 {
189 ptr[read_index] = static_cast<char>(*current);
190 std::advance(current, 1);
191 }
192 else
193 {
194 return read_index;
195 }
196 }
197 return count * sizeof(T);
198 }
199
200 private:
201 IteratorType current;
202 IteratorType end;
203
204 template<typename BaseInputAdapter, size_t T>
205 friend struct wide_string_input_helper;
206
207 bool empty() const
208 {
209 return current == end;
210 }
211};
212
213template<typename BaseInputAdapter, size_t T>
215
216template<typename BaseInputAdapter>
217struct wide_string_input_helper<BaseInputAdapter, 4>
218{
219 // UTF-32
220 static void fill_buffer(BaseInputAdapter& input,
221 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
222 size_t& utf8_bytes_index,
223 size_t& utf8_bytes_filled)
224 {
225 utf8_bytes_index = 0;
226
227 if (JSON_HEDLEY_UNLIKELY(input.empty()))
228 {
229 utf8_bytes[0] = std::char_traits<char>::eof();
230 utf8_bytes_filled = 1;
231 }
232 else
233 {
234 // get the current character
235 const auto wc = input.get_character();
236
237 // UTF-32 to UTF-8 encoding
238 if (wc < 0x80)
239 {
240 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
241 utf8_bytes_filled = 1;
242 }
243 else if (wc <= 0x7FF)
244 {
245 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
246 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
247 utf8_bytes_filled = 2;
248 }
249 else if (wc <= 0xFFFF)
250 {
251 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
252 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
253 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
254 utf8_bytes_filled = 3;
255 }
256 else if (wc <= 0x10FFFF)
257 {
258 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
259 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
260 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
261 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
262 utf8_bytes_filled = 4;
263 }
264 else
265 {
266 // unknown character
267 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
268 utf8_bytes_filled = 1;
269 }
270 }
271 }
272};
273
274template<typename BaseInputAdapter>
275struct wide_string_input_helper<BaseInputAdapter, 2>
276{
277 // UTF-16
278 static void fill_buffer(BaseInputAdapter& input,
279 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
280 size_t& utf8_bytes_index,
281 size_t& utf8_bytes_filled)
282 {
283 utf8_bytes_index = 0;
284
285 if (JSON_HEDLEY_UNLIKELY(input.empty()))
286 {
287 utf8_bytes[0] = std::char_traits<char>::eof();
288 utf8_bytes_filled = 1;
289 }
290 else
291 {
292 // get the current character
293 const auto wc = input.get_character();
294
295 // UTF-16 to UTF-8 encoding
296 if (wc < 0x80)
297 {
298 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
299 utf8_bytes_filled = 1;
300 }
301 else if (wc <= 0x7FF)
302 {
303 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
304 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
305 utf8_bytes_filled = 2;
306 }
307 else if (0xD800 > wc || wc >= 0xE000)
308 {
309 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
310 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
311 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
312 utf8_bytes_filled = 3;
313 }
314 else
315 {
316 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
317 {
318 const auto wc2 = static_cast<unsigned int>(input.get_character());
319 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
320 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
321 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
322 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
323 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
324 utf8_bytes_filled = 4;
325 }
326 else
327 {
328 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
329 utf8_bytes_filled = 1;
330 }
331 }
332 }
333 }
334};
335
336// Wraps another input adapter to convert wide character types into individual bytes.
337template<typename BaseInputAdapter, typename WideCharType>
338class wide_string_input_adapter
339{
340 public:
341 using char_type = char;
342
343 wide_string_input_adapter(BaseInputAdapter base)
344 : base_adapter(base) {}
345
346 typename std::char_traits<char>::int_type get_character() noexcept
347 {
348 // check if the buffer needs to be filled
349 if (utf8_bytes_index == utf8_bytes_filled)
350 {
351 fill_buffer<sizeof(WideCharType)>();
352
353 JSON_ASSERT(utf8_bytes_filled > 0);
354 JSON_ASSERT(utf8_bytes_index == 0);
355 }
356
357 // use buffer
358 JSON_ASSERT(utf8_bytes_filled > 0);
359 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
360 return utf8_bytes[utf8_bytes_index++];
361 }
362
363 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
364 template<class T>
365 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
366 {
367 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
368 }
369
370 private:
371 BaseInputAdapter base_adapter;
372
373 template<size_t T>
374 void fill_buffer()
375 {
376 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
377 }
378
379 /// a buffer for UTF-8 bytes
380 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
381
382 /// index to the utf8_codes array for the next valid byte
383 std::size_t utf8_bytes_index = 0;
384 /// number of valid bytes in the utf8_codes array
385 std::size_t utf8_bytes_filled = 0;
386};
387
388template<typename IteratorType, typename Enable = void>
390{
391 using iterator_type = IteratorType;
392 using char_type = typename std::iterator_traits<iterator_type>::value_type;
393 using adapter_type = iterator_input_adapter<iterator_type>;
394
395 static adapter_type create(IteratorType first, IteratorType last)
396 {
397 return adapter_type(std::move(first), std::move(last));
398 }
399};
400
401template<typename T>
403{
404 using value_type = typename std::iterator_traits<T>::value_type;
405 enum // NOLINT(cppcoreguidelines-use-enum-class)
406 {
407 value = sizeof(value_type) > 1
408 };
409};
410
411template<typename IteratorType>
412struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
413{
414 using iterator_type = IteratorType;
415 using char_type = typename std::iterator_traits<iterator_type>::value_type;
416 using base_adapter_type = iterator_input_adapter<iterator_type>;
418
419 static adapter_type create(IteratorType first, IteratorType last)
420 {
421 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
422 }
423};
424
425// General purpose iterator-based input
426template<typename IteratorType>
427typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
428{
430 return factory_type::create(first, last);
431}
432
433// Convenience shorthand from container to iterator
434// Enables ADL on begin(container) and end(container)
435// Encloses the using declarations in namespace for not to leak them to outside scope
436
437namespace container_input_adapter_factory_impl
438{
439
440using std::begin;
441using std::end;
442
443template<typename ContainerType, typename Enable = void>
445
446template<typename ContainerType>
448 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
449 {
450 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
451
452 static adapter_type create(const ContainerType& container)
453{
454 return input_adapter(begin(container), end(container));
455}
456 };
457
458} // namespace container_input_adapter_factory_impl
459
460template<typename ContainerType>
462{
464}
465
466// specialization for std::string
467using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
468
469#ifndef JSON_NO_IO
470// Special cases with fast paths
471inline file_input_adapter input_adapter(std::FILE* file)
472{
473 if (file == nullptr)
474 {
475 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));
476 }
477 return file_input_adapter(file);
478}
479
480inline input_stream_adapter input_adapter(std::istream& stream)
481{
482 return input_stream_adapter(stream);
483}
484
485inline input_stream_adapter input_adapter(std::istream&& stream)
486{
487 return input_stream_adapter(stream);
488}
489#endif // JSON_NO_IO
490
491using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
492
493// Null-delimited strings, and the like.
494template < typename CharT,
495 typename std::enable_if <
496 std::is_pointer<CharT>::value&&
497 !std::is_array<CharT>::value&&
498 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
499 sizeof(typename std::remove_pointer<CharT>::type) == 1,
500 int >::type = 0 >
501contiguous_bytes_input_adapter input_adapter(CharT b)
502{
503 if (b == nullptr)
504 {
505 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));
506 }
507 auto length = std::strlen(reinterpret_cast<const char*>(b));
508 const auto* ptr = reinterpret_cast<const char*>(b);
509 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
510}
511
512template<typename T, std::size_t N>
513auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
514{
515 return input_adapter(array, array + N);
516}
517
518// This class only handles inputs of input_buffer_adapter type.
519// It's required so that expressions like {ptr, len} can be implicitly cast
520// to the correct adapter.
521class span_input_adapter
522{
523 public:
524 template < typename CharT,
525 typename std::enable_if <
526 std::is_pointer<CharT>::value&&
527 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
528 sizeof(typename std::remove_pointer<CharT>::type) == 1,
529 int >::type = 0 >
530 span_input_adapter(CharT b, std::size_t l)
531 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
532
533 template<class IteratorType,
534 typename std::enable_if<
535 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
536 int>::type = 0>
537 span_input_adapter(IteratorType first, IteratorType last)
538 : ia(input_adapter(first, last)) {}
539
540 contiguous_bytes_input_adapter&& get()
541 {
542 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
543 }
544
545 private:
546 contiguous_bytes_input_adapter ia;
547};
548
549} // namespace detail
550NLOHMANN_JSON_NAMESPACE_END
定义 input_adapters.hpp:49
定义 input_adapters.hpp:94
定义 input_adapters.hpp:160
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
定义 exceptions.hpp:179
定义 input_adapters.hpp:339
detail namespace with internal helper functions
定义 from_json.hpp:43
@ array
array (ordered collection of values)
定义 value_t.hpp:57
input_format_t
the supported input formats
定义 input_adapters.hpp:37
定义 type_traits.hpp:194
定义 input_adapters.hpp:403
定义 input_adapters.hpp:390
定义 input_adapters.hpp:214