未验证 提交 988077e0 编写于 作者: N Niels Lohmann

Merge branch 'develop' into feature/travis_clang

...@@ -463,13 +463,8 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept ...@@ -463,13 +463,8 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
}; };
// discarded values are not comparable // discarded values are not comparable
if (lhs == value_t::discarded or rhs == value_t::discarded) return lhs != value_t::discarded and rhs != value_t::discarded and
{ order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
return false;
}
return order[static_cast<std::size_t>(lhs)] <
order[static_cast<std::size_t>(rhs)];
} }
...@@ -1007,11 +1002,10 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) ...@@ -1007,11 +1002,10 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
break; break;
} }
default: default:
{
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
} }
}
} }
template<typename BasicJsonType> template<typename BasicJsonType>
...@@ -1080,11 +1074,11 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) ...@@ -1080,11 +1074,11 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
} }
std::transform(j.rbegin(), j.rend(),
for (auto it = j.rbegin(), end = j.rend(); it != end; ++it) std::front_inserter(l), [](const BasicJsonType & i)
{ {
l.push_front(it->template get<T>()); return i.template get<T>();
} });
} }
template<typename BasicJsonType, typename CompatibleArrayType> template<typename BasicJsonType, typename CompatibleArrayType>
...@@ -1198,11 +1192,10 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) ...@@ -1198,11 +1192,10 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
break; break;
} }
default: default:
{
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
} }
}
} }
template<typename BasicJsonType, typename... Args> template<typename BasicJsonType, typename... Args>
...@@ -1629,13 +1622,10 @@ class lexer ...@@ -1629,13 +1622,10 @@ class lexer
return "end of input"; return "end of input";
case token_type::literal_or_value: case token_type::literal_or_value:
return "'[', '{', or a literal"; return "'[', '{', or a literal";
default: default: // catch non-enum values
{
// catch non-enum values
return "unknown token"; // LCOV_EXCL_LINE return "unknown token"; // LCOV_EXCL_LINE
} }
} }
}
explicit lexer(detail::input_adapter_t adapter) explicit lexer(detail::input_adapter_t adapter)
: ia(adapter), decimal_point_char(get_decimal_point()) {} : ia(adapter), decimal_point_char(get_decimal_point()) {}
...@@ -1682,7 +1672,8 @@ class lexer ...@@ -1682,7 +1672,8 @@ class lexer
assert(current == 'u'); assert(current == 'u');
int codepoint = 0; int codepoint = 0;
for (int factor = 12; factor >= 0; factor -= 4) const auto factors = { 12, 8, 4, 0 };
for (const auto factor : factors)
{ {
get(); get();
...@@ -2339,10 +2330,8 @@ scan_number_zero: ...@@ -2339,10 +2330,8 @@ scan_number_zero:
} }
default: default:
{
goto scan_number_done; goto scan_number_done;
} }
}
scan_number_any1: scan_number_any1:
// state: we just parsed a number 0-9 (maybe with a leading minus sign) // state: we just parsed a number 0-9 (maybe with a leading minus sign)
...@@ -2377,10 +2366,8 @@ scan_number_any1: ...@@ -2377,10 +2366,8 @@ scan_number_any1:
} }
default: default:
{
goto scan_number_done; goto scan_number_done;
} }
}
scan_number_decimal1: scan_number_decimal1:
// state: we just parsed a decimal point // state: we just parsed a decimal point
...@@ -2436,10 +2423,8 @@ scan_number_decimal2: ...@@ -2436,10 +2423,8 @@ scan_number_decimal2:
} }
default: default:
{
goto scan_number_done; goto scan_number_done;
} }
}
scan_number_exponent: scan_number_exponent:
// we just parsed an exponent // we just parsed an exponent
...@@ -2522,10 +2507,8 @@ scan_number_any2: ...@@ -2522,10 +2507,8 @@ scan_number_any2:
} }
default: default:
{
goto scan_number_done; goto scan_number_done;
} }
}
scan_number_done: scan_number_done:
// unget the character after the number (we only read it to know that // unget the character after the number (we only read it to know that
...@@ -2537,11 +2520,12 @@ scan_number_done: ...@@ -2537,11 +2520,12 @@ scan_number_done:
add('\0'); add('\0');
--yylen; --yylen;
char* endptr = nullptr;
errno = 0;
// try to parse integers first and fall back to floats // try to parse integers first and fall back to floats
if (number_type == token_type::value_unsigned) if (number_type == token_type::value_unsigned)
{ {
char* endptr = nullptr;
errno = 0;
const auto x = std::strtoull(yytext.data(), &endptr, 10); const auto x = std::strtoull(yytext.data(), &endptr, 10);
// we checked the number format before // we checked the number format before
...@@ -2558,8 +2542,6 @@ scan_number_done: ...@@ -2558,8 +2542,6 @@ scan_number_done:
} }
else if (number_type == token_type::value_integer) else if (number_type == token_type::value_integer)
{ {
char* endptr = nullptr;
errno = 0;
const auto x = std::strtoll(yytext.data(), &endptr, 10); const auto x = std::strtoll(yytext.data(), &endptr, 10);
// we checked the number format before // we checked the number format before
...@@ -2577,7 +2559,11 @@ scan_number_done: ...@@ -2577,7 +2559,11 @@ scan_number_done:
// this code is reached if we parse a floating-point number or if an // this code is reached if we parse a floating-point number or if an
// integer conversion above failed // integer conversion above failed
strtof(value_float, yytext.data(), nullptr); strtof(value_float, yytext.data(), &endptr);
// we checked the number format before
assert(endptr == yytext.data() + yylen);
return token_type::value_float; return token_type::value_float;
} }
...@@ -2700,7 +2686,7 @@ scan_number_done: ...@@ -2700,7 +2686,7 @@ scan_number_done:
else else
{ {
// add character as is // add character as is
result.append(1, c); result.push_back(c);
} }
} }
...@@ -2851,8 +2837,7 @@ class parser ...@@ -2851,8 +2837,7 @@ class parser
explicit parser(detail::input_adapter_t adapter, explicit parser(detail::input_adapter_t adapter,
const parser_callback_t cb = nullptr, const parser_callback_t cb = nullptr,
const bool allow_exceptions_ = true) const bool allow_exceptions_ = true)
: callback(cb), m_lexer(adapter), : callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)
allow_exceptions(allow_exceptions_)
{} {}
/*! /*!
...@@ -2911,12 +2896,8 @@ class parser ...@@ -2911,12 +2896,8 @@ class parser
return false; return false;
} }
if (strict and get_token() != token_type::end_of_input) // strict => last token must be EOF
{ return not strict or (get_token() == token_type::end_of_input);
return false;
}
return true;
} }
private: private:
...@@ -3156,11 +3137,8 @@ class parser ...@@ -3156,11 +3137,8 @@ class parser
JSON_THROW(out_of_range::create(406, "number overflow parsing '" + JSON_THROW(out_of_range::create(406, "number overflow parsing '" +
m_lexer.get_token_string() + "'")); m_lexer.get_token_string() + "'"));
} }
else
{
expect(token_type::uninitialized); expect(token_type::uninitialized);
} }
}
break; break;
} }
...@@ -3297,17 +3275,12 @@ class parser ...@@ -3297,17 +3275,12 @@ class parser
case token_type::value_integer: case token_type::value_integer:
case token_type::value_string: case token_type::value_string:
case token_type::value_unsigned: case token_type::value_unsigned:
{
return true; return true;
}
default: default: // the last token was unexpected
{
// the last token was unexpected
return false; return false;
} }
} }
}
/// get next token from lexer /// get next token from lexer
token_type get_token() token_type get_token()
...@@ -3740,9 +3713,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3740,9 +3713,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
} }
case value_t::null: case value_t::null:
{
JSON_THROW(invalid_iterator::create(214, "cannot get value")); JSON_THROW(invalid_iterator::create(214, "cannot get value"));
}
default: default:
{ {
...@@ -3893,21 +3864,15 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3893,21 +3864,15 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
return (m_it.object_iterator == other.m_it.object_iterator); return (m_it.object_iterator == other.m_it.object_iterator);
}
case value_t::array: case value_t::array:
{
return (m_it.array_iterator == other.m_it.array_iterator); return (m_it.array_iterator == other.m_it.array_iterator);
}
default: default:
{
return (m_it.primitive_iterator == other.m_it.primitive_iterator); return (m_it.primitive_iterator == other.m_it.primitive_iterator);
} }
} }
}
/*! /*!
@brief comparison: not equal @brief comparison: not equal
...@@ -3935,21 +3900,15 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3935,21 +3900,15 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
}
case value_t::array: case value_t::array:
{
return (m_it.array_iterator < other.m_it.array_iterator); return (m_it.array_iterator < other.m_it.array_iterator);
}
default: default:
{
return (m_it.primitive_iterator < other.m_it.primitive_iterator); return (m_it.primitive_iterator < other.m_it.primitive_iterator);
} }
} }
}
/*! /*!
@brief comparison: less than or equal @brief comparison: less than or equal
...@@ -3989,9 +3948,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3989,9 +3948,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
}
case value_t::array: case value_t::array:
{ {
...@@ -4062,21 +4019,15 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4062,21 +4019,15 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
}
case value_t::array: case value_t::array:
{
return m_it.array_iterator - other.m_it.array_iterator; return m_it.array_iterator - other.m_it.array_iterator;
}
default: default:
{
return m_it.primitive_iterator - other.m_it.primitive_iterator; return m_it.primitive_iterator - other.m_it.primitive_iterator;
} }
} }
}
/*! /*!
@brief access to successor @brief access to successor
...@@ -4089,19 +4040,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4089,19 +4040,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
}
case value_t::array: case value_t::array:
{
return *std::next(m_it.array_iterator, n); return *std::next(m_it.array_iterator, n);
}
case value_t::null: case value_t::null:
{
JSON_THROW(invalid_iterator::create(214, "cannot get value")); JSON_THROW(invalid_iterator::create(214, "cannot get value"));
}
default: default:
{ {
...@@ -4193,23 +4138,17 @@ template<typename IteratorType> class iteration_proxy ...@@ -4193,23 +4138,17 @@ template<typename IteratorType> class iteration_proxy
{ {
// use integer array index as key // use integer array index as key
case value_t::array: case value_t::array:
{
return std::to_string(array_index); return std::to_string(array_index);
}
// use key from the object // use key from the object
case value_t::object: case value_t::object:
{
return anchor.key(); return anchor.key();
}
// use an empty key for all primitive types // use an empty key for all primitive types
default: default:
{
return ""; return "";
} }
} }
}
/// return value of the iterator /// return value of the iterator
typename IteratorType::reference value() const typename IteratorType::reference value() const
...@@ -4486,9 +4425,7 @@ class binary_reader ...@@ -4486,9 +4425,7 @@ class binary_reader
{ {
// EOF // EOF
case std::char_traits<char>::eof(): case std::char_traits<char>::eof():
{
JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input")); JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
}
// Integer 0x00..0x17 (0..23) // Integer 0x00..0x17 (0..23)
case 0x00: case 0x00:
...@@ -4515,29 +4452,19 @@ class binary_reader ...@@ -4515,29 +4452,19 @@ class binary_reader
case 0x15: case 0x15:
case 0x16: case 0x16:
case 0x17: case 0x17:
{
return static_cast<number_unsigned_t>(current); return static_cast<number_unsigned_t>(current);
}
case 0x18: // Unsigned integer (one-byte uint8_t follows) case 0x18: // Unsigned integer (one-byte uint8_t follows)
{
return get_number<uint8_t>(); return get_number<uint8_t>();
}
case 0x19: // Unsigned integer (two-byte uint16_t follows) case 0x19: // Unsigned integer (two-byte uint16_t follows)
{
return get_number<uint16_t>(); return get_number<uint16_t>();
}
case 0x1a: // Unsigned integer (four-byte uint32_t follows) case 0x1a: // Unsigned integer (four-byte uint32_t follows)
{
return get_number<uint32_t>(); return get_number<uint32_t>();
}
case 0x1b: // Unsigned integer (eight-byte uint64_t follows) case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
{
return get_number<uint64_t>(); return get_number<uint64_t>();
}
// Negative integer -1-0x00..-1-0x17 (-1..-24) // Negative integer -1-0x00..-1-0x17 (-1..-24)
case 0x20: case 0x20:
...@@ -4564,9 +4491,7 @@ class binary_reader ...@@ -4564,9 +4491,7 @@ class binary_reader
case 0x35: case 0x35:
case 0x36: case 0x36:
case 0x37: case 0x37:
{
return static_cast<int8_t>(0x20 - 1 - current); return static_cast<int8_t>(0x20 - 1 - current);
}
case 0x38: // Negative integer (one-byte uint8_t follows) case 0x38: // Negative integer (one-byte uint8_t follows)
{ {
...@@ -4650,57 +4575,27 @@ class binary_reader ...@@ -4650,57 +4575,27 @@ class binary_reader
case 0x96: case 0x96:
case 0x97: case 0x97:
{ {
BasicJsonType result = value_t::array; return get_cbor_array(current & 0x1f);
const auto len = static_cast<size_t>(current & 0x1f);
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x98: // array (one-byte uint8_t for n follows) case 0x98: // array (one-byte uint8_t for n follows)
{ {
BasicJsonType result = value_t::array; return get_cbor_array(get_number<uint8_t>());
const auto len = static_cast<size_t>(get_number<uint8_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x99: // array (two-byte uint16_t for n follow) case 0x99: // array (two-byte uint16_t for n follow)
{ {
BasicJsonType result = value_t::array; return get_cbor_array(get_number<uint16_t>());
const auto len = static_cast<size_t>(get_number<uint16_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x9a: // array (four-byte uint32_t for n follow) case 0x9a: // array (four-byte uint32_t for n follow)
{ {
BasicJsonType result = value_t::array; return get_cbor_array(get_number<uint32_t>());
const auto len = static_cast<size_t>(get_number<uint32_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x9b: // array (eight-byte uint64_t for n follow) case 0x9b: // array (eight-byte uint64_t for n follow)
{ {
BasicJsonType result = value_t::array; return get_cbor_array(get_number<uint64_t>());
const auto len = static_cast<size_t>(get_number<uint64_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x9f: // array (indefinite length) case 0x9f: // array (indefinite length)
...@@ -4739,67 +4634,27 @@ class binary_reader ...@@ -4739,67 +4634,27 @@ class binary_reader
case 0xb6: case 0xb6:
case 0xb7: case 0xb7:
{ {
BasicJsonType result = value_t::object; return get_cbor_object(current & 0x1f);
const auto len = static_cast<size_t>(current & 0x1f);
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xb8: // map (one-byte uint8_t for n follows) case 0xb8: // map (one-byte uint8_t for n follows)
{ {
BasicJsonType result = value_t::object; return get_cbor_object(get_number<uint8_t>());
const auto len = static_cast<size_t>(get_number<uint8_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xb9: // map (two-byte uint16_t for n follow) case 0xb9: // map (two-byte uint16_t for n follow)
{ {
BasicJsonType result = value_t::object; return get_cbor_object(get_number<uint16_t>());
const auto len = static_cast<size_t>(get_number<uint16_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xba: // map (four-byte uint32_t for n follow) case 0xba: // map (four-byte uint32_t for n follow)
{ {
BasicJsonType result = value_t::object; return get_cbor_object(get_number<uint32_t>());
const auto len = static_cast<size_t>(get_number<uint32_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xbb: // map (eight-byte uint64_t for n follow) case 0xbb: // map (eight-byte uint64_t for n follow)
{ {
BasicJsonType result = value_t::object; return get_cbor_object(get_number<uint64_t>());
const auto len = static_cast<size_t>(get_number<uint64_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xbf: // map (indefinite length) case 0xbf: // map (indefinite length)
...@@ -4896,9 +4751,7 @@ class binary_reader ...@@ -4896,9 +4751,7 @@ class binary_reader
{ {
// EOF // EOF
case std::char_traits<char>::eof(): case std::char_traits<char>::eof():
{
JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input")); JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
}
// positive fixint // positive fixint
case 0x00: case 0x00:
...@@ -5029,9 +4882,7 @@ class binary_reader ...@@ -5029,9 +4882,7 @@ class binary_reader
case 0x7d: case 0x7d:
case 0x7e: case 0x7e:
case 0x7f: case 0x7f:
{
return static_cast<number_unsigned_t>(current); return static_cast<number_unsigned_t>(current);
}
// fixmap // fixmap
case 0x80: case 0x80:
...@@ -5051,15 +4902,7 @@ class binary_reader ...@@ -5051,15 +4902,7 @@ class binary_reader
case 0x8e: case 0x8e:
case 0x8f: case 0x8f:
{ {
BasicJsonType result = value_t::object; return get_msgpack_object(current & 0x0f);
const auto len = static_cast<size_t>(current & 0x0f);
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_msgpack_string();
result[key] = parse_msgpack();
}
return result;
} }
// fixarray // fixarray
...@@ -5080,13 +4923,7 @@ class binary_reader ...@@ -5080,13 +4923,7 @@ class binary_reader
case 0x9e: case 0x9e:
case 0x9f: case 0x9f:
{ {
BasicJsonType result = value_t::array; return get_msgpack_array(current & 0x0f);
const auto len = static_cast<size_t>(current & 0x0f);
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_msgpack());
}
return result;
} }
// fixstr // fixstr
...@@ -5122,128 +4959,70 @@ class binary_reader ...@@ -5122,128 +4959,70 @@ class binary_reader
case 0xbd: case 0xbd:
case 0xbe: case 0xbe:
case 0xbf: case 0xbf:
{
return get_msgpack_string(); return get_msgpack_string();
}
case 0xc0: // nil case 0xc0: // nil
{
return value_t::null; return value_t::null;
}
case 0xc2: // false case 0xc2: // false
{
return false; return false;
}
case 0xc3: // true case 0xc3: // true
{
return true; return true;
}
case 0xca: // float 32 case 0xca: // float 32
{
return get_number<float>(); return get_number<float>();
}
case 0xcb: // float 64 case 0xcb: // float 64
{
return get_number<double>(); return get_number<double>();
}
case 0xcc: // uint 8 case 0xcc: // uint 8
{
return get_number<uint8_t>(); return get_number<uint8_t>();
}
case 0xcd: // uint 16 case 0xcd: // uint 16
{
return get_number<uint16_t>(); return get_number<uint16_t>();
}
case 0xce: // uint 32 case 0xce: // uint 32
{
return get_number<uint32_t>(); return get_number<uint32_t>();
}
case 0xcf: // uint 64 case 0xcf: // uint 64
{
return get_number<uint64_t>(); return get_number<uint64_t>();
}
case 0xd0: // int 8 case 0xd0: // int 8
{
return get_number<int8_t>(); return get_number<int8_t>();
}
case 0xd1: // int 16 case 0xd1: // int 16
{
return get_number<int16_t>(); return get_number<int16_t>();
}
case 0xd2: // int 32 case 0xd2: // int 32
{
return get_number<int32_t>(); return get_number<int32_t>();
}
case 0xd3: // int 64 case 0xd3: // int 64
{
return get_number<int64_t>(); return get_number<int64_t>();
}
case 0xd9: // str 8 case 0xd9: // str 8
case 0xda: // str 16 case 0xda: // str 16
case 0xdb: // str 32 case 0xdb: // str 32
{
return get_msgpack_string(); return get_msgpack_string();
}
case 0xdc: // array 16 case 0xdc: // array 16
{ {
BasicJsonType result = value_t::array; return get_msgpack_array(get_number<uint16_t>());
const auto len = static_cast<size_t>(get_number<uint16_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_msgpack());
}
return result;
} }
case 0xdd: // array 32 case 0xdd: // array 32
{ {
BasicJsonType result = value_t::array; return get_msgpack_array(get_number<uint32_t>());
const auto len = static_cast<size_t>(get_number<uint32_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_msgpack());
}
return result;
} }
case 0xde: // map 16 case 0xde: // map 16
{ {
BasicJsonType result = value_t::object; return get_msgpack_object(get_number<uint16_t>());
const auto len = static_cast<size_t>(get_number<uint16_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_msgpack_string();
result[key] = parse_msgpack();
}
return result;
} }
case 0xdf: // map 32 case 0xdf: // map 32
{ {
BasicJsonType result = value_t::object; return get_msgpack_object(get_number<uint32_t>());
const auto len = static_cast<size_t>(get_number<uint32_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_msgpack_string();
result[key] = parse_msgpack();
}
return result;
} }
// positive fixint // positive fixint
...@@ -5279,9 +5058,7 @@ class binary_reader ...@@ -5279,9 +5058,7 @@ class binary_reader
case 0xfd: case 0xfd:
case 0xfe: case 0xfe:
case 0xff: case 0xff:
{
return static_cast<int8_t>(current); return static_cast<int8_t>(current);
}
default: // anything else default: // anything else
{ {
...@@ -5373,15 +5150,16 @@ class binary_reader ...@@ -5373,15 +5150,16 @@ class binary_reader
@throw parse_error.110 if input has less than @a len bytes @throw parse_error.110 if input has less than @a len bytes
*/ */
std::string get_string(const std::size_t len) template<typename NumberType>
std::string get_string(const NumberType len)
{ {
std::string result; std::string result;
for (std::size_t i = 0; i < len; ++i) std::generate_n(std::back_inserter(result), len, [this]()
{ {
get(); get();
check_eof(); check_eof();
result.append(1, static_cast<char>(current)); return current;
} });
return result; return result;
} }
...@@ -5429,32 +5207,27 @@ class binary_reader ...@@ -5429,32 +5207,27 @@ class binary_reader
case 0x76: case 0x76:
case 0x77: case 0x77:
{ {
const auto len = static_cast<size_t>(current & 0x1f); return get_string(current & 0x1f);
return get_string(len);
} }
case 0x78: // UTF-8 string (one-byte uint8_t for n follows) case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
{ {
const auto len = static_cast<size_t>(get_number<uint8_t>()); return get_string(get_number<uint8_t>());
return get_string(len);
} }
case 0x79: // UTF-8 string (two-byte uint16_t for n follow) case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
{ {
const auto len = static_cast<size_t>(get_number<uint16_t>()); return get_string(get_number<uint16_t>());
return get_string(len);
} }
case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
{ {
const auto len = static_cast<size_t>(get_number<uint32_t>()); return get_string(get_number<uint32_t>());
return get_string(len);
} }
case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
{ {
const auto len = static_cast<size_t>(get_number<uint64_t>()); return get_string(get_number<uint64_t>());
return get_string(len);
} }
case 0x7f: // UTF-8 string (indefinite length) case 0x7f: // UTF-8 string (indefinite length)
...@@ -5463,7 +5236,7 @@ class binary_reader ...@@ -5463,7 +5236,7 @@ class binary_reader
while (get() != 0xff) while (get() != 0xff)
{ {
check_eof(); check_eof();
result.append(1, static_cast<char>(current)); result.push_back(static_cast<char>(current));
} }
return result; return result;
} }
...@@ -5477,6 +5250,33 @@ class binary_reader ...@@ -5477,6 +5250,33 @@ class binary_reader
} }
} }
template<typename NumberType>
BasicJsonType get_cbor_array(const NumberType len)
{
BasicJsonType result = value_t::array;
std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
{
return parse_cbor();
});
return result;
}
template<typename NumberType>
BasicJsonType get_cbor_object(const NumberType len)
{
BasicJsonType result = value_t::object;
std::generate_n(std::inserter(*result.m_value.object,
result.m_value.object->end()),
len, [this]()
{
get();
auto key = get_cbor_string();
auto val = parse_cbor();
return std::make_pair(std::move(key), std::move(val));
});
return result;
}
/*! /*!
@brief reads a MessagePack string @brief reads a MessagePack string
...@@ -5528,26 +5328,22 @@ class binary_reader ...@@ -5528,26 +5328,22 @@ class binary_reader
case 0xbe: case 0xbe:
case 0xbf: case 0xbf:
{ {
const auto len = static_cast<size_t>(current & 0x1f); return get_string(current & 0x1f);
return get_string(len);
} }
case 0xd9: // str 8 case 0xd9: // str 8
{ {
const auto len = static_cast<size_t>(get_number<uint8_t>()); return get_string(get_number<uint8_t>());
return get_string(len);
} }
case 0xda: // str 16 case 0xda: // str 16
{ {
const auto len = static_cast<size_t>(get_number<uint16_t>()); return get_string(get_number<uint16_t>());
return get_string(len);
} }
case 0xdb: // str 32 case 0xdb: // str 32
{ {
const auto len = static_cast<size_t>(get_number<uint32_t>()); return get_string(get_number<uint32_t>());
return get_string(len);
} }
default: default:
...@@ -5560,6 +5356,33 @@ class binary_reader ...@@ -5560,6 +5356,33 @@ class binary_reader
} }
} }
template<typename NumberType>
BasicJsonType get_msgpack_array(const NumberType len)
{
BasicJsonType result = value_t::array;
std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
{
return parse_msgpack();
});
return result;
}
template<typename NumberType>
BasicJsonType get_msgpack_object(const NumberType len)
{
BasicJsonType result = value_t::object;
std::generate_n(std::inserter(*result.m_value.object,
result.m_value.object->end()),
len, [this]()
{
get();
auto key = get_msgpack_string();
auto val = parse_msgpack();
return std::make_pair(std::move(key), std::move(val));
});
return result;
}
/*! /*!
@brief check if input ended @brief check if input ended
@throw parse_error.110 if input ended @throw parse_error.110 if input ended
...@@ -5718,9 +5541,8 @@ class binary_writer ...@@ -5718,9 +5541,8 @@ class binary_writer
break; break;
} }
case value_t::number_float: case value_t::number_float: // Double-Precision Float
{ {
// Double-Precision Float
oa->write_character(static_cast<CharType>(0xfb)); oa->write_character(static_cast<CharType>(0xfb));
write_number(j.m_value.number_float); write_number(j.m_value.number_float);
break; break;
...@@ -5844,11 +5666,9 @@ class binary_writer ...@@ -5844,11 +5666,9 @@ class binary_writer
} }
default: default:
{
break; break;
} }
} }
}
/*! /*!
@brief[in] j JSON value to serialize @brief[in] j JSON value to serialize
...@@ -5857,16 +5677,14 @@ class binary_writer ...@@ -5857,16 +5677,14 @@ class binary_writer
{ {
switch (j.type()) switch (j.type())
{ {
case value_t::null: case value_t::null: // nil
{ {
// nil
oa->write_character(static_cast<CharType>(0xc0)); oa->write_character(static_cast<CharType>(0xc0));
break; break;
} }
case value_t::boolean: case value_t::boolean: // true and false
{ {
// true and false
oa->write_character(j.m_value.boolean oa->write_character(j.m_value.boolean
? static_cast<CharType>(0xc3) ? static_cast<CharType>(0xc3)
: static_cast<CharType>(0xc2)); : static_cast<CharType>(0xc2));
...@@ -5983,9 +5801,8 @@ class binary_writer ...@@ -5983,9 +5801,8 @@ class binary_writer
break; break;
} }
case value_t::number_float: case value_t::number_float: // float 64
{ {
// float 64
oa->write_character(static_cast<CharType>(0xcb)); oa->write_character(static_cast<CharType>(0xcb));
write_number(j.m_value.number_float); write_number(j.m_value.number_float);
break; break;
...@@ -6088,11 +5905,9 @@ class binary_writer ...@@ -6088,11 +5905,9 @@ class binary_writer
} }
default: default:
{
break; break;
} }
} }
}
private: private:
/* /*
...@@ -6212,6 +6027,7 @@ class serializer ...@@ -6212,6 +6027,7 @@ class serializer
// last element // last element
assert(i != val.m_value.object->cend()); assert(i != val.m_value.object->cend());
assert(std::next(i) == val.m_value.object->cend());
o->write_characters(indent_string.c_str(), new_indent); o->write_characters(indent_string.c_str(), new_indent);
o->write_character('\"'); o->write_character('\"');
dump_escaped(i->first, ensure_ascii); dump_escaped(i->first, ensure_ascii);
...@@ -6239,6 +6055,7 @@ class serializer ...@@ -6239,6 +6055,7 @@ class serializer
// last element // last element
assert(i != val.m_value.object->cend()); assert(i != val.m_value.object->cend());
assert(std::next(i) == val.m_value.object->cend());
o->write_character('\"'); o->write_character('\"');
dump_escaped(i->first, ensure_ascii); dump_escaped(i->first, ensure_ascii);
o->write_characters("\":", 2); o->write_characters("\":", 2);
...@@ -6459,7 +6276,7 @@ class serializer ...@@ -6459,7 +6276,7 @@ class serializer
if (bytes == 3) if (bytes == 3)
{ {
// codepoints that need 4 bytes (i.e., 3 additional // codepoints that need 4 bytes (i.e., 3 additional
// bytes) in UTF-8 needs a surrogate pair when \u // bytes) in UTF-8 need a surrogate pair when \u
// escaping is used: from 4 bytes to \uxxxx\uxxxx // escaping is used: from 4 bytes to \uxxxx\uxxxx
// (12 bytes) // (12 bytes)
res += (12 - bytes - 1); res += (12 - bytes - 1);
...@@ -6481,7 +6298,7 @@ class serializer ...@@ -6481,7 +6298,7 @@ class serializer
return res; return res;
} }
static void escape_codepoint(int codepoint, string_t& result, size_t& pos) static void escape_codepoint(int codepoint, string_t& result, std::size_t& pos)
{ {
// expecting a proper codepoint // expecting a proper codepoint
assert(0x00 <= codepoint and codepoint <= 0x10FFFF); assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
...@@ -6563,56 +6380,49 @@ class serializer ...@@ -6563,56 +6380,49 @@ class serializer
{ {
switch (s[i]) switch (s[i])
{ {
// quotation mark (0x22) case '"': // quotation mark (0x22)
case '"':
{ {
result[pos + 1] = '"'; result[pos + 1] = '"';
pos += 2; pos += 2;
break; break;
} }
// reverse solidus (0x5c) case '\\': // reverse solidus (0x5c)
case '\\':
{ {
// nothing to change // nothing to change
pos += 2; pos += 2;
break; break;
} }
// backspace (0x08) case '\b': // backspace (0x08)
case '\b':
{ {
result[pos + 1] = 'b'; result[pos + 1] = 'b';
pos += 2; pos += 2;
break; break;
} }
// formfeed (0x0c) case '\f': // formfeed (0x0c)
case '\f':
{ {
result[pos + 1] = 'f'; result[pos + 1] = 'f';
pos += 2; pos += 2;
break; break;
} }
// newline (0x0a) case '\n': // newline (0x0a)
case '\n':
{ {
result[pos + 1] = 'n'; result[pos + 1] = 'n';
pos += 2; pos += 2;
break; break;
} }
// carriage return (0x0d) case '\r': // carriage return (0x0d)
case '\r':
{ {
result[pos + 1] = 'r'; result[pos + 1] = 'r';
pos += 2; pos += 2;
break; break;
} }
// horizontal tab (0x09) case '\t': // horizontal tab (0x09)
case '\t':
{ {
result[pos + 1] = 't'; result[pos + 1] = 't';
pos += 2; pos += 2;
...@@ -6780,7 +6590,7 @@ class serializer ...@@ -6780,7 +6590,7 @@ class serializer
// negative value indicates an error // negative value indicates an error
assert(len > 0); assert(len > 0);
// check if buffer was large enough // check if buffer was large enough
assert(static_cast<size_t>(len) < number_buffer.size()); assert(static_cast<std::size_t>(len) < number_buffer.size());
// erase thousands separator // erase thousands separator
if (thousands_sep != '\0') if (thousands_sep != '\0')
...@@ -6805,7 +6615,7 @@ class serializer ...@@ -6805,7 +6615,7 @@ class serializer
} }
} }
o->write_characters(number_buffer.data(), static_cast<size_t>(len)); o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
// determine if need to append ".0" // determine if need to append ".0"
const bool value_is_int_like = const bool value_is_int_like =
...@@ -7372,6 +7182,9 @@ class basic_json ...@@ -7372,6 +7182,9 @@ class basic_json
friend class ::nlohmann::detail::iter_impl; friend class ::nlohmann::detail::iter_impl;
template<typename BasicJsonType, typename CharType> template<typename BasicJsonType, typename CharType>
friend class ::nlohmann::detail::binary_writer; friend class ::nlohmann::detail::binary_writer;
template<typename BasicJsonType>
friend class ::nlohmann::detail::binary_reader;
/// workaround type for MSVC /// workaround type for MSVC
using basic_json_t = NLOHMANN_BASIC_JSON_TPL; using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
...@@ -8710,10 +8523,8 @@ class basic_json ...@@ -8710,10 +8523,8 @@ class basic_json
} }
default: default:
{
break; break;
} }
}
switch (m_type) switch (m_type)
{ {
...@@ -8762,11 +8573,9 @@ class basic_json ...@@ -8762,11 +8573,9 @@ class basic_json
} }
default: default:
{
JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
std::string(first.m_object->type_name()))); std::string(first.m_object->type_name())));
} }
}
assert_invariant(); assert_invariant();
} }
...@@ -8851,10 +8660,8 @@ class basic_json ...@@ -8851,10 +8660,8 @@ class basic_json
} }
default: default:
{
break; break;
} }
}
assert_invariant(); assert_invariant();
} }
...@@ -10648,10 +10455,8 @@ class basic_json ...@@ -10648,10 +10455,8 @@ class basic_json
} }
default: default:
{
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
} }
}
return result; return result;
} }
...@@ -10758,10 +10563,8 @@ class basic_json ...@@ -10758,10 +10563,8 @@ class basic_json
} }
default: default:
{
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
} }
}
return result; return result;
} }
...@@ -11529,11 +11332,9 @@ class basic_json ...@@ -11529,11 +11332,9 @@ class basic_json
} }
default: default:
{
break; break;
} }
} }
}
/*! /*!
@brief add an object to an array @brief add an object to an array
...@@ -12238,43 +12039,33 @@ class basic_json ...@@ -12238,43 +12039,33 @@ class basic_json
switch (lhs_type) switch (lhs_type)
{ {
case value_t::array: case value_t::array:
{
return (*lhs.m_value.array == *rhs.m_value.array); return (*lhs.m_value.array == *rhs.m_value.array);
}
case value_t::object: case value_t::object:
{
return (*lhs.m_value.object == *rhs.m_value.object); return (*lhs.m_value.object == *rhs.m_value.object);
}
case value_t::null: case value_t::null:
{
return true; return true;
}
case value_t::string: case value_t::string:
{
return (*lhs.m_value.string == *rhs.m_value.string); return (*lhs.m_value.string == *rhs.m_value.string);
}
case value_t::boolean: case value_t::boolean:
{
return (lhs.m_value.boolean == rhs.m_value.boolean); return (lhs.m_value.boolean == rhs.m_value.boolean);
}
case value_t::number_integer: case value_t::number_integer:
{
return (lhs.m_value.number_integer == rhs.m_value.number_integer); return (lhs.m_value.number_integer == rhs.m_value.number_integer);
}
case value_t::number_unsigned: case value_t::number_unsigned:
{
return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned); return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
}
case value_t::number_float: case value_t::number_float:
{
return (lhs.m_value.number_float == rhs.m_value.number_float); return (lhs.m_value.number_float == rhs.m_value.number_float);
}
default: default:
{
return false; return false;
} }
} }
}
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
{ {
return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float); return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
...@@ -12402,43 +12193,33 @@ class basic_json ...@@ -12402,43 +12193,33 @@ class basic_json
switch (lhs_type) switch (lhs_type)
{ {
case value_t::array: case value_t::array:
{
return (*lhs.m_value.array) < (*rhs.m_value.array); return (*lhs.m_value.array) < (*rhs.m_value.array);
}
case value_t::object: case value_t::object:
{
return *lhs.m_value.object < *rhs.m_value.object; return *lhs.m_value.object < *rhs.m_value.object;
}
case value_t::null: case value_t::null:
{
return false; return false;
}
case value_t::string: case value_t::string:
{
return *lhs.m_value.string < *rhs.m_value.string; return *lhs.m_value.string < *rhs.m_value.string;
}
case value_t::boolean: case value_t::boolean:
{
return lhs.m_value.boolean < rhs.m_value.boolean; return lhs.m_value.boolean < rhs.m_value.boolean;
}
case value_t::number_integer: case value_t::number_integer:
{
return lhs.m_value.number_integer < rhs.m_value.number_integer; return lhs.m_value.number_integer < rhs.m_value.number_integer;
}
case value_t::number_unsigned: case value_t::number_unsigned:
{
return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned; return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
}
case value_t::number_float: case value_t::number_float:
{
return lhs.m_value.number_float < rhs.m_value.number_float; return lhs.m_value.number_float < rhs.m_value.number_float;
}
default: default:
{
return false; return false;
} }
} }
}
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
{ {
return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float; return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
...@@ -13018,6 +12799,10 @@ class basic_json ...@@ -13018,6 +12799,10 @@ class basic_json
@note The mapping is **complete** in the sense that any JSON value type @note The mapping is **complete** in the sense that any JSON value type
can be converted to a CBOR value. can be converted to a CBOR value.
@note If NaN or Infinity are stored inside a JSON number, they are
serialized properly. This behavior differs from the @ref dump()
function which serializes NaN or Infinity to `null`.
@note The following CBOR types are not used in the conversion: @note The following CBOR types are not used in the conversion:
- byte strings (0x40..0x5f) - byte strings (0x40..0x5f)
- UTF-8 strings terminated by "break" (0x7f) - UTF-8 strings terminated by "break" (0x7f)
...@@ -13045,7 +12830,7 @@ class basic_json ...@@ -13045,7 +12830,7 @@ class basic_json
@sa http://cbor.io @sa http://cbor.io
@sa @ref from_cbor(const std::vector<uint8_t>&, const size_t) for the @sa @ref from_cbor(const std::vector<uint8_t>&, const size_t) for the
analogous deserialization analogous deserialization
@sa @ref to_msgpack(const basic_json& for the related MessagePack format @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
@since version 2.0.9 @since version 2.0.9
*/ */
...@@ -13125,6 +12910,10 @@ class basic_json ...@@ -13125,6 +12910,10 @@ class basic_json
@note Any MessagePack output created @ref to_msgpack can be successfully @note Any MessagePack output created @ref to_msgpack can be successfully
parsed by @ref from_msgpack. parsed by @ref from_msgpack.
@note If NaN or Infinity are stored inside a JSON number, they are
serialized properly. This behavior differs from the @ref dump()
function which serializes NaN or Infinity to `null`.
@param[in] j JSON value to serialize @param[in] j JSON value to serialize
@return MessagePack serialization as byte vector @return MessagePack serialization as byte vector
...@@ -14105,11 +13894,9 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const ...@@ -14105,11 +13894,9 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const
single value; that is, with an empty list of reference tokens. single value; that is, with an empty list of reference tokens.
*/ */
default: default:
{
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
} }
} }
}
return *result; return *result;
} }
...@@ -14179,11 +13966,9 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14179,11 +13966,9 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
default: default:
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
} }
} }
}
return *ptr; return *ptr;
} }
...@@ -14235,11 +14020,9 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14235,11 +14020,9 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
default: default:
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
} }
} }
}
return *ptr; return *ptr;
} }
...@@ -14292,11 +14075,9 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14292,11 +14075,9 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
default: default:
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
} }
} }
}
return *ptr; return *ptr;
} }
...@@ -14348,11 +14129,9 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14348,11 +14129,9 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
default: default:
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
} }
} }
}
return *ptr; return *ptr;
} }
...@@ -14491,9 +14270,10 @@ struct hash<nlohmann::json> ...@@ -14491,9 +14270,10 @@ struct hash<nlohmann::json>
}; };
/// specialization for std::less<value_t> /// specialization for std::less<value_t>
/// @note: do not remove the space after '<',
/// see https://github.com/nlohmann/json/pull/679
template<> template<>
struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', struct less< ::nlohmann::detail::value_t>
// see https://github.com/nlohmann/json/pull/679
{ {
/*! /*!
@brief compare two value_t enum values @brief compare two value_t enum values
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册