#
tokens: 35238/50000 1/161 files (page 17/21)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 17 of 21. Use http://codebase.md/wasdubya/x64dbgmcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── build
│   ├── MCPx64dbg.dp32
│   └── MCPx64dbg.dp64
├── CMakeLists.txt
├── deps
│   ├── pluginsdk
│   │   ├── _dbgfunctions.h
│   │   ├── _plugin_types.h
│   │   ├── _plugins.h
│   │   ├── _scriptapi_argument.h
│   │   ├── _scriptapi_assembler.h
│   │   ├── _scriptapi_bookmark.h
│   │   ├── _scriptapi_comment.h
│   │   ├── _scriptapi_debug.h
│   │   ├── _scriptapi_flag.h
│   │   ├── _scriptapi_function.h
│   │   ├── _scriptapi_gui.h
│   │   ├── _scriptapi_label.h
│   │   ├── _scriptapi_memory.h
│   │   ├── _scriptapi_misc.h
│   │   ├── _scriptapi_module.h
│   │   ├── _scriptapi_pattern.h
│   │   ├── _scriptapi_register.h
│   │   ├── _scriptapi_stack.h
│   │   ├── _scriptapi_symbol.h
│   │   ├── _scriptapi.h
│   │   ├── bridgegraph.h
│   │   ├── bridgelist.h
│   │   ├── bridgemain.h
│   │   ├── dbghelp
│   │   │   ├── dbghelp_x64.a
│   │   │   ├── dbghelp_x64.lib
│   │   │   ├── dbghelp_x86.a
│   │   │   ├── dbghelp_x86.lib
│   │   │   └── dbghelp.h
│   │   ├── DeviceNameResolver
│   │   │   ├── DeviceNameResolver_x64.a
│   │   │   ├── DeviceNameResolver_x64.lib
│   │   │   ├── DeviceNameResolver_x86.a
│   │   │   ├── DeviceNameResolver_x86.lib
│   │   │   └── DeviceNameResolver.h
│   │   ├── jansson
│   │   │   ├── jansson_config.h
│   │   │   ├── jansson_x64.a
│   │   │   ├── jansson_x64.lib
│   │   │   ├── jansson_x64dbg.h
│   │   │   ├── jansson_x86.a
│   │   │   ├── jansson_x86.lib
│   │   │   └── jansson.h
│   │   ├── lz4
│   │   │   ├── lz4_x64.a
│   │   │   ├── lz4_x64.lib
│   │   │   ├── lz4_x86.a
│   │   │   ├── lz4_x86.lib
│   │   │   ├── lz4.h
│   │   │   ├── lz4file.h
│   │   │   └── lz4hc.h
│   │   ├── nlohmann
│   │   │   ├── adl_serializer.hpp
│   │   │   ├── byte_container_with_subtype.hpp
│   │   │   ├── detail
│   │   │   │   ├── abi_macros.hpp
│   │   │   │   ├── conversions
│   │   │   │   │   ├── from_json.hpp
│   │   │   │   │   ├── to_chars.hpp
│   │   │   │   │   └── to_json.hpp
│   │   │   │   ├── exceptions.hpp
│   │   │   │   ├── hash.hpp
│   │   │   │   ├── input
│   │   │   │   │   ├── binary_reader.hpp
│   │   │   │   │   ├── input_adapters.hpp
│   │   │   │   │   ├── json_sax.hpp
│   │   │   │   │   ├── lexer.hpp
│   │   │   │   │   ├── parser.hpp
│   │   │   │   │   └── position_t.hpp
│   │   │   │   ├── iterators
│   │   │   │   │   ├── internal_iterator.hpp
│   │   │   │   │   ├── iter_impl.hpp
│   │   │   │   │   ├── iteration_proxy.hpp
│   │   │   │   │   ├── iterator_traits.hpp
│   │   │   │   │   ├── json_reverse_iterator.hpp
│   │   │   │   │   └── primitive_iterator.hpp
│   │   │   │   ├── json_custom_base_class.hpp
│   │   │   │   ├── json_pointer.hpp
│   │   │   │   ├── json_ref.hpp
│   │   │   │   ├── macro_scope.hpp
│   │   │   │   ├── macro_unscope.hpp
│   │   │   │   ├── meta
│   │   │   │   │   ├── call_std
│   │   │   │   │   │   ├── begin.hpp
│   │   │   │   │   │   └── end.hpp
│   │   │   │   │   ├── cpp_future.hpp
│   │   │   │   │   ├── detected.hpp
│   │   │   │   │   ├── identity_tag.hpp
│   │   │   │   │   ├── is_sax.hpp
│   │   │   │   │   ├── std_fs.hpp
│   │   │   │   │   ├── type_traits.hpp
│   │   │   │   │   └── void_t.hpp
│   │   │   │   ├── output
│   │   │   │   │   ├── binary_writer.hpp
│   │   │   │   │   ├── output_adapters.hpp
│   │   │   │   │   └── serializer.hpp
│   │   │   │   ├── string_concat.hpp
│   │   │   │   ├── string_escape.hpp
│   │   │   │   └── value_t.hpp
│   │   │   ├── json_fwd.hpp
│   │   │   ├── json.hpp
│   │   │   ├── ordered_map.hpp
│   │   │   └── thirdparty
│   │   │       └── hedley
│   │   │           ├── hedley_undef.hpp
│   │   │           └── hedley.hpp
│   │   ├── TitanEngine
│   │   │   ├── TitanEngine_x64.a
│   │   │   ├── TitanEngine_x64.lib
│   │   │   ├── TitanEngine_x86.a
│   │   │   ├── TitanEngine_x86.lib
│   │   │   └── TitanEngine.h
│   │   ├── x32bridge.lib
│   │   ├── x32dbg.lib
│   │   ├── x64bridge.lib
│   │   ├── x64dbg.lib
│   │   └── XEDParse
│   │       ├── XEDParse_x64.a
│   │       ├── XEDParse_x64.lib
│   │       ├── XEDParse_x86.a
│   │       ├── XEDParse_x86.lib
│   │       └── XEDParse.h
│   └── x64dbg_sdk
│       └── pluginsdk
│           ├── _dbgfunctions.h
│           ├── _plugin_types.h
│           ├── _plugins.h
│           ├── _scriptapi_argument.h
│           ├── _scriptapi_assembler.h
│           ├── _scriptapi_bookmark.h
│           ├── _scriptapi_comment.h
│           ├── _scriptapi_debug.h
│           ├── _scriptapi_flag.h
│           ├── _scriptapi_function.h
│           ├── _scriptapi_gui.h
│           ├── _scriptapi_label.h
│           ├── _scriptapi_memory.h
│           ├── _scriptapi_misc.h
│           ├── _scriptapi_module.h
│           ├── _scriptapi_pattern.h
│           ├── _scriptapi_register.h
│           ├── _scriptapi_stack.h
│           ├── _scriptapi_symbol.h
│           ├── _scriptapi.h
│           ├── bridgegraph.h
│           ├── bridgelist.h
│           ├── bridgemain.h
│           ├── dbghelp
│           │   ├── dbghelp_x64.a
│           │   ├── dbghelp_x64.lib
│           │   ├── dbghelp_x86.a
│           │   ├── dbghelp_x86.lib
│           │   └── dbghelp.h
│           ├── DeviceNameResolver
│           │   ├── DeviceNameResolver_x64.a
│           │   ├── DeviceNameResolver_x64.lib
│           │   ├── DeviceNameResolver_x86.a
│           │   ├── DeviceNameResolver_x86.lib
│           │   └── DeviceNameResolver.h
│           ├── jansson
│           │   ├── jansson_config.h
│           │   ├── jansson_x64.a
│           │   ├── jansson_x64.lib
│           │   ├── jansson_x64dbg.h
│           │   ├── jansson_x86.a
│           │   ├── jansson_x86.lib
│           │   └── jansson.h
│           ├── lz4
│           │   ├── lz4_x64.a
│           │   ├── lz4_x64.lib
│           │   ├── lz4_x86.a
│           │   ├── lz4_x86.lib
│           │   ├── lz4.h
│           │   ├── lz4file.h
│           │   └── lz4hc.h
│           ├── TitanEngine
│           │   ├── TitanEngine_x64.a
│           │   ├── TitanEngine_x64.lib
│           │   ├── TitanEngine_x86.a
│           │   ├── TitanEngine_x86.lib
│           │   └── TitanEngine.h
│           ├── TitanEngine_x64.a
│           ├── TitanEngine_x64.lib
│           ├── TitanEngine_x86.a
│           ├── TitanEngine_x86.lib
│           ├── TitanEngine.h
│           ├── x32bridge.lib
│           ├── x32dbg.lib
│           ├── x64bridge.lib
│           ├── x64dbg.lib
│           └── XEDParse
│               ├── XEDParse_x64.a
│               ├── XEDParse_x64.lib
│               ├── XEDParse_x86.a
│               ├── XEDParse_x86.lib
│               └── XEDParse.h
├── include
│   └── nlohmann
│       ├── adl_serializer.hpp
│       ├── byte_container_with_subtype.hpp
│       ├── detail
│       │   ├── abi_macros.hpp
│       │   ├── conversions
│       │   │   ├── from_json.hpp
│       │   │   ├── to_chars.hpp
│       │   │   └── to_json.hpp
│       │   ├── exceptions.hpp
│       │   ├── hash.hpp
│       │   ├── input
│       │   │   ├── binary_reader.hpp
│       │   │   ├── input_adapters.hpp
│       │   │   ├── json_sax.hpp
│       │   │   ├── lexer.hpp
│       │   │   ├── parser.hpp
│       │   │   └── position_t.hpp
│       │   ├── iterators
│       │   │   ├── internal_iterator.hpp
│       │   │   ├── iter_impl.hpp
│       │   │   ├── iteration_proxy.hpp
│       │   │   ├── iterator_traits.hpp
│       │   │   ├── json_reverse_iterator.hpp
│       │   │   └── primitive_iterator.hpp
│       │   ├── json_custom_base_class.hpp
│       │   ├── json_pointer.hpp
│       │   ├── json_ref.hpp
│       │   ├── macro_scope.hpp
│       │   ├── macro_unscope.hpp
│       │   ├── meta
│       │   │   ├── call_std
│       │   │   │   ├── begin.hpp
│       │   │   │   └── end.hpp
│       │   │   ├── cpp_future.hpp
│       │   │   ├── detected.hpp
│       │   │   ├── identity_tag.hpp
│       │   │   ├── is_sax.hpp
│       │   │   ├── std_fs.hpp
│       │   │   ├── type_traits.hpp
│       │   │   └── void_t.hpp
│       │   ├── output
│       │   │   ├── binary_writer.hpp
│       │   │   ├── output_adapters.hpp
│       │   │   └── serializer.hpp
│       │   ├── string_concat.hpp
│       │   ├── string_escape.hpp
│       │   └── value_t.hpp
│       ├── json_fwd.hpp
│       ├── json.hpp
│       ├── ordered_map.hpp
│       └── thirdparty
│           └── hedley
│               ├── hedley_undef.hpp
│               └── hedley.hpp
├── README.md
├── Showcase.gif
├── side profile of a voxel spider walking.jpg
└── src
    ├── MCPx64dbg.cpp
    └── x64dbg.py
```

# Files

--------------------------------------------------------------------------------
/include/nlohmann/detail/input/binary_reader.hpp:
--------------------------------------------------------------------------------

```
   1 | //     __ _____ _____ _____
   2 | //  __|  |   __|     |   | |  JSON for Modern C++
   3 | // |  |  |__   |  |  | | | |  version 3.11.3
   4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   5 | //
   6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   7 | // SPDX-License-Identifier: MIT
   8 | 
   9 | #pragma once
  10 | 
  11 | #include <algorithm> // generate_n
  12 | #include <array> // array
  13 | #include <cmath> // ldexp
  14 | #include <cstddef> // size_t
  15 | #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
  16 | #include <cstdio> // snprintf
  17 | #include <cstring> // memcpy
  18 | #include <iterator> // back_inserter
  19 | #include <limits> // numeric_limits
  20 | #include <string> // char_traits, string
  21 | #include <utility> // make_pair, move
  22 | #include <vector> // vector
  23 | 
  24 | #include <nlohmann/detail/exceptions.hpp>
  25 | #include <nlohmann/detail/input/input_adapters.hpp>
  26 | #include <nlohmann/detail/input/json_sax.hpp>
  27 | #include <nlohmann/detail/input/lexer.hpp>
  28 | #include <nlohmann/detail/macro_scope.hpp>
  29 | #include <nlohmann/detail/meta/is_sax.hpp>
  30 | #include <nlohmann/detail/meta/type_traits.hpp>
  31 | #include <nlohmann/detail/string_concat.hpp>
  32 | #include <nlohmann/detail/value_t.hpp>
  33 | 
  34 | NLOHMANN_JSON_NAMESPACE_BEGIN
  35 | namespace detail
  36 | {
  37 | 
  38 | /// how to treat CBOR tags
  39 | enum class cbor_tag_handler_t
  40 | {
  41 |     error,   ///< throw a parse_error exception in case of a tag
  42 |     ignore,  ///< ignore tags
  43 |     store    ///< store tags as binary type
  44 | };
  45 | 
  46 | /*!
  47 | @brief determine system byte order
  48 | 
  49 | @return true if and only if system's byte order is little endian
  50 | 
  51 | @note from https://stackoverflow.com/a/1001328/266378
  52 | */
  53 | static inline bool little_endianness(int num = 1) noexcept
  54 | {
  55 |     return *reinterpret_cast<char*>(&num) == 1;
  56 | }
  57 | 
  58 | ///////////////////
  59 | // binary reader //
  60 | ///////////////////
  61 | 
  62 | /*!
  63 | @brief deserialization of CBOR, MessagePack, and UBJSON values
  64 | */
  65 | template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
  66 | class binary_reader
  67 | {
  68 |     using number_integer_t = typename BasicJsonType::number_integer_t;
  69 |     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
  70 |     using number_float_t = typename BasicJsonType::number_float_t;
  71 |     using string_t = typename BasicJsonType::string_t;
  72 |     using binary_t = typename BasicJsonType::binary_t;
  73 |     using json_sax_t = SAX;
  74 |     using char_type = typename InputAdapterType::char_type;
  75 |     using char_int_type = typename char_traits<char_type>::int_type;
  76 | 
  77 |   public:
  78 |     /*!
  79 |     @brief create a binary reader
  80 | 
  81 |     @param[in] adapter  input adapter to read from
  82 |     */
  83 |     explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
  84 |     {
  85 |         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
  86 |     }
  87 | 
  88 |     // make class move-only
  89 |     binary_reader(const binary_reader&) = delete;
  90 |     binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
  91 |     binary_reader& operator=(const binary_reader&) = delete;
  92 |     binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
  93 |     ~binary_reader() = default;
  94 | 
  95 |     /*!
  96 |     @param[in] format  the binary format to parse
  97 |     @param[in] sax_    a SAX event processor
  98 |     @param[in] strict  whether to expect the input to be consumed completed
  99 |     @param[in] tag_handler  how to treat CBOR tags
 100 | 
 101 |     @return whether parsing was successful
 102 |     */
 103 |     JSON_HEDLEY_NON_NULL(3)
 104 |     bool sax_parse(const input_format_t format,
 105 |                    json_sax_t* sax_,
 106 |                    const bool strict = true,
 107 |                    const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
 108 |     {
 109 |         sax = sax_;
 110 |         bool result = false;
 111 | 
 112 |         switch (format)
 113 |         {
 114 |             case input_format_t::bson:
 115 |                 result = parse_bson_internal();
 116 |                 break;
 117 | 
 118 |             case input_format_t::cbor:
 119 |                 result = parse_cbor_internal(true, tag_handler);
 120 |                 break;
 121 | 
 122 |             case input_format_t::msgpack:
 123 |                 result = parse_msgpack_internal();
 124 |                 break;
 125 | 
 126 |             case input_format_t::ubjson:
 127 |             case input_format_t::bjdata:
 128 |                 result = parse_ubjson_internal();
 129 |                 break;
 130 | 
 131 |             case input_format_t::json: // LCOV_EXCL_LINE
 132 |             default:            // LCOV_EXCL_LINE
 133 |                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
 134 |         }
 135 | 
 136 |         // strict mode: next byte must be EOF
 137 |         if (result && strict)
 138 |         {
 139 |             if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
 140 |             {
 141 |                 get_ignore_noop();
 142 |             }
 143 |             else
 144 |             {
 145 |                 get();
 146 |             }
 147 | 
 148 |             if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
 149 |             {
 150 |                 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
 151 |                                         exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
 152 |             }
 153 |         }
 154 | 
 155 |         return result;
 156 |     }
 157 | 
 158 |   private:
 159 |     //////////
 160 |     // BSON //
 161 |     //////////
 162 | 
 163 |     /*!
 164 |     @brief Reads in a BSON-object and passes it to the SAX-parser.
 165 |     @return whether a valid BSON-value was passed to the SAX parser
 166 |     */
 167 |     bool parse_bson_internal()
 168 |     {
 169 |         std::int32_t document_size{};
 170 |         get_number<std::int32_t, true>(input_format_t::bson, document_size);
 171 | 
 172 |         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
 173 |         {
 174 |             return false;
 175 |         }
 176 | 
 177 |         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
 178 |         {
 179 |             return false;
 180 |         }
 181 | 
 182 |         return sax->end_object();
 183 |     }
 184 | 
 185 |     /*!
 186 |     @brief Parses a C-style string from the BSON input.
 187 |     @param[in,out] result  A reference to the string variable where the read
 188 |                             string is to be stored.
 189 |     @return `true` if the \x00-byte indicating the end of the string was
 190 |              encountered before the EOF; false` indicates an unexpected EOF.
 191 |     */
 192 |     bool get_bson_cstr(string_t& result)
 193 |     {
 194 |         auto out = std::back_inserter(result);
 195 |         while (true)
 196 |         {
 197 |             get();
 198 |             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
 199 |             {
 200 |                 return false;
 201 |             }
 202 |             if (current == 0x00)
 203 |             {
 204 |                 return true;
 205 |             }
 206 |             *out++ = static_cast<typename string_t::value_type>(current);
 207 |         }
 208 |     }
 209 | 
 210 |     /*!
 211 |     @brief Parses a zero-terminated string of length @a len from the BSON
 212 |            input.
 213 |     @param[in] len  The length (including the zero-byte at the end) of the
 214 |                     string to be read.
 215 |     @param[in,out] result  A reference to the string variable where the read
 216 |                             string is to be stored.
 217 |     @tparam NumberType The type of the length @a len
 218 |     @pre len >= 1
 219 |     @return `true` if the string was successfully parsed
 220 |     */
 221 |     template<typename NumberType>
 222 |     bool get_bson_string(const NumberType len, string_t& result)
 223 |     {
 224 |         if (JSON_HEDLEY_UNLIKELY(len < 1))
 225 |         {
 226 |             auto last_token = get_token_string();
 227 |             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
 228 |                                     exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
 229 |         }
 230 | 
 231 |         return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
 232 |     }
 233 | 
 234 |     /*!
 235 |     @brief Parses a byte array input of length @a len from the BSON input.
 236 |     @param[in] len  The length of the byte array to be read.
 237 |     @param[in,out] result  A reference to the binary variable where the read
 238 |                             array is to be stored.
 239 |     @tparam NumberType The type of the length @a len
 240 |     @pre len >= 0
 241 |     @return `true` if the byte array was successfully parsed
 242 |     */
 243 |     template<typename NumberType>
 244 |     bool get_bson_binary(const NumberType len, binary_t& result)
 245 |     {
 246 |         if (JSON_HEDLEY_UNLIKELY(len < 0))
 247 |         {
 248 |             auto last_token = get_token_string();
 249 |             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
 250 |                                     exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
 251 |         }
 252 | 
 253 |         // All BSON binary values have a subtype
 254 |         std::uint8_t subtype{};
 255 |         get_number<std::uint8_t>(input_format_t::bson, subtype);
 256 |         result.set_subtype(subtype);
 257 | 
 258 |         return get_binary(input_format_t::bson, len, result);
 259 |     }
 260 | 
 261 |     /*!
 262 |     @brief Read a BSON document element of the given @a element_type.
 263 |     @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
 264 |     @param[in] element_type_parse_position The position in the input stream,
 265 |                where the `element_type` was read.
 266 |     @warning Not all BSON element types are supported yet. An unsupported
 267 |              @a element_type will give rise to a parse_error.114:
 268 |              Unsupported BSON record type 0x...
 269 |     @return whether a valid BSON-object/array was passed to the SAX parser
 270 |     */
 271 |     bool parse_bson_element_internal(const char_int_type element_type,
 272 |                                      const std::size_t element_type_parse_position)
 273 |     {
 274 |         switch (element_type)
 275 |         {
 276 |             case 0x01: // double
 277 |             {
 278 |                 double number{};
 279 |                 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
 280 |             }
 281 | 
 282 |             case 0x02: // string
 283 |             {
 284 |                 std::int32_t len{};
 285 |                 string_t value;
 286 |                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
 287 |             }
 288 | 
 289 |             case 0x03: // object
 290 |             {
 291 |                 return parse_bson_internal();
 292 |             }
 293 | 
 294 |             case 0x04: // array
 295 |             {
 296 |                 return parse_bson_array();
 297 |             }
 298 | 
 299 |             case 0x05: // binary
 300 |             {
 301 |                 std::int32_t len{};
 302 |                 binary_t value;
 303 |                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
 304 |             }
 305 | 
 306 |             case 0x08: // boolean
 307 |             {
 308 |                 return sax->boolean(get() != 0);
 309 |             }
 310 | 
 311 |             case 0x0A: // null
 312 |             {
 313 |                 return sax->null();
 314 |             }
 315 | 
 316 |             case 0x10: // int32
 317 |             {
 318 |                 std::int32_t value{};
 319 |                 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
 320 |             }
 321 | 
 322 |             case 0x12: // int64
 323 |             {
 324 |                 std::int64_t value{};
 325 |                 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
 326 |             }
 327 | 
 328 |             default: // anything else not supported (yet)
 329 |             {
 330 |                 std::array<char, 3> cr{{}};
 331 |                 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
 332 |                 const std::string cr_str{cr.data()};
 333 |                 return sax->parse_error(element_type_parse_position, cr_str,
 334 |                                         parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
 335 |             }
 336 |         }
 337 |     }
 338 | 
 339 |     /*!
 340 |     @brief Read a BSON element list (as specified in the BSON-spec)
 341 | 
 342 |     The same binary layout is used for objects and arrays, hence it must be
 343 |     indicated with the argument @a is_array which one is expected
 344 |     (true --> array, false --> object).
 345 | 
 346 |     @param[in] is_array Determines if the element list being read is to be
 347 |                         treated as an object (@a is_array == false), or as an
 348 |                         array (@a is_array == true).
 349 |     @return whether a valid BSON-object/array was passed to the SAX parser
 350 |     */
 351 |     bool parse_bson_element_list(const bool is_array)
 352 |     {
 353 |         string_t key;
 354 | 
 355 |         while (auto element_type = get())
 356 |         {
 357 |             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
 358 |             {
 359 |                 return false;
 360 |             }
 361 | 
 362 |             const std::size_t element_type_parse_position = chars_read;
 363 |             if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
 364 |             {
 365 |                 return false;
 366 |             }
 367 | 
 368 |             if (!is_array && !sax->key(key))
 369 |             {
 370 |                 return false;
 371 |             }
 372 | 
 373 |             if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
 374 |             {
 375 |                 return false;
 376 |             }
 377 | 
 378 |             // get_bson_cstr only appends
 379 |             key.clear();
 380 |         }
 381 | 
 382 |         return true;
 383 |     }
 384 | 
 385 |     /*!
 386 |     @brief Reads an array from the BSON input and passes it to the SAX-parser.
 387 |     @return whether a valid BSON-array was passed to the SAX parser
 388 |     */
 389 |     bool parse_bson_array()
 390 |     {
 391 |         std::int32_t document_size{};
 392 |         get_number<std::int32_t, true>(input_format_t::bson, document_size);
 393 | 
 394 |         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
 395 |         {
 396 |             return false;
 397 |         }
 398 | 
 399 |         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
 400 |         {
 401 |             return false;
 402 |         }
 403 | 
 404 |         return sax->end_array();
 405 |     }
 406 | 
 407 |     //////////
 408 |     // CBOR //
 409 |     //////////
 410 | 
 411 |     /*!
 412 |     @param[in] get_char  whether a new character should be retrieved from the
 413 |                          input (true) or whether the last read character should
 414 |                          be considered instead (false)
 415 |     @param[in] tag_handler how CBOR tags should be treated
 416 | 
 417 |     @return whether a valid CBOR value was passed to the SAX parser
 418 |     */
 419 |     bool parse_cbor_internal(const bool get_char,
 420 |                              const cbor_tag_handler_t tag_handler)
 421 |     {
 422 |         switch (get_char ? get() : current)
 423 |         {
 424 |             // EOF
 425 |             case char_traits<char_type>::eof():
 426 |                 return unexpect_eof(input_format_t::cbor, "value");
 427 | 
 428 |             // Integer 0x00..0x17 (0..23)
 429 |             case 0x00:
 430 |             case 0x01:
 431 |             case 0x02:
 432 |             case 0x03:
 433 |             case 0x04:
 434 |             case 0x05:
 435 |             case 0x06:
 436 |             case 0x07:
 437 |             case 0x08:
 438 |             case 0x09:
 439 |             case 0x0A:
 440 |             case 0x0B:
 441 |             case 0x0C:
 442 |             case 0x0D:
 443 |             case 0x0E:
 444 |             case 0x0F:
 445 |             case 0x10:
 446 |             case 0x11:
 447 |             case 0x12:
 448 |             case 0x13:
 449 |             case 0x14:
 450 |             case 0x15:
 451 |             case 0x16:
 452 |             case 0x17:
 453 |                 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
 454 | 
 455 |             case 0x18: // Unsigned integer (one-byte uint8_t follows)
 456 |             {
 457 |                 std::uint8_t number{};
 458 |                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
 459 |             }
 460 | 
 461 |             case 0x19: // Unsigned integer (two-byte uint16_t follows)
 462 |             {
 463 |                 std::uint16_t number{};
 464 |                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
 465 |             }
 466 | 
 467 |             case 0x1A: // Unsigned integer (four-byte uint32_t follows)
 468 |             {
 469 |                 std::uint32_t number{};
 470 |                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
 471 |             }
 472 | 
 473 |             case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
 474 |             {
 475 |                 std::uint64_t number{};
 476 |                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
 477 |             }
 478 | 
 479 |             // Negative integer -1-0x00..-1-0x17 (-1..-24)
 480 |             case 0x20:
 481 |             case 0x21:
 482 |             case 0x22:
 483 |             case 0x23:
 484 |             case 0x24:
 485 |             case 0x25:
 486 |             case 0x26:
 487 |             case 0x27:
 488 |             case 0x28:
 489 |             case 0x29:
 490 |             case 0x2A:
 491 |             case 0x2B:
 492 |             case 0x2C:
 493 |             case 0x2D:
 494 |             case 0x2E:
 495 |             case 0x2F:
 496 |             case 0x30:
 497 |             case 0x31:
 498 |             case 0x32:
 499 |             case 0x33:
 500 |             case 0x34:
 501 |             case 0x35:
 502 |             case 0x36:
 503 |             case 0x37:
 504 |                 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
 505 | 
 506 |             case 0x38: // Negative integer (one-byte uint8_t follows)
 507 |             {
 508 |                 std::uint8_t number{};
 509 |                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
 510 |             }
 511 | 
 512 |             case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
 513 |             {
 514 |                 std::uint16_t number{};
 515 |                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
 516 |             }
 517 | 
 518 |             case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
 519 |             {
 520 |                 std::uint32_t number{};
 521 |                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
 522 |             }
 523 | 
 524 |             case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
 525 |             {
 526 |                 std::uint64_t number{};
 527 |                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
 528 |                         - static_cast<number_integer_t>(number));
 529 |             }
 530 | 
 531 |             // Binary data (0x00..0x17 bytes follow)
 532 |             case 0x40:
 533 |             case 0x41:
 534 |             case 0x42:
 535 |             case 0x43:
 536 |             case 0x44:
 537 |             case 0x45:
 538 |             case 0x46:
 539 |             case 0x47:
 540 |             case 0x48:
 541 |             case 0x49:
 542 |             case 0x4A:
 543 |             case 0x4B:
 544 |             case 0x4C:
 545 |             case 0x4D:
 546 |             case 0x4E:
 547 |             case 0x4F:
 548 |             case 0x50:
 549 |             case 0x51:
 550 |             case 0x52:
 551 |             case 0x53:
 552 |             case 0x54:
 553 |             case 0x55:
 554 |             case 0x56:
 555 |             case 0x57:
 556 |             case 0x58: // Binary data (one-byte uint8_t for n follows)
 557 |             case 0x59: // Binary data (two-byte uint16_t for n follow)
 558 |             case 0x5A: // Binary data (four-byte uint32_t for n follow)
 559 |             case 0x5B: // Binary data (eight-byte uint64_t for n follow)
 560 |             case 0x5F: // Binary data (indefinite length)
 561 |             {
 562 |                 binary_t b;
 563 |                 return get_cbor_binary(b) && sax->binary(b);
 564 |             }
 565 | 
 566 |             // UTF-8 string (0x00..0x17 bytes follow)
 567 |             case 0x60:
 568 |             case 0x61:
 569 |             case 0x62:
 570 |             case 0x63:
 571 |             case 0x64:
 572 |             case 0x65:
 573 |             case 0x66:
 574 |             case 0x67:
 575 |             case 0x68:
 576 |             case 0x69:
 577 |             case 0x6A:
 578 |             case 0x6B:
 579 |             case 0x6C:
 580 |             case 0x6D:
 581 |             case 0x6E:
 582 |             case 0x6F:
 583 |             case 0x70:
 584 |             case 0x71:
 585 |             case 0x72:
 586 |             case 0x73:
 587 |             case 0x74:
 588 |             case 0x75:
 589 |             case 0x76:
 590 |             case 0x77:
 591 |             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
 592 |             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
 593 |             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
 594 |             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
 595 |             case 0x7F: // UTF-8 string (indefinite length)
 596 |             {
 597 |                 string_t s;
 598 |                 return get_cbor_string(s) && sax->string(s);
 599 |             }
 600 | 
 601 |             // array (0x00..0x17 data items follow)
 602 |             case 0x80:
 603 |             case 0x81:
 604 |             case 0x82:
 605 |             case 0x83:
 606 |             case 0x84:
 607 |             case 0x85:
 608 |             case 0x86:
 609 |             case 0x87:
 610 |             case 0x88:
 611 |             case 0x89:
 612 |             case 0x8A:
 613 |             case 0x8B:
 614 |             case 0x8C:
 615 |             case 0x8D:
 616 |             case 0x8E:
 617 |             case 0x8F:
 618 |             case 0x90:
 619 |             case 0x91:
 620 |             case 0x92:
 621 |             case 0x93:
 622 |             case 0x94:
 623 |             case 0x95:
 624 |             case 0x96:
 625 |             case 0x97:
 626 |                 return get_cbor_array(
 627 |                            conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
 628 | 
 629 |             case 0x98: // array (one-byte uint8_t for n follows)
 630 |             {
 631 |                 std::uint8_t len{};
 632 |                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
 633 |             }
 634 | 
 635 |             case 0x99: // array (two-byte uint16_t for n follow)
 636 |             {
 637 |                 std::uint16_t len{};
 638 |                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
 639 |             }
 640 | 
 641 |             case 0x9A: // array (four-byte uint32_t for n follow)
 642 |             {
 643 |                 std::uint32_t len{};
 644 |                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
 645 |             }
 646 | 
 647 |             case 0x9B: // array (eight-byte uint64_t for n follow)
 648 |             {
 649 |                 std::uint64_t len{};
 650 |                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
 651 |             }
 652 | 
 653 |             case 0x9F: // array (indefinite length)
 654 |                 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
 655 | 
 656 |             // map (0x00..0x17 pairs of data items follow)
 657 |             case 0xA0:
 658 |             case 0xA1:
 659 |             case 0xA2:
 660 |             case 0xA3:
 661 |             case 0xA4:
 662 |             case 0xA5:
 663 |             case 0xA6:
 664 |             case 0xA7:
 665 |             case 0xA8:
 666 |             case 0xA9:
 667 |             case 0xAA:
 668 |             case 0xAB:
 669 |             case 0xAC:
 670 |             case 0xAD:
 671 |             case 0xAE:
 672 |             case 0xAF:
 673 |             case 0xB0:
 674 |             case 0xB1:
 675 |             case 0xB2:
 676 |             case 0xB3:
 677 |             case 0xB4:
 678 |             case 0xB5:
 679 |             case 0xB6:
 680 |             case 0xB7:
 681 |                 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
 682 | 
 683 |             case 0xB8: // map (one-byte uint8_t for n follows)
 684 |             {
 685 |                 std::uint8_t len{};
 686 |                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
 687 |             }
 688 | 
 689 |             case 0xB9: // map (two-byte uint16_t for n follow)
 690 |             {
 691 |                 std::uint16_t len{};
 692 |                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
 693 |             }
 694 | 
 695 |             case 0xBA: // map (four-byte uint32_t for n follow)
 696 |             {
 697 |                 std::uint32_t len{};
 698 |                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
 699 |             }
 700 | 
 701 |             case 0xBB: // map (eight-byte uint64_t for n follow)
 702 |             {
 703 |                 std::uint64_t len{};
 704 |                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
 705 |             }
 706 | 
 707 |             case 0xBF: // map (indefinite length)
 708 |                 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
 709 | 
 710 |             case 0xC6: // tagged item
 711 |             case 0xC7:
 712 |             case 0xC8:
 713 |             case 0xC9:
 714 |             case 0xCA:
 715 |             case 0xCB:
 716 |             case 0xCC:
 717 |             case 0xCD:
 718 |             case 0xCE:
 719 |             case 0xCF:
 720 |             case 0xD0:
 721 |             case 0xD1:
 722 |             case 0xD2:
 723 |             case 0xD3:
 724 |             case 0xD4:
 725 |             case 0xD8: // tagged item (1 bytes follow)
 726 |             case 0xD9: // tagged item (2 bytes follow)
 727 |             case 0xDA: // tagged item (4 bytes follow)
 728 |             case 0xDB: // tagged item (8 bytes follow)
 729 |             {
 730 |                 switch (tag_handler)
 731 |                 {
 732 |                     case cbor_tag_handler_t::error:
 733 |                     {
 734 |                         auto last_token = get_token_string();
 735 |                         return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
 736 |                                                 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
 737 |                     }
 738 | 
 739 |                     case cbor_tag_handler_t::ignore:
 740 |                     {
 741 |                         // ignore binary subtype
 742 |                         switch (current)
 743 |                         {
 744 |                             case 0xD8:
 745 |                             {
 746 |                                 std::uint8_t subtype_to_ignore{};
 747 |                                 get_number(input_format_t::cbor, subtype_to_ignore);
 748 |                                 break;
 749 |                             }
 750 |                             case 0xD9:
 751 |                             {
 752 |                                 std::uint16_t subtype_to_ignore{};
 753 |                                 get_number(input_format_t::cbor, subtype_to_ignore);
 754 |                                 break;
 755 |                             }
 756 |                             case 0xDA:
 757 |                             {
 758 |                                 std::uint32_t subtype_to_ignore{};
 759 |                                 get_number(input_format_t::cbor, subtype_to_ignore);
 760 |                                 break;
 761 |                             }
 762 |                             case 0xDB:
 763 |                             {
 764 |                                 std::uint64_t subtype_to_ignore{};
 765 |                                 get_number(input_format_t::cbor, subtype_to_ignore);
 766 |                                 break;
 767 |                             }
 768 |                             default:
 769 |                                 break;
 770 |                         }
 771 |                         return parse_cbor_internal(true, tag_handler);
 772 |                     }
 773 | 
 774 |                     case cbor_tag_handler_t::store:
 775 |                     {
 776 |                         binary_t b;
 777 |                         // use binary subtype and store in binary container
 778 |                         switch (current)
 779 |                         {
 780 |                             case 0xD8:
 781 |                             {
 782 |                                 std::uint8_t subtype{};
 783 |                                 get_number(input_format_t::cbor, subtype);
 784 |                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
 785 |                                 break;
 786 |                             }
 787 |                             case 0xD9:
 788 |                             {
 789 |                                 std::uint16_t subtype{};
 790 |                                 get_number(input_format_t::cbor, subtype);
 791 |                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
 792 |                                 break;
 793 |                             }
 794 |                             case 0xDA:
 795 |                             {
 796 |                                 std::uint32_t subtype{};
 797 |                                 get_number(input_format_t::cbor, subtype);
 798 |                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
 799 |                                 break;
 800 |                             }
 801 |                             case 0xDB:
 802 |                             {
 803 |                                 std::uint64_t subtype{};
 804 |                                 get_number(input_format_t::cbor, subtype);
 805 |                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
 806 |                                 break;
 807 |                             }
 808 |                             default:
 809 |                                 return parse_cbor_internal(true, tag_handler);
 810 |                         }
 811 |                         get();
 812 |                         return get_cbor_binary(b) && sax->binary(b);
 813 |                     }
 814 | 
 815 |                     default:                 // LCOV_EXCL_LINE
 816 |                         JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
 817 |                         return false;        // LCOV_EXCL_LINE
 818 |                 }
 819 |             }
 820 | 
 821 |             case 0xF4: // false
 822 |                 return sax->boolean(false);
 823 | 
 824 |             case 0xF5: // true
 825 |                 return sax->boolean(true);
 826 | 
 827 |             case 0xF6: // null
 828 |                 return sax->null();
 829 | 
 830 |             case 0xF9: // Half-Precision Float (two-byte IEEE 754)
 831 |             {
 832 |                 const auto byte1_raw = get();
 833 |                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
 834 |                 {
 835 |                     return false;
 836 |                 }
 837 |                 const auto byte2_raw = get();
 838 |                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
 839 |                 {
 840 |                     return false;
 841 |                 }
 842 | 
 843 |                 const auto byte1 = static_cast<unsigned char>(byte1_raw);
 844 |                 const auto byte2 = static_cast<unsigned char>(byte2_raw);
 845 | 
 846 |                 // code from RFC 7049, Appendix D, Figure 3:
 847 |                 // As half-precision floating-point numbers were only added
 848 |                 // to IEEE 754 in 2008, today's programming platforms often
 849 |                 // still only have limited support for them. It is very
 850 |                 // easy to include at least decoding support for them even
 851 |                 // without such support. An example of a small decoder for
 852 |                 // half-precision floating-point numbers in the C language
 853 |                 // is shown in Fig. 3.
 854 |                 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
 855 |                 const double val = [&half]
 856 |                 {
 857 |                     const int exp = (half >> 10u) & 0x1Fu;
 858 |                     const unsigned int mant = half & 0x3FFu;
 859 |                     JSON_ASSERT(0 <= exp&& exp <= 32);
 860 |                     JSON_ASSERT(mant <= 1024);
 861 |                     switch (exp)
 862 |                     {
 863 |                         case 0:
 864 |                             return std::ldexp(mant, -24);
 865 |                         case 31:
 866 |                             return (mant == 0)
 867 |                             ? std::numeric_limits<double>::infinity()
 868 |                             : std::numeric_limits<double>::quiet_NaN();
 869 |                         default:
 870 |                             return std::ldexp(mant + 1024, exp - 25);
 871 |                     }
 872 |                 }();
 873 |                 return sax->number_float((half & 0x8000u) != 0
 874 |                                          ? static_cast<number_float_t>(-val)
 875 |                                          : static_cast<number_float_t>(val), "");
 876 |             }
 877 | 
 878 |             case 0xFA: // Single-Precision Float (four-byte IEEE 754)
 879 |             {
 880 |                 float number{};
 881 |                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
 882 |             }
 883 | 
 884 |             case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
 885 |             {
 886 |                 double number{};
 887 |                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
 888 |             }
 889 | 
 890 |             default: // anything else (0xFF is handled inside the other types)
 891 |             {
 892 |                 auto last_token = get_token_string();
 893 |                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
 894 |                                         exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
 895 |             }
 896 |         }
 897 |     }
 898 | 
 899 |     /*!
 900 |     @brief reads a CBOR string
 901 | 
 902 |     This function first reads starting bytes to determine the expected
 903 |     string length and then copies this number of bytes into a string.
 904 |     Additionally, CBOR's strings with indefinite lengths are supported.
 905 | 
 906 |     @param[out] result  created string
 907 | 
 908 |     @return whether string creation completed
 909 |     */
 910 |     bool get_cbor_string(string_t& result)
 911 |     {
 912 |         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
 913 |         {
 914 |             return false;
 915 |         }
 916 | 
 917 |         switch (current)
 918 |         {
 919 |             // UTF-8 string (0x00..0x17 bytes follow)
 920 |             case 0x60:
 921 |             case 0x61:
 922 |             case 0x62:
 923 |             case 0x63:
 924 |             case 0x64:
 925 |             case 0x65:
 926 |             case 0x66:
 927 |             case 0x67:
 928 |             case 0x68:
 929 |             case 0x69:
 930 |             case 0x6A:
 931 |             case 0x6B:
 932 |             case 0x6C:
 933 |             case 0x6D:
 934 |             case 0x6E:
 935 |             case 0x6F:
 936 |             case 0x70:
 937 |             case 0x71:
 938 |             case 0x72:
 939 |             case 0x73:
 940 |             case 0x74:
 941 |             case 0x75:
 942 |             case 0x76:
 943 |             case 0x77:
 944 |             {
 945 |                 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
 946 |             }
 947 | 
 948 |             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
 949 |             {
 950 |                 std::uint8_t len{};
 951 |                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
 952 |             }
 953 | 
 954 |             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
 955 |             {
 956 |                 std::uint16_t len{};
 957 |                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
 958 |             }
 959 | 
 960 |             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
 961 |             {
 962 |                 std::uint32_t len{};
 963 |                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
 964 |             }
 965 | 
 966 |             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
 967 |             {
 968 |                 std::uint64_t len{};
 969 |                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
 970 |             }
 971 | 
 972 |             case 0x7F: // UTF-8 string (indefinite length)
 973 |             {
 974 |                 while (get() != 0xFF)
 975 |                 {
 976 |                     string_t chunk;
 977 |                     if (!get_cbor_string(chunk))
 978 |                     {
 979 |                         return false;
 980 |                     }
 981 |                     result.append(chunk);
 982 |                 }
 983 |                 return true;
 984 |             }
 985 | 
 986 |             default:
 987 |             {
 988 |                 auto last_token = get_token_string();
 989 |                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
 990 |                                         exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
 991 |             }
 992 |         }
 993 |     }
 994 | 
 995 |     /*!
 996 |     @brief reads a CBOR byte array
 997 | 
 998 |     This function first reads starting bytes to determine the expected
 999 |     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
3010 | 
```
Page 17/21FirstPrevNextLast