Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/nlohmann/detail/input/binary_reader.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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 <algorithm> // generate_n
0012 #include <array> // array
0013 #include <cmath> // ldexp
0014 #include <cstddef> // size_t
0015 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
0016 #include <cstdio> // snprintf
0017 #include <cstring> // memcpy
0018 #include <iterator> // back_inserter
0019 #include <limits> // numeric_limits
0020 #include <string> // char_traits, string
0021 #include <utility> // make_pair, move
0022 #include <vector> // vector
0023 
0024 #include <nlohmann/detail/exceptions.hpp>
0025 #include <nlohmann/detail/input/input_adapters.hpp>
0026 #include <nlohmann/detail/input/json_sax.hpp>
0027 #include <nlohmann/detail/input/lexer.hpp>
0028 #include <nlohmann/detail/macro_scope.hpp>
0029 #include <nlohmann/detail/meta/is_sax.hpp>
0030 #include <nlohmann/detail/meta/type_traits.hpp>
0031 #include <nlohmann/detail/string_concat.hpp>
0032 #include <nlohmann/detail/value_t.hpp>
0033 
0034 NLOHMANN_JSON_NAMESPACE_BEGIN
0035 namespace detail
0036 {
0037 
0038 /// how to treat CBOR tags
0039 enum class cbor_tag_handler_t
0040 {
0041     error,   ///< throw a parse_error exception in case of a tag
0042     ignore,  ///< ignore tags
0043     store    ///< store tags as binary type
0044 };
0045 
0046 /*!
0047 @brief determine system byte order
0048 
0049 @return true if and only if system's byte order is little endian
0050 
0051 @note from https://stackoverflow.com/a/1001328/266378
0052 */
0053 static inline bool little_endianness(int num = 1) noexcept
0054 {
0055     return *reinterpret_cast<char*>(&num) == 1;
0056 }
0057 
0058 ///////////////////
0059 // binary reader //
0060 ///////////////////
0061 
0062 /*!
0063 @brief deserialization of CBOR, MessagePack, and UBJSON values
0064 */
0065 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
0066 class binary_reader
0067 {
0068     using number_integer_t = typename BasicJsonType::number_integer_t;
0069     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
0070     using number_float_t = typename BasicJsonType::number_float_t;
0071     using string_t = typename BasicJsonType::string_t;
0072     using binary_t = typename BasicJsonType::binary_t;
0073     using json_sax_t = SAX;
0074     using char_type = typename InputAdapterType::char_type;
0075     using char_int_type = typename char_traits<char_type>::int_type;
0076 
0077   public:
0078     /*!
0079     @brief create a binary reader
0080 
0081     @param[in] adapter  input adapter to read from
0082     */
0083     explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
0084     {
0085         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
0086     }
0087 
0088     // make class move-only
0089     binary_reader(const binary_reader&) = delete;
0090     binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
0091     binary_reader& operator=(const binary_reader&) = delete;
0092     binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
0093     ~binary_reader() = default;
0094 
0095     /*!
0096     @param[in] format  the binary format to parse
0097     @param[in] sax_    a SAX event processor
0098     @param[in] strict  whether to expect the input to be consumed completed
0099     @param[in] tag_handler  how to treat CBOR tags
0100 
0101     @return whether parsing was successful
0102     */
0103     JSON_HEDLEY_NON_NULL(3)
0104     bool sax_parse(const input_format_t format,
0105                    json_sax_t* sax_,
0106                    const bool strict = true,
0107                    const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
0108     {
0109         sax = sax_;
0110         bool result = false;
0111 
0112         switch (format)
0113         {
0114             case input_format_t::bson:
0115                 result = parse_bson_internal();
0116                 break;
0117 
0118             case input_format_t::cbor:
0119                 result = parse_cbor_internal(true, tag_handler);
0120                 break;
0121 
0122             case input_format_t::msgpack:
0123                 result = parse_msgpack_internal();
0124                 break;
0125 
0126             case input_format_t::ubjson:
0127             case input_format_t::bjdata:
0128                 result = parse_ubjson_internal();
0129                 break;
0130 
0131             case input_format_t::json: // LCOV_EXCL_LINE
0132             default:            // LCOV_EXCL_LINE
0133                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
0134         }
0135 
0136         // strict mode: next byte must be EOF
0137         if (result && strict)
0138         {
0139             if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
0140             {
0141                 get_ignore_noop();
0142             }
0143             else
0144             {
0145                 get();
0146             }
0147 
0148             if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
0149             {
0150                 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
0151                                         exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
0152             }
0153         }
0154 
0155         return result;
0156     }
0157 
0158   private:
0159     //////////
0160     // BSON //
0161     //////////
0162 
0163     /*!
0164     @brief Reads in a BSON-object and passes it to the SAX-parser.
0165     @return whether a valid BSON-value was passed to the SAX parser
0166     */
0167     bool parse_bson_internal()
0168     {
0169         std::int32_t document_size{};
0170         get_number<std::int32_t, true>(input_format_t::bson, document_size);
0171 
0172         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
0173         {
0174             return false;
0175         }
0176 
0177         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
0178         {
0179             return false;
0180         }
0181 
0182         return sax->end_object();
0183     }
0184 
0185     /*!
0186     @brief Parses a C-style string from the BSON input.
0187     @param[in,out] result  A reference to the string variable where the read
0188                             string is to be stored.
0189     @return `true` if the \x00-byte indicating the end of the string was
0190              encountered before the EOF; false` indicates an unexpected EOF.
0191     */
0192     bool get_bson_cstr(string_t& result)
0193     {
0194         auto out = std::back_inserter(result);
0195         while (true)
0196         {
0197             get();
0198             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
0199             {
0200                 return false;
0201             }
0202             if (current == 0x00)
0203             {
0204                 return true;
0205             }
0206             *out++ = static_cast<typename string_t::value_type>(current);
0207         }
0208     }
0209 
0210     /*!
0211     @brief Parses a zero-terminated string of length @a len from the BSON
0212            input.
0213     @param[in] len  The length (including the zero-byte at the end) of the
0214                     string to be read.
0215     @param[in,out] result  A reference to the string variable where the read
0216                             string is to be stored.
0217     @tparam NumberType The type of the length @a len
0218     @pre len >= 1
0219     @return `true` if the string was successfully parsed
0220     */
0221     template<typename NumberType>
0222     bool get_bson_string(const NumberType len, string_t& result)
0223     {
0224         if (JSON_HEDLEY_UNLIKELY(len < 1))
0225         {
0226             auto last_token = get_token_string();
0227             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
0228                                     exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
0229         }
0230 
0231         return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
0232     }
0233 
0234     /*!
0235     @brief Parses a byte array input of length @a len from the BSON input.
0236     @param[in] len  The length of the byte array to be read.
0237     @param[in,out] result  A reference to the binary variable where the read
0238                             array is to be stored.
0239     @tparam NumberType The type of the length @a len
0240     @pre len >= 0
0241     @return `true` if the byte array was successfully parsed
0242     */
0243     template<typename NumberType>
0244     bool get_bson_binary(const NumberType len, binary_t& result)
0245     {
0246         if (JSON_HEDLEY_UNLIKELY(len < 0))
0247         {
0248             auto last_token = get_token_string();
0249             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
0250                                     exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
0251         }
0252 
0253         // All BSON binary values have a subtype
0254         std::uint8_t subtype{};
0255         get_number<std::uint8_t>(input_format_t::bson, subtype);
0256         result.set_subtype(subtype);
0257 
0258         return get_binary(input_format_t::bson, len, result);
0259     }
0260 
0261     /*!
0262     @brief Read a BSON document element of the given @a element_type.
0263     @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
0264     @param[in] element_type_parse_position The position in the input stream,
0265                where the `element_type` was read.
0266     @warning Not all BSON element types are supported yet. An unsupported
0267              @a element_type will give rise to a parse_error.114:
0268              Unsupported BSON record type 0x...
0269     @return whether a valid BSON-object/array was passed to the SAX parser
0270     */
0271     bool parse_bson_element_internal(const char_int_type element_type,
0272                                      const std::size_t element_type_parse_position)
0273     {
0274         switch (element_type)
0275         {
0276             case 0x01: // double
0277             {
0278                 double number{};
0279                 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
0280             }
0281 
0282             case 0x02: // string
0283             {
0284                 std::int32_t len{};
0285                 string_t value;
0286                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
0287             }
0288 
0289             case 0x03: // object
0290             {
0291                 return parse_bson_internal();
0292             }
0293 
0294             case 0x04: // array
0295             {
0296                 return parse_bson_array();
0297             }
0298 
0299             case 0x05: // binary
0300             {
0301                 std::int32_t len{};
0302                 binary_t value;
0303                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
0304             }
0305 
0306             case 0x08: // boolean
0307             {
0308                 return sax->boolean(get() != 0);
0309             }
0310 
0311             case 0x0A: // null
0312             {
0313                 return sax->null();
0314             }
0315 
0316             case 0x10: // int32
0317             {
0318                 std::int32_t value{};
0319                 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
0320             }
0321 
0322             case 0x12: // int64
0323             {
0324                 std::int64_t value{};
0325                 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
0326             }
0327 
0328             default: // anything else not supported (yet)
0329             {
0330                 std::array<char, 3> cr{{}};
0331                 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
0332                 const std::string cr_str{cr.data()};
0333                 return sax->parse_error(element_type_parse_position, cr_str,
0334                                         parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
0335             }
0336         }
0337     }
0338 
0339     /*!
0340     @brief Read a BSON element list (as specified in the BSON-spec)
0341 
0342     The same binary layout is used for objects and arrays, hence it must be
0343     indicated with the argument @a is_array which one is expected
0344     (true --> array, false --> object).
0345 
0346     @param[in] is_array Determines if the element list being read is to be
0347                         treated as an object (@a is_array == false), or as an
0348                         array (@a is_array == true).
0349     @return whether a valid BSON-object/array was passed to the SAX parser
0350     */
0351     bool parse_bson_element_list(const bool is_array)
0352     {
0353         string_t key;
0354 
0355         while (auto element_type = get())
0356         {
0357             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
0358             {
0359                 return false;
0360             }
0361 
0362             const std::size_t element_type_parse_position = chars_read;
0363             if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
0364             {
0365                 return false;
0366             }
0367 
0368             if (!is_array && !sax->key(key))
0369             {
0370                 return false;
0371             }
0372 
0373             if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
0374             {
0375                 return false;
0376             }
0377 
0378             // get_bson_cstr only appends
0379             key.clear();
0380         }
0381 
0382         return true;
0383     }
0384 
0385     /*!
0386     @brief Reads an array from the BSON input and passes it to the SAX-parser.
0387     @return whether a valid BSON-array was passed to the SAX parser
0388     */
0389     bool parse_bson_array()
0390     {
0391         std::int32_t document_size{};
0392         get_number<std::int32_t, true>(input_format_t::bson, document_size);
0393 
0394         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
0395         {
0396             return false;
0397         }
0398 
0399         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
0400         {
0401             return false;
0402         }
0403 
0404         return sax->end_array();
0405     }
0406 
0407     //////////
0408     // CBOR //
0409     //////////
0410 
0411     /*!
0412     @param[in] get_char  whether a new character should be retrieved from the
0413                          input (true) or whether the last read character should
0414                          be considered instead (false)
0415     @param[in] tag_handler how CBOR tags should be treated
0416 
0417     @return whether a valid CBOR value was passed to the SAX parser
0418     */
0419     bool parse_cbor_internal(const bool get_char,
0420                              const cbor_tag_handler_t tag_handler)
0421     {
0422         switch (get_char ? get() : current)
0423         {
0424             // EOF
0425             case char_traits<char_type>::eof():
0426                 return unexpect_eof(input_format_t::cbor, "value");
0427 
0428             // Integer 0x00..0x17 (0..23)
0429             case 0x00:
0430             case 0x01:
0431             case 0x02:
0432             case 0x03:
0433             case 0x04:
0434             case 0x05:
0435             case 0x06:
0436             case 0x07:
0437             case 0x08:
0438             case 0x09:
0439             case 0x0A:
0440             case 0x0B:
0441             case 0x0C:
0442             case 0x0D:
0443             case 0x0E:
0444             case 0x0F:
0445             case 0x10:
0446             case 0x11:
0447             case 0x12:
0448             case 0x13:
0449             case 0x14:
0450             case 0x15:
0451             case 0x16:
0452             case 0x17:
0453                 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
0454 
0455             case 0x18: // Unsigned integer (one-byte uint8_t follows)
0456             {
0457                 std::uint8_t number{};
0458                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
0459             }
0460 
0461             case 0x19: // Unsigned integer (two-byte uint16_t follows)
0462             {
0463                 std::uint16_t number{};
0464                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
0465             }
0466 
0467             case 0x1A: // Unsigned integer (four-byte uint32_t follows)
0468             {
0469                 std::uint32_t number{};
0470                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
0471             }
0472 
0473             case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
0474             {
0475                 std::uint64_t number{};
0476                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
0477             }
0478 
0479             // Negative integer -1-0x00..-1-0x17 (-1..-24)
0480             case 0x20:
0481             case 0x21:
0482             case 0x22:
0483             case 0x23:
0484             case 0x24:
0485             case 0x25:
0486             case 0x26:
0487             case 0x27:
0488             case 0x28:
0489             case 0x29:
0490             case 0x2A:
0491             case 0x2B:
0492             case 0x2C:
0493             case 0x2D:
0494             case 0x2E:
0495             case 0x2F:
0496             case 0x30:
0497             case 0x31:
0498             case 0x32:
0499             case 0x33:
0500             case 0x34:
0501             case 0x35:
0502             case 0x36:
0503             case 0x37:
0504                 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
0505 
0506             case 0x38: // Negative integer (one-byte uint8_t follows)
0507             {
0508                 std::uint8_t number{};
0509                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
0510             }
0511 
0512             case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
0513             {
0514                 std::uint16_t number{};
0515                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
0516             }
0517 
0518             case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
0519             {
0520                 std::uint32_t number{};
0521                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
0522             }
0523 
0524             case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
0525             {
0526                 std::uint64_t number{};
0527                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
0528                         - static_cast<number_integer_t>(number));
0529             }
0530 
0531             // Binary data (0x00..0x17 bytes follow)
0532             case 0x40:
0533             case 0x41:
0534             case 0x42:
0535             case 0x43:
0536             case 0x44:
0537             case 0x45:
0538             case 0x46:
0539             case 0x47:
0540             case 0x48:
0541             case 0x49:
0542             case 0x4A:
0543             case 0x4B:
0544             case 0x4C:
0545             case 0x4D:
0546             case 0x4E:
0547             case 0x4F:
0548             case 0x50:
0549             case 0x51:
0550             case 0x52:
0551             case 0x53:
0552             case 0x54:
0553             case 0x55:
0554             case 0x56:
0555             case 0x57:
0556             case 0x58: // Binary data (one-byte uint8_t for n follows)
0557             case 0x59: // Binary data (two-byte uint16_t for n follow)
0558             case 0x5A: // Binary data (four-byte uint32_t for n follow)
0559             case 0x5B: // Binary data (eight-byte uint64_t for n follow)
0560             case 0x5F: // Binary data (indefinite length)
0561             {
0562                 binary_t b;
0563                 return get_cbor_binary(b) && sax->binary(b);
0564             }
0565 
0566             // UTF-8 string (0x00..0x17 bytes follow)
0567             case 0x60:
0568             case 0x61:
0569             case 0x62:
0570             case 0x63:
0571             case 0x64:
0572             case 0x65:
0573             case 0x66:
0574             case 0x67:
0575             case 0x68:
0576             case 0x69:
0577             case 0x6A:
0578             case 0x6B:
0579             case 0x6C:
0580             case 0x6D:
0581             case 0x6E:
0582             case 0x6F:
0583             case 0x70:
0584             case 0x71:
0585             case 0x72:
0586             case 0x73:
0587             case 0x74:
0588             case 0x75:
0589             case 0x76:
0590             case 0x77:
0591             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
0592             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
0593             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
0594             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
0595             case 0x7F: // UTF-8 string (indefinite length)
0596             {
0597                 string_t s;
0598                 return get_cbor_string(s) && sax->string(s);
0599             }
0600 
0601             // array (0x00..0x17 data items follow)
0602             case 0x80:
0603             case 0x81:
0604             case 0x82:
0605             case 0x83:
0606             case 0x84:
0607             case 0x85:
0608             case 0x86:
0609             case 0x87:
0610             case 0x88:
0611             case 0x89:
0612             case 0x8A:
0613             case 0x8B:
0614             case 0x8C:
0615             case 0x8D:
0616             case 0x8E:
0617             case 0x8F:
0618             case 0x90:
0619             case 0x91:
0620             case 0x92:
0621             case 0x93:
0622             case 0x94:
0623             case 0x95:
0624             case 0x96:
0625             case 0x97:
0626                 return get_cbor_array(
0627                            conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
0628 
0629             case 0x98: // array (one-byte uint8_t for n follows)
0630             {
0631                 std::uint8_t len{};
0632                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
0633             }
0634 
0635             case 0x99: // array (two-byte uint16_t for n follow)
0636             {
0637                 std::uint16_t len{};
0638                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
0639             }
0640 
0641             case 0x9A: // array (four-byte uint32_t for n follow)
0642             {
0643                 std::uint32_t len{};
0644                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
0645             }
0646 
0647             case 0x9B: // array (eight-byte uint64_t for n follow)
0648             {
0649                 std::uint64_t len{};
0650                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
0651             }
0652 
0653             case 0x9F: // array (indefinite length)
0654                 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
0655 
0656             // map (0x00..0x17 pairs of data items follow)
0657             case 0xA0:
0658             case 0xA1:
0659             case 0xA2:
0660             case 0xA3:
0661             case 0xA4:
0662             case 0xA5:
0663             case 0xA6:
0664             case 0xA7:
0665             case 0xA8:
0666             case 0xA9:
0667             case 0xAA:
0668             case 0xAB:
0669             case 0xAC:
0670             case 0xAD:
0671             case 0xAE:
0672             case 0xAF:
0673             case 0xB0:
0674             case 0xB1:
0675             case 0xB2:
0676             case 0xB3:
0677             case 0xB4:
0678             case 0xB5:
0679             case 0xB6:
0680             case 0xB7:
0681                 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
0682 
0683             case 0xB8: // map (one-byte uint8_t for n follows)
0684             {
0685                 std::uint8_t len{};
0686                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
0687             }
0688 
0689             case 0xB9: // map (two-byte uint16_t for n follow)
0690             {
0691                 std::uint16_t len{};
0692                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
0693             }
0694 
0695             case 0xBA: // map (four-byte uint32_t for n follow)
0696             {
0697                 std::uint32_t len{};
0698                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
0699             }
0700 
0701             case 0xBB: // map (eight-byte uint64_t for n follow)
0702             {
0703                 std::uint64_t len{};
0704                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
0705             }
0706 
0707             case 0xBF: // map (indefinite length)
0708                 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
0709 
0710             case 0xC6: // tagged item
0711             case 0xC7:
0712             case 0xC8:
0713             case 0xC9:
0714             case 0xCA:
0715             case 0xCB:
0716             case 0xCC:
0717             case 0xCD:
0718             case 0xCE:
0719             case 0xCF:
0720             case 0xD0:
0721             case 0xD1:
0722             case 0xD2:
0723             case 0xD3:
0724             case 0xD4:
0725             case 0xD8: // tagged item (1 bytes follow)
0726             case 0xD9: // tagged item (2 bytes follow)
0727             case 0xDA: // tagged item (4 bytes follow)
0728             case 0xDB: // tagged item (8 bytes follow)
0729             {
0730                 switch (tag_handler)
0731                 {
0732                     case cbor_tag_handler_t::error:
0733                     {
0734                         auto last_token = get_token_string();
0735                         return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
0736                                                 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
0737                     }
0738 
0739                     case cbor_tag_handler_t::ignore:
0740                     {
0741                         // ignore binary subtype
0742                         switch (current)
0743                         {
0744                             case 0xD8:
0745                             {
0746                                 std::uint8_t subtype_to_ignore{};
0747                                 get_number(input_format_t::cbor, subtype_to_ignore);
0748                                 break;
0749                             }
0750                             case 0xD9:
0751                             {
0752                                 std::uint16_t subtype_to_ignore{};
0753                                 get_number(input_format_t::cbor, subtype_to_ignore);
0754                                 break;
0755                             }
0756                             case 0xDA:
0757                             {
0758                                 std::uint32_t subtype_to_ignore{};
0759                                 get_number(input_format_t::cbor, subtype_to_ignore);
0760                                 break;
0761                             }
0762                             case 0xDB:
0763                             {
0764                                 std::uint64_t subtype_to_ignore{};
0765                                 get_number(input_format_t::cbor, subtype_to_ignore);
0766                                 break;
0767                             }
0768                             default:
0769                                 break;
0770                         }
0771                         return parse_cbor_internal(true, tag_handler);
0772                     }
0773 
0774                     case cbor_tag_handler_t::store:
0775                     {
0776                         binary_t b;
0777                         // use binary subtype and store in binary container
0778                         switch (current)
0779                         {
0780                             case 0xD8:
0781                             {
0782                                 std::uint8_t subtype{};
0783                                 get_number(input_format_t::cbor, subtype);
0784                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
0785                                 break;
0786                             }
0787                             case 0xD9:
0788                             {
0789                                 std::uint16_t subtype{};
0790                                 get_number(input_format_t::cbor, subtype);
0791                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
0792                                 break;
0793                             }
0794                             case 0xDA:
0795                             {
0796                                 std::uint32_t subtype{};
0797                                 get_number(input_format_t::cbor, subtype);
0798                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
0799                                 break;
0800                             }
0801                             case 0xDB:
0802                             {
0803                                 std::uint64_t subtype{};
0804                                 get_number(input_format_t::cbor, subtype);
0805                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
0806                                 break;
0807                             }
0808                             default:
0809                                 return parse_cbor_internal(true, tag_handler);
0810                         }
0811                         get();
0812                         return get_cbor_binary(b) && sax->binary(b);
0813                     }
0814 
0815                     default:                 // LCOV_EXCL_LINE
0816                         JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
0817                         return false;        // LCOV_EXCL_LINE
0818                 }
0819             }
0820 
0821             case 0xF4: // false
0822                 return sax->boolean(false);
0823 
0824             case 0xF5: // true
0825                 return sax->boolean(true);
0826 
0827             case 0xF6: // null
0828                 return sax->null();
0829 
0830             case 0xF9: // Half-Precision Float (two-byte IEEE 754)
0831             {
0832                 const auto byte1_raw = get();
0833                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
0834                 {
0835                     return false;
0836                 }
0837                 const auto byte2_raw = get();
0838                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
0839                 {
0840                     return false;
0841                 }
0842 
0843                 const auto byte1 = static_cast<unsigned char>(byte1_raw);
0844                 const auto byte2 = static_cast<unsigned char>(byte2_raw);
0845 
0846                 // code from RFC 7049, Appendix D, Figure 3:
0847                 // As half-precision floating-point numbers were only added
0848                 // to IEEE 754 in 2008, today's programming platforms often
0849                 // still only have limited support for them. It is very
0850                 // easy to include at least decoding support for them even
0851                 // without such support. An example of a small decoder for
0852                 // half-precision floating-point numbers in the C language
0853                 // is shown in Fig. 3.
0854                 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
0855                 const double val = [&half]
0856                 {
0857                     const int exp = (half >> 10u) & 0x1Fu;
0858                     const unsigned int mant = half & 0x3FFu;
0859                     JSON_ASSERT(0 <= exp&& exp <= 32);
0860                     JSON_ASSERT(mant <= 1024);
0861                     switch (exp)
0862                     {
0863                         case 0:
0864                             return std::ldexp(mant, -24);
0865                         case 31:
0866                             return (mant == 0)
0867                             ? std::numeric_limits<double>::infinity()
0868                             : std::numeric_limits<double>::quiet_NaN();
0869                         default:
0870                             return std::ldexp(mant + 1024, exp - 25);
0871                     }
0872                 }();
0873                 return sax->number_float((half & 0x8000u) != 0
0874                                          ? static_cast<number_float_t>(-val)
0875                                          : static_cast<number_float_t>(val), "");
0876             }
0877 
0878             case 0xFA: // Single-Precision Float (four-byte IEEE 754)
0879             {
0880                 float number{};
0881                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
0882             }
0883 
0884             case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
0885             {
0886                 double number{};
0887                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
0888             }
0889 
0890             default: // anything else (0xFF is handled inside the other types)
0891             {
0892                 auto last_token = get_token_string();
0893                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
0894                                         exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
0895             }
0896         }
0897     }
0898 
0899     /*!
0900     @brief reads a CBOR string
0901 
0902     This function first reads starting bytes to determine the expected
0903     string length and then copies this number of bytes into a string.
0904     Additionally, CBOR's strings with indefinite lengths are supported.
0905 
0906     @param[out] result  created string
0907 
0908     @return whether string creation completed
0909     */
0910     bool get_cbor_string(string_t& result)
0911     {
0912         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
0913         {
0914             return false;
0915         }
0916 
0917         switch (current)
0918         {
0919             // UTF-8 string (0x00..0x17 bytes follow)
0920             case 0x60:
0921             case 0x61:
0922             case 0x62:
0923             case 0x63:
0924             case 0x64:
0925             case 0x65:
0926             case 0x66:
0927             case 0x67:
0928             case 0x68:
0929             case 0x69:
0930             case 0x6A:
0931             case 0x6B:
0932             case 0x6C:
0933             case 0x6D:
0934             case 0x6E:
0935             case 0x6F:
0936             case 0x70:
0937             case 0x71:
0938             case 0x72:
0939             case 0x73:
0940             case 0x74:
0941             case 0x75:
0942             case 0x76:
0943             case 0x77:
0944             {
0945                 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
0946             }
0947 
0948             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
0949             {
0950                 std::uint8_t len{};
0951                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
0952             }
0953 
0954             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
0955             {
0956                 std::uint16_t len{};
0957                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
0958             }
0959 
0960             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
0961             {
0962                 std::uint32_t len{};
0963                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
0964             }
0965 
0966             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
0967             {
0968                 std::uint64_t len{};
0969                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
0970             }
0971 
0972             case 0x7F: // UTF-8 string (indefinite length)
0973             {
0974                 while (get() != 0xFF)
0975                 {
0976                     string_t chunk;
0977                     if (!get_cbor_string(chunk))
0978                     {
0979                         return false;
0980                     }
0981                     result.append(chunk);
0982                 }
0983                 return true;
0984             }
0985 
0986             default:
0987             {
0988                 auto last_token = get_token_string();
0989                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
0990                                         exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
0991             }
0992         }
0993     }
0994 
0995     /*!
0996     @brief reads a CBOR byte array
0997 
0998     This function first reads starting bytes to determine the expected
0999     byte array length and then copies this number of bytes into the byte array.
1000     Additionally, CBOR's byte arrays with indefinite lengths are supported.
1001 
1002     @param[out] result  created byte array
1003 
1004     @return whether byte array creation completed
1005     */
1006     bool get_cbor_binary(binary_t& result)
1007     {
1008         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
1009         {
1010             return false;
1011         }
1012 
1013         switch (current)
1014         {
1015             // Binary data (0x00..0x17 bytes follow)
1016             case 0x40:
1017             case 0x41:
1018             case 0x42:
1019             case 0x43:
1020             case 0x44:
1021             case 0x45:
1022             case 0x46:
1023             case 0x47:
1024             case 0x48:
1025             case 0x49:
1026             case 0x4A:
1027             case 0x4B:
1028             case 0x4C:
1029             case 0x4D:
1030             case 0x4E:
1031             case 0x4F:
1032             case 0x50:
1033             case 0x51:
1034             case 0x52:
1035             case 0x53:
1036             case 0x54:
1037             case 0x55:
1038             case 0x56:
1039             case 0x57:
1040             {
1041                 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
1042             }
1043 
1044             case 0x58: // Binary data (one-byte uint8_t for n follows)
1045             {
1046                 std::uint8_t len{};
1047                 return get_number(input_format_t::cbor, len) &&
1048                        get_binary(input_format_t::cbor, len, result);
1049             }
1050 
1051             case 0x59: // Binary data (two-byte uint16_t for n follow)
1052             {
1053                 std::uint16_t len{};
1054                 return get_number(input_format_t::cbor, len) &&
1055                        get_binary(input_format_t::cbor, len, result);
1056             }
1057 
1058             case 0x5A: // Binary data (four-byte uint32_t for n follow)
1059             {
1060                 std::uint32_t len{};
1061                 return get_number(input_format_t::cbor, len) &&
1062                        get_binary(input_format_t::cbor, len, result);
1063             }
1064 
1065             case 0x5B: // Binary data (eight-byte uint64_t for n follow)
1066             {
1067                 std::uint64_t len{};
1068                 return get_number(input_format_t::cbor, len) &&
1069                        get_binary(input_format_t::cbor, len, result);
1070             }
1071 
1072             case 0x5F: // Binary data (indefinite length)
1073             {
1074                 while (get() != 0xFF)
1075                 {
1076                     binary_t chunk;
1077                     if (!get_cbor_binary(chunk))
1078                     {
1079                         return false;
1080                     }
1081                     result.insert(result.end(), chunk.begin(), chunk.end());
1082                 }
1083                 return true;
1084             }
1085 
1086             default:
1087             {
1088                 auto last_token = get_token_string();
1089                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
1090                                         exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
1091             }
1092         }
1093     }
1094 
1095     /*!
1096     @param[in] len  the length of the array or static_cast<std::size_t>(-1) for an
1097                     array of indefinite size
1098     @param[in] tag_handler how CBOR tags should be treated
1099     @return whether array creation completed
1100     */
1101     bool get_cbor_array(const std::size_t len,
1102                         const cbor_tag_handler_t tag_handler)
1103     {
1104         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
1105         {
1106             return false;
1107         }
1108 
1109         if (len != static_cast<std::size_t>(-1))
1110         {
1111             for (std::size_t i = 0; i < len; ++i)
1112             {
1113                 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
1114                 {
1115                     return false;
1116                 }
1117             }
1118         }
1119         else
1120         {
1121             while (get() != 0xFF)
1122             {
1123                 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
1124                 {
1125                     return false;
1126                 }
1127             }
1128         }
1129 
1130         return sax->end_array();
1131     }
1132 
1133     /*!
1134     @param[in] len  the length of the object or static_cast<std::size_t>(-1) for an
1135                     object of indefinite size
1136     @param[in] tag_handler how CBOR tags should be treated
1137     @return whether object creation completed
1138     */
1139     bool get_cbor_object(const std::size_t len,
1140                          const cbor_tag_handler_t tag_handler)
1141     {
1142         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
1143         {
1144             return false;
1145         }
1146 
1147         if (len != 0)
1148         {
1149             string_t key;
1150             if (len != static_cast<std::size_t>(-1))
1151             {
1152                 for (std::size_t i = 0; i < len; ++i)
1153                 {
1154                     get();
1155                     if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
1156                     {
1157                         return false;
1158                     }
1159 
1160                     if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
1161                     {
1162                         return false;
1163                     }
1164                     key.clear();
1165                 }
1166             }
1167             else
1168             {
1169                 while (get() != 0xFF)
1170                 {
1171                     if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
1172                     {
1173                         return false;
1174                     }
1175 
1176                     if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
1177                     {
1178                         return false;
1179                     }
1180                     key.clear();
1181                 }
1182             }
1183         }
1184 
1185         return sax->end_object();
1186     }
1187 
1188     /////////////
1189     // MsgPack //
1190     /////////////
1191 
1192     /*!
1193     @return whether a valid MessagePack value was passed to the SAX parser
1194     */
1195     bool parse_msgpack_internal()
1196     {
1197         switch (get())
1198         {
1199             // EOF
1200             case char_traits<char_type>::eof():
1201                 return unexpect_eof(input_format_t::msgpack, "value");
1202 
1203             // positive fixint
1204             case 0x00:
1205             case 0x01:
1206             case 0x02:
1207             case 0x03:
1208             case 0x04:
1209             case 0x05:
1210             case 0x06:
1211             case 0x07:
1212             case 0x08:
1213             case 0x09:
1214             case 0x0A:
1215             case 0x0B:
1216             case 0x0C:
1217             case 0x0D:
1218             case 0x0E:
1219             case 0x0F:
1220             case 0x10:
1221             case 0x11:
1222             case 0x12:
1223             case 0x13:
1224             case 0x14:
1225             case 0x15:
1226             case 0x16:
1227             case 0x17:
1228             case 0x18:
1229             case 0x19:
1230             case 0x1A:
1231             case 0x1B:
1232             case 0x1C:
1233             case 0x1D:
1234             case 0x1E:
1235             case 0x1F:
1236             case 0x20:
1237             case 0x21:
1238             case 0x22:
1239             case 0x23:
1240             case 0x24:
1241             case 0x25:
1242             case 0x26:
1243             case 0x27:
1244             case 0x28:
1245             case 0x29:
1246             case 0x2A:
1247             case 0x2B:
1248             case 0x2C:
1249             case 0x2D:
1250             case 0x2E:
1251             case 0x2F:
1252             case 0x30:
1253             case 0x31:
1254             case 0x32:
1255             case 0x33:
1256             case 0x34:
1257             case 0x35:
1258             case 0x36:
1259             case 0x37:
1260             case 0x38:
1261             case 0x39:
1262             case 0x3A:
1263             case 0x3B:
1264             case 0x3C:
1265             case 0x3D:
1266             case 0x3E:
1267             case 0x3F:
1268             case 0x40:
1269             case 0x41:
1270             case 0x42:
1271             case 0x43:
1272             case 0x44:
1273             case 0x45:
1274             case 0x46:
1275             case 0x47:
1276             case 0x48:
1277             case 0x49:
1278             case 0x4A:
1279             case 0x4B:
1280             case 0x4C:
1281             case 0x4D:
1282             case 0x4E:
1283             case 0x4F:
1284             case 0x50:
1285             case 0x51:
1286             case 0x52:
1287             case 0x53:
1288             case 0x54:
1289             case 0x55:
1290             case 0x56:
1291             case 0x57:
1292             case 0x58:
1293             case 0x59:
1294             case 0x5A:
1295             case 0x5B:
1296             case 0x5C:
1297             case 0x5D:
1298             case 0x5E:
1299             case 0x5F:
1300             case 0x60:
1301             case 0x61:
1302             case 0x62:
1303             case 0x63:
1304             case 0x64:
1305             case 0x65:
1306             case 0x66:
1307             case 0x67:
1308             case 0x68:
1309             case 0x69:
1310             case 0x6A:
1311             case 0x6B:
1312             case 0x6C:
1313             case 0x6D:
1314             case 0x6E:
1315             case 0x6F:
1316             case 0x70:
1317             case 0x71:
1318             case 0x72:
1319             case 0x73:
1320             case 0x74:
1321             case 0x75:
1322             case 0x76:
1323             case 0x77:
1324             case 0x78:
1325             case 0x79:
1326             case 0x7A:
1327             case 0x7B:
1328             case 0x7C:
1329             case 0x7D:
1330             case 0x7E:
1331             case 0x7F:
1332                 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
1333 
1334             // fixmap
1335             case 0x80:
1336             case 0x81:
1337             case 0x82:
1338             case 0x83:
1339             case 0x84:
1340             case 0x85:
1341             case 0x86:
1342             case 0x87:
1343             case 0x88:
1344             case 0x89:
1345             case 0x8A:
1346             case 0x8B:
1347             case 0x8C:
1348             case 0x8D:
1349             case 0x8E:
1350             case 0x8F:
1351                 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
1352 
1353             // fixarray
1354             case 0x90:
1355             case 0x91:
1356             case 0x92:
1357             case 0x93:
1358             case 0x94:
1359             case 0x95:
1360             case 0x96:
1361             case 0x97:
1362             case 0x98:
1363             case 0x99:
1364             case 0x9A:
1365             case 0x9B:
1366             case 0x9C:
1367             case 0x9D:
1368             case 0x9E:
1369             case 0x9F:
1370                 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
1371 
1372             // fixstr
1373             case 0xA0:
1374             case 0xA1:
1375             case 0xA2:
1376             case 0xA3:
1377             case 0xA4:
1378             case 0xA5:
1379             case 0xA6:
1380             case 0xA7:
1381             case 0xA8:
1382             case 0xA9:
1383             case 0xAA:
1384             case 0xAB:
1385             case 0xAC:
1386             case 0xAD:
1387             case 0xAE:
1388             case 0xAF:
1389             case 0xB0:
1390             case 0xB1:
1391             case 0xB2:
1392             case 0xB3:
1393             case 0xB4:
1394             case 0xB5:
1395             case 0xB6:
1396             case 0xB7:
1397             case 0xB8:
1398             case 0xB9:
1399             case 0xBA:
1400             case 0xBB:
1401             case 0xBC:
1402             case 0xBD:
1403             case 0xBE:
1404             case 0xBF:
1405             case 0xD9: // str 8
1406             case 0xDA: // str 16
1407             case 0xDB: // str 32
1408             {
1409                 string_t s;
1410                 return get_msgpack_string(s) && sax->string(s);
1411             }
1412 
1413             case 0xC0: // nil
1414                 return sax->null();
1415 
1416             case 0xC2: // false
1417                 return sax->boolean(false);
1418 
1419             case 0xC3: // true
1420                 return sax->boolean(true);
1421 
1422             case 0xC4: // bin 8
1423             case 0xC5: // bin 16
1424             case 0xC6: // bin 32
1425             case 0xC7: // ext 8
1426             case 0xC8: // ext 16
1427             case 0xC9: // ext 32
1428             case 0xD4: // fixext 1
1429             case 0xD5: // fixext 2
1430             case 0xD6: // fixext 4
1431             case 0xD7: // fixext 8
1432             case 0xD8: // fixext 16
1433             {
1434                 binary_t b;
1435                 return get_msgpack_binary(b) && sax->binary(b);
1436             }
1437 
1438             case 0xCA: // float 32
1439             {
1440                 float number{};
1441                 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
1442             }
1443 
1444             case 0xCB: // float 64
1445             {
1446                 double number{};
1447                 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
1448             }
1449 
1450             case 0xCC: // uint 8
1451             {
1452                 std::uint8_t number{};
1453                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
1454             }
1455 
1456             case 0xCD: // uint 16
1457             {
1458                 std::uint16_t number{};
1459                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
1460             }
1461 
1462             case 0xCE: // uint 32
1463             {
1464                 std::uint32_t number{};
1465                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
1466             }
1467 
1468             case 0xCF: // uint 64
1469             {
1470                 std::uint64_t number{};
1471                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
1472             }
1473 
1474             case 0xD0: // int 8
1475             {
1476                 std::int8_t number{};
1477                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
1478             }
1479 
1480             case 0xD1: // int 16
1481             {
1482                 std::int16_t number{};
1483                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
1484             }
1485 
1486             case 0xD2: // int 32
1487             {
1488                 std::int32_t number{};
1489                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
1490             }
1491 
1492             case 0xD3: // int 64
1493             {
1494                 std::int64_t number{};
1495                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
1496             }
1497 
1498             case 0xDC: // array 16
1499             {
1500                 std::uint16_t len{};
1501                 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
1502             }
1503 
1504             case 0xDD: // array 32
1505             {
1506                 std::uint32_t len{};
1507                 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
1508             }
1509 
1510             case 0xDE: // map 16
1511             {
1512                 std::uint16_t len{};
1513                 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
1514             }
1515 
1516             case 0xDF: // map 32
1517             {
1518                 std::uint32_t len{};
1519                 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
1520             }
1521 
1522             // negative fixint
1523             case 0xE0:
1524             case 0xE1:
1525             case 0xE2:
1526             case 0xE3:
1527             case 0xE4:
1528             case 0xE5:
1529             case 0xE6:
1530             case 0xE7:
1531             case 0xE8:
1532             case 0xE9:
1533             case 0xEA:
1534             case 0xEB:
1535             case 0xEC:
1536             case 0xED:
1537             case 0xEE:
1538             case 0xEF:
1539             case 0xF0:
1540             case 0xF1:
1541             case 0xF2:
1542             case 0xF3:
1543             case 0xF4:
1544             case 0xF5:
1545             case 0xF6:
1546             case 0xF7:
1547             case 0xF8:
1548             case 0xF9:
1549             case 0xFA:
1550             case 0xFB:
1551             case 0xFC:
1552             case 0xFD:
1553             case 0xFE:
1554             case 0xFF:
1555                 return sax->number_integer(static_cast<std::int8_t>(current));
1556 
1557             default: // anything else
1558             {
1559                 auto last_token = get_token_string();
1560                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
1561                                         exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
1562             }
1563         }
1564     }
1565 
1566     /*!
1567     @brief reads a MessagePack string
1568 
1569     This function first reads starting bytes to determine the expected
1570     string length and then copies this number of bytes into a string.
1571 
1572     @param[out] result  created string
1573 
1574     @return whether string creation completed
1575     */
1576     bool get_msgpack_string(string_t& result)
1577     {
1578         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
1579         {
1580             return false;
1581         }
1582 
1583         switch (current)
1584         {
1585             // fixstr
1586             case 0xA0:
1587             case 0xA1:
1588             case 0xA2:
1589             case 0xA3:
1590             case 0xA4:
1591             case 0xA5:
1592             case 0xA6:
1593             case 0xA7:
1594             case 0xA8:
1595             case 0xA9:
1596             case 0xAA:
1597             case 0xAB:
1598             case 0xAC:
1599             case 0xAD:
1600             case 0xAE:
1601             case 0xAF:
1602             case 0xB0:
1603             case 0xB1:
1604             case 0xB2:
1605             case 0xB3:
1606             case 0xB4:
1607             case 0xB5:
1608             case 0xB6:
1609             case 0xB7:
1610             case 0xB8:
1611             case 0xB9:
1612             case 0xBA:
1613             case 0xBB:
1614             case 0xBC:
1615             case 0xBD:
1616             case 0xBE:
1617             case 0xBF:
1618             {
1619                 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
1620             }
1621 
1622             case 0xD9: // str 8
1623             {
1624                 std::uint8_t len{};
1625                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
1626             }
1627 
1628             case 0xDA: // str 16
1629             {
1630                 std::uint16_t len{};
1631                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
1632             }
1633 
1634             case 0xDB: // str 32
1635             {
1636                 std::uint32_t len{};
1637                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
1638             }
1639 
1640             default:
1641             {
1642                 auto last_token = get_token_string();
1643                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
1644                                         exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
1645             }
1646         }
1647     }
1648 
1649     /*!
1650     @brief reads a MessagePack byte array
1651 
1652     This function first reads starting bytes to determine the expected
1653     byte array length and then copies this number of bytes into a byte array.
1654 
1655     @param[out] result  created byte array
1656 
1657     @return whether byte array creation completed
1658     */
1659     bool get_msgpack_binary(binary_t& result)
1660     {
1661         // helper function to set the subtype
1662         auto assign_and_return_true = [&result](std::int8_t subtype)
1663         {
1664             result.set_subtype(static_cast<std::uint8_t>(subtype));
1665             return true;
1666         };
1667 
1668         switch (current)
1669         {
1670             case 0xC4: // bin 8
1671             {
1672                 std::uint8_t len{};
1673                 return get_number(input_format_t::msgpack, len) &&
1674                        get_binary(input_format_t::msgpack, len, result);
1675             }
1676 
1677             case 0xC5: // bin 16
1678             {
1679                 std::uint16_t len{};
1680                 return get_number(input_format_t::msgpack, len) &&
1681                        get_binary(input_format_t::msgpack, len, result);
1682             }
1683 
1684             case 0xC6: // bin 32
1685             {
1686                 std::uint32_t len{};
1687                 return get_number(input_format_t::msgpack, len) &&
1688                        get_binary(input_format_t::msgpack, len, result);
1689             }
1690 
1691             case 0xC7: // ext 8
1692             {
1693                 std::uint8_t len{};
1694                 std::int8_t subtype{};
1695                 return get_number(input_format_t::msgpack, len) &&
1696                        get_number(input_format_t::msgpack, subtype) &&
1697                        get_binary(input_format_t::msgpack, len, result) &&
1698                        assign_and_return_true(subtype);
1699             }
1700 
1701             case 0xC8: // ext 16
1702             {
1703                 std::uint16_t len{};
1704                 std::int8_t subtype{};
1705                 return get_number(input_format_t::msgpack, len) &&
1706                        get_number(input_format_t::msgpack, subtype) &&
1707                        get_binary(input_format_t::msgpack, len, result) &&
1708                        assign_and_return_true(subtype);
1709             }
1710 
1711             case 0xC9: // ext 32
1712             {
1713                 std::uint32_t len{};
1714                 std::int8_t subtype{};
1715                 return get_number(input_format_t::msgpack, len) &&
1716                        get_number(input_format_t::msgpack, subtype) &&
1717                        get_binary(input_format_t::msgpack, len, result) &&
1718                        assign_and_return_true(subtype);
1719             }
1720 
1721             case 0xD4: // fixext 1
1722             {
1723                 std::int8_t subtype{};
1724                 return get_number(input_format_t::msgpack, subtype) &&
1725                        get_binary(input_format_t::msgpack, 1, result) &&
1726                        assign_and_return_true(subtype);
1727             }
1728 
1729             case 0xD5: // fixext 2
1730             {
1731                 std::int8_t subtype{};
1732                 return get_number(input_format_t::msgpack, subtype) &&
1733                        get_binary(input_format_t::msgpack, 2, result) &&
1734                        assign_and_return_true(subtype);
1735             }
1736 
1737             case 0xD6: // fixext 4
1738             {
1739                 std::int8_t subtype{};
1740                 return get_number(input_format_t::msgpack, subtype) &&
1741                        get_binary(input_format_t::msgpack, 4, result) &&
1742                        assign_and_return_true(subtype);
1743             }
1744 
1745             case 0xD7: // fixext 8
1746             {
1747                 std::int8_t subtype{};
1748                 return get_number(input_format_t::msgpack, subtype) &&
1749                        get_binary(input_format_t::msgpack, 8, result) &&
1750                        assign_and_return_true(subtype);
1751             }
1752 
1753             case 0xD8: // fixext 16
1754             {
1755                 std::int8_t subtype{};
1756                 return get_number(input_format_t::msgpack, subtype) &&
1757                        get_binary(input_format_t::msgpack, 16, result) &&
1758                        assign_and_return_true(subtype);
1759             }
1760 
1761             default:           // LCOV_EXCL_LINE
1762                 return false;  // LCOV_EXCL_LINE
1763         }
1764     }
1765 
1766     /*!
1767     @param[in] len  the length of the array
1768     @return whether array creation completed
1769     */
1770     bool get_msgpack_array(const std::size_t len)
1771     {
1772         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
1773         {
1774             return false;
1775         }
1776 
1777         for (std::size_t i = 0; i < len; ++i)
1778         {
1779             if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
1780             {
1781                 return false;
1782             }
1783         }
1784 
1785         return sax->end_array();
1786     }
1787 
1788     /*!
1789     @param[in] len  the length of the object
1790     @return whether object creation completed
1791     */
1792     bool get_msgpack_object(const std::size_t len)
1793     {
1794         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
1795         {
1796             return false;
1797         }
1798 
1799         string_t key;
1800         for (std::size_t i = 0; i < len; ++i)
1801         {
1802             get();
1803             if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
1804             {
1805                 return false;
1806             }
1807 
1808             if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
1809             {
1810                 return false;
1811             }
1812             key.clear();
1813         }
1814 
1815         return sax->end_object();
1816     }
1817 
1818     ////////////
1819     // UBJSON //
1820     ////////////
1821 
1822     /*!
1823     @param[in] get_char  whether a new character should be retrieved from the
1824                          input (true, default) or whether the last read
1825                          character should be considered instead
1826 
1827     @return whether a valid UBJSON value was passed to the SAX parser
1828     */
1829     bool parse_ubjson_internal(const bool get_char = true)
1830     {
1831         return get_ubjson_value(get_char ? get_ignore_noop() : current);
1832     }
1833 
1834     /*!
1835     @brief reads a UBJSON string
1836 
1837     This function is either called after reading the 'S' byte explicitly
1838     indicating a string, or in case of an object key where the 'S' byte can be
1839     left out.
1840 
1841     @param[out] result   created string
1842     @param[in] get_char  whether a new character should be retrieved from the
1843                          input (true, default) or whether the last read
1844                          character should be considered instead
1845 
1846     @return whether string creation completed
1847     */
1848     bool get_ubjson_string(string_t& result, const bool get_char = true)
1849     {
1850         if (get_char)
1851         {
1852             get();  // TODO(niels): may we ignore N here?
1853         }
1854 
1855         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
1856         {
1857             return false;
1858         }
1859 
1860         switch (current)
1861         {
1862             case 'U':
1863             {
1864                 std::uint8_t len{};
1865                 return get_number(input_format, len) && get_string(input_format, len, result);
1866             }
1867 
1868             case 'i':
1869             {
1870                 std::int8_t len{};
1871                 return get_number(input_format, len) && get_string(input_format, len, result);
1872             }
1873 
1874             case 'I':
1875             {
1876                 std::int16_t len{};
1877                 return get_number(input_format, len) && get_string(input_format, len, result);
1878             }
1879 
1880             case 'l':
1881             {
1882                 std::int32_t len{};
1883                 return get_number(input_format, len) && get_string(input_format, len, result);
1884             }
1885 
1886             case 'L':
1887             {
1888                 std::int64_t len{};
1889                 return get_number(input_format, len) && get_string(input_format, len, result);
1890             }
1891 
1892             case 'u':
1893             {
1894                 if (input_format != input_format_t::bjdata)
1895                 {
1896                     break;
1897                 }
1898                 std::uint16_t len{};
1899                 return get_number(input_format, len) && get_string(input_format, len, result);
1900             }
1901 
1902             case 'm':
1903             {
1904                 if (input_format != input_format_t::bjdata)
1905                 {
1906                     break;
1907                 }
1908                 std::uint32_t len{};
1909                 return get_number(input_format, len) && get_string(input_format, len, result);
1910             }
1911 
1912             case 'M':
1913             {
1914                 if (input_format != input_format_t::bjdata)
1915                 {
1916                     break;
1917                 }
1918                 std::uint64_t len{};
1919                 return get_number(input_format, len) && get_string(input_format, len, result);
1920             }
1921 
1922             default:
1923                 break;
1924         }
1925         auto last_token = get_token_string();
1926         std::string message;
1927 
1928         if (input_format != input_format_t::bjdata)
1929         {
1930             message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
1931         }
1932         else
1933         {
1934             message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
1935         }
1936         return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
1937     }
1938 
1939     /*!
1940     @param[out] dim  an integer vector storing the ND array dimensions
1941     @return whether reading ND array size vector is successful
1942     */
1943     bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
1944     {
1945         std::pair<std::size_t, char_int_type> size_and_type;
1946         size_t dimlen = 0;
1947         bool no_ndarray = true;
1948 
1949         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
1950         {
1951             return false;
1952         }
1953 
1954         if (size_and_type.first != npos)
1955         {
1956             if (size_and_type.second != 0)
1957             {
1958                 if (size_and_type.second != 'N')
1959                 {
1960                     for (std::size_t i = 0; i < size_and_type.first; ++i)
1961                     {
1962                         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
1963                         {
1964                             return false;
1965                         }
1966                         dim.push_back(dimlen);
1967                     }
1968                 }
1969             }
1970             else
1971             {
1972                 for (std::size_t i = 0; i < size_and_type.first; ++i)
1973                 {
1974                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
1975                     {
1976                         return false;
1977                     }
1978                     dim.push_back(dimlen);
1979                 }
1980             }
1981         }
1982         else
1983         {
1984             while (current != ']')
1985             {
1986                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
1987                 {
1988                     return false;
1989                 }
1990                 dim.push_back(dimlen);
1991                 get_ignore_noop();
1992             }
1993         }
1994         return true;
1995     }
1996 
1997     /*!
1998     @param[out] result  determined size
1999     @param[in,out] is_ndarray  for input, `true` means already inside an ndarray vector
2000                                or ndarray dimension is not allowed; `false` means ndarray
2001                                is allowed; for output, `true` means an ndarray is found;
2002                                is_ndarray can only return `true` when its initial value
2003                                is `false`
2004     @param[in] prefix  type marker if already read, otherwise set to 0
2005 
2006     @return whether size determination completed
2007     */
2008     bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
2009     {
2010         if (prefix == 0)
2011         {
2012             prefix = get_ignore_noop();
2013         }
2014 
2015         switch (prefix)
2016         {
2017             case 'U':
2018             {
2019                 std::uint8_t number{};
2020                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
2021                 {
2022                     return false;
2023                 }
2024                 result = static_cast<std::size_t>(number);
2025                 return true;
2026             }
2027 
2028             case 'i':
2029             {
2030                 std::int8_t number{};
2031                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
2032                 {
2033                     return false;
2034                 }
2035                 if (number < 0)
2036                 {
2037                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
2038                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
2039                 }
2040                 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
2041                 return true;
2042             }
2043 
2044             case 'I':
2045             {
2046                 std::int16_t number{};
2047                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
2048                 {
2049                     return false;
2050                 }
2051                 if (number < 0)
2052                 {
2053                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
2054                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
2055                 }
2056                 result = static_cast<std::size_t>(number);
2057                 return true;
2058             }
2059 
2060             case 'l':
2061             {
2062                 std::int32_t number{};
2063                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
2064                 {
2065                     return false;
2066                 }
2067                 if (number < 0)
2068                 {
2069                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
2070                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
2071                 }
2072                 result = static_cast<std::size_t>(number);
2073                 return true;
2074             }
2075 
2076             case 'L':
2077             {
2078                 std::int64_t number{};
2079                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
2080                 {
2081                     return false;
2082                 }
2083                 if (number < 0)
2084                 {
2085                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
2086                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
2087                 }
2088                 if (!value_in_range_of<std::size_t>(number))
2089                 {
2090                     return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
2091                                             exception_message(input_format, "integer value overflow", "size"), nullptr));
2092                 }
2093                 result = static_cast<std::size_t>(number);
2094                 return true;
2095             }
2096 
2097             case 'u':
2098             {
2099                 if (input_format != input_format_t::bjdata)
2100                 {
2101                     break;
2102                 }
2103                 std::uint16_t number{};
2104                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
2105                 {
2106                     return false;
2107                 }
2108                 result = static_cast<std::size_t>(number);
2109                 return true;
2110             }
2111 
2112             case 'm':
2113             {
2114                 if (input_format != input_format_t::bjdata)
2115                 {
2116                     break;
2117                 }
2118                 std::uint32_t number{};
2119                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
2120                 {
2121                     return false;
2122                 }
2123                 result = conditional_static_cast<std::size_t>(number);
2124                 return true;
2125             }
2126 
2127             case 'M':
2128             {
2129                 if (input_format != input_format_t::bjdata)
2130                 {
2131                     break;
2132                 }
2133                 std::uint64_t number{};
2134                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
2135                 {
2136                     return false;
2137                 }
2138                 if (!value_in_range_of<std::size_t>(number))
2139                 {
2140                     return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
2141                                             exception_message(input_format, "integer value overflow", "size"), nullptr));
2142                 }
2143                 result = detail::conditional_static_cast<std::size_t>(number);
2144                 return true;
2145             }
2146 
2147             case '[':
2148             {
2149                 if (input_format != input_format_t::bjdata)
2150                 {
2151                     break;
2152                 }
2153                 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
2154                 {
2155                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
2156                 }
2157                 std::vector<size_t> dim;
2158                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
2159                 {
2160                     return false;
2161                 }
2162                 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
2163                 {
2164                     result = dim.at(dim.size() - 1);
2165                     return true;
2166                 }
2167                 if (!dim.empty())  // if ndarray, convert to an object in JData annotated array format
2168                 {
2169                     for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
2170                     {
2171                         if ( i == 0 )
2172                         {
2173                             result = 0;
2174                             return true;
2175                         }
2176                     }
2177 
2178                     string_t key = "_ArraySize_";
2179                     if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
2180                     {
2181                         return false;
2182                     }
2183                     result = 1;
2184                     for (auto i : dim)
2185                     {
2186                         result *= i;
2187                         if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
2188                         {
2189                             return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
2190                         }
2191                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
2192                         {
2193                             return false;
2194                         }
2195                     }
2196                     is_ndarray = true;
2197                     return sax->end_array();
2198                 }
2199                 result = 0;
2200                 return true;
2201             }
2202 
2203             default:
2204                 break;
2205         }
2206         auto last_token = get_token_string();
2207         std::string message;
2208 
2209         if (input_format != input_format_t::bjdata)
2210         {
2211             message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
2212         }
2213         else
2214         {
2215             message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
2216         }
2217         return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
2218     }
2219 
2220     /*!
2221     @brief determine the type and size for a container
2222 
2223     In the optimized UBJSON format, a type and a size can be provided to allow
2224     for a more compact representation.
2225 
2226     @param[out] result  pair of the size and the type
2227     @param[in] inside_ndarray  whether the parser is parsing an ND array dimensional vector
2228 
2229     @return whether pair creation completed
2230     */
2231     bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
2232     {
2233         result.first = npos; // size
2234         result.second = 0; // type
2235         bool is_ndarray = false;
2236 
2237         get_ignore_noop();
2238 
2239         if (current == '$')
2240         {
2241             result.second = get();  // must not ignore 'N', because 'N' maybe the type
2242             if (input_format == input_format_t::bjdata
2243                     && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
2244             {
2245                 auto last_token = get_token_string();
2246                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
2247                                         exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
2248             }
2249 
2250             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
2251             {
2252                 return false;
2253             }
2254 
2255             get_ignore_noop();
2256             if (JSON_HEDLEY_UNLIKELY(current != '#'))
2257             {
2258                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
2259                 {
2260                     return false;
2261                 }
2262                 auto last_token = get_token_string();
2263                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
2264                                         exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
2265             }
2266 
2267             const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
2268             if (input_format == input_format_t::bjdata && is_ndarray)
2269             {
2270                 if (inside_ndarray)
2271                 {
2272                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
2273                                             exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
2274                 }
2275                 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
2276             }
2277             return is_error;
2278         }
2279 
2280         if (current == '#')
2281         {
2282             const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
2283             if (input_format == input_format_t::bjdata && is_ndarray)
2284             {
2285                 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
2286                                         exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
2287             }
2288             return is_error;
2289         }
2290 
2291         return true;
2292     }
2293 
2294     /*!
2295     @param prefix  the previously read or set type prefix
2296     @return whether value creation completed
2297     */
2298     bool get_ubjson_value(const char_int_type prefix)
2299     {
2300         switch (prefix)
2301         {
2302             case char_traits<char_type>::eof():  // EOF
2303                 return unexpect_eof(input_format, "value");
2304 
2305             case 'T':  // true
2306                 return sax->boolean(true);
2307             case 'F':  // false
2308                 return sax->boolean(false);
2309 
2310             case 'Z':  // null
2311                 return sax->null();
2312 
2313             case 'U':
2314             {
2315                 std::uint8_t number{};
2316                 return get_number(input_format, number) && sax->number_unsigned(number);
2317             }
2318 
2319             case 'i':
2320             {
2321                 std::int8_t number{};
2322                 return get_number(input_format, number) && sax->number_integer(number);
2323             }
2324 
2325             case 'I':
2326             {
2327                 std::int16_t number{};
2328                 return get_number(input_format, number) && sax->number_integer(number);
2329             }
2330 
2331             case 'l':
2332             {
2333                 std::int32_t number{};
2334                 return get_number(input_format, number) && sax->number_integer(number);
2335             }
2336 
2337             case 'L':
2338             {
2339                 std::int64_t number{};
2340                 return get_number(input_format, number) && sax->number_integer(number);
2341             }
2342 
2343             case 'u':
2344             {
2345                 if (input_format != input_format_t::bjdata)
2346                 {
2347                     break;
2348                 }
2349                 std::uint16_t number{};
2350                 return get_number(input_format, number) && sax->number_unsigned(number);
2351             }
2352 
2353             case 'm':
2354             {
2355                 if (input_format != input_format_t::bjdata)
2356                 {
2357                     break;
2358                 }
2359                 std::uint32_t number{};
2360                 return get_number(input_format, number) && sax->number_unsigned(number);
2361             }
2362 
2363             case 'M':
2364             {
2365                 if (input_format != input_format_t::bjdata)
2366                 {
2367                     break;
2368                 }
2369                 std::uint64_t number{};
2370                 return get_number(input_format, number) && sax->number_unsigned(number);
2371             }
2372 
2373             case 'h':
2374             {
2375                 if (input_format != input_format_t::bjdata)
2376                 {
2377                     break;
2378                 }
2379                 const auto byte1_raw = get();
2380                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
2381                 {
2382                     return false;
2383                 }
2384                 const auto byte2_raw = get();
2385                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
2386                 {
2387                     return false;
2388                 }
2389 
2390                 const auto byte1 = static_cast<unsigned char>(byte1_raw);
2391                 const auto byte2 = static_cast<unsigned char>(byte2_raw);
2392 
2393                 // code from RFC 7049, Appendix D, Figure 3:
2394                 // As half-precision floating-point numbers were only added
2395                 // to IEEE 754 in 2008, today's programming platforms often
2396                 // still only have limited support for them. It is very
2397                 // easy to include at least decoding support for them even
2398                 // without such support. An example of a small decoder for
2399                 // half-precision floating-point numbers in the C language
2400                 // is shown in Fig. 3.
2401                 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
2402                 const double val = [&half]
2403                 {
2404                     const int exp = (half >> 10u) & 0x1Fu;
2405                     const unsigned int mant = half & 0x3FFu;
2406                     JSON_ASSERT(0 <= exp&& exp <= 32);
2407                     JSON_ASSERT(mant <= 1024);
2408                     switch (exp)
2409                     {
2410                         case 0:
2411                             return std::ldexp(mant, -24);
2412                         case 31:
2413                             return (mant == 0)
2414                             ? std::numeric_limits<double>::infinity()
2415                             : std::numeric_limits<double>::quiet_NaN();
2416                         default:
2417                             return std::ldexp(mant + 1024, exp - 25);
2418                     }
2419                 }();
2420                 return sax->number_float((half & 0x8000u) != 0
2421                                          ? static_cast<number_float_t>(-val)
2422                                          : static_cast<number_float_t>(val), "");
2423             }
2424 
2425             case 'd':
2426             {
2427                 float number{};
2428                 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
2429             }
2430 
2431             case 'D':
2432             {
2433                 double number{};
2434                 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
2435             }
2436 
2437             case 'H':
2438             {
2439                 return get_ubjson_high_precision_number();
2440             }
2441 
2442             case 'C':  // char
2443             {
2444                 get();
2445                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
2446                 {
2447                     return false;
2448                 }
2449                 if (JSON_HEDLEY_UNLIKELY(current > 127))
2450                 {
2451                     auto last_token = get_token_string();
2452                     return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
2453                                             exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
2454                 }
2455                 string_t s(1, static_cast<typename string_t::value_type>(current));
2456                 return sax->string(s);
2457             }
2458 
2459             case 'S':  // string
2460             {
2461                 string_t s;
2462                 return get_ubjson_string(s) && sax->string(s);
2463             }
2464 
2465             case '[':  // array
2466                 return get_ubjson_array();
2467 
2468             case '{':  // object
2469                 return get_ubjson_object();
2470 
2471             default: // anything else
2472                 break;
2473         }
2474         auto last_token = get_token_string();
2475         return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
2476     }
2477 
2478     /*!
2479     @return whether array creation completed
2480     */
2481     bool get_ubjson_array()
2482     {
2483         std::pair<std::size_t, char_int_type> size_and_type;
2484         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
2485         {
2486             return false;
2487         }
2488 
2489         // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
2490         // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
2491 
2492         if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
2493         {
2494             size_and_type.second &= ~(static_cast<char_int_type>(1) << 8);  // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
2495             auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
2496             {
2497                 return p.first < t;
2498             });
2499             string_t key = "_ArrayType_";
2500             if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
2501             {
2502                 auto last_token = get_token_string();
2503                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
2504                                         exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
2505             }
2506 
2507             string_t type = it->second; // sax->string() takes a reference
2508             if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
2509             {
2510                 return false;
2511             }
2512 
2513             if (size_and_type.second == 'C')
2514             {
2515                 size_and_type.second = 'U';
2516             }
2517 
2518             key = "_ArrayData_";
2519             if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
2520             {
2521                 return false;
2522             }
2523 
2524             for (std::size_t i = 0; i < size_and_type.first; ++i)
2525             {
2526                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
2527                 {
2528                     return false;
2529                 }
2530             }
2531 
2532             return (sax->end_array() && sax->end_object());
2533         }
2534 
2535         if (size_and_type.first != npos)
2536         {
2537             if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
2538             {
2539                 return false;
2540             }
2541 
2542             if (size_and_type.second != 0)
2543             {
2544                 if (size_and_type.second != 'N')
2545                 {
2546                     for (std::size_t i = 0; i < size_and_type.first; ++i)
2547                     {
2548                         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
2549                         {
2550                             return false;
2551                         }
2552                     }
2553                 }
2554             }
2555             else
2556             {
2557                 for (std::size_t i = 0; i < size_and_type.first; ++i)
2558                 {
2559                     if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
2560                     {
2561                         return false;
2562                     }
2563                 }
2564             }
2565         }
2566         else
2567         {
2568             if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
2569             {
2570                 return false;
2571             }
2572 
2573             while (current != ']')
2574             {
2575                 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
2576                 {
2577                     return false;
2578                 }
2579                 get_ignore_noop();
2580             }
2581         }
2582 
2583         return sax->end_array();
2584     }
2585 
2586     /*!
2587     @return whether object creation completed
2588     */
2589     bool get_ubjson_object()
2590     {
2591         std::pair<std::size_t, char_int_type> size_and_type;
2592         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
2593         {
2594             return false;
2595         }
2596 
2597         // do not accept ND-array size in objects in BJData
2598         if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
2599         {
2600             auto last_token = get_token_string();
2601             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
2602                                     exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
2603         }
2604 
2605         string_t key;
2606         if (size_and_type.first != npos)
2607         {
2608             if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
2609             {
2610                 return false;
2611             }
2612 
2613             if (size_and_type.second != 0)
2614             {
2615                 for (std::size_t i = 0; i < size_and_type.first; ++i)
2616                 {
2617                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
2618                     {
2619                         return false;
2620                     }
2621                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
2622                     {
2623                         return false;
2624                     }
2625                     key.clear();
2626                 }
2627             }
2628             else
2629             {
2630                 for (std::size_t i = 0; i < size_and_type.first; ++i)
2631                 {
2632                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
2633                     {
2634                         return false;
2635                     }
2636                     if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
2637                     {
2638                         return false;
2639                     }
2640                     key.clear();
2641                 }
2642             }
2643         }
2644         else
2645         {
2646             if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
2647             {
2648                 return false;
2649             }
2650 
2651             while (current != '}')
2652             {
2653                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
2654                 {
2655                     return false;
2656                 }
2657                 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
2658                 {
2659                     return false;
2660                 }
2661                 get_ignore_noop();
2662                 key.clear();
2663             }
2664         }
2665 
2666         return sax->end_object();
2667     }
2668 
2669     // Note, no reader for UBJSON binary types is implemented because they do
2670     // not exist
2671 
2672     bool get_ubjson_high_precision_number()
2673     {
2674         // get size of following number string
2675         std::size_t size{};
2676         bool no_ndarray = true;
2677         auto res = get_ubjson_size_value(size, no_ndarray);
2678         if (JSON_HEDLEY_UNLIKELY(!res))
2679         {
2680             return res;
2681         }
2682 
2683         // get number string
2684         std::vector<char> number_vector;
2685         for (std::size_t i = 0; i < size; ++i)
2686         {
2687             get();
2688             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
2689             {
2690                 return false;
2691             }
2692             number_vector.push_back(static_cast<char>(current));
2693         }
2694 
2695         // parse number string
2696         using ia_type = decltype(detail::input_adapter(number_vector));
2697         auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
2698         const auto result_number = number_lexer.scan();
2699         const auto number_string = number_lexer.get_token_string();
2700         const auto result_remainder = number_lexer.scan();
2701 
2702         using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
2703 
2704         if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
2705         {
2706             return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
2707                                     exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
2708         }
2709 
2710         switch (result_number)
2711         {
2712             case token_type::value_integer:
2713                 return sax->number_integer(number_lexer.get_number_integer());
2714             case token_type::value_unsigned:
2715                 return sax->number_unsigned(number_lexer.get_number_unsigned());
2716             case token_type::value_float:
2717                 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
2718             case token_type::uninitialized:
2719             case token_type::literal_true:
2720             case token_type::literal_false:
2721             case token_type::literal_null:
2722             case token_type::value_string:
2723             case token_type::begin_array:
2724             case token_type::begin_object:
2725             case token_type::end_array:
2726             case token_type::end_object:
2727             case token_type::name_separator:
2728             case token_type::value_separator:
2729             case token_type::parse_error:
2730             case token_type::end_of_input:
2731             case token_type::literal_or_value:
2732             default:
2733                 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
2734                                         exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
2735         }
2736     }
2737 
2738     ///////////////////////
2739     // Utility functions //
2740     ///////////////////////
2741 
2742     /*!
2743     @brief get next character from the input
2744 
2745     This function provides the interface to the used input adapter. It does
2746     not throw in case the input reached EOF, but returns a -'ve valued
2747     `char_traits<char_type>::eof()` in that case.
2748 
2749     @return character read from the input
2750     */
2751     char_int_type get()
2752     {
2753         ++chars_read;
2754         return current = ia.get_character();
2755     }
2756 
2757     /*!
2758     @return character read from the input after ignoring all 'N' entries
2759     */
2760     char_int_type get_ignore_noop()
2761     {
2762         do
2763         {
2764             get();
2765         }
2766         while (current == 'N');
2767 
2768         return current;
2769     }
2770 
2771     /*
2772     @brief read a number from the input
2773 
2774     @tparam NumberType the type of the number
2775     @param[in] format   the current format (for diagnostics)
2776     @param[out] result  number of type @a NumberType
2777 
2778     @return whether conversion completed
2779 
2780     @note This function needs to respect the system's endianness, because
2781           bytes in CBOR, MessagePack, and UBJSON are stored in network order
2782           (big endian) and therefore need reordering on little endian systems.
2783           On the other hand, BSON and BJData use little endian and should reorder
2784           on big endian systems.
2785     */
2786     template<typename NumberType, bool InputIsLittleEndian = false>
2787     bool get_number(const input_format_t format, NumberType& result)
2788     {
2789         // step 1: read input into array with system's byte order
2790         std::array<std::uint8_t, sizeof(NumberType)> vec{};
2791         for (std::size_t i = 0; i < sizeof(NumberType); ++i)
2792         {
2793             get();
2794             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
2795             {
2796                 return false;
2797             }
2798 
2799             // reverse byte order prior to conversion if necessary
2800             if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
2801             {
2802                 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
2803             }
2804             else
2805             {
2806                 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
2807             }
2808         }
2809 
2810         // step 2: convert array into number of type T and return
2811         std::memcpy(&result, vec.data(), sizeof(NumberType));
2812         return true;
2813     }
2814 
2815     /*!
2816     @brief create a string by reading characters from the input
2817 
2818     @tparam NumberType the type of the number
2819     @param[in] format the current format (for diagnostics)
2820     @param[in] len number of characters to read
2821     @param[out] result string created by reading @a len bytes
2822 
2823     @return whether string creation completed
2824 
2825     @note We can not reserve @a len bytes for the result, because @a len
2826           may be too large. Usually, @ref unexpect_eof() detects the end of
2827           the input before we run out of string memory.
2828     */
2829     template<typename NumberType>
2830     bool get_string(const input_format_t format,
2831                     const NumberType len,
2832                     string_t& result)
2833     {
2834         bool success = true;
2835         for (NumberType i = 0; i < len; i++)
2836         {
2837             get();
2838             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
2839             {
2840                 success = false;
2841                 break;
2842             }
2843             result.push_back(static_cast<typename string_t::value_type>(current));
2844         }
2845         return success;
2846     }
2847 
2848     /*!
2849     @brief create a byte array by reading bytes from the input
2850 
2851     @tparam NumberType the type of the number
2852     @param[in] format the current format (for diagnostics)
2853     @param[in] len number of bytes to read
2854     @param[out] result byte array created by reading @a len bytes
2855 
2856     @return whether byte array creation completed
2857 
2858     @note We can not reserve @a len bytes for the result, because @a len
2859           may be too large. Usually, @ref unexpect_eof() detects the end of
2860           the input before we run out of memory.
2861     */
2862     template<typename NumberType>
2863     bool get_binary(const input_format_t format,
2864                     const NumberType len,
2865                     binary_t& result)
2866     {
2867         bool success = true;
2868         for (NumberType i = 0; i < len; i++)
2869         {
2870             get();
2871             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
2872             {
2873                 success = false;
2874                 break;
2875             }
2876             result.push_back(static_cast<std::uint8_t>(current));
2877         }
2878         return success;
2879     }
2880 
2881     /*!
2882     @param[in] format   the current format (for diagnostics)
2883     @param[in] context  further context information (for diagnostics)
2884     @return whether the last read character is not EOF
2885     */
2886     JSON_HEDLEY_NON_NULL(3)
2887     bool unexpect_eof(const input_format_t format, const char* context) const
2888     {
2889         if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
2890         {
2891             return sax->parse_error(chars_read, "<end of file>",
2892                                     parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
2893         }
2894         return true;
2895     }
2896 
2897     /*!
2898     @return a string representation of the last read byte
2899     */
2900     std::string get_token_string() const
2901     {
2902         std::array<char, 3> cr{{}};
2903         static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
2904         return std::string{cr.data()};
2905     }
2906 
2907     /*!
2908     @param[in] format   the current format
2909     @param[in] detail   a detailed error message
2910     @param[in] context  further context information
2911     @return a message string to use in the parse_error exceptions
2912     */
2913     std::string exception_message(const input_format_t format,
2914                                   const std::string& detail,
2915                                   const std::string& context) const
2916     {
2917         std::string error_msg = "syntax error while parsing ";
2918 
2919         switch (format)
2920         {
2921             case input_format_t::cbor:
2922                 error_msg += "CBOR";
2923                 break;
2924 
2925             case input_format_t::msgpack:
2926                 error_msg += "MessagePack";
2927                 break;
2928 
2929             case input_format_t::ubjson:
2930                 error_msg += "UBJSON";
2931                 break;
2932 
2933             case input_format_t::bson:
2934                 error_msg += "BSON";
2935                 break;
2936 
2937             case input_format_t::bjdata:
2938                 error_msg += "BJData";
2939                 break;
2940 
2941             case input_format_t::json: // LCOV_EXCL_LINE
2942             default:            // LCOV_EXCL_LINE
2943                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
2944         }
2945 
2946         return concat(error_msg, ' ', context, ": ", detail);
2947     }
2948 
2949   private:
2950     static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
2951 
2952     /// input adapter
2953     InputAdapterType ia;
2954 
2955     /// the current character
2956     char_int_type current = char_traits<char_type>::eof();
2957 
2958     /// the number of characters read
2959     std::size_t chars_read = 0;
2960 
2961     /// whether we can assume little endianness
2962     const bool is_little_endian = little_endianness();
2963 
2964     /// input format
2965     const input_format_t input_format = input_format_t::json;
2966 
2967     /// the SAX parser
2968     json_sax_t* sax = nullptr;
2969 
2970     // excluded markers in bjdata optimized type
2971 #define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
2972     make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
2973 
2974 #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
2975     make_array<bjd_type>(                      \
2976     bjd_type{'C', "char"},                     \
2977     bjd_type{'D', "double"},                   \
2978     bjd_type{'I', "int16"},                    \
2979     bjd_type{'L', "int64"},                    \
2980     bjd_type{'M', "uint64"},                   \
2981     bjd_type{'U', "uint8"},                    \
2982     bjd_type{'d', "single"},                   \
2983     bjd_type{'i', "int8"},                     \
2984     bjd_type{'l', "int32"},                    \
2985     bjd_type{'m', "uint32"},                   \
2986     bjd_type{'u', "uint16"})
2987 
2988   JSON_PRIVATE_UNLESS_TESTED:
2989     // lookup tables
2990     // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
2991     const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
2992         JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
2993 
2994     using bjd_type = std::pair<char_int_type, string_t>;
2995     // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
2996     const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
2997         JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
2998 
2999 #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
3000 #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
3001 };
3002 
3003 #ifndef JSON_HAS_CPP_17
3004     template<typename BasicJsonType, typename InputAdapterType, typename SAX>
3005     constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
3006 #endif
3007 
3008 }  // namespace detail
3009 NLOHMANN_JSON_NAMESPACE_END