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();
|
||||
|
|
|
@ -18,8 +18,6 @@ template<typename BasicJsonType> struct internal_iterator
|
|||
typename BasicJsonType::object_t::iterator object_iterator {};
|
||||
/// iterator for JSON arrays
|
||||
typename BasicJsonType::array_t::iterator array_iterator {};
|
||||
/// iterator for JSON binary arrays
|
||||
typename BasicJsonType::binary_t::container_type::iterator binary_iterator {};
|
||||
/// generic iterator for all other types
|
||||
primitive_iterator_t primitive_iterator {};
|
||||
};
|
||||
|
|
|
@ -15,7 +15,9 @@ namespace detail
|
|||
template<typename string_type>
|
||||
void int_to_string( string_type& target, std::size_t value )
|
||||
{
|
||||
target = std::to_string(value);
|
||||
// For ADL
|
||||
using std::to_string;
|
||||
target = to_string(value);
|
||||
}
|
||||
template<typename IteratorType> class iteration_proxy_value
|
||||
{
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <algorithm> // all_of
|
||||
#include <cassert> // assert
|
||||
#include <cctype> // isdigit
|
||||
#include <limits> // max
|
||||
#include <numeric> // accumulate
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
|
@ -325,10 +326,15 @@ class json_pointer
|
|||
|
||||
@return integer representation of @a s
|
||||
|
||||
@throw parse_error.106 if an array index begins with '0'
|
||||
@throw parse_error.109 if an array index begins not with a digit
|
||||
@throw out_of_range.404 if string @a s could not be converted to an integer
|
||||
@throw out_of_range.410 if an array index exceeds size_type
|
||||
*/
|
||||
static int array_index(const std::string& s)
|
||||
static typename BasicJsonType::size_type array_index(const std::string& s)
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
|
||||
// error condition (cf. RFC 6901, Sect. 4)
|
||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
|
||||
{
|
||||
|
@ -344,10 +350,10 @@ class json_pointer
|
|||
}
|
||||
|
||||
std::size_t processed_chars = 0;
|
||||
int res = 0;
|
||||
unsigned long long res = 0;
|
||||
JSON_TRY
|
||||
{
|
||||
res = std::stoi(s, &processed_chars);
|
||||
res = std::stoull(s, &processed_chars);
|
||||
}
|
||||
JSON_CATCH(std::out_of_range&)
|
||||
{
|
||||
|
@ -360,7 +366,14 @@ class json_pointer
|
|||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
|
||||
}
|
||||
|
||||
return res;
|
||||
// only triggered on special platforms (like 32bit), see also
|
||||
// https://github.com/nlohmann/json/pull/2203
|
||||
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
return static_cast<size_type>(res);
|
||||
}
|
||||
|
||||
json_pointer top() const
|
||||
|
@ -419,7 +432,7 @@ class json_pointer
|
|||
case detail::value_t::array:
|
||||
{
|
||||
// create an entry in the array
|
||||
result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
|
||||
result = &result->operator[](array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -497,8 +510,7 @@ class json_pointer
|
|||
else
|
||||
{
|
||||
// convert array index to number; unchecked access
|
||||
ptr = &ptr->operator[](
|
||||
static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->operator[](array_index(reference_token));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -542,7 +554,7 @@ class json_pointer
|
|||
}
|
||||
|
||||
// note: at performs range check
|
||||
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->at(array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -592,8 +604,7 @@ class json_pointer
|
|||
}
|
||||
|
||||
// use unchecked array access
|
||||
ptr = &ptr->operator[](
|
||||
static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->operator[](array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -636,7 +647,7 @@ class json_pointer
|
|||
}
|
||||
|
||||
// note: at performs range check
|
||||
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->at(array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -700,7 +711,7 @@ class json_pointer
|
|||
}
|
||||
}
|
||||
|
||||
const auto idx = static_cast<size_type>(array_index(reference_token));
|
||||
const auto idx = array_index(reference_token);
|
||||
if (idx >= ptr->size())
|
||||
{
|
||||
// index out of range
|
||||
|
|
|
@ -16,23 +16,30 @@ class json_ref
|
|||
using value_type = BasicJsonType;
|
||||
|
||||
json_ref(value_type&& value)
|
||||
: owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
|
||||
: owned_value(std::move(value))
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
json_ref(const value_type& value)
|
||||
: value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
|
||||
: value_ref(const_cast<value_type*>(&value))
|
||||
, is_rvalue(false)
|
||||
{}
|
||||
|
||||
json_ref(std::initializer_list<json_ref> init)
|
||||
: owned_value(init), value_ref(&owned_value), is_rvalue(true)
|
||||
: owned_value(init)
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
template <
|
||||
class... Args,
|
||||
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
|
||||
json_ref(Args && ... args)
|
||||
: owned_value(std::forward<Args>(args)...), value_ref(&owned_value),
|
||||
is_rvalue(true) {}
|
||||
: owned_value(std::forward<Args>(args)...)
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
// class should be movable only
|
||||
json_ref(json_ref&&) = default;
|
||||
|
@ -63,7 +70,7 @@ class json_ref
|
|||
private:
|
||||
mutable value_type owned_value = nullptr;
|
||||
value_type* value_ref = nullptr;
|
||||
const bool is_rvalue;
|
||||
const bool is_rvalue = true;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
|
|
@ -20,7 +20,11 @@
|
|||
#endif
|
||||
|
||||
// C++ language standard detection
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
|
||||
#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
#define JSON_HAS_CPP_20
|
||||
#define JSON_HAS_CPP_17
|
||||
#define JSON_HAS_CPP_14
|
||||
#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
|
||||
#define JSON_HAS_CPP_17
|
||||
#define JSON_HAS_CPP_14
|
||||
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
|
||||
|
|
|
@ -28,6 +28,7 @@ class binary_writer
|
|||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
|
||||
public:
|
||||
/*!
|
||||
|
@ -194,18 +195,7 @@ class binary_writer
|
|||
}
|
||||
else
|
||||
{
|
||||
if (static_cast<double>(j.m_value.number_float) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
|
||||
static_cast<double>(j.m_value.number_float) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
|
||||
static_cast<double>(static_cast<float>(j.m_value.number_float)) == static_cast<double>(j.m_value.number_float))
|
||||
{
|
||||
oa->write_character(get_cbor_float_prefix(static_cast<float>(j.m_value.number_float)));
|
||||
write_number(static_cast<float>(j.m_value.number_float));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
|
||||
write_number(j.m_value.number_float);
|
||||
}
|
||||
write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -504,8 +494,7 @@ class binary_writer
|
|||
|
||||
case value_t::number_float:
|
||||
{
|
||||
oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
|
||||
write_number(j.m_value.number_float);
|
||||
write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -584,7 +573,7 @@ class binary_writer
|
|||
const auto N = j.m_value.binary->size();
|
||||
if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
std::uint8_t output_type;
|
||||
std::uint8_t output_type{};
|
||||
bool fixed = true;
|
||||
if (use_ext)
|
||||
{
|
||||
|
@ -626,30 +615,18 @@ class binary_writer
|
|||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
std::uint8_t output_type;
|
||||
if (use_ext)
|
||||
{
|
||||
output_type = 0xC8; // ext 16
|
||||
}
|
||||
else
|
||||
{
|
||||
output_type = 0xC5; // bin 16
|
||||
}
|
||||
std::uint8_t output_type = use_ext
|
||||
? 0xC8 // ext 16
|
||||
: 0xC5; // bin 16
|
||||
|
||||
oa->write_character(to_char_type(output_type));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
std::uint8_t output_type;
|
||||
if (use_ext)
|
||||
{
|
||||
output_type = 0xC9; // ext 32
|
||||
}
|
||||
else
|
||||
{
|
||||
output_type = 0xC6; // bin 32
|
||||
}
|
||||
std::uint8_t output_type = use_ext
|
||||
? 0xC9 // ext 32
|
||||
: 0xC6; // bin 32
|
||||
|
||||
oa->write_character(to_char_type(output_type));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
|
@ -1518,6 +1495,26 @@ class binary_writer
|
|||
oa->write_characters(vec.data(), sizeof(NumberType));
|
||||
}
|
||||
|
||||
void write_compact_float(const number_float_t n, detail::input_format_t format)
|
||||
{
|
||||
if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) and
|
||||
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) and
|
||||
static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
|
||||
{
|
||||
oa->write_character(format == detail::input_format_t::cbor
|
||||
? get_cbor_float_prefix(static_cast<float>(n))
|
||||
: get_msgpack_float_prefix(static_cast<float>(n)));
|
||||
write_number(static_cast<float>(n));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(format == detail::input_format_t::cbor
|
||||
? get_cbor_float_prefix(n)
|
||||
: get_msgpack_float_prefix(n));
|
||||
write_number(n);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// The following to_char_type functions are implement the conversion
|
||||
// between uint8_t and CharType. In case CharType is not unsigned,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <cstdint> // uint8_t
|
||||
#include <cstdio> // snprintf
|
||||
#include <limits> // numeric_limits
|
||||
#include <string> // string
|
||||
#include <string> // string, char_traits
|
||||
#include <type_traits> // is_same
|
||||
#include <utility> // move
|
||||
|
||||
|
@ -59,8 +59,8 @@ class serializer
|
|||
error_handler_t error_handler_ = error_handler_t::strict)
|
||||
: o(std::move(s))
|
||||
, loc(std::localeconv())
|
||||
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep))
|
||||
, decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point))
|
||||
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
|
||||
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
|
||||
, indent_char(ichar)
|
||||
, indent_string(512, indent_char)
|
||||
, error_handler(error_handler_)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue