Merge branch 'develop' of https://github.com/nlohmann/json into clang_windows
Conflicts: include/nlohmann/detail/input/binary_reader.hpp include/nlohmann/detail/input/input_adapters.hpp include/nlohmann/detail/input/lexer.hpp include/nlohmann/detail/output/binary_writer.hpp include/nlohmann/json.hpp single_include/nlohmann/json.hpp
This commit is contained in:
		
						commit
						ac3922c7aa
					
				
					 128 changed files with 7773 additions and 2268 deletions
				
			
		| 
						 | 
				
			
			@ -54,6 +54,8 @@ class binary_reader
 | 
			
		|||
    using string_t = typename BasicJsonType::string_t;
 | 
			
		||||
    using binary_t = typename BasicJsonType::binary_t;
 | 
			
		||||
    using json_sax_t = SAX;
 | 
			
		||||
    using char_type = typename InputAdapterType::char_type;
 | 
			
		||||
    using char_int_type = typename std::char_traits<char_type>::int_type;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			@ -122,7 +124,7 @@ class binary_reader
 | 
			
		|||
                get();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char>::eof()))
 | 
			
		||||
            if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
 | 
			
		||||
            {
 | 
			
		||||
                return sax->parse_error(chars_read, get_token_string(),
 | 
			
		||||
                                        parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +145,7 @@ class binary_reader
 | 
			
		|||
    */
 | 
			
		||||
    bool parse_bson_internal()
 | 
			
		||||
    {
 | 
			
		||||
        std::int32_t document_size;
 | 
			
		||||
        std::int32_t document_size{};
 | 
			
		||||
        get_number<std::int32_t, true>(input_format_t::bson, document_size);
 | 
			
		||||
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
 | 
			
		||||
| 
						 | 
				
			
			@ -180,10 +182,8 @@ class binary_reader
 | 
			
		|||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            *out++ = static_cast<char>(current);
 | 
			
		||||
            *out++ = static_cast<typename string_t::value_type>(current);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			@ -206,7 +206,7 @@ class binary_reader
 | 
			
		|||
            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char>::eof();
 | 
			
		||||
        return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +228,7 @@ class binary_reader
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // All BSON binary values have a subtype
 | 
			
		||||
        std::uint8_t subtype;
 | 
			
		||||
        std::uint8_t subtype{};
 | 
			
		||||
        get_number<std::uint8_t>(input_format_t::bson, subtype);
 | 
			
		||||
        result.set_subtype(subtype);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -245,20 +245,20 @@ class binary_reader
 | 
			
		|||
             Unsupported BSON record type 0x...
 | 
			
		||||
    @return whether a valid BSON-object/array was passed to the SAX parser
 | 
			
		||||
    */
 | 
			
		||||
    bool parse_bson_element_internal(const int element_type,
 | 
			
		||||
    bool parse_bson_element_internal(const char_int_type element_type,
 | 
			
		||||
                                     const std::size_t element_type_parse_position)
 | 
			
		||||
    {
 | 
			
		||||
        switch (element_type)
 | 
			
		||||
        {
 | 
			
		||||
            case 0x01: // double
 | 
			
		||||
            {
 | 
			
		||||
                double number;
 | 
			
		||||
                double number{};
 | 
			
		||||
                return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x02: // string
 | 
			
		||||
            {
 | 
			
		||||
                std::int32_t len;
 | 
			
		||||
                std::int32_t len{};
 | 
			
		||||
                string_t value;
 | 
			
		||||
                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -275,7 +275,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0x05: // binary
 | 
			
		||||
            {
 | 
			
		||||
                std::int32_t len;
 | 
			
		||||
                std::int32_t len{};
 | 
			
		||||
                binary_t value;
 | 
			
		||||
                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -292,13 +292,13 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0x10: // int32
 | 
			
		||||
            {
 | 
			
		||||
                std::int32_t value;
 | 
			
		||||
                std::int32_t value{};
 | 
			
		||||
                return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x12: // int64
 | 
			
		||||
            {
 | 
			
		||||
                std::int64_t value;
 | 
			
		||||
                std::int64_t value{};
 | 
			
		||||
                return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -327,7 +327,7 @@ class binary_reader
 | 
			
		|||
    {
 | 
			
		||||
        string_t key;
 | 
			
		||||
 | 
			
		||||
        while (int element_type = get())
 | 
			
		||||
        while (auto element_type = get())
 | 
			
		||||
        {
 | 
			
		||||
            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -363,7 +363,7 @@ class binary_reader
 | 
			
		|||
    */
 | 
			
		||||
    bool parse_bson_array()
 | 
			
		||||
    {
 | 
			
		||||
        std::int32_t document_size;
 | 
			
		||||
        std::int32_t document_size{};
 | 
			
		||||
        get_number<std::int32_t, true>(input_format_t::bson, document_size);
 | 
			
		||||
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
 | 
			
		||||
| 
						 | 
				
			
			@ -395,7 +395,7 @@ class binary_reader
 | 
			
		|||
        switch (get_char ? get() : current)
 | 
			
		||||
        {
 | 
			
		||||
            // EOF
 | 
			
		||||
            case std::char_traits<char>::eof():
 | 
			
		||||
            case std::char_traits<char_type>::eof():
 | 
			
		||||
                return unexpect_eof(input_format_t::cbor, "value");
 | 
			
		||||
 | 
			
		||||
            // Integer 0x00..0x17 (0..23)
 | 
			
		||||
| 
						 | 
				
			
			@ -427,25 +427,25 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0x18: // Unsigned integer (one-byte uint8_t follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t number;
 | 
			
		||||
                std::uint8_t number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x19: // Unsigned integer (two-byte uint16_t follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t number;
 | 
			
		||||
                std::uint16_t number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t number;
 | 
			
		||||
                std::uint32_t number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint64_t number;
 | 
			
		||||
                std::uint64_t number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -478,25 +478,25 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0x38: // Negative integer (one-byte uint8_t follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t number;
 | 
			
		||||
                std::uint8_t number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t number;
 | 
			
		||||
                std::uint16_t number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t number;
 | 
			
		||||
                std::uint32_t number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint64_t number;
 | 
			
		||||
                std::uint64_t number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
 | 
			
		||||
                        - static_cast<number_integer_t>(number));
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -600,25 +600,25 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0x98: // array (one-byte uint8_t for n follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t len;
 | 
			
		||||
                std::uint8_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x99: // array (two-byte uint16_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t len;
 | 
			
		||||
                std::uint16_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x9A: // array (four-byte uint32_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t len;
 | 
			
		||||
                std::uint32_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x9B: // array (eight-byte uint64_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint64_t len;
 | 
			
		||||
                std::uint64_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -654,25 +654,25 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xB8: // map (one-byte uint8_t for n follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t len;
 | 
			
		||||
                std::uint8_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xB9: // map (two-byte uint16_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t len;
 | 
			
		||||
                std::uint16_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xBA: // map (four-byte uint32_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t len;
 | 
			
		||||
                std::uint32_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xBB: // map (eight-byte uint64_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint64_t len;
 | 
			
		||||
                std::uint64_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -690,12 +690,12 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
 | 
			
		||||
            {
 | 
			
		||||
                const int byte1_raw = get();
 | 
			
		||||
                const auto byte1_raw = get();
 | 
			
		||||
                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
                const int byte2_raw = get();
 | 
			
		||||
                const auto byte2_raw = get();
 | 
			
		||||
                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -738,13 +738,13 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
 | 
			
		||||
            {
 | 
			
		||||
                float number;
 | 
			
		||||
                float number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
 | 
			
		||||
            {
 | 
			
		||||
                double number;
 | 
			
		||||
                double number{};
 | 
			
		||||
                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -807,25 +807,25 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t len;
 | 
			
		||||
                std::uint8_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t len;
 | 
			
		||||
                std::uint16_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t len;
 | 
			
		||||
                std::uint32_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint64_t len;
 | 
			
		||||
                std::uint64_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -902,28 +902,28 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0x58: // Binary data (one-byte uint8_t for n follows)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t len;
 | 
			
		||||
                std::uint8_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) &&
 | 
			
		||||
                       get_binary(input_format_t::cbor, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x59: // Binary data (two-byte uint16_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t len;
 | 
			
		||||
                std::uint16_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) &&
 | 
			
		||||
                       get_binary(input_format_t::cbor, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x5A: // Binary data (four-byte uint32_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t len;
 | 
			
		||||
                std::uint32_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) &&
 | 
			
		||||
                       get_binary(input_format_t::cbor, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0x5B: // Binary data (eight-byte uint64_t for n follow)
 | 
			
		||||
            {
 | 
			
		||||
                std::uint64_t len;
 | 
			
		||||
                std::uint64_t len{};
 | 
			
		||||
                return get_number(input_format_t::cbor, len) &&
 | 
			
		||||
                       get_binary(input_format_t::cbor, len, result);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1048,7 +1048,7 @@ class binary_reader
 | 
			
		|||
        switch (get())
 | 
			
		||||
        {
 | 
			
		||||
            // EOF
 | 
			
		||||
            case std::char_traits<char>::eof():
 | 
			
		||||
            case std::char_traits<char_type>::eof():
 | 
			
		||||
                return unexpect_eof(input_format_t::msgpack, "value");
 | 
			
		||||
 | 
			
		||||
            // positive fixint
 | 
			
		||||
| 
						 | 
				
			
			@ -1288,85 +1288,85 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xCA: // float 32
 | 
			
		||||
            {
 | 
			
		||||
                float number;
 | 
			
		||||
                float number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xCB: // float 64
 | 
			
		||||
            {
 | 
			
		||||
                double number;
 | 
			
		||||
                double number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xCC: // uint 8
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t number;
 | 
			
		||||
                std::uint8_t number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xCD: // uint 16
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t number;
 | 
			
		||||
                std::uint16_t number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xCE: // uint 32
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t number;
 | 
			
		||||
                std::uint32_t number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xCF: // uint 64
 | 
			
		||||
            {
 | 
			
		||||
                std::uint64_t number;
 | 
			
		||||
                std::uint64_t number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xD0: // int 8
 | 
			
		||||
            {
 | 
			
		||||
                std::int8_t number;
 | 
			
		||||
                std::int8_t number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xD1: // int 16
 | 
			
		||||
            {
 | 
			
		||||
                std::int16_t number;
 | 
			
		||||
                std::int16_t number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xD2: // int 32
 | 
			
		||||
            {
 | 
			
		||||
                std::int32_t number;
 | 
			
		||||
                std::int32_t number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xD3: // int 64
 | 
			
		||||
            {
 | 
			
		||||
                std::int64_t number;
 | 
			
		||||
                std::int64_t number{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xDC: // array 16
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t len;
 | 
			
		||||
                std::uint16_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xDD: // array 32
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t len;
 | 
			
		||||
                std::uint32_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xDE: // map 16
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t len;
 | 
			
		||||
                std::uint16_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xDF: // map 32
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t len;
 | 
			
		||||
                std::uint32_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1471,19 +1471,19 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xD9: // str 8
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t len;
 | 
			
		||||
                std::uint8_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xDA: // str 16
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t len;
 | 
			
		||||
                std::uint16_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xDB: // str 32
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t len;
 | 
			
		||||
                std::uint32_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1518,29 +1518,29 @@ class binary_reader
 | 
			
		|||
        {
 | 
			
		||||
            case 0xC4: // bin 8
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t len;
 | 
			
		||||
                std::uint8_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xC5: // bin 16
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t len;
 | 
			
		||||
                std::uint16_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xC6: // bin 32
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t len;
 | 
			
		||||
                std::uint32_t len{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 0xC7: // ext 8
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t len;
 | 
			
		||||
                std::int8_t subtype;
 | 
			
		||||
                std::uint8_t len{};
 | 
			
		||||
                std::int8_t subtype{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) &&
 | 
			
		||||
                       get_number(input_format_t::msgpack, subtype) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, len, result) &&
 | 
			
		||||
| 
						 | 
				
			
			@ -1549,8 +1549,8 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xC8: // ext 16
 | 
			
		||||
            {
 | 
			
		||||
                std::uint16_t len;
 | 
			
		||||
                std::int8_t subtype;
 | 
			
		||||
                std::uint16_t len{};
 | 
			
		||||
                std::int8_t subtype{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) &&
 | 
			
		||||
                       get_number(input_format_t::msgpack, subtype) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, len, result) &&
 | 
			
		||||
| 
						 | 
				
			
			@ -1559,8 +1559,8 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xC9: // ext 32
 | 
			
		||||
            {
 | 
			
		||||
                std::uint32_t len;
 | 
			
		||||
                std::int8_t subtype;
 | 
			
		||||
                std::uint32_t len{};
 | 
			
		||||
                std::int8_t subtype{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, len) &&
 | 
			
		||||
                       get_number(input_format_t::msgpack, subtype) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, len, result) &&
 | 
			
		||||
| 
						 | 
				
			
			@ -1569,7 +1569,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xD4: // fixext 1
 | 
			
		||||
            {
 | 
			
		||||
                std::int8_t subtype;
 | 
			
		||||
                std::int8_t subtype{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, subtype) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, 1, result) &&
 | 
			
		||||
                       assign_and_return_true(subtype);
 | 
			
		||||
| 
						 | 
				
			
			@ -1577,7 +1577,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xD5: // fixext 2
 | 
			
		||||
            {
 | 
			
		||||
                std::int8_t subtype;
 | 
			
		||||
                std::int8_t subtype{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, subtype) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, 2, result) &&
 | 
			
		||||
                       assign_and_return_true(subtype);
 | 
			
		||||
| 
						 | 
				
			
			@ -1585,7 +1585,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xD6: // fixext 4
 | 
			
		||||
            {
 | 
			
		||||
                std::int8_t subtype;
 | 
			
		||||
                std::int8_t subtype{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, subtype) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, 4, result) &&
 | 
			
		||||
                       assign_and_return_true(subtype);
 | 
			
		||||
| 
						 | 
				
			
			@ -1593,7 +1593,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xD7: // fixext 8
 | 
			
		||||
            {
 | 
			
		||||
                std::int8_t subtype;
 | 
			
		||||
                std::int8_t subtype{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, subtype) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, 8, result) &&
 | 
			
		||||
                       assign_and_return_true(subtype);
 | 
			
		||||
| 
						 | 
				
			
			@ -1601,7 +1601,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 0xD8: // fixext 16
 | 
			
		||||
            {
 | 
			
		||||
                std::int8_t subtype;
 | 
			
		||||
                std::int8_t subtype{};
 | 
			
		||||
                return get_number(input_format_t::msgpack, subtype) &&
 | 
			
		||||
                       get_binary(input_format_t::msgpack, 16, result) &&
 | 
			
		||||
                       assign_and_return_true(subtype);
 | 
			
		||||
| 
						 | 
				
			
			@ -1710,31 +1710,31 @@ class binary_reader
 | 
			
		|||
        {
 | 
			
		||||
            case 'U':
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t len;
 | 
			
		||||
                std::uint8_t len{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'i':
 | 
			
		||||
            {
 | 
			
		||||
                std::int8_t len;
 | 
			
		||||
                std::int8_t len{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'I':
 | 
			
		||||
            {
 | 
			
		||||
                std::int16_t len;
 | 
			
		||||
                std::int16_t len{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'l':
 | 
			
		||||
            {
 | 
			
		||||
                std::int32_t len;
 | 
			
		||||
                std::int32_t len{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'L':
 | 
			
		||||
            {
 | 
			
		||||
                std::int64_t len;
 | 
			
		||||
                std::int64_t len{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1754,7 +1754,7 @@ class binary_reader
 | 
			
		|||
        {
 | 
			
		||||
            case 'U':
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t number;
 | 
			
		||||
                std::uint8_t number{};
 | 
			
		||||
                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1765,7 +1765,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 'i':
 | 
			
		||||
            {
 | 
			
		||||
                std::int8_t number;
 | 
			
		||||
                std::int8_t number{};
 | 
			
		||||
                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1776,7 +1776,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 'I':
 | 
			
		||||
            {
 | 
			
		||||
                std::int16_t number;
 | 
			
		||||
                std::int16_t number{};
 | 
			
		||||
                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1787,7 +1787,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 'l':
 | 
			
		||||
            {
 | 
			
		||||
                std::int32_t number;
 | 
			
		||||
                std::int32_t number{};
 | 
			
		||||
                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1798,7 +1798,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 'L':
 | 
			
		||||
            {
 | 
			
		||||
                std::int64_t number;
 | 
			
		||||
                std::int64_t number{};
 | 
			
		||||
                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1825,7 +1825,7 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
    @return whether pair creation completed
 | 
			
		||||
    */
 | 
			
		||||
    bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
 | 
			
		||||
    bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
 | 
			
		||||
    {
 | 
			
		||||
        result.first = string_t::npos; // size
 | 
			
		||||
        result.second = 0; // type
 | 
			
		||||
| 
						 | 
				
			
			@ -1866,11 +1866,11 @@ class binary_reader
 | 
			
		|||
    @param prefix  the previously read or set type prefix
 | 
			
		||||
    @return whether value creation completed
 | 
			
		||||
    */
 | 
			
		||||
    bool get_ubjson_value(const int prefix)
 | 
			
		||||
    bool get_ubjson_value(const char_int_type prefix)
 | 
			
		||||
    {
 | 
			
		||||
        switch (prefix)
 | 
			
		||||
        {
 | 
			
		||||
            case std::char_traits<char>::eof():  // EOF
 | 
			
		||||
            case std::char_traits<char_type>::eof():  // EOF
 | 
			
		||||
                return unexpect_eof(input_format_t::ubjson, "value");
 | 
			
		||||
 | 
			
		||||
            case 'T':  // true
 | 
			
		||||
| 
						 | 
				
			
			@ -1883,43 +1883,43 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
            case 'U':
 | 
			
		||||
            {
 | 
			
		||||
                std::uint8_t number;
 | 
			
		||||
                std::uint8_t number{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'i':
 | 
			
		||||
            {
 | 
			
		||||
                std::int8_t number;
 | 
			
		||||
                std::int8_t number{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'I':
 | 
			
		||||
            {
 | 
			
		||||
                std::int16_t number;
 | 
			
		||||
                std::int16_t number{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'l':
 | 
			
		||||
            {
 | 
			
		||||
                std::int32_t number;
 | 
			
		||||
                std::int32_t number{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'L':
 | 
			
		||||
            {
 | 
			
		||||
                std::int64_t number;
 | 
			
		||||
                std::int64_t number{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'd':
 | 
			
		||||
            {
 | 
			
		||||
                float number;
 | 
			
		||||
                float number{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case 'D':
 | 
			
		||||
            {
 | 
			
		||||
                double number;
 | 
			
		||||
                double number{};
 | 
			
		||||
                return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1935,7 +1935,7 @@ class binary_reader
 | 
			
		|||
                    auto last_token = get_token_string();
 | 
			
		||||
                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
 | 
			
		||||
                }
 | 
			
		||||
                string_t s(1, static_cast<char>(current));
 | 
			
		||||
                string_t s(1, static_cast<typename string_t::value_type>(current));
 | 
			
		||||
                return sax->string(s);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1964,7 +1964,7 @@ class binary_reader
 | 
			
		|||
    */
 | 
			
		||||
    bool get_ubjson_array()
 | 
			
		||||
    {
 | 
			
		||||
        std::pair<std::size_t, int> size_and_type;
 | 
			
		||||
        std::pair<std::size_t, char_int_type> size_and_type;
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -2026,7 +2026,7 @@ class binary_reader
 | 
			
		|||
    */
 | 
			
		||||
    bool get_ubjson_object()
 | 
			
		||||
    {
 | 
			
		||||
        std::pair<std::size_t, int> size_and_type;
 | 
			
		||||
        std::pair<std::size_t, char_int_type> size_and_type;
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -2108,11 +2108,11 @@ class binary_reader
 | 
			
		|||
 | 
			
		||||
    This function provides the interface to the used input adapter. It does
 | 
			
		||||
    not throw in case the input reached EOF, but returns a -'ve valued
 | 
			
		||||
    `std::char_traits<char>::eof()` in that case.
 | 
			
		||||
    `std::char_traits<char_type>::eof()` in that case.
 | 
			
		||||
 | 
			
		||||
    @return character read from the input
 | 
			
		||||
    */
 | 
			
		||||
    int get()
 | 
			
		||||
    char_int_type get()
 | 
			
		||||
    {
 | 
			
		||||
        ++chars_read;
 | 
			
		||||
        return current = ia.get_character();
 | 
			
		||||
| 
						 | 
				
			
			@ -2121,7 +2121,7 @@ class binary_reader
 | 
			
		|||
    /*!
 | 
			
		||||
    @return character read from the input after ignoring all 'N' entries
 | 
			
		||||
    */
 | 
			
		||||
    int get_ignore_noop()
 | 
			
		||||
    char_int_type get_ignore_noop()
 | 
			
		||||
    {
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -2201,7 +2201,7 @@ class binary_reader
 | 
			
		|||
            {
 | 
			
		||||
                success = false;
 | 
			
		||||
            }
 | 
			
		||||
            return static_cast<char>(current);
 | 
			
		||||
            return std::char_traits<char_type>::to_char_type(current);
 | 
			
		||||
        });
 | 
			
		||||
        return success;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2246,7 +2246,7 @@ class binary_reader
 | 
			
		|||
    JSON_HEDLEY_NON_NULL(3)
 | 
			
		||||
    bool unexpect_eof(const input_format_t format, const char* context) const
 | 
			
		||||
    {
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char>::eof()))
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
 | 
			
		||||
        {
 | 
			
		||||
            return sax->parse_error(chars_read, "<end of file>",
 | 
			
		||||
                                    parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
 | 
			
		||||
| 
						 | 
				
			
			@ -2306,7 +2306,7 @@ class binary_reader
 | 
			
		|||
    InputAdapterType ia;
 | 
			
		||||
 | 
			
		||||
    /// the current character
 | 
			
		||||
    int current = std::char_traits<char>::eof();
 | 
			
		||||
    char_int_type current = std::char_traits<char_type>::eof();
 | 
			
		||||
 | 
			
		||||
    /// the number of characters read
 | 
			
		||||
    std::size_t chars_read = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,8 @@ Input adapter for stdio file access. This adapter read only 1 byte and do not us
 | 
			
		|||
class file_input_adapter
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
    using char_type = char;
 | 
			
		||||
 | 
			
		||||
    JSON_HEDLEY_NON_NULL(2)
 | 
			
		||||
    explicit file_input_adapter(std::FILE* f)  noexcept
 | 
			
		||||
        : m_file(f)
 | 
			
		||||
| 
						 | 
				
			
			@ -68,11 +70,13 @@ subsequent call for input from the std::istream.
 | 
			
		|||
class input_stream_adapter
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
    using char_type = char;
 | 
			
		||||
 | 
			
		||||
    ~input_stream_adapter()
 | 
			
		||||
    {
 | 
			
		||||
        // clear stream flags; we use underlying streambuf I/O, do not
 | 
			
		||||
        // maintain ifstream flags, except eof
 | 
			
		||||
        if (is)
 | 
			
		||||
        if (is != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            is->clear(is->rdstate() & std::ios::eofbit);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +104,7 @@ class input_stream_adapter
 | 
			
		|||
    {
 | 
			
		||||
        auto res = sb->sbumpc();
 | 
			
		||||
        // set eof manually, as we don't use the istream interface.
 | 
			
		||||
        if (res == EOF)
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(res == EOF))
 | 
			
		||||
        {
 | 
			
		||||
            is->clear(is->rdstate() | std::ios::eofbit);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -113,51 +117,61 @@ class input_stream_adapter
 | 
			
		|||
    std::streambuf* sb = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// input adapter for buffer input
 | 
			
		||||
class input_buffer_adapter
 | 
			
		||||
// General-purpose iterator-based adapter. It might not be as fast as
 | 
			
		||||
// theoretically possible for some containers, but it is extremely versatile.
 | 
			
		||||
template<typename IteratorType>
 | 
			
		||||
class iterator_input_adapter
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
    input_buffer_adapter(const char* b, const std::size_t l) noexcept
 | 
			
		||||
        : cursor(b), limit(b == nullptr ? nullptr : (b + l))
 | 
			
		||||
    {}
 | 
			
		||||
    using char_type = typename std::iterator_traits<IteratorType>::value_type;
 | 
			
		||||
 | 
			
		||||
    // delete because of pointer members
 | 
			
		||||
    input_buffer_adapter(const input_buffer_adapter&) = delete;
 | 
			
		||||
    input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
 | 
			
		||||
    input_buffer_adapter(input_buffer_adapter&&) = default;
 | 
			
		||||
    input_buffer_adapter& operator=(input_buffer_adapter&&) = delete;
 | 
			
		||||
    iterator_input_adapter(IteratorType first, IteratorType last)
 | 
			
		||||
        : current(std::move(first)), end(std::move(last)) {}
 | 
			
		||||
 | 
			
		||||
    std::char_traits<char>::int_type get_character() noexcept
 | 
			
		||||
    typename std::char_traits<char_type>::int_type get_character()
 | 
			
		||||
    {
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(cursor < limit))
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(current != end))
 | 
			
		||||
        {
 | 
			
		||||
            assert(cursor != nullptr && limit != nullptr);
 | 
			
		||||
            return std::char_traits<char>::to_int_type(*(cursor++));
 | 
			
		||||
            auto result = std::char_traits<char_type>::to_int_type(*current);
 | 
			
		||||
            std::advance(current, 1);
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return std::char_traits<char_type>::eof();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return std::char_traits<char>::eof();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    /// pointer to the current character
 | 
			
		||||
    const char* cursor;
 | 
			
		||||
    /// pointer past the last character
 | 
			
		||||
    const char* const limit;
 | 
			
		||||
    IteratorType current;
 | 
			
		||||
    IteratorType end;
 | 
			
		||||
 | 
			
		||||
    template<typename BaseInputAdapter, size_t T>
 | 
			
		||||
    friend struct wide_string_input_helper;
 | 
			
		||||
 | 
			
		||||
    bool empty() const
 | 
			
		||||
    {
 | 
			
		||||
        return current == end;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename WideStringType, size_t T>
 | 
			
		||||
struct wide_string_input_helper
 | 
			
		||||
 | 
			
		||||
template<typename BaseInputAdapter, size_t T>
 | 
			
		||||
struct wide_string_input_helper;
 | 
			
		||||
 | 
			
		||||
template<typename BaseInputAdapter>
 | 
			
		||||
struct wide_string_input_helper<BaseInputAdapter, 4>
 | 
			
		||||
{
 | 
			
		||||
    // UTF-32
 | 
			
		||||
    static void fill_buffer(const WideStringType& str,
 | 
			
		||||
                            size_t& current_wchar,
 | 
			
		||||
    static void fill_buffer(BaseInputAdapter& input,
 | 
			
		||||
                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
 | 
			
		||||
                            size_t& utf8_bytes_index,
 | 
			
		||||
                            size_t& utf8_bytes_filled)
 | 
			
		||||
    {
 | 
			
		||||
        utf8_bytes_index = 0;
 | 
			
		||||
 | 
			
		||||
        if (current_wchar == str.size())
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(input.empty()))
 | 
			
		||||
        {
 | 
			
		||||
            utf8_bytes[0] = std::char_traits<char>::eof();
 | 
			
		||||
            utf8_bytes_filled = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +179,7 @@ struct wide_string_input_helper
 | 
			
		|||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // get the current character
 | 
			
		||||
            const auto wc = static_cast<unsigned int>(str[current_wchar++]);
 | 
			
		||||
            const auto wc = input.get_character();
 | 
			
		||||
 | 
			
		||||
            // UTF-32 to UTF-8 encoding
 | 
			
		||||
            if (wc < 0x80)
 | 
			
		||||
| 
						 | 
				
			
			@ -175,23 +189,23 @@ struct wide_string_input_helper
 | 
			
		|||
            }
 | 
			
		||||
            else if (wc <= 0x7FF)
 | 
			
		||||
            {
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 | 
			
		||||
                utf8_bytes_filled = 2;
 | 
			
		||||
            }
 | 
			
		||||
            else if (wc <= 0xFFFF)
 | 
			
		||||
            {
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
 | 
			
		||||
                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
 | 
			
		||||
                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 | 
			
		||||
                utf8_bytes_filled = 3;
 | 
			
		||||
            }
 | 
			
		||||
            else if (wc <= 0x10FFFF)
 | 
			
		||||
            {
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((wc >> 18u) & 0x07u));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 12u) & 0x3Fu));
 | 
			
		||||
                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
 | 
			
		||||
                utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
 | 
			
		||||
                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
 | 
			
		||||
                utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 | 
			
		||||
                utf8_bytes_filled = 4;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
| 
						 | 
				
			
			@ -204,19 +218,18 @@ struct wide_string_input_helper
 | 
			
		|||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename WideStringType>
 | 
			
		||||
struct wide_string_input_helper<WideStringType, 2>
 | 
			
		||||
template<typename BaseInputAdapter>
 | 
			
		||||
struct wide_string_input_helper<BaseInputAdapter, 2>
 | 
			
		||||
{
 | 
			
		||||
    // UTF-16
 | 
			
		||||
    static void fill_buffer(const WideStringType& str,
 | 
			
		||||
                            size_t& current_wchar,
 | 
			
		||||
    static void fill_buffer(BaseInputAdapter& input,
 | 
			
		||||
                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
 | 
			
		||||
                            size_t& utf8_bytes_index,
 | 
			
		||||
                            size_t& utf8_bytes_filled)
 | 
			
		||||
    {
 | 
			
		||||
        utf8_bytes_index = 0;
 | 
			
		||||
 | 
			
		||||
        if (current_wchar == str.size())
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(input.empty()))
 | 
			
		||||
        {
 | 
			
		||||
            utf8_bytes[0] = std::char_traits<char>::eof();
 | 
			
		||||
            utf8_bytes_filled = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -224,7 +237,7 @@ struct wide_string_input_helper<WideStringType, 2>
 | 
			
		|||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // get the current character
 | 
			
		||||
            const auto wc = static_cast<unsigned int>(str[current_wchar++]);
 | 
			
		||||
            const auto wc = input.get_character();
 | 
			
		||||
 | 
			
		||||
            // UTF-16 to UTF-8 encoding
 | 
			
		||||
            if (wc < 0x80)
 | 
			
		||||
| 
						 | 
				
			
			@ -234,23 +247,23 @@ struct wide_string_input_helper<WideStringType, 2>
 | 
			
		|||
            }
 | 
			
		||||
            else if (wc <= 0x7FF)
 | 
			
		||||
            {
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u)));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 | 
			
		||||
                utf8_bytes_filled = 2;
 | 
			
		||||
            }
 | 
			
		||||
            else if (0xD800 > wc || wc >= 0xE000)
 | 
			
		||||
            {
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u)));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
 | 
			
		||||
                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
 | 
			
		||||
                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
 | 
			
		||||
                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
 | 
			
		||||
                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 | 
			
		||||
                utf8_bytes_filled = 3;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (current_wchar < str.size())
 | 
			
		||||
                if (JSON_HEDLEY_UNLIKELY(not input.empty()))
 | 
			
		||||
                {
 | 
			
		||||
                    const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
 | 
			
		||||
                    const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
 | 
			
		||||
                    const auto wc2 = static_cast<unsigned int>(input.get_character());
 | 
			
		||||
                    const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
 | 
			
		||||
                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
 | 
			
		||||
                    utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
 | 
			
		||||
                    utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
 | 
			
		||||
| 
						 | 
				
			
			@ -259,8 +272,6 @@ struct wide_string_input_helper<WideStringType, 2>
 | 
			
		|||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    // unknown character
 | 
			
		||||
                    ++current_wchar;
 | 
			
		||||
                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
 | 
			
		||||
                    utf8_bytes_filled = 1;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -269,20 +280,22 @@ struct wide_string_input_helper<WideStringType, 2>
 | 
			
		|||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename WideStringType>
 | 
			
		||||
// Wraps another input apdater to convert wide character types into individual bytes.
 | 
			
		||||
template<typename BaseInputAdapter, typename WideCharType>
 | 
			
		||||
class wide_string_input_adapter
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
    explicit wide_string_input_adapter(const WideStringType& w) noexcept
 | 
			
		||||
        : str(w)
 | 
			
		||||
    {}
 | 
			
		||||
    using char_type = char;
 | 
			
		||||
 | 
			
		||||
    std::char_traits<char>::int_type get_character() noexcept
 | 
			
		||||
    wide_string_input_adapter(BaseInputAdapter base)
 | 
			
		||||
        : base_adapter(base) {}
 | 
			
		||||
 | 
			
		||||
    typename std::char_traits<char>::int_type get_character() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        // check if buffer needs to be filled
 | 
			
		||||
        if (utf8_bytes_index == utf8_bytes_filled)
 | 
			
		||||
        {
 | 
			
		||||
            fill_buffer<sizeof(typename WideStringType::value_type)>();
 | 
			
		||||
            fill_buffer<sizeof(WideCharType)>();
 | 
			
		||||
 | 
			
		||||
            assert(utf8_bytes_filled > 0);
 | 
			
		||||
            assert(utf8_bytes_index == 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -295,18 +308,14 @@ class wide_string_input_adapter
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    BaseInputAdapter base_adapter;
 | 
			
		||||
 | 
			
		||||
    template<size_t T>
 | 
			
		||||
    void fill_buffer()
 | 
			
		||||
    {
 | 
			
		||||
        wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
 | 
			
		||||
        wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// the wstring to process
 | 
			
		||||
    const WideStringType& str;
 | 
			
		||||
 | 
			
		||||
    /// index of the current wchar in str
 | 
			
		||||
    std::size_t current_wchar = 0;
 | 
			
		||||
 | 
			
		||||
    /// a buffer for UTF-8 bytes
 | 
			
		||||
    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -316,6 +325,64 @@ class wide_string_input_adapter
 | 
			
		|||
    std::size_t utf8_bytes_filled = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<typename IteratorType, typename Enable = void>
 | 
			
		||||
struct iterator_input_adapter_factory
 | 
			
		||||
{
 | 
			
		||||
    using iterator_type = IteratorType;
 | 
			
		||||
    using char_type = typename std::iterator_traits<iterator_type>::value_type;
 | 
			
		||||
    using adapter_type = iterator_input_adapter<iterator_type>;
 | 
			
		||||
 | 
			
		||||
    static adapter_type create(IteratorType first, IteratorType last)
 | 
			
		||||
    {
 | 
			
		||||
        return adapter_type(std::move(first), std::move(last));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct is_iterator_of_multibyte
 | 
			
		||||
{
 | 
			
		||||
    using value_type = typename std::iterator_traits<T>::value_type;
 | 
			
		||||
    enum
 | 
			
		||||
    {
 | 
			
		||||
        value = sizeof(value_type) > 1
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename IteratorType>
 | 
			
		||||
struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
 | 
			
		||||
{
 | 
			
		||||
    using iterator_type = IteratorType;
 | 
			
		||||
    using char_type = typename std::iterator_traits<iterator_type>::value_type;
 | 
			
		||||
    using base_adapter_type = iterator_input_adapter<iterator_type>;
 | 
			
		||||
    using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
 | 
			
		||||
 | 
			
		||||
    static adapter_type create(IteratorType first, IteratorType last)
 | 
			
		||||
    {
 | 
			
		||||
        return adapter_type(base_adapter_type(std::move(first), std::move(last)));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// General purpose iterator-based input
 | 
			
		||||
template<typename IteratorType>
 | 
			
		||||
typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
 | 
			
		||||
{
 | 
			
		||||
    using factory_type = iterator_input_adapter_factory<IteratorType>;
 | 
			
		||||
    return factory_type::create(first, last);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Convenience shorthand from container to iterator
 | 
			
		||||
template<typename ContainerType>
 | 
			
		||||
auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container)))
 | 
			
		||||
{
 | 
			
		||||
    // Enable ADL
 | 
			
		||||
    using std::begin;
 | 
			
		||||
    using std::end;
 | 
			
		||||
 | 
			
		||||
    return input_adapter(begin(container), end(container));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Special cases with fast paths
 | 
			
		||||
inline file_input_adapter input_adapter(std::FILE* file)
 | 
			
		||||
{
 | 
			
		||||
    return file_input_adapter(file);
 | 
			
		||||
| 
						 | 
				
			
			@ -331,97 +398,27 @@ inline input_stream_adapter input_adapter(std::istream&& stream)
 | 
			
		|||
    return input_stream_adapter(stream);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template < typename CharT, typename SizeT,
 | 
			
		||||
           typename std::enable_if <
 | 
			
		||||
               std::is_pointer<CharT>::value&&
 | 
			
		||||
               std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
 | 
			
		||||
               !std::is_same<SizeT, bool>::value&&
 | 
			
		||||
               sizeof(typename std::remove_pointer<CharT>::type) == 1,
 | 
			
		||||
               int >::type = 0 >
 | 
			
		||||
input_buffer_adapter input_adapter(CharT b, SizeT l)
 | 
			
		||||
{
 | 
			
		||||
    return input_buffer_adapter(reinterpret_cast<const char*>(b), l);
 | 
			
		||||
}
 | 
			
		||||
using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
 | 
			
		||||
 | 
			
		||||
// Null-delimited strings, and the like.
 | 
			
		||||
template < typename CharT,
 | 
			
		||||
           typename std::enable_if <
 | 
			
		||||
               std::is_pointer<CharT>::value&&
 | 
			
		||||
               std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
 | 
			
		||||
               std::is_pointer<CharT>::value &&
 | 
			
		||||
               not std::is_array<CharT>::value &&
 | 
			
		||||
               std::is_integral<typename std::remove_pointer<CharT>::type>::value &&
 | 
			
		||||
               sizeof(typename std::remove_pointer<CharT>::type) == 1,
 | 
			
		||||
               int >::type = 0 >
 | 
			
		||||
input_buffer_adapter input_adapter(CharT b)
 | 
			
		||||
contiguous_bytes_input_adapter input_adapter(CharT b)
 | 
			
		||||
{
 | 
			
		||||
    return input_adapter(reinterpret_cast<const char*>(b),
 | 
			
		||||
                         std::strlen(reinterpret_cast<const char*>(b)));
 | 
			
		||||
    auto length = std::strlen(reinterpret_cast<const char*>(b));
 | 
			
		||||
    const auto* ptr = reinterpret_cast<const char*>(b);
 | 
			
		||||
    return input_adapter(ptr, ptr + length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class IteratorType,
 | 
			
		||||
         typename std::enable_if<
 | 
			
		||||
             std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
 | 
			
		||||
             int>::type = 0>
 | 
			
		||||
input_buffer_adapter input_adapter(IteratorType first, IteratorType last)
 | 
			
		||||
template<typename T, std::size_t N>
 | 
			
		||||
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N))
 | 
			
		||||
{
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
    // assertion to check that the iterator range is indeed contiguous,
 | 
			
		||||
    // see https://stackoverflow.com/a/35008842/266378 for more discussion
 | 
			
		||||
    const auto is_contiguous = std::accumulate(
 | 
			
		||||
                                   first, last, std::pair<bool, int>(true, 0),
 | 
			
		||||
                                   [&first](std::pair<bool, int> res, decltype(*first) val)
 | 
			
		||||
    {
 | 
			
		||||
        res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
 | 
			
		||||
        return res;
 | 
			
		||||
    }).first;
 | 
			
		||||
    assert(is_contiguous);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // assertion to check that each element is 1 byte long
 | 
			
		||||
    static_assert(
 | 
			
		||||
        sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
 | 
			
		||||
        "each element in the iterator range must have the size of 1 byte");
 | 
			
		||||
 | 
			
		||||
    const auto len = static_cast<size_t>(std::distance(first, last));
 | 
			
		||||
    if (JSON_HEDLEY_LIKELY(len > 0))
 | 
			
		||||
    {
 | 
			
		||||
        // there is at least one element: use the address of first
 | 
			
		||||
        return input_buffer_adapter(reinterpret_cast<const char*>(&(*first)), len);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // the address of first cannot be used: use nullptr
 | 
			
		||||
        return input_buffer_adapter(nullptr, len);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline wide_string_input_adapter<std::wstring> input_adapter(const std::wstring& ws)
 | 
			
		||||
{
 | 
			
		||||
    return wide_string_input_adapter<std::wstring>(ws);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline wide_string_input_adapter<std::u16string> input_adapter(const std::u16string& ws)
 | 
			
		||||
{
 | 
			
		||||
    return wide_string_input_adapter<std::u16string>(ws);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline wide_string_input_adapter<std::u32string> input_adapter(const std::u32string& ws)
 | 
			
		||||
{
 | 
			
		||||
    return wide_string_input_adapter<std::u32string>(ws);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template < class ContiguousContainer, typename
 | 
			
		||||
           std::enable_if < !std::is_pointer<ContiguousContainer>::value&&
 | 
			
		||||
                            std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
 | 
			
		||||
                            int >::type = 0 >
 | 
			
		||||
input_buffer_adapter input_adapter(const ContiguousContainer& c)
 | 
			
		||||
{
 | 
			
		||||
    return input_adapter(std::begin(c), std::end(c));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<class T, std::size_t N>
 | 
			
		||||
input_buffer_adapter input_adapter(T (&array)[N])
 | 
			
		||||
{
 | 
			
		||||
    return input_adapter(std::begin(array), std::end(array));
 | 
			
		||||
    return input_adapter(array, array + N);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This class only handles inputs of input_buffer_adapter type.
 | 
			
		||||
| 
						 | 
				
			
			@ -437,17 +434,7 @@ class span_input_adapter
 | 
			
		|||
                   sizeof(typename std::remove_pointer<CharT>::type) == 1,
 | 
			
		||||
                   int >::type = 0 >
 | 
			
		||||
    span_input_adapter(CharT b, std::size_t l)
 | 
			
		||||
        : ia(reinterpret_cast<const char*>(b), l) {}
 | 
			
		||||
 | 
			
		||||
    template < typename CharT,
 | 
			
		||||
               typename std::enable_if <
 | 
			
		||||
                   std::is_pointer<CharT>::value&&
 | 
			
		||||
                   std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
 | 
			
		||||
                   sizeof(typename std::remove_pointer<CharT>::type) == 1,
 | 
			
		||||
                   int >::type = 0 >
 | 
			
		||||
    span_input_adapter(CharT b)
 | 
			
		||||
        : span_input_adapter(reinterpret_cast<const char*>(b),
 | 
			
		||||
                             std::strlen(reinterpret_cast<const char*>(b))) {}
 | 
			
		||||
        : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
 | 
			
		||||
 | 
			
		||||
    template<class IteratorType,
 | 
			
		||||
             typename std::enable_if<
 | 
			
		||||
| 
						 | 
				
			
			@ -456,25 +443,13 @@ class span_input_adapter
 | 
			
		|||
    span_input_adapter(IteratorType first, IteratorType last)
 | 
			
		||||
        : ia(input_adapter(first, last)) {}
 | 
			
		||||
 | 
			
		||||
    template<class T, std::size_t N>
 | 
			
		||||
    span_input_adapter(T (&array)[N])
 | 
			
		||||
        : span_input_adapter(std::begin(array), std::end(array)) {}
 | 
			
		||||
 | 
			
		||||
    /// input adapter for contiguous container
 | 
			
		||||
    template < class ContiguousContainer, typename
 | 
			
		||||
               std::enable_if < !std::is_pointer<ContiguousContainer>::value&&
 | 
			
		||||
                                std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
 | 
			
		||||
                                int >::type = 0 >
 | 
			
		||||
    span_input_adapter(const ContiguousContainer& c)
 | 
			
		||||
        : span_input_adapter(std::begin(c), std::end(c)) {}
 | 
			
		||||
 | 
			
		||||
    input_buffer_adapter&& get()
 | 
			
		||||
    contiguous_bytes_input_adapter&& get()
 | 
			
		||||
    {
 | 
			
		||||
        return std::move(ia);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    input_buffer_adapter ia;
 | 
			
		||||
    contiguous_bytes_input_adapter ia;
 | 
			
		||||
};
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
}  // namespace nlohmann
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -269,16 +269,16 @@ class json_sax_dom_parser
 | 
			
		|||
            switch ((ex.id / 100) % 100)
 | 
			
		||||
            {
 | 
			
		||||
                case 1:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::parse_error*>(&ex));
 | 
			
		||||
                case 4:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::out_of_range*>(&ex));
 | 
			
		||||
                // LCOV_EXCL_START
 | 
			
		||||
                case 2:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::invalid_iterator*>(&ex));
 | 
			
		||||
                case 3:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::type_error*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::type_error*>(&ex));
 | 
			
		||||
                case 5:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::other_error*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::other_error*>(&ex));
 | 
			
		||||
                default:
 | 
			
		||||
                    assert(false);
 | 
			
		||||
                    // LCOV_EXCL_STOP
 | 
			
		||||
| 
						 | 
				
			
			@ -523,16 +523,16 @@ class json_sax_dom_callback_parser
 | 
			
		|||
            switch ((ex.id / 100) % 100)
 | 
			
		||||
            {
 | 
			
		||||
                case 1:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::parse_error*>(&ex));
 | 
			
		||||
                case 4:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::out_of_range*>(&ex));
 | 
			
		||||
                // LCOV_EXCL_START
 | 
			
		||||
                case 2:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::invalid_iterator*>(&ex));
 | 
			
		||||
                case 3:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::type_error*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::type_error*>(&ex));
 | 
			
		||||
                case 5:
 | 
			
		||||
                    JSON_THROW(*static_cast<const detail::other_error*>(&ex));
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::other_error*>(&ex));
 | 
			
		||||
                default:
 | 
			
		||||
                    assert(false);
 | 
			
		||||
                    // LCOV_EXCL_STOP
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,12 +106,17 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 | 
			
		||||
    using number_float_t = typename BasicJsonType::number_float_t;
 | 
			
		||||
    using string_t = typename BasicJsonType::string_t;
 | 
			
		||||
    using char_type = typename InputAdapterType::char_type;
 | 
			
		||||
    using char_int_type = typename std::char_traits<char_type>::int_type;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    using token_type = typename lexer_base<BasicJsonType>::token_type;
 | 
			
		||||
 | 
			
		||||
    explicit lexer(InputAdapterType&& adapter)
 | 
			
		||||
        : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
 | 
			
		||||
    explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false)
 | 
			
		||||
        : ia(std::move(adapter))
 | 
			
		||||
        , ignore_comments(ignore_comments_)
 | 
			
		||||
        , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    // delete because of pointer members
 | 
			
		||||
    lexer(const lexer&) = delete;
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +134,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
    JSON_HEDLEY_PURE
 | 
			
		||||
    static char get_decimal_point() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        const auto loc = localeconv();
 | 
			
		||||
        const auto* loc = localeconv();
 | 
			
		||||
        assert(loc != nullptr);
 | 
			
		||||
        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -201,7 +206,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
 | 
			
		||||
    @return true if and only if no range violation was detected
 | 
			
		||||
    */
 | 
			
		||||
    bool next_byte_in_range(std::initializer_list<int> ranges)
 | 
			
		||||
    bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
 | 
			
		||||
        add(current);
 | 
			
		||||
| 
						 | 
				
			
			@ -252,7 +257,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
            switch (get())
 | 
			
		||||
            {
 | 
			
		||||
                // end of file while parsing string
 | 
			
		||||
                case std::char_traits<char>::eof():
 | 
			
		||||
                case std::char_traits<char_type>::eof():
 | 
			
		||||
                {
 | 
			
		||||
                    error_message = "invalid string: missing closing quote";
 | 
			
		||||
                    return token_type::parse_error;
 | 
			
		||||
| 
						 | 
				
			
			@ -370,28 +375,28 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
                            if (codepoint < 0x80)
 | 
			
		||||
                            {
 | 
			
		||||
                                // 1-byte characters: 0xxxxxxx (ASCII)
 | 
			
		||||
                                add(codepoint);
 | 
			
		||||
                                add(static_cast<char_int_type>(codepoint));
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (codepoint <= 0x7FF)
 | 
			
		||||
                            {
 | 
			
		||||
                                // 2-byte characters: 110xxxxx 10xxxxxx
 | 
			
		||||
                                add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
 | 
			
		||||
                                add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
 | 
			
		||||
                                add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
 | 
			
		||||
                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (codepoint <= 0xFFFF)
 | 
			
		||||
                            {
 | 
			
		||||
                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
 | 
			
		||||
                                add(static_cast<int>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
 | 
			
		||||
                                add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
 | 
			
		||||
                                add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
 | 
			
		||||
                                add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
 | 
			
		||||
                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
 | 
			
		||||
                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
 | 
			
		||||
                                add(static_cast<int>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
 | 
			
		||||
                                add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
 | 
			
		||||
                                add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
 | 
			
		||||
                                add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
 | 
			
		||||
                                add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
 | 
			
		||||
                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
 | 
			
		||||
                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
 | 
			
		||||
                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -824,6 +829,77 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
     * @brief scan a comment
 | 
			
		||||
     * @return whether comment could be scanned successfully
 | 
			
		||||
     */
 | 
			
		||||
    bool scan_comment()
 | 
			
		||||
    {
 | 
			
		||||
        switch (get())
 | 
			
		||||
        {
 | 
			
		||||
            // single-line comments skip input until a newline or EOF is read
 | 
			
		||||
            case '/':
 | 
			
		||||
            {
 | 
			
		||||
                while (true)
 | 
			
		||||
                {
 | 
			
		||||
                    switch (get())
 | 
			
		||||
                    {
 | 
			
		||||
                        case '\n':
 | 
			
		||||
                        case '\r':
 | 
			
		||||
                        case std::char_traits<char_type>::eof():
 | 
			
		||||
                        case '\0':
 | 
			
		||||
                            return true;
 | 
			
		||||
 | 
			
		||||
                        default:
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // multi-line comments skip input until */ is read
 | 
			
		||||
            case '*':
 | 
			
		||||
            {
 | 
			
		||||
                while (true)
 | 
			
		||||
                {
 | 
			
		||||
                    switch (get())
 | 
			
		||||
                    {
 | 
			
		||||
                        case std::char_traits<char_type>::eof():
 | 
			
		||||
                        case '\0':
 | 
			
		||||
                        {
 | 
			
		||||
                            error_message = "invalid comment; missing closing '*/'";
 | 
			
		||||
                            return false;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        case '*':
 | 
			
		||||
                        {
 | 
			
		||||
                            switch (get())
 | 
			
		||||
                            {
 | 
			
		||||
                                case '/':
 | 
			
		||||
                                    return true;
 | 
			
		||||
 | 
			
		||||
                                default:
 | 
			
		||||
                                {
 | 
			
		||||
                                    unget();
 | 
			
		||||
                                    break;
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        default:
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // unexpected character after reading '/'
 | 
			
		||||
            default:
 | 
			
		||||
            {
 | 
			
		||||
                error_message = "invalid comment; expecting '/' or '*' after '/'";
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    JSON_HEDLEY_NON_NULL(2)
 | 
			
		||||
    static void strtof(float& f, const char* str, char** endptr) noexcept
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1213,13 +1289,13 @@ scan_number_done:
 | 
			
		|||
    @param[in] return_type   the token type to return on success
 | 
			
		||||
    */
 | 
			
		||||
    JSON_HEDLEY_NON_NULL(2)
 | 
			
		||||
    token_type scan_literal(const char* literal_text, const std::size_t length,
 | 
			
		||||
    token_type scan_literal(const char_type* literal_text, const std::size_t length,
 | 
			
		||||
                            token_type return_type)
 | 
			
		||||
    {
 | 
			
		||||
        assert(current == literal_text[0]);
 | 
			
		||||
        assert(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
 | 
			
		||||
        for (std::size_t i = 1; i < length; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            if (JSON_HEDLEY_UNLIKELY(get() != literal_text[i]))
 | 
			
		||||
            if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
 | 
			
		||||
            {
 | 
			
		||||
                error_message = "invalid literal";
 | 
			
		||||
                return token_type::parse_error;
 | 
			
		||||
| 
						 | 
				
			
			@ -1237,7 +1313,7 @@ scan_number_done:
 | 
			
		|||
    {
 | 
			
		||||
        token_buffer.clear();
 | 
			
		||||
        token_string.clear();
 | 
			
		||||
        token_string.push_back(std::char_traits<char>::to_char_type(current));
 | 
			
		||||
        token_string.push_back(std::char_traits<char_type>::to_char_type(current));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
| 
						 | 
				
			
			@ -1250,7 +1326,7 @@ scan_number_done:
 | 
			
		|||
 | 
			
		||||
    @return character read from the input
 | 
			
		||||
    */
 | 
			
		||||
    std::char_traits<char>::int_type get()
 | 
			
		||||
    char_int_type get()
 | 
			
		||||
    {
 | 
			
		||||
        ++position.chars_read_total;
 | 
			
		||||
        ++position.chars_read_current_line;
 | 
			
		||||
| 
						 | 
				
			
			@ -1265,9 +1341,9 @@ scan_number_done:
 | 
			
		|||
            current = ia.get_character();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
 | 
			
		||||
        {
 | 
			
		||||
            token_string.push_back(std::char_traits<char>::to_char_type(current));
 | 
			
		||||
            token_string.push_back(std::char_traits<char_type>::to_char_type(current));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (current == '\n')
 | 
			
		||||
| 
						 | 
				
			
			@ -1306,7 +1382,7 @@ scan_number_done:
 | 
			
		|||
            --position.chars_read_current_line;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
 | 
			
		||||
        {
 | 
			
		||||
            assert(!token_string.empty());
 | 
			
		||||
            token_string.pop_back();
 | 
			
		||||
| 
						 | 
				
			
			@ -1314,9 +1390,9 @@ scan_number_done:
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    /// add a character to token_buffer
 | 
			
		||||
    void add(int c)
 | 
			
		||||
    void add(char_int_type c)
 | 
			
		||||
    {
 | 
			
		||||
        token_buffer.push_back(std::char_traits<char>::to_char_type(c));
 | 
			
		||||
        token_buffer.push_back(static_cast<typename string_t::value_type>(c));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
| 
						 | 
				
			
			@ -1377,7 +1453,7 @@ scan_number_done:
 | 
			
		|||
            else
 | 
			
		||||
            {
 | 
			
		||||
                // add character as is
 | 
			
		||||
                result.push_back(c);
 | 
			
		||||
                result.push_back(static_cast<std::string::value_type>(c));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1413,6 +1489,15 @@ scan_number_done:
 | 
			
		|||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void skip_whitespace()
 | 
			
		||||
    {
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            get();
 | 
			
		||||
        }
 | 
			
		||||
        while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    token_type scan()
 | 
			
		||||
    {
 | 
			
		||||
        // initially, skip the BOM
 | 
			
		||||
| 
						 | 
				
			
			@ -1423,9 +1508,18 @@ scan_number_done:
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // read next character and ignore whitespace
 | 
			
		||||
        do
 | 
			
		||||
        skip_whitespace();
 | 
			
		||||
 | 
			
		||||
        // ignore comments
 | 
			
		||||
        if (ignore_comments and current == '/')
 | 
			
		||||
        {
 | 
			
		||||
            get();
 | 
			
		||||
            if (not scan_comment())
 | 
			
		||||
            {
 | 
			
		||||
                return token_type::parse_error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // skip following whitespace
 | 
			
		||||
            skip_whitespace();
 | 
			
		||||
        }
 | 
			
		||||
        while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1447,11 +1541,20 @@ scan_number_done:
 | 
			
		|||
 | 
			
		||||
            // literals
 | 
			
		||||
            case 't':
 | 
			
		||||
                return scan_literal("true", 4, token_type::literal_true);
 | 
			
		||||
            {
 | 
			
		||||
                std::array<char_type, 4> true_literal = {{'t', 'r', 'u', 'e'}};
 | 
			
		||||
                return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
 | 
			
		||||
            }
 | 
			
		||||
            case 'f':
 | 
			
		||||
                return scan_literal("false", 5, token_type::literal_false);
 | 
			
		||||
            {
 | 
			
		||||
                std::array<char_type, 5> false_literal = {{'f', 'a', 'l', 's', 'e'}};
 | 
			
		||||
                return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
 | 
			
		||||
            }
 | 
			
		||||
            case 'n':
 | 
			
		||||
                return scan_literal("null", 4, token_type::literal_null);
 | 
			
		||||
            {
 | 
			
		||||
                std::array<char_type, 4> null_literal = {{'n', 'u', 'l', 'l'}};
 | 
			
		||||
                return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // string
 | 
			
		||||
            case '\"':
 | 
			
		||||
| 
						 | 
				
			
			@ -1474,7 +1577,7 @@ scan_number_done:
 | 
			
		|||
            // end of input (the null byte is needed when parsing from
 | 
			
		||||
            // string literals)
 | 
			
		||||
            case '\0':
 | 
			
		||||
            case std::char_traits<char>::eof():
 | 
			
		||||
            case std::char_traits<char_type>::eof():
 | 
			
		||||
                return token_type::end_of_input;
 | 
			
		||||
 | 
			
		||||
            // error
 | 
			
		||||
| 
						 | 
				
			
			@ -1488,8 +1591,11 @@ scan_number_done:
 | 
			
		|||
    /// input adapter
 | 
			
		||||
    InputAdapterType ia;
 | 
			
		||||
 | 
			
		||||
    /// whether comments should be ignored (true) or signaled as errors (false)
 | 
			
		||||
    const bool ignore_comments = false;
 | 
			
		||||
 | 
			
		||||
    /// the current character
 | 
			
		||||
    std::char_traits<char>::int_type current = std::char_traits<char>::eof();
 | 
			
		||||
    char_int_type current = std::char_traits<char_type>::eof();
 | 
			
		||||
 | 
			
		||||
    /// whether the next get() call should just return current
 | 
			
		||||
    bool next_unget = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -1498,7 +1604,7 @@ scan_number_done:
 | 
			
		|||
    position_t position {};
 | 
			
		||||
 | 
			
		||||
    /// raw input token string (for error messages)
 | 
			
		||||
    std::vector<char> token_string {};
 | 
			
		||||
    std::vector<char_type> token_string {};
 | 
			
		||||
 | 
			
		||||
    /// buffer for variable-length tokens (numbers, strings)
 | 
			
		||||
    string_t token_buffer {};
 | 
			
		||||
| 
						 | 
				
			
			@ -1512,7 +1618,7 @@ scan_number_done:
 | 
			
		|||
    number_float_t value_float = 0;
 | 
			
		||||
 | 
			
		||||
    /// the decimal point
 | 
			
		||||
    const char decimal_point_char = '.';
 | 
			
		||||
    const char_int_type decimal_point_char = '.';
 | 
			
		||||
};
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
}  // namespace nlohmann
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,8 +63,11 @@ class parser
 | 
			
		|||
    /// a parser reading from an input adapter
 | 
			
		||||
    explicit parser(InputAdapterType&& adapter,
 | 
			
		||||
                    const parser_callback_t<BasicJsonType> cb = nullptr,
 | 
			
		||||
                    const bool allow_exceptions_ = true)
 | 
			
		||||
        : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
 | 
			
		||||
                    const bool allow_exceptions_ = true,
 | 
			
		||||
                    const bool skip_comments = false)
 | 
			
		||||
        : callback(cb)
 | 
			
		||||
        , m_lexer(std::move(adapter), skip_comments)
 | 
			
		||||
        , allow_exceptions(allow_exceptions_)
 | 
			
		||||
    {
 | 
			
		||||
        // read first token
 | 
			
		||||
        get_token();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue