🔨 cleanup

parent 4414f94c
...@@ -119,15 +119,15 @@ template<typename = void, typename = void> ...@@ -119,15 +119,15 @@ template<typename = void, typename = void>
struct adl_serializer; struct adl_serializer;
// forward declaration of basic_json (required to split the class) // forward declaration of basic_json (required to split the class)
template <template <typename U, typename V, typename... Args> class ObjectType = template<template<typename U, typename V, typename... Args> class ObjectType =
std::map, std::map,
template <typename U, typename... Args> class ArrayType = std::vector, template<typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string, class BooleanType = bool, class StringType = std::string, class BooleanType = bool,
class NumberIntegerType = std::int64_t, class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t, class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double, class NumberFloatType = double,
template <typename U> class AllocatorType = std::allocator, template<typename U> class AllocatorType = std::allocator,
template <typename T, typename SFINAE = void> class JSONSerializer = template<typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer> adl_serializer>
class basic_json; class basic_json;
...@@ -135,12 +135,12 @@ class basic_json; ...@@ -135,12 +135,12 @@ class basic_json;
// This is only temporary and will be removed in 3.0 // This is only temporary and will be removed in 3.0
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ #define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
template <template <typename, typename, typename...> class ObjectType, \ template<template<typename, typename, typename...> class ObjectType, \
template <typename, typename...> class ArrayType, \ template<typename, typename...> class ArrayType, \
class StringType, class BooleanType, class NumberIntegerType, \ class StringType, class BooleanType, class NumberIntegerType, \
class NumberUnsignedType, class NumberFloatType, \ class NumberUnsignedType, class NumberFloatType, \
template <typename> class AllocatorType, \ template<typename> class AllocatorType, \
template <typename, typename = void> class JSONSerializer> template<typename, typename = void> class JSONSerializer>
#define NLOHMANN_BASIC_JSON_TPL \ #define NLOHMANN_BASIC_JSON_TPL \
basic_json<ObjectType, ArrayType, StringType, BooleanType, \ basic_json<ObjectType, ArrayType, StringType, BooleanType, \
...@@ -188,8 +188,7 @@ class exception : public std::exception ...@@ -188,8 +188,7 @@ class exception : public std::exception
const int id; const int id;
protected: protected:
exception(int id_, const char* what_arg) exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
: id(id_), m(what_arg) {}
static std::string name(const std::string& ename, int id) static std::string name(const std::string& ename, int id)
{ {
...@@ -341,8 +340,7 @@ class type_error : public exception ...@@ -341,8 +340,7 @@ class type_error : public exception
} }
private: private:
type_error(int id_, const char* what_arg) type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
: exception(id_, what_arg) {}
}; };
/*! /*!
...@@ -371,8 +369,7 @@ class out_of_range : public exception ...@@ -371,8 +369,7 @@ class out_of_range : public exception
} }
private: private:
out_of_range(int id_, const char* what_arg) out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
: exception(id_, what_arg) {}
}; };
/*! /*!
...@@ -397,8 +394,7 @@ class other_error : public exception ...@@ -397,8 +394,7 @@ class other_error : public exception
} }
private: private:
other_error(int id_, const char* what_arg) other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
: exception(id_, what_arg) {}
}; };
...@@ -482,9 +478,10 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept ...@@ -482,9 +478,10 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
// helpers // // helpers //
///////////// /////////////
template <typename> struct is_basic_json : std::false_type {}; template<typename> struct is_basic_json : std::false_type {};
NLOHMANN_BASIC_JSON_TPL_DECLARATION struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {}; NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
// alias templates to reduce boilerplate // alias templates to reduce boilerplate
template<bool B, typename T = void> template<bool B, typename T = void>
...@@ -495,7 +492,7 @@ using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::typ ...@@ -495,7 +492,7 @@ using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::typ
// implementation of C++14 index_sequence and affiliates // implementation of C++14 index_sequence and affiliates
// source: https://stackoverflow.com/a/32223343 // source: https://stackoverflow.com/a/32223343
template <std::size_t... Ints> template<std::size_t... Ints>
struct index_sequence struct index_sequence
{ {
using type = index_sequence; using type = index_sequence;
...@@ -506,15 +503,15 @@ struct index_sequence ...@@ -506,15 +503,15 @@ struct index_sequence
} }
}; };
template <class Sequence1, class Sequence2> template<class Sequence1, class Sequence2>
struct merge_and_renumber; struct merge_and_renumber;
template <std::size_t... I1, std::size_t... I2> template<std::size_t... I1, std::size_t... I2>
struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>> struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
: index_sequence < I1..., (sizeof...(I1) + I2)... > : index_sequence < I1..., (sizeof...(I1) + I2)... >
{ }; { };
template <std::size_t N> template<std::size_t N>
struct make_index_sequence struct make_index_sequence
: merge_and_renumber < typename make_index_sequence < N / 2 >::type, : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
typename make_index_sequence < N - N / 2 >::type > typename make_index_sequence < N - N / 2 >::type >
...@@ -722,10 +719,8 @@ template<class RealType, class CompatibleObjectType> ...@@ -722,10 +719,8 @@ template<class RealType, class CompatibleObjectType>
struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType> struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
{ {
static constexpr auto value = static constexpr auto value =
std::is_constructible<typename RealType::key_type, std::is_constructible<typename RealType::key_type, typename CompatibleObjectType::key_type>::value and
typename CompatibleObjectType::key_type>::value and std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
std::is_constructible<typename RealType::mapped_type,
typename CompatibleObjectType::mapped_type>::value;
}; };
template<class BasicJsonType, class CompatibleObjectType> template<class BasicJsonType, class CompatibleObjectType>
...@@ -772,8 +767,7 @@ struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIn ...@@ -772,8 +767,7 @@ struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIn
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>; using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
static constexpr auto value = static constexpr auto value =
std::is_constructible<RealIntegerType, std::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and
CompatibleNumberIntegerType>::value and
CompatibleLimits::is_integer and CompatibleLimits::is_integer and
RealLimits::is_signed == CompatibleLimits::is_signed; RealLimits::is_signed == CompatibleLimits::is_signed;
}; };
...@@ -917,7 +911,7 @@ void to_json(BasicJsonType& j, const CompatibleObjectType& arr) ...@@ -917,7 +911,7 @@ void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
external_constructor<value_t::object>::construct(j, arr); external_constructor<value_t::object>::construct(j, arr);
} }
template <typename BasicJsonType, typename T, std::size_t N, template<typename BasicJsonType, typename T, std::size_t N,
enable_if_t<not std::is_constructible< enable_if_t<not std::is_constructible<
typename BasicJsonType::string_t, T (&)[N]>::value, typename BasicJsonType::string_t, T (&)[N]>::value,
int> = 0> int> = 0>
...@@ -926,19 +920,19 @@ void to_json(BasicJsonType& j, T (&arr)[N]) ...@@ -926,19 +920,19 @@ void to_json(BasicJsonType& j, T (&arr)[N])
external_constructor<value_t::array>::construct(j, arr); external_constructor<value_t::array>::construct(j, arr);
} }
template <typename BasicJsonType, typename... Args> template<typename BasicJsonType, typename... Args>
void to_json(BasicJsonType& j, const std::pair<Args...>& p) void to_json(BasicJsonType& j, const std::pair<Args...>& p)
{ {
j = {p.first, p.second}; j = {p.first, p.second};
} }
template <typename BasicJsonType, typename Tuple, std::size_t... Idx> template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>) void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
{ {
j = {std::get<Idx>(t)...}; j = {std::get<Idx>(t)...};
} }
template <typename BasicJsonType, typename... Args> template<typename BasicJsonType, typename... Args>
void to_json(BasicJsonType& j, const std::tuple<Args...>& t) void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
{ {
to_json_tuple_impl(j, t, index_sequence_for<Args...> {}); to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
...@@ -960,25 +954,22 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) ...@@ -960,25 +954,22 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
{ {
case value_t::number_unsigned: case value_t::number_unsigned:
{ {
val = static_cast<ArithmeticType>( val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
break; break;
} }
case value_t::number_integer: case value_t::number_integer:
{ {
val = static_cast<ArithmeticType>( val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
break; break;
} }
case value_t::number_float: case value_t::number_float:
{ {
val = static_cast<ArithmeticType>( val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
*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 " + j.type_name())); JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
} }
} }
} }
...@@ -986,9 +977,9 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) ...@@ -986,9 +977,9 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
template<typename BasicJsonType> template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
{ {
if (not j.is_boolean()) if (JSON_UNLIKELY(not j.is_boolean()))
{ {
JSON_THROW(type_error::create(302, "type must be boolean, but is " + j.type_name())); JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
} }
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>(); b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
} }
...@@ -996,9 +987,9 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) ...@@ -996,9 +987,9 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
template<typename BasicJsonType> template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
{ {
if (not j.is_string()) if (JSON_UNLIKELY(not j.is_string()))
{ {
JSON_THROW(type_error::create(302, "type must be string, but is " + j.type_name())); JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
} }
s = *j.template get_ptr<const typename BasicJsonType::string_t*>(); s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
} }
...@@ -1033,9 +1024,9 @@ void from_json(const BasicJsonType& j, EnumType& e) ...@@ -1033,9 +1024,9 @@ void from_json(const BasicJsonType& j, EnumType& e)
template<typename BasicJsonType> template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
{ {
if (not j.is_array()) if (JSON_UNLIKELY(not j.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
} }
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>(); arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
} }
...@@ -1045,9 +1036,9 @@ template<typename BasicJsonType, typename T, typename Allocator, ...@@ -1045,9 +1036,9 @@ template<typename BasicJsonType, typename T, typename Allocator,
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0> enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{ {
if (not j.is_array()) if (JSON_UNLIKELY(not j.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
} }
for (auto it = j.rbegin(), end = j.rend(); it != end; ++it) for (auto it = j.rbegin(), end = j.rend(); it != end; ++it)
...@@ -1059,7 +1050,6 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) ...@@ -1059,7 +1050,6 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
template<typename BasicJsonType, typename CompatibleArrayType> template<typename BasicJsonType, typename CompatibleArrayType>
void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/) void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)
{ {
using std::begin;
using std::end; using std::end;
std::transform(j.begin(), j.end(), std::transform(j.begin(), j.end(),
...@@ -1077,7 +1067,6 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio ...@@ -1077,7 +1067,6 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
arr.reserve(std::declval<typename CompatibleArrayType::size_type>()), arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
void()) void())
{ {
using std::begin;
using std::end; using std::end;
arr.reserve(j.size()); arr.reserve(j.size());
...@@ -1090,7 +1079,7 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio ...@@ -1090,7 +1079,7 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
}); });
} }
template <typename BasicJsonType, typename T, std::size_t N> template<typename BasicJsonType, typename T, std::size_t N>
void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/) void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
{ {
for (std::size_t i = 0; i < N; ++i) for (std::size_t i = 0; i < N; ++i)
...@@ -1105,9 +1094,9 @@ template<typename BasicJsonType, typename CompatibleArrayType, ...@@ -1105,9 +1094,9 @@ template<typename BasicJsonType, typename CompatibleArrayType,
not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0> not std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, int> = 0>
void from_json(const BasicJsonType& j, CompatibleArrayType& arr) void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
{ {
if (not j.is_array()) if (JSON_UNLIKELY(not j.is_array()))
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + j.type_name())); JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
} }
from_json_array_impl(j, arr, priority_tag<2> {}); from_json_array_impl(j, arr, priority_tag<2> {});
...@@ -1117,14 +1106,12 @@ template<typename BasicJsonType, typename CompatibleObjectType, ...@@ -1117,14 +1106,12 @@ template<typename BasicJsonType, typename CompatibleObjectType,
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0> enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0>
void from_json(const BasicJsonType& j, CompatibleObjectType& obj) void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
{ {
if (not j.is_object()) if (JSON_UNLIKELY(not j.is_object()))
{ {
JSON_THROW(type_error::create(302, "type must be object, but is " + j.type_name())); JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
} }
auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>(); auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
using std::begin;
using std::end;
using value_type = typename CompatibleObjectType::value_type; using value_type = typename CompatibleObjectType::value_type;
std::transform( std::transform(
inner_object->begin(), inner_object->end(), inner_object->begin(), inner_object->end(),
...@@ -1132,8 +1119,7 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj) ...@@ -1132,8 +1119,7 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj)
[](typename BasicJsonType::object_t::value_type const & p) [](typename BasicJsonType::object_t::value_type const & p)
{ {
return value_type( return value_type(
p.first, p.first, p.second
p.second
.template get<typename CompatibleObjectType::mapped_type>()); .template get<typename CompatibleObjectType::mapped_type>());
}); });
} }
...@@ -1176,24 +1162,24 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) ...@@ -1176,24 +1162,24 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
} }
default: default:
{ {
JSON_THROW(type_error::create(302, "type must be number, but is " + 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>
void from_json(const BasicJsonType& j, std::pair<Args...>& p) void from_json(const BasicJsonType& j, std::pair<Args...>& p)
{ {
p = {j.at(0), j.at(1)}; p = {j.at(0), j.at(1)};
} }
template <typename BasicJsonType, typename Tuple, std::size_t... Idx> template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>) void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence<Idx...>)
{ {
t = std::make_tuple(j.at(Idx)...); t = std::make_tuple(j.at(Idx)...);
} }
template <typename BasicJsonType, typename... Args> template<typename BasicJsonType, typename... Args>
void from_json(const BasicJsonType& j, std::tuple<Args...>& t) void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
{ {
from_json_tuple_impl(j, t, index_sequence_for<Args...> {}); from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
...@@ -1299,9 +1285,9 @@ class cached_input_stream_adapter : public input_adapter_protocol ...@@ -1299,9 +1285,9 @@ class cached_input_stream_adapter : public input_adapter_protocol
{ {
// clear stream flags // clear stream flags
is.clear(); is.clear();
// We initially read a lot of characters into the buffer, and we may not // We initially read a lot of characters into the buffer, and we may
// have processed all of them. Therefore, we need to "rewind" the stream // not have processed all of them. Therefore, we need to "rewind" the
// after the last processed char. // stream after the last processed char.
is.seekg(start_position); is.seekg(start_position);
is.ignore(static_cast<std::streamsize>(processed_chars)); is.ignore(static_cast<std::streamsize>(processed_chars));
// clear stream flags // clear stream flags
...@@ -1443,7 +1429,7 @@ class input_adapter ...@@ -1443,7 +1429,7 @@ class input_adapter
: ia(std::make_shared<cached_input_stream_adapter<16384>>(i)) {} : ia(std::make_shared<cached_input_stream_adapter<16384>>(i)) {}
/// input adapter for buffer /// input adapter for buffer
template <typename CharT, template<typename CharT,
typename std::enable_if< typename std::enable_if<
std::is_pointer<CharT>::value and std::is_pointer<CharT>::value and
std::is_integral< std::is_integral<
...@@ -1456,7 +1442,7 @@ class input_adapter ...@@ -1456,7 +1442,7 @@ class input_adapter
// derived support // derived support
/// input adapter for string literal /// input adapter for string literal
template <typename CharT, template<typename CharT,
typename std::enable_if< typename std::enable_if<
std::is_pointer<CharT>::value and std::is_pointer<CharT>::value and
std::is_integral< std::is_integral<
...@@ -1468,7 +1454,7 @@ class input_adapter ...@@ -1468,7 +1454,7 @@ class input_adapter
std::strlen(reinterpret_cast<const char*>(b))) {} std::strlen(reinterpret_cast<const char*>(b))) {}
/// input adapter for iterator range with contiguous storage /// input adapter for iterator range with contiguous storage
template <class IteratorType, template<class IteratorType,
typename std::enable_if< typename std::enable_if<
std::is_same<typename std::iterator_traits< std::is_same<typename std::iterator_traits<
IteratorType>::iterator_category, IteratorType>::iterator_category,
...@@ -1505,7 +1491,7 @@ class input_adapter ...@@ -1505,7 +1491,7 @@ class input_adapter
} }
/// input adapter for array /// input adapter for array
template <class T, std::size_t N> template<class T, std::size_t N>
input_adapter(T (&array)[N]) input_adapter(T (&array)[N])
: input_adapter(std::begin(array), std::end(array)) {} : input_adapter(std::begin(array), std::end(array)) {}
...@@ -1541,7 +1527,7 @@ class input_adapter ...@@ -1541,7 +1527,7 @@ class input_adapter
This class organizes the lexical analysis during JSON deserialization. This class organizes the lexical analysis during JSON deserialization.
*/ */
template <typename BasicJsonType> template<typename BasicJsonType>
class lexer class lexer
{ {
using number_integer_t = typename BasicJsonType::number_integer_t; using number_integer_t = typename BasicJsonType::number_integer_t;
...@@ -1557,12 +1543,9 @@ class lexer ...@@ -1557,12 +1543,9 @@ class lexer
literal_false, ///< the `false` literal literal_false, ///< the `false` literal
literal_null, ///< the `null` literal literal_null, ///< the `null` literal
value_string, ///< a string -- use get_string() for actual value value_string, ///< a string -- use get_string() for actual value
value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
///actual value value_integer, ///< a signed integer -- use get_number_integer() for actual value
value_integer, ///< a signed integer -- use get_number_integer() for actual value_float, ///< an floating point number -- use get_number_float() for actual value
///value
value_float, ///< an floating point number -- use get_number_float() for
///actual value
begin_array, ///< the character for array begin `[` begin_array, ///< the character for array begin `[`
begin_object, ///< the character for object begin `{` begin_object, ///< the character for object begin `{`
end_array, ///< the character for array end `]` end_array, ///< the character for array end `]`
...@@ -1571,8 +1554,7 @@ class lexer ...@@ -1571,8 +1554,7 @@ class lexer
value_separator, ///< the value separator `,` value_separator, ///< the value separator `,`
parse_error, ///< indicating a parse error parse_error, ///< indicating a parse error
end_of_input, ///< indicating the end of the input buffer end_of_input, ///< indicating the end of the input buffer
literal_or_value ///< a literal or the begin of a value (only for literal_or_value ///< a literal or the begin of a value (only for diagnostics)
///diagnostics)
}; };
/// return name of values of type token_type (only used for errors) /// return name of values of type token_type (only used for errors)
...@@ -1647,8 +1629,7 @@ class lexer ...@@ -1647,8 +1629,7 @@ class lexer
/*! /*!
@brief get codepoint from 4 hex characters following `\u` @brief get codepoint from 4 hex characters following `\u`
@return codepoint or -1 in case of an error (e.g. EOF or non-hex @return codepoint or -1 in case of an error (e.g. EOF or non-hex character)
character)
*/ */
int get_codepoint() int get_codepoint()
{ {
...@@ -1903,9 +1884,9 @@ class lexer ...@@ -1903,9 +1884,9 @@ class lexer
@brief scan a string literal @brief scan a string literal
This function scans a string according to Sect. 7 of RFC 7159. While This function scans a string according to Sect. 7 of RFC 7159. While
scanning, bytes are escaped and copied into buffer yytext. Then the function scanning, bytes are escaped and copied into buffer yytext. Then the
returns successfully, yytext is null-terminated and yylen contains the function returns successfully, yytext is null-terminated and yylen
number of bytes in the string. contains the number of bytes in the string.
@return token_type::value_string if string could be successfully scanned, @return token_type::value_string if string could be successfully scanned,
token_type::parse_error otherwise token_type::parse_error otherwise
...@@ -1988,8 +1969,7 @@ class lexer ...@@ -1988,8 +1969,7 @@ class lexer
if (JSON_UNLIKELY(codepoint1 == -1)) if (JSON_UNLIKELY(codepoint1 == -1))
{ {
error_message = error_message = "invalid string: '\\u' must be followed by 4 hex digits";
"invalid string: '\\u' must be followed by 4 hex digits";
return token_type::parse_error; return token_type::parse_error;
} }
...@@ -2457,27 +2437,17 @@ class lexer ...@@ -2457,27 +2437,17 @@ class lexer
errors. In the table below, "anything" means any character but the ones errors. In the table below, "anything" means any character but the ones
listed before. listed before.
state | 0 | 1-9 | e E | + | - | . | state | 0 | 1-9 | e E | + | - | . | anything
anything
---------|----------|----------|----------|---------|---------|----------|----------- ---------|----------|----------|----------|---------|---------|----------|-----------
init | zero | any1 | [error] | [error] | minus | [error] | init | zero | any1 | [error] | [error] | minus | [error] | [error]
[error] minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
minus | zero | any1 | [error] | [error] | [error] | [error] | zero | done | done | exponent | done | done | decimal1 | done
[error] any1 | any1 | any1 | exponent | done | done | decimal1 | done
zero | done | done | exponent | done | done | decimal1 | decimal1 | decimal2 | [error] | [error] | [error] | [error] | [error] | [error]
done decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
any1 | any1 | any1 | exponent | done | done | decimal1 | exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
done sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
decimal1 | decimal2 | [error] | [error] | [error] | [error] | [error] | any2 | any2 | any2 | done | done | done | done | done
[error]
decimal2 | decimal2 | decimal2 | exponent | done | done | done |
done
exponent | any2 | any2 | [error] | sign | sign | [error] |
[error]
sign | any2 | any2 | [error] | [error] | [error] | [error] |
[error]
any2 | any2 | any2 | done | done | done | done |
done
The state machine is realized with one label per state (prefixed with The state machine is realized with one label per state (prefixed with
"scan_number_") and `goto` statements between them. The state machine "scan_number_") and `goto` statements between them. The state machine
...@@ -2780,8 +2750,8 @@ scan_number_any2: ...@@ -2780,8 +2750,8 @@ scan_number_any2:
} }
scan_number_done: scan_number_done:
// unget the character after the number (we only read it to know // unget the character after the number (we only read it to know that we
// that we are done scanning a number) // are done scanning a number)
--chars_read; --chars_read;
next_unget = true; next_unget = true;
...@@ -2827,8 +2797,8 @@ scan_number_done: ...@@ -2827,8 +2797,8 @@ scan_number_done:
} }
} }
// this code is reached if we parse a floating-point number or if // this code is reached if we parse a floating-point number or if an
// an integer conversion above failed // integer conversion above failed
strtof(value_float, yytext.data(), nullptr); strtof(value_float, yytext.data(), nullptr);
return token_type::value_float; return token_type::value_float;
} }
...@@ -2911,8 +2881,8 @@ scan_number_done: ...@@ -2911,8 +2881,8 @@ scan_number_done:
/// return string value /// return string value
const std::string get_string() const std::string get_string()
{ {
// yytext cannot be returned as char*, because it may contain a // yytext cannot be returned as char*, because it may contain a null
// null byte (parsed as "\u0000") // byte (parsed as "\u0000")
return std::string(yytext.data(), yylen); return std::string(yytext.data(), yylen);
} }
...@@ -2976,8 +2946,7 @@ scan_number_done: ...@@ -2976,8 +2946,7 @@ scan_number_done:
{ {
get(); get();
} }
while (current == ' ' or current == '\t' or current == '\n' or while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
current == '\r');
switch (current) switch (current)
{ {
...@@ -3071,13 +3040,12 @@ scan_number_done: ...@@ -3071,13 +3040,12 @@ scan_number_done:
This class implements a recursive decent parser. This class implements a recursive decent parser.
*/ */
template <typename BasicJsonType> template<typename BasicJsonType>
class parser class parser
{ {
using number_integer_t = typename BasicJsonType::number_integer_t; using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t; using number_float_t = typename BasicJsonType::number_float_t;
using lexer_t = lexer<BasicJsonType>; using lexer_t = lexer<BasicJsonType>;
using token_type = typename lexer_t::token_type; using token_type = typename lexer_t::token_type;
...@@ -3367,8 +3335,7 @@ class parser ...@@ -3367,8 +3335,7 @@ class parser
if (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float))) if (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float)))
{ {
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() + "'"));
"'"));
} }
break; break;
} }
...@@ -3397,9 +3364,8 @@ class parser ...@@ -3397,9 +3364,8 @@ class parser
/*! /*!
@brief the acutal acceptor @brief the acutal acceptor
@invariant 1. The last token is not yet processed. Therefore, the @invariant 1. The last token is not yet processed. Therefore, the caller
caller of this function must make sure a token has of this function must make sure a token has been read.
been read.
2. When this function returns, the last token is processed. 2. When this function returns, the last token is processed.
That is, the last read character was already considered. That is, the last read character was already considered.
...@@ -3581,10 +3547,11 @@ class primitive_iterator_t ...@@ -3581,10 +3547,11 @@ class primitive_iterator_t
public: public:
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
difference_type get_value() const noexcept constexpr difference_type get_value() const noexcept
{ {
return m_it; return m_it;
} }
/// set iterator to a defined beginning /// set iterator to a defined beginning
void set_begin() noexcept void set_begin() noexcept
{ {
...@@ -3609,38 +3576,32 @@ class primitive_iterator_t ...@@ -3609,38 +3576,32 @@ class primitive_iterator_t
return (m_it == end_value); return (m_it == end_value);
} }
friend constexpr bool operator==(primitive_iterator_t lhs, friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
primitive_iterator_t rhs) noexcept
{ {
return lhs.m_it == rhs.m_it; return (lhs.m_it == rhs.m_it);
} }
friend constexpr bool operator!=(primitive_iterator_t lhs, friend constexpr bool operator!=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
primitive_iterator_t rhs) noexcept
{ {
return !(lhs == rhs); return not(lhs == rhs);
} }
friend constexpr bool operator<(primitive_iterator_t lhs, friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
primitive_iterator_t rhs) noexcept
{ {
return lhs.m_it < rhs.m_it; return lhs.m_it < rhs.m_it;
} }
friend constexpr bool operator<=(primitive_iterator_t lhs, friend constexpr bool operator<=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
primitive_iterator_t rhs) noexcept
{ {
return lhs.m_it <= rhs.m_it; return lhs.m_it <= rhs.m_it;
} }
friend constexpr bool operator>(primitive_iterator_t lhs, friend constexpr bool operator>(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
primitive_iterator_t rhs) noexcept
{ {
return lhs.m_it > rhs.m_it; return lhs.m_it > rhs.m_it;
} }
friend constexpr bool operator>=(primitive_iterator_t lhs, friend constexpr bool operator>=(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
primitive_iterator_t rhs) noexcept
{ {
return lhs.m_it >= rhs.m_it; return lhs.m_it >= rhs.m_it;
} }
...@@ -3652,13 +3613,12 @@ class primitive_iterator_t ...@@ -3652,13 +3613,12 @@ class primitive_iterator_t
return result; return result;
} }
friend constexpr difference_type friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
{ {
return lhs.m_it - rhs.m_it; return lhs.m_it - rhs.m_it;
} }
friend std::ostream& operator<<(std::ostream& os, primitive_iterator_t it) friend constexpr std::ostream& operator<<(std::ostream& os, primitive_iterator_t it)
{ {
return os << it.m_it; return os << it.m_it;
} }
...@@ -3712,11 +3672,10 @@ class primitive_iterator_t ...@@ -3712,11 +3672,10 @@ class primitive_iterator_t
/*! /*!
@brief an iterator value @brief an iterator value
@note This structure could easily be a union, but MSVC currently does not @note This structure could easily be a union, but MSVC currently does not allow
allow unions members with complex constructors, see unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
https://github.com/nlohmann/json/pull/105.
*/ */
template <typename BasicJsonType> struct internal_iterator template<typename BasicJsonType> struct internal_iterator
{ {
/// iterator for JSON objects /// iterator for JSON objects
typename BasicJsonType::object_t::iterator object_iterator {}; typename BasicJsonType::object_t::iterator object_iterator {};
...@@ -3726,7 +3685,7 @@ template <typename BasicJsonType> struct internal_iterator ...@@ -3726,7 +3685,7 @@ template <typename BasicJsonType> struct internal_iterator
primitive_iterator_t primitive_iterator {}; primitive_iterator_t primitive_iterator {};
}; };
template <typename IteratorType> class iteration_proxy; template<typename IteratorType> class iteration_proxy;
/*! /*!
@brief a template for a random access iterator for the @ref basic_json class @brief a template for a random access iterator for the @ref basic_json class
...@@ -3747,7 +3706,7 @@ This class implements a both iterators (iterator and const_iterator) for the ...@@ -3747,7 +3706,7 @@ This class implements a both iterators (iterator and const_iterator) for the
@since version 1.0.0, simplified in version 2.0.9 @since version 1.0.0, simplified in version 2.0.9
*/ */
template <typename BasicJsonType> template<typename BasicJsonType>
class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJsonType> class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJsonType>
{ {
/// allow basic_json to access private members /// allow basic_json to access private members
...@@ -3814,13 +3773,12 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3814,13 +3773,12 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
} }
/*! /*!
@note The conventional copy constructor and copy assignment are @note The conventional copy constructor and copy assignment are implicitly
implicitly defined. defined. Combined with the following converting constructor and
Combined with the following converting constructor and assignment, assignment, they support: (1) copy from iterator to iterator, (2)
they support: copy from iterator to iterator, copy from const iterator to const iterator, and (3) conversion from
copy from const iterator to const iterator, iterator to const iterator. However conversion from const iterator
and conversion from iterator to const iterator. to iterator is not defined.
However conversion from const iterator to iterator is not defined.
*/ */
/*! /*!
...@@ -3829,8 +3787,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3829,8 +3787,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
@note It is not checked whether @a other is initialized. @note It is not checked whether @a other is initialized.
*/ */
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
: m_object(other.m_object), : m_object(other.m_object), m_it(other.m_it) {}
m_it(other.m_it) {}
/*! /*!
@brief converting assignment @brief converting assignment
...@@ -3943,7 +3900,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3943,7 +3900,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
default: default:
{ {
if (m_it.primitive_iterator.is_begin()) if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
{ {
return *m_object; return *m_object;
} }
...@@ -3977,7 +3934,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3977,7 +3934,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
default: default:
{ {
if (m_it.primitive_iterator.is_begin()) if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
{ {
return m_object; return m_object;
} }
...@@ -4080,10 +4037,9 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4080,10 +4037,9 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
bool operator==(const iter_impl& other) const bool operator==(const iter_impl& other) const
{ {
// if objects are not the same, the comparison is undefined // if objects are not the same, the comparison is undefined
if (m_object != other.m_object) if (JSON_UNLIKELY(m_object != other.m_object))
{ {
JSON_THROW(invalid_iterator::create( JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
212, "cannot compare iterators of different containers"));
} }
assert(m_object != nullptr); assert(m_object != nullptr);
...@@ -4123,10 +4079,9 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4123,10 +4079,9 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
bool operator<(const iter_impl& other) const bool operator<(const iter_impl& other) const
{ {
// if objects are not the same, the comparison is undefined // if objects are not the same, the comparison is undefined
if (m_object != other.m_object) if (JSON_UNLIKELY(m_object != other.m_object))
{ {
JSON_THROW(invalid_iterator::create( JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
212, "cannot compare iterators of different containers"));
} }
assert(m_object != nullptr); assert(m_object != nullptr);
...@@ -4135,8 +4090,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4135,8 +4090,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
{ {
case value_t::object: case value_t::object:
{ {
JSON_THROW(invalid_iterator::create( JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
213, "cannot compare order of object iterators"));
} }
case value_t::array: case value_t::array:
...@@ -4190,8 +4144,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4190,8 +4144,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
{ {
case value_t::object: case value_t::object:
{ {
JSON_THROW(invalid_iterator::create( JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
209, "cannot use offsets with object iterators"));
} }
case value_t::array: case value_t::array:
...@@ -4264,8 +4217,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4264,8 +4217,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
{ {
case value_t::object: case value_t::object:
{ {
JSON_THROW(invalid_iterator::create( JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
209, "cannot use offsets with object iterators"));
} }
case value_t::array: case value_t::array:
...@@ -4292,8 +4244,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4292,8 +4244,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
{ {
case value_t::object: case value_t::object:
{ {
JSON_THROW(invalid_iterator::create( JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
208, "cannot use operator[] for object iterators"));
} }
case value_t::array: case value_t::array:
...@@ -4308,7 +4259,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4308,7 +4259,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
default: default:
{ {
if (m_it.primitive_iterator.get_value() == -n) if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
{ {
return *m_object; return *m_object;
} }
...@@ -4326,13 +4277,12 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4326,13 +4277,12 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
{ {
assert(m_object != nullptr); assert(m_object != nullptr);
if (m_object->is_object()) if (JSON_LIKELY(m_object->is_object()))
{ {
return m_it.object_iterator->first; return m_it.object_iterator->first;
} }
JSON_THROW(invalid_iterator::create( JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
207, "cannot use key() for non-object iterators"));
} }
/*! /*!
...@@ -4352,7 +4302,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4352,7 +4302,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
}; };
/// proxy class for the iterator_wrapper functions /// proxy class for the iterator_wrapper functions
template <typename IteratorType> class iteration_proxy template<typename IteratorType> class iteration_proxy
{ {
private: private:
/// helper class for iteration /// helper class for iteration
...@@ -4383,7 +4333,7 @@ template <typename IteratorType> class iteration_proxy ...@@ -4383,7 +4333,7 @@ template <typename IteratorType> class iteration_proxy
} }
/// inequality operator (needed for range-based for) /// inequality operator (needed for range-based for)
bool operator!=(const iteration_proxy_internal& o) const constexpr bool operator!=(const iteration_proxy_internal& o) const
{ {
return anchor != o.anchor; return anchor != o.anchor;
} }
...@@ -4461,7 +4411,7 @@ create @ref const_reverse_iterator). ...@@ -4461,7 +4411,7 @@ create @ref const_reverse_iterator).
@since version 1.0.0 @since version 1.0.0
*/ */
template <typename Base> template<typename Base>
class json_reverse_iterator : public std::reverse_iterator<Base> class json_reverse_iterator : public std::reverse_iterator<Base>
{ {
public: public:
...@@ -4472,8 +4422,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base> ...@@ -4472,8 +4422,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
using reference = typename Base::reference; using reference = typename Base::reference;
/// create reverse iterator from iterator /// create reverse iterator from iterator
json_reverse_iterator( json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
const typename base_iterator::iterator_type& it) noexcept
: base_iterator(it) {} : base_iterator(it) {}
/// create reverse iterator from base class /// create reverse iterator from base class
...@@ -4553,7 +4502,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base> ...@@ -4553,7 +4502,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
///////////////////// /////////////////////
/// abstract output adapter interface /// abstract output adapter interface
template <typename CharType> struct output_adapter_protocol template<typename CharType> struct output_adapter_protocol
{ {
virtual void write_character(CharType c) = 0; virtual void write_character(CharType c) = 0;
virtual void write_characters(const CharType* s, std::size_t length) = 0; virtual void write_characters(const CharType* s, std::size_t length) = 0;
...@@ -4561,11 +4510,11 @@ template <typename CharType> struct output_adapter_protocol ...@@ -4561,11 +4510,11 @@ template <typename CharType> struct output_adapter_protocol
}; };
/// a type to simplify interfaces /// a type to simplify interfaces
template <typename CharType> template<typename CharType>
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>; using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
/// output adapter for byte vectors /// output adapter for byte vectors
template <typename CharType> template<typename CharType>
class output_vector_adapter : public output_adapter_protocol<CharType> class output_vector_adapter : public output_adapter_protocol<CharType>
{ {
public: public:
...@@ -4586,7 +4535,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType> ...@@ -4586,7 +4535,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
}; };
/// output adapter for output streams /// output adapter for output streams
template <typename CharType> template<typename CharType>
class output_stream_adapter : public output_adapter_protocol<CharType> class output_stream_adapter : public output_adapter_protocol<CharType>
{ {
public: public:
...@@ -4607,7 +4556,7 @@ class output_stream_adapter : public output_adapter_protocol<CharType> ...@@ -4607,7 +4556,7 @@ class output_stream_adapter : public output_adapter_protocol<CharType>
}; };
/// output adapter for basic_string /// output adapter for basic_string
template <typename CharType> template<typename CharType>
class output_string_adapter : public output_adapter_protocol<CharType> class output_string_adapter : public output_adapter_protocol<CharType>
{ {
public: public:
...@@ -4627,7 +4576,7 @@ class output_string_adapter : public output_adapter_protocol<CharType> ...@@ -4627,7 +4576,7 @@ class output_string_adapter : public output_adapter_protocol<CharType>
std::basic_string<CharType>& str; std::basic_string<CharType>& str;
}; };
template <typename CharType> template<typename CharType>
class output_adapter class output_adapter
{ {
public: public:
...@@ -4656,7 +4605,7 @@ class output_adapter ...@@ -4656,7 +4605,7 @@ class output_adapter
/*! /*!
@brief deserialization of CBOR and MessagePack values @brief deserialization of CBOR and MessagePack values
*/ */
template <typename BasicJsonType> template<typename BasicJsonType>
class binary_reader class binary_reader
{ {
using number_integer_t = typename BasicJsonType::number_integer_t; using number_integer_t = typename BasicJsonType::number_integer_t;
...@@ -5493,8 +5442,7 @@ class binary_reader ...@@ -5493,8 +5442,7 @@ class binary_reader
{ {
std::stringstream ss; std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << std::hex << current; ss << std::setw(2) << std::setfill('0') << std::hex << current;
JSON_THROW(parse_error::create( JSON_THROW(parse_error::create(112, chars_read,
112, chars_read,
"error reading MessagePack; last byte: 0x" + ss.str())); "error reading MessagePack; last byte: 0x" + ss.str()));
} }
} }
...@@ -5539,10 +5487,9 @@ class binary_reader ...@@ -5539,10 +5487,9 @@ class binary_reader
bytes in CBOR and MessagePack are stored in network order (big bytes in CBOR and MessagePack are stored in network order (big
endian) and therefore need reordering on little endian systems. endian) and therefore need reordering on little endian systems.
@throw parse_error.110 if input has less than `sizeof(NumberType)` @throw parse_error.110 if input has less than `sizeof(NumberType)` bytes
bytes
*/ */
template <typename NumberType> NumberType get_number() template<typename NumberType> NumberType get_number()
{ {
// step 1: read input into array with system's byte order // step 1: read input into array with system's byte order
std::array<uint8_t, sizeof(NumberType)> vec; std::array<uint8_t, sizeof(NumberType)> vec;
...@@ -5680,8 +5627,7 @@ class binary_reader ...@@ -5680,8 +5627,7 @@ class binary_reader
{ {
std::stringstream ss; std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << std::hex << current; ss << std::setw(2) << std::setfill('0') << std::hex << current;
JSON_THROW(parse_error::create( JSON_THROW(parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + ss.str()));
113, chars_read, "expected a CBOR string; last byte: 0x" + ss.str()));
} }
} }
} }
...@@ -5763,8 +5709,7 @@ class binary_reader ...@@ -5763,8 +5709,7 @@ class binary_reader
{ {
std::stringstream ss; std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << std::hex << current; ss << std::setw(2) << std::setfill('0') << std::hex << current;
JSON_THROW(parse_error::create( JSON_THROW(parse_error::create(113, chars_read,
113, chars_read,
"expected a MessagePack string; last byte: 0x" + ss.str())); "expected a MessagePack string; last byte: 0x" + ss.str()));
} }
} }
...@@ -5799,7 +5744,7 @@ class binary_reader ...@@ -5799,7 +5744,7 @@ class binary_reader
/*! /*!
@brief serialization to CBOR and MessagePack values @brief serialization to CBOR and MessagePack values
*/ */
template <typename BasicJsonType> template<typename BasicJsonType>
class binary_writer class binary_writer
{ {
public: public:
...@@ -6085,9 +6030,8 @@ class binary_writer ...@@ -6085,9 +6030,8 @@ class binary_writer
if (j.m_value.number_integer >= 0) if (j.m_value.number_integer >= 0)
{ {
// MessagePack does not differentiate between positive // MessagePack does not differentiate between positive
// signed integers and unsigned integers. Therefore, we // signed integers and unsigned integers. Therefore, we used
// used the code from the value_t::number_unsigned case // the code from the value_t::number_unsigned case here.
// here.
if (j.m_value.number_unsigned < 128) if (j.m_value.number_unsigned < 128)
{ {
// positive fixnum // positive fixnum
...@@ -6309,11 +6253,11 @@ class binary_writer ...@@ -6309,11 +6253,11 @@ class binary_writer
@param[in] n number of type @a NumberType @param[in] n number of type @a NumberType
@tparam NumberType the type of the number @tparam NumberType the type of the number
@note This function needs to respect the system's endianess, because @note This function needs to respect the system's endianess, because bytes
bytes in CBOR and MessagePack are stored in network order (big in CBOR and MessagePack are stored in network order (big endian) and
endian) and therefore need reordering on little endian systems. therefore need reordering on little endian systems.
*/ */
template <typename NumberType> void write_number(NumberType n) template<typename NumberType> void write_number(NumberType n)
{ {
// step 1: write number to array of length NumberType // step 1: write number to array of length NumberType
std::array<uint8_t, sizeof(NumberType)> vec; std::array<uint8_t, sizeof(NumberType)> vec;
...@@ -6341,7 +6285,7 @@ class binary_writer ...@@ -6341,7 +6285,7 @@ class binary_writer
// serialization // // serialization //
/////////////////// ///////////////////
template <typename BasicJsonType> template<typename BasicJsonType>
class serializer class serializer
{ {
using string_t = typename BasicJsonType::string_t; using string_t = typename BasicJsonType::string_t;
...@@ -6366,10 +6310,10 @@ class serializer ...@@ -6366,10 +6310,10 @@ class serializer
/*! /*!
@brief internal implementation of the serialization function @brief internal implementation of the serialization function
This function is called by the public member function dump and This function is called by the public member function dump and organizes
organizes the serialization internally. The indentation level is the serialization internally. The indentation level is propagated as
propagated as additional parameter. In case of arrays and objects, the additional parameter. In case of arrays and objects, the function is
function is called recursively. called recursively.
- strings and object keys are escaped using `escape_string()` - strings and object keys are escaped using `escape_string()`
- integer numbers are converted implicitly via `operator<<` - integer numbers are converted implicitly via `operator<<`
...@@ -6472,9 +6416,9 @@ class serializer ...@@ -6472,9 +6416,9 @@ class serializer
// variable to hold indentation for recursive calls // variable to hold indentation for recursive calls
const auto new_indent = current_indent + indent_step; const auto new_indent = current_indent + indent_step;
if (indent_string.size() < new_indent) if (JSON_UNLIKELY(indent_string.size() < new_indent))
{ {
indent_string.resize(new_indent, ' '); indent_string.resize(indent_string.size() * 2, ' ');
} }
// first n-1 elements // first n-1 elements
...@@ -6666,10 +6610,10 @@ class serializer ...@@ -6666,10 +6610,10 @@ class serializer
if (bytes == 3) if (bytes == 3)
{ {
// codepoints that need 4 bytes (i.e., 3 // codepoints that need 4 bytes (i.e., 3 additional
// additional bytes) in UTF-8 needs a surrogate // bytes) in UTF-8 needs a surrogate pair when \u
// pair when \u escaping is used: // escaping is used: from 4 bytes to \uxxxx\uxxxx
// from 4 bytes to \uxxxx\uxxxx (12 bytes) // (12 bytes)
res += (12 - bytes - 1); res += (12 - bytes - 1);
} }
else else
...@@ -6743,13 +6687,14 @@ class serializer ...@@ -6743,13 +6687,14 @@ class serializer
/*! /*!
@brief dump escaped string @brief dump escaped string
Escape a string by replacing certain special characters by a sequence Escape a string by replacing certain special characters by a sequence of an
of an escape character (backslash) and another character and other escape character (backslash) and another character and other control
control characters by a sequence of "\u" followed by a four-digit hex characters by a sequence of "\u" followed by a four-digit hex
representation. The escaped string is written to output stream @a o. representation. The escaped string is written to output stream @a o.
@param[in] s the string to escape @param[in] s the string to escape
@param[in] ensure_ascii whether to escape non-ASCII characters with \uXXXX sequences @param[in] ensure_ascii whether to escape non-ASCII characters with
\uXXXX sequences
@complexity Linear in the length of string @a s. @complexity Linear in the length of string @a s.
*/ */
...@@ -6950,8 +6895,8 @@ class serializer ...@@ -6950,8 +6895,8 @@ class serializer
/*! /*!
@brief dump a floating-point number @brief dump a floating-point number
Dump a given floating-point number to output stream @a o. Works Dump a given floating-point number to output stream @a o. Works internally
internally with @a number_buffer. with @a number_buffer.
@param[in] x floating-point number to dump @param[in] x floating-point number to dump
*/ */
...@@ -7019,7 +6964,7 @@ class serializer ...@@ -7019,7 +6964,7 @@ class serializer
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
[](char c) [](char c)
{ {
return c == '.' or c == 'e'; return (c == '.' or c == 'e');
}); });
if (value_is_int_like) if (value_is_int_like)
...@@ -7180,7 +7125,7 @@ class json_pointer ...@@ -7180,7 +7125,7 @@ class json_pointer
*/ */
std::string pop_back() std::string pop_back()
{ {
if (is_root()) if (JSON_UNLIKELY(is_root()))
{ {
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
} }
...@@ -7198,7 +7143,7 @@ class json_pointer ...@@ -7198,7 +7143,7 @@ class json_pointer
json_pointer top() const json_pointer top() const
{ {
if (is_root()) if (JSON_UNLIKELY(is_root()))
{ {
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
} }
...@@ -7296,10 +7241,9 @@ class json_pointer ...@@ -7296,10 +7241,9 @@ class json_pointer
} }
// check if nonempty reference string begins with slash // check if nonempty reference string begins with slash
if (reference_string[0] != '/') if (JSON_UNLIKELY(reference_string[0] != '/'))
{ {
JSON_THROW(detail::parse_error::create( JSON_THROW(detail::parse_error::create(107, 1,
107, 1,
"JSON pointer must be empty or begin with '/' - was: '" + "JSON pointer must be empty or begin with '/' - was: '" +
reference_string + "'")); reference_string + "'"));
} }
...@@ -7332,12 +7276,11 @@ class json_pointer ...@@ -7332,12 +7276,11 @@ class json_pointer
assert(reference_token[pos] == '~'); assert(reference_token[pos] == '~');
// ~ must be followed by 0 or 1 // ~ must be followed by 0 or 1
if (pos == reference_token.size() - 1 or if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
(reference_token[pos + 1] != '0' and (reference_token[pos + 1] != '0' and
reference_token[pos + 1] != '1')) reference_token[pos + 1] != '1')))
{ {
JSON_THROW(detail::parse_error::create( JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
108, 0, "escape character '~' must be followed with '0' or '1'"));
} }
} }
...@@ -7373,21 +7316,18 @@ class json_pointer ...@@ -7373,21 +7316,18 @@ class json_pointer
{} {}
} }
/// escape tilde and slash /// escape "~"" to "~0" and "/" to "~1"
static std::string escape(std::string s) static std::string escape(std::string s)
{ {
// escape "~"" to "~0" and "/" to "~1"
replace_substring(s, "~", "~0"); replace_substring(s, "~", "~0");
replace_substring(s, "/", "~1"); replace_substring(s, "/", "~1");
return s; return s;
} }
/// unescape tilde and slash /// unescape "~1" to tilde and "~0" to slash (order is important!)
static void unescape(std::string& s) static void unescape(std::string& s)
{ {
// first transform any occurrence of the sequence '~1' to '/'
replace_substring(s, "~1", "/"); replace_substring(s, "~1", "/");
// then transform any occurrence of the sequence '~0' to '~'
replace_substring(s, "~0", "~"); replace_substring(s, "~0", "~");
} }
...@@ -7516,7 +7456,7 @@ class basic_json ...@@ -7516,7 +7456,7 @@ class basic_json
friend ::nlohmann::json_pointer; friend ::nlohmann::json_pointer;
friend ::nlohmann::detail::parser<basic_json>; friend ::nlohmann::detail::parser<basic_json>;
friend ::nlohmann::detail::serializer<basic_json>; friend ::nlohmann::detail::serializer<basic_json>;
template <typename BasicJsonType> template<typename BasicJsonType>
friend class ::nlohmann::detail::iter_impl; friend class ::nlohmann::detail::iter_impl;
friend ::nlohmann::detail::binary_writer<basic_json>; friend ::nlohmann::detail::binary_writer<basic_json>;
/// workaround type for MSVC /// workaround type for MSVC
...@@ -7527,15 +7467,15 @@ class basic_json ...@@ -7527,15 +7467,15 @@ class basic_json
using parser = ::nlohmann::detail::parser<basic_json>; using parser = ::nlohmann::detail::parser<basic_json>;
using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
template <typename BasicJsonType> template<typename BasicJsonType>
using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>; using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
template <typename BasicJsonType> template<typename BasicJsonType>
using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>; using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
template <typename Iterator> template<typename Iterator>
using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>; using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>; template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
template <typename CharType> template<typename CharType>
using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>; using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
using binary_reader = ::nlohmann::detail::binary_reader<basic_json>; using binary_reader = ::nlohmann::detail::binary_reader<basic_json>;
...@@ -8614,7 +8554,7 @@ class basic_json ...@@ -8614,7 +8554,7 @@ class basic_json
bool is_an_object = std::all_of(init.begin(), init.end(), bool is_an_object = std::all_of(init.begin(), init.end(),
[](const basic_json & element) [](const basic_json & element)
{ {
return element.is_array() and element.size() == 2 and element[0].is_string(); return (element.is_array() and element.size() == 2 and element[0].is_string());
}); });
// adjust type if type deduction is not wanted // adjust type if type deduction is not wanted
...@@ -8627,7 +8567,7 @@ class basic_json ...@@ -8627,7 +8567,7 @@ class basic_json
} }
// if object is wanted but impossible, throw an exception // if object is wanted but impossible, throw an exception
if (manual_type == value_t::object and not is_an_object) if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object))
{ {
JSON_THROW(type_error::create(301, "cannot create object from initializer list")); JSON_THROW(type_error::create(301, "cannot create object from initializer list"));
} }
...@@ -8811,7 +8751,7 @@ class basic_json ...@@ -8811,7 +8751,7 @@ class basic_json
assert(last.m_object != nullptr); assert(last.m_object != nullptr);
// make sure iterator fits the current value // make sure iterator fits the current value
if (first.m_object != last.m_object) if (JSON_UNLIKELY(first.m_object != last.m_object))
{ {
JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); JSON_THROW(invalid_iterator::create(201, "iterators are not compatible"));
} }
...@@ -8828,7 +8768,8 @@ class basic_json ...@@ -8828,7 +8768,8 @@ class basic_json
case value_t::number_unsigned: case value_t::number_unsigned:
case value_t::string: case value_t::string:
{ {
if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin()
or not last.m_it.primitive_iterator.is_end()))
{ {
JSON_THROW(invalid_iterator::create(204, "iterators out of range")); JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
} }
...@@ -8890,7 +8831,7 @@ class basic_json ...@@ -8890,7 +8831,7 @@ 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 " +
first.m_object->type_name())); std::string(first.m_object->type_name())));
} }
} }
...@@ -9231,7 +9172,7 @@ class basic_json ...@@ -9231,7 +9172,7 @@ class basic_json
*/ */
constexpr bool is_null() const noexcept constexpr bool is_null() const noexcept
{ {
return m_type == value_t::null; return (m_type == value_t::null);
} }
/*! /*!
...@@ -9253,7 +9194,7 @@ class basic_json ...@@ -9253,7 +9194,7 @@ class basic_json
*/ */
constexpr bool is_boolean() const noexcept constexpr bool is_boolean() const noexcept
{ {
return m_type == value_t::boolean; return (m_type == value_t::boolean);
} }
/*! /*!
...@@ -9312,7 +9253,7 @@ class basic_json ...@@ -9312,7 +9253,7 @@ class basic_json
*/ */
constexpr bool is_number_integer() const noexcept constexpr bool is_number_integer() const noexcept
{ {
return m_type == value_t::number_integer or m_type == value_t::number_unsigned; return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
} }
/*! /*!
...@@ -9340,7 +9281,7 @@ class basic_json ...@@ -9340,7 +9281,7 @@ class basic_json
*/ */
constexpr bool is_number_unsigned() const noexcept constexpr bool is_number_unsigned() const noexcept
{ {
return m_type == value_t::number_unsigned; return (m_type == value_t::number_unsigned);
} }
/*! /*!
...@@ -9368,7 +9309,7 @@ class basic_json ...@@ -9368,7 +9309,7 @@ class basic_json
*/ */
constexpr bool is_number_float() const noexcept constexpr bool is_number_float() const noexcept
{ {
return m_type == value_t::number_float; return (m_type == value_t::number_float);
} }
/*! /*!
...@@ -9390,7 +9331,7 @@ class basic_json ...@@ -9390,7 +9331,7 @@ class basic_json
*/ */
constexpr bool is_object() const noexcept constexpr bool is_object() const noexcept
{ {
return m_type == value_t::object; return (m_type == value_t::object);
} }
/*! /*!
...@@ -9412,7 +9353,7 @@ class basic_json ...@@ -9412,7 +9353,7 @@ class basic_json
*/ */
constexpr bool is_array() const noexcept constexpr bool is_array() const noexcept
{ {
return m_type == value_t::array; return (m_type == value_t::array);
} }
/*! /*!
...@@ -9434,7 +9375,7 @@ class basic_json ...@@ -9434,7 +9375,7 @@ class basic_json
*/ */
constexpr bool is_string() const noexcept constexpr bool is_string() const noexcept
{ {
return m_type == value_t::string; return (m_type == value_t::string);
} }
/*! /*!
...@@ -9461,7 +9402,7 @@ class basic_json ...@@ -9461,7 +9402,7 @@ class basic_json
*/ */
constexpr bool is_discarded() const noexcept constexpr bool is_discarded() const noexcept
{ {
return m_type == value_t::discarded; return (m_type == value_t::discarded);
} }
/*! /*!
...@@ -9497,12 +9438,12 @@ class basic_json ...@@ -9497,12 +9438,12 @@ class basic_json
/// get a boolean (explicit) /// get a boolean (explicit)
boolean_t get_impl(boolean_t* /*unused*/) const boolean_t get_impl(boolean_t* /*unused*/) const
{ {
if (is_boolean()) if (JSON_LIKELY(is_boolean()))
{ {
return m_value.boolean; return m_value.boolean;
} }
JSON_THROW(type_error::create(302, "type must be boolean, but is " + type_name())); JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name())));
} }
/// get a pointer to the value (object) /// get a pointer to the value (object)
...@@ -9603,18 +9544,15 @@ class basic_json ...@@ -9603,18 +9544,15 @@ class basic_json
template<typename ReferenceType, typename ThisType> template<typename ReferenceType, typename ThisType>
static ReferenceType get_ref_impl(ThisType& obj) static ReferenceType get_ref_impl(ThisType& obj)
{ {
// helper type
using PointerType = typename std::add_pointer<ReferenceType>::type;
// delegate the call to get_ptr<>() // delegate the call to get_ptr<>()
auto ptr = obj.template get_ptr<PointerType>(); auto ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
if (ptr != nullptr) if (JSON_LIKELY(ptr != nullptr))
{ {
return *ptr; return *ptr;
} }
JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + obj.type_name())); JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name())));
} }
public: public:
...@@ -10010,7 +9948,7 @@ class basic_json ...@@ -10010,7 +9948,7 @@ class basic_json
reference at(size_type idx) reference at(size_type idx)
{ {
// at only works for arrays // at only works for arrays
if (is_array()) if (JSON_LIKELY(is_array()))
{ {
JSON_TRY JSON_TRY
{ {
...@@ -10024,7 +9962,7 @@ class basic_json ...@@ -10024,7 +9962,7 @@ class basic_json
} }
else else
{ {
JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
} }
} }
...@@ -10057,7 +9995,7 @@ class basic_json ...@@ -10057,7 +9995,7 @@ class basic_json
const_reference at(size_type idx) const const_reference at(size_type idx) const
{ {
// at only works for arrays // at only works for arrays
if (is_array()) if (JSON_LIKELY(is_array()))
{ {
JSON_TRY JSON_TRY
{ {
...@@ -10071,7 +10009,7 @@ class basic_json ...@@ -10071,7 +10009,7 @@ class basic_json
} }
else else
{ {
JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
} }
} }
...@@ -10108,7 +10046,7 @@ class basic_json ...@@ -10108,7 +10046,7 @@ class basic_json
reference at(const typename object_t::key_type& key) reference at(const typename object_t::key_type& key)
{ {
// at only works for objects // at only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
JSON_TRY JSON_TRY
{ {
...@@ -10122,7 +10060,7 @@ class basic_json ...@@ -10122,7 +10060,7 @@ class basic_json
} }
else else
{ {
JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
} }
} }
...@@ -10159,7 +10097,7 @@ class basic_json ...@@ -10159,7 +10097,7 @@ class basic_json
const_reference at(const typename object_t::key_type& key) const const_reference at(const typename object_t::key_type& key) const
{ {
// at only works for objects // at only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
JSON_TRY JSON_TRY
{ {
...@@ -10173,7 +10111,7 @@ class basic_json ...@@ -10173,7 +10111,7 @@ class basic_json
} }
else else
{ {
JSON_THROW(type_error::create(304, "cannot use at() with " + type_name())); JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name())));
} }
} }
...@@ -10213,7 +10151,7 @@ class basic_json ...@@ -10213,7 +10151,7 @@ class basic_json
} }
// operator[] only works for arrays // operator[] only works for arrays
if (is_array()) if (JSON_LIKELY(is_array()))
{ {
// fill up array with null values if given idx is outside range // fill up array with null values if given idx is outside range
if (idx >= m_value.array->size()) if (idx >= m_value.array->size())
...@@ -10226,7 +10164,7 @@ class basic_json ...@@ -10226,7 +10164,7 @@ class basic_json
return m_value.array->operator[](idx); return m_value.array->operator[](idx);
} }
JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
} }
/*! /*!
...@@ -10251,12 +10189,12 @@ class basic_json ...@@ -10251,12 +10189,12 @@ class basic_json
const_reference operator[](size_type idx) const const_reference operator[](size_type idx) const
{ {
// const operator[] only works for arrays // const operator[] only works for arrays
if (is_array()) if (JSON_LIKELY(is_array()))
{ {
return m_value.array->operator[](idx); return m_value.array->operator[](idx);
} }
JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
} }
/*! /*!
...@@ -10297,12 +10235,12 @@ class basic_json ...@@ -10297,12 +10235,12 @@ class basic_json
} }
// operator[] only works for objects // operator[] only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
return m_value.object->operator[](key); return m_value.object->operator[](key);
} }
JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
} }
/*! /*!
...@@ -10338,13 +10276,13 @@ class basic_json ...@@ -10338,13 +10276,13 @@ class basic_json
const_reference operator[](const typename object_t::key_type& key) const const_reference operator[](const typename object_t::key_type& key) const
{ {
// const operator[] only works for objects // const operator[] only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
assert(m_value.object->find(key) != m_value.object->end()); assert(m_value.object->find(key) != m_value.object->end());
return m_value.object->find(key)->second; return m_value.object->find(key)->second;
} }
JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
} }
/*! /*!
...@@ -10386,12 +10324,12 @@ class basic_json ...@@ -10386,12 +10324,12 @@ class basic_json
} }
// at only works for objects // at only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
return m_value.object->operator[](key); return m_value.object->operator[](key);
} }
JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
} }
/*! /*!
...@@ -10428,13 +10366,13 @@ class basic_json ...@@ -10428,13 +10366,13 @@ class basic_json
const_reference operator[](T* key) const const_reference operator[](T* key) const
{ {
// at only works for objects // at only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
assert(m_value.object->find(key) != m_value.object->end()); assert(m_value.object->find(key) != m_value.object->end());
return m_value.object->find(key)->second; return m_value.object->find(key)->second;
} }
JSON_THROW(type_error::create(305, "cannot use operator[] with " + type_name())); JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
} }
/*! /*!
...@@ -10490,7 +10428,7 @@ class basic_json ...@@ -10490,7 +10428,7 @@ class basic_json
ValueType value(const typename object_t::key_type& key, ValueType default_value) const ValueType value(const typename object_t::key_type& key, ValueType default_value) const
{ {
// at only works for objects // at only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
// if key is found, return value and given default value otherwise // if key is found, return value and given default value otherwise
const auto it = find(key); const auto it = find(key);
...@@ -10503,7 +10441,7 @@ class basic_json ...@@ -10503,7 +10441,7 @@ class basic_json
} }
else else
{ {
JSON_THROW(type_error::create(306, "cannot use value() with " + type_name())); JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
} }
} }
...@@ -10562,7 +10500,7 @@ class basic_json ...@@ -10562,7 +10500,7 @@ class basic_json
ValueType value(const json_pointer& ptr, ValueType default_value) const ValueType value(const json_pointer& ptr, ValueType default_value) const
{ {
// at only works for objects // at only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
// if pointer resolves a value, return it or use default value // if pointer resolves a value, return it or use default value
JSON_TRY JSON_TRY
...@@ -10575,7 +10513,7 @@ class basic_json ...@@ -10575,7 +10513,7 @@ class basic_json
} }
} }
JSON_THROW(type_error::create(306, "cannot use value() with " + type_name())); JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
} }
/*! /*!
...@@ -10726,7 +10664,7 @@ class basic_json ...@@ -10726,7 +10664,7 @@ class basic_json
IteratorType erase(IteratorType pos) IteratorType erase(IteratorType pos)
{ {
// make sure iterator fits the current value // make sure iterator fits the current value
if (this != pos.m_object) if (JSON_UNLIKELY(this != pos.m_object))
{ {
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
} }
...@@ -10741,7 +10679,7 @@ class basic_json ...@@ -10741,7 +10679,7 @@ class basic_json
case value_t::number_unsigned: case value_t::number_unsigned:
case value_t::string: case value_t::string:
{ {
if (not pos.m_it.primitive_iterator.is_begin()) if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
{ {
JSON_THROW(invalid_iterator::create(205, "iterator out of range")); JSON_THROW(invalid_iterator::create(205, "iterator out of range"));
} }
...@@ -10773,7 +10711,7 @@ class basic_json ...@@ -10773,7 +10711,7 @@ class basic_json
default: default:
{ {
JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
} }
} }
...@@ -10833,7 +10771,7 @@ class basic_json ...@@ -10833,7 +10771,7 @@ class basic_json
IteratorType erase(IteratorType first, IteratorType last) IteratorType erase(IteratorType first, IteratorType last)
{ {
// make sure iterator fits the current value // make sure iterator fits the current value
if (this != first.m_object or this != last.m_object) if (JSON_UNLIKELY(this != first.m_object or this != last.m_object))
{ {
JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value"));
} }
...@@ -10848,7 +10786,8 @@ class basic_json ...@@ -10848,7 +10786,8 @@ class basic_json
case value_t::number_unsigned: case value_t::number_unsigned:
case value_t::string: case value_t::string:
{ {
if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin()
or not last.m_it.primitive_iterator.is_end()))
{ {
JSON_THROW(invalid_iterator::create(204, "iterators out of range")); JSON_THROW(invalid_iterator::create(204, "iterators out of range"));
} }
...@@ -10882,7 +10821,7 @@ class basic_json ...@@ -10882,7 +10821,7 @@ class basic_json
default: default:
{ {
JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
} }
} }
...@@ -10921,12 +10860,12 @@ class basic_json ...@@ -10921,12 +10860,12 @@ class basic_json
size_type erase(const typename object_t::key_type& key) size_type erase(const typename object_t::key_type& key)
{ {
// this erase only works for objects // this erase only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
return m_value.object->erase(key); return m_value.object->erase(key);
} }
JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
} }
/*! /*!
...@@ -10956,9 +10895,9 @@ class basic_json ...@@ -10956,9 +10895,9 @@ class basic_json
void erase(const size_type idx) void erase(const size_type idx)
{ {
// this erase only works for arrays // this erase only works for arrays
if (is_array()) if (JSON_LIKELY(is_array()))
{ {
if (idx >= size()) if (JSON_UNLIKELY(idx >= size()))
{ {
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
} }
...@@ -10967,7 +10906,7 @@ class basic_json ...@@ -10967,7 +10906,7 @@ class basic_json
} }
else else
{ {
JSON_THROW(type_error::create(307, "cannot use erase() with " + type_name())); JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
} }
} }
...@@ -11681,9 +11620,9 @@ class basic_json ...@@ -11681,9 +11620,9 @@ class basic_json
void push_back(basic_json&& val) void push_back(basic_json&& val)
{ {
// push_back only works for null objects or arrays // push_back only works for null objects or arrays
if (not(is_null() or is_array())) if (JSON_UNLIKELY(not(is_null() or is_array())))
{ {
JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
} }
// transform null object into an array // transform null object into an array
...@@ -11717,9 +11656,9 @@ class basic_json ...@@ -11717,9 +11656,9 @@ class basic_json
void push_back(const basic_json& val) void push_back(const basic_json& val)
{ {
// push_back only works for null objects or arrays // push_back only works for null objects or arrays
if (not(is_null() or is_array())) if (JSON_UNLIKELY(not(is_null() or is_array())))
{ {
JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
} }
// transform null object into an array // transform null object into an array
...@@ -11767,9 +11706,9 @@ class basic_json ...@@ -11767,9 +11706,9 @@ class basic_json
void push_back(const typename object_t::value_type& val) void push_back(const typename object_t::value_type& val)
{ {
// push_back only works for null objects or objects // push_back only works for null objects or objects
if (not(is_null() or is_object())) if (JSON_UNLIKELY(not(is_null() or is_object())))
{ {
JSON_THROW(type_error::create(308, "cannot use push_back() with " + type_name())); JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name())));
} }
// transform null object into an object // transform null object into an object
...@@ -11867,9 +11806,9 @@ class basic_json ...@@ -11867,9 +11806,9 @@ class basic_json
void emplace_back(Args&& ... args) void emplace_back(Args&& ... args)
{ {
// emplace_back only works for null objects or arrays // emplace_back only works for null objects or arrays
if (not(is_null() or is_array())) if (JSON_UNLIKELY(not(is_null() or is_array())))
{ {
JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + type_name())); JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name())));
} }
// transform null object into an array // transform null object into an array
...@@ -11915,9 +11854,9 @@ class basic_json ...@@ -11915,9 +11854,9 @@ class basic_json
std::pair<iterator, bool> emplace(Args&& ... args) std::pair<iterator, bool> emplace(Args&& ... args)
{ {
// emplace only works for null objects or arrays // emplace only works for null objects or arrays
if (not(is_null() or is_object())) if (JSON_UNLIKELY(not(is_null() or is_object())))
{ {
JSON_THROW(type_error::create(311, "cannot use emplace() with " + type_name())); JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name())));
} }
// transform null object into an object // transform null object into an object
...@@ -11963,10 +11902,10 @@ class basic_json ...@@ -11963,10 +11902,10 @@ class basic_json
iterator insert(const_iterator pos, const basic_json& val) iterator insert(const_iterator pos, const basic_json& val)
{ {
// insert only works for arrays // insert only works for arrays
if (is_array()) if (JSON_LIKELY(is_array()))
{ {
// check if iterator pos fits to this JSON value // check if iterator pos fits to this JSON value
if (pos.m_object != this) if (JSON_UNLIKELY(pos.m_object != this))
{ {
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
} }
...@@ -11977,7 +11916,7 @@ class basic_json ...@@ -11977,7 +11916,7 @@ class basic_json
return result; return result;
} }
JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
} }
/*! /*!
...@@ -12016,10 +11955,10 @@ class basic_json ...@@ -12016,10 +11955,10 @@ class basic_json
iterator insert(const_iterator pos, size_type cnt, const basic_json& val) iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
{ {
// insert only works for arrays // insert only works for arrays
if (is_array()) if (JSON_LIKELY(is_array()))
{ {
// check if iterator pos fits to this JSON value // check if iterator pos fits to this JSON value
if (pos.m_object != this) if (JSON_UNLIKELY(pos.m_object != this))
{ {
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
} }
...@@ -12030,7 +11969,7 @@ class basic_json ...@@ -12030,7 +11969,7 @@ class basic_json
return result; return result;
} }
JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
} }
/*! /*!
...@@ -12066,24 +12005,24 @@ class basic_json ...@@ -12066,24 +12005,24 @@ class basic_json
iterator insert(const_iterator pos, const_iterator first, const_iterator last) iterator insert(const_iterator pos, const_iterator first, const_iterator last)
{ {
// insert only works for arrays // insert only works for arrays
if (not is_array()) if (JSON_UNLIKELY(not is_array()))
{ {
JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
} }
// check if iterator pos fits to this JSON value // check if iterator pos fits to this JSON value
if (pos.m_object != this) if (JSON_UNLIKELY(pos.m_object != this))
{ {
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
} }
// check if range iterators belong to the same JSON object // check if range iterators belong to the same JSON object
if (first.m_object != last.m_object) if (JSON_UNLIKELY(first.m_object != last.m_object))
{ {
JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
} }
if (first.m_object == this or last.m_object == this) if (JSON_UNLIKELY(first.m_object == this or last.m_object == this))
{ {
JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container"));
} }
...@@ -12124,13 +12063,13 @@ class basic_json ...@@ -12124,13 +12063,13 @@ class basic_json
iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist) iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
{ {
// insert only works for arrays // insert only works for arrays
if (not is_array()) if (JSON_UNLIKELY(not is_array()))
{ {
JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
} }
// check if iterator pos fits to this JSON value // check if iterator pos fits to this JSON value
if (pos.m_object != this) if (JSON_UNLIKELY(pos.m_object != this))
{ {
JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value"));
} }
...@@ -12167,19 +12106,20 @@ class basic_json ...@@ -12167,19 +12106,20 @@ class basic_json
void insert(const_iterator first, const_iterator last) void insert(const_iterator first, const_iterator last)
{ {
// insert only works for objects // insert only works for objects
if (not is_object()) if (JSON_UNLIKELY(not is_object()))
{ {
JSON_THROW(type_error::create(309, "cannot use insert() with " + type_name())); JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
} }
// check if range iterators belong to the same JSON object // check if range iterators belong to the same JSON object
if (first.m_object != last.m_object) if (JSON_UNLIKELY(first.m_object != last.m_object))
{ {
JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); JSON_THROW(invalid_iterator::create(210, "iterators do not fit"));
} }
// passed iterators must belong to objects // passed iterators must belong to objects
if (not first.m_object->is_object() or not first.m_object->is_object()) if (JSON_UNLIKELY(not first.m_object->is_object()
or not first.m_object->is_object()))
{ {
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
} }
...@@ -12239,13 +12179,13 @@ class basic_json ...@@ -12239,13 +12179,13 @@ class basic_json
void swap(array_t& other) void swap(array_t& other)
{ {
// swap only works for arrays // swap only works for arrays
if (is_array()) if (JSON_LIKELY(is_array()))
{ {
std::swap(*(m_value.array), other); std::swap(*(m_value.array), other);
} }
else else
{ {
JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
} }
} }
...@@ -12272,13 +12212,13 @@ class basic_json ...@@ -12272,13 +12212,13 @@ class basic_json
void swap(object_t& other) void swap(object_t& other)
{ {
// swap only works for objects // swap only works for objects
if (is_object()) if (JSON_LIKELY(is_object()))
{ {
std::swap(*(m_value.object), other); std::swap(*(m_value.object), other);
} }
else else
{ {
JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
} }
} }
...@@ -12305,13 +12245,13 @@ class basic_json ...@@ -12305,13 +12245,13 @@ class basic_json
void swap(string_t& other) void swap(string_t& other)
{ {
// swap only works for strings // swap only works for strings
if (is_string()) if (JSON_LIKELY(is_string()))
{ {
std::swap(*(m_value.string), other); std::swap(*(m_value.string), other);
} }
else else
{ {
JSON_THROW(type_error::create(310, "cannot use swap() with " + type_name())); JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
} }
} }
...@@ -12360,11 +12300,11 @@ class basic_json ...@@ -12360,11 +12300,11 @@ class basic_json
{ {
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:
{ {
...@@ -12372,23 +12312,23 @@ class basic_json ...@@ -12372,23 +12312,23 @@ class basic_json
} }
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:
{ {
...@@ -12398,27 +12338,27 @@ class basic_json ...@@ -12398,27 +12338,27 @@ class basic_json
} }
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);
} }
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer) else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
{ {
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer); return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
} }
else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float) else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
{ {
return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float; return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
} }
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned) else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
{ {
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned); return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
} }
else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer) else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
{ {
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
} }
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned) else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
{ {
return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned); return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
} }
return false; return false;
...@@ -13041,9 +12981,9 @@ class basic_json ...@@ -13041,9 +12981,9 @@ class basic_json
@liveexample{The following code exemplifies `type_name()` for all JSON @liveexample{The following code exemplifies `type_name()` for all JSON
types.,type_name} types.,type_name}
@since version 1.0.0, public since 2.1.0 @since version 1.0.0, public since 2.1.0, const char* since 3.0.0
*/ */
std::string type_name() const const char* type_name() const
{ {
{ {
switch (m_type) switch (m_type)
...@@ -13804,7 +13744,7 @@ class basic_json ...@@ -13804,7 +13744,7 @@ class basic_json
else else
{ {
const auto idx = std::stoi(last_path); const auto idx = std::stoi(last_path);
if (static_cast<size_type>(idx) > parent.size()) if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
{ {
// avoid undefined behavior // avoid undefined behavior
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
...@@ -13839,7 +13779,7 @@ class basic_json ...@@ -13839,7 +13779,7 @@ class basic_json
{ {
// perform range check // perform range check
auto it = parent.find(last_path); auto it = parent.find(last_path);
if (it != parent.end()) if (JSON_LIKELY(it != parent.end()))
{ {
parent.erase(it); parent.erase(it);
} }
...@@ -13856,7 +13796,7 @@ class basic_json ...@@ -13856,7 +13796,7 @@ class basic_json
}; };
// type check: top level value must be an array // type check: top level value must be an array
if (not json_patch.is_array()) if (JSON_UNLIKELY(not json_patch.is_array()))
{ {
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
} }
...@@ -13876,13 +13816,13 @@ class basic_json ...@@ -13876,13 +13816,13 @@ class basic_json
const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
// check if desired value is present // check if desired value is present
if (it == val.m_value.object->end()) if (JSON_UNLIKELY(it == val.m_value.object->end()))
{ {
JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'"));
} }
// check if result is of type string // check if result is of type string
if (string_type and not it->second.is_string()) if (JSON_UNLIKELY(string_type and not it->second.is_string()))
{ {
JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'"));
} }
...@@ -13892,7 +13832,7 @@ class basic_json ...@@ -13892,7 +13832,7 @@ class basic_json
}; };
// type check: every element of the array must be an object // type check: every element of the array must be an object
if (not val.is_object()) if (JSON_UNLIKELY(not val.is_object()))
{ {
JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects"));
} }
...@@ -13965,7 +13905,7 @@ class basic_json ...@@ -13965,7 +13905,7 @@ class basic_json
} }
// throw an exception if test fails // throw an exception if test fails
if (not success) if (JSON_UNLIKELY(not success))
{ {
JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump()));
} }
...@@ -14017,8 +13957,7 @@ class basic_json ...@@ -14017,8 +13957,7 @@ class basic_json
@since version 2.0.0 @since version 2.0.0
*/ */
static basic_json diff(const basic_json& source, static basic_json diff(const basic_json& source, const basic_json& target,
const basic_json& target,
const std::string& path = "") const std::string& path = "")
{ {
// the patch // the patch
...@@ -14035,9 +13974,7 @@ class basic_json ...@@ -14035,9 +13974,7 @@ class basic_json
// different types: replace value // different types: replace value
result.push_back( result.push_back(
{ {
{"op", "replace"}, {"op", "replace"}, {"path", path}, {"value", target}
{"path", path},
{"value", target}
}); });
} }
else else
...@@ -14107,8 +14044,7 @@ class basic_json ...@@ -14107,8 +14044,7 @@ class basic_json
// found a key that is not in o -> remove it // found a key that is not in o -> remove it
result.push_back(object( result.push_back(object(
{ {
{"op", "remove"}, {"op", "remove"}, {"path", path + "/" + key}
{"path", path + "/" + key}
})); }));
} }
} }
...@@ -14122,8 +14058,7 @@ class basic_json ...@@ -14122,8 +14058,7 @@ class basic_json
const auto key = json_pointer::escape(it.key()); const auto key = json_pointer::escape(it.key());
result.push_back( result.push_back(
{ {
{"op", "add"}, {"op", "add"}, {"path", path + "/" + key},
{"path", path + "/" + key},
{"value", it.value()} {"value", it.value()}
}); });
} }
...@@ -14137,9 +14072,7 @@ class basic_json ...@@ -14137,9 +14072,7 @@ class basic_json
// both primitive type: replace value // both primitive type: replace value
result.push_back( result.push_back(
{ {
{"op", "replace"}, {"op", "replace"}, {"path", path}, {"value", target}
{"path", path},
{"value", target}
}); });
break; break;
} }
...@@ -14177,8 +14110,8 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const ...@@ -14177,8 +14110,8 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const
using size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type; using size_type = typename NLOHMANN_BASIC_JSON_TPL::size_type;
auto result = &j; auto result = &j;
// in case no reference tokens exist, return a reference to the // in case no reference tokens exist, return a reference to the JSON value
// JSON value j which will be overwritten by a primitive value // j which will be overwritten by a primitive value
for (const auto& reference_token : reference_tokens) for (const auto& reference_token : reference_tokens)
{ {
switch (result->m_type) switch (result->m_type)
...@@ -14210,23 +14143,20 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const ...@@ -14210,23 +14143,20 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const
// create an entry in the array // create an entry in the array
JSON_TRY JSON_TRY
{ {
result = &result->operator[]( result = &result->operator[](static_cast<size_type>(std::stoi(reference_token)));
static_cast<size_type>(std::stoi(reference_token)));
} }
JSON_CATCH(std::invalid_argument&) JSON_CATCH(std::invalid_argument&)
{ {
JSON_THROW(detail::parse_error::create( JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
109, 0, "array index '" + reference_token + "' is not a number"));
} }
break; break;
} }
/* /*
The following code is only reached if there exists a The following code is only reached if there exists a reference
reference token _and_ the current value is primitive. In token _and_ the current value is primitive. In this case, we have
this case, we have an error situation, because primitive an error situation, because primitive values may only occur as
values may only occur as single value; that is, with an single value; that is, with an empty list of reference tokens.
empty list of reference tokens.
*/ */
default: default:
{ {
...@@ -14256,16 +14186,10 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14256,16 +14186,10 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const
return (x >= '0' and x <= '9'); return (x >= '0' and x <= '9');
}); });
// change value to array for numbers or "-" or to object // change value to array for numbers or "-" or to object otherwise
// otherwise *ptr = (nums or reference_token == "-")
if (nums or reference_token == "-") ? detail::value_t::array
{ : detail::value_t::object;
*ptr = detail::value_t::array;
}
else
{
*ptr = detail::value_t::object;
}
} }
switch (ptr->m_type) switch (ptr->m_type)
...@@ -14280,7 +14204,7 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14280,7 +14204,7 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const
case detail::value_t::array: case detail::value_t::array:
{ {
// error condition (cf. RFC 6901, Sect. 4) // error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0') if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{ {
JSON_THROW(detail::parse_error::create(106, 0, JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token + "array index '" + reference_token +
...@@ -14302,8 +14226,7 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14302,8 +14226,7 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
JSON_CATCH(std::invalid_argument&) JSON_CATCH(std::invalid_argument&)
{ {
JSON_THROW(detail::parse_error::create( JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
109, 0, "array index '" + reference_token + "' is not a number"));
} }
} }
break; break;
...@@ -14311,8 +14234,7 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14311,8 +14234,7 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const
default: default:
{ {
JSON_THROW(detail::out_of_range::create( JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
404, "unresolved reference token '" + reference_token + "'"));
} }
} }
} }
...@@ -14338,17 +14260,16 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14338,17 +14260,16 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const
case detail::value_t::array: case detail::value_t::array:
{ {
if (reference_token == "-") if (JSON_UNLIKELY(reference_token == "-"))
{ {
// "-" always fails the range check // "-" always fails the range check
JSON_THROW(detail::out_of_range::create( JSON_THROW(detail::out_of_range::create(402,
402,
"array index '-' (" + std::to_string(ptr->m_value.array->size()) + "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
") is out of range")); ") is out of range"));
} }
// error condition (cf. RFC 6901, Sect. 4) // error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0') if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{ {
JSON_THROW(detail::parse_error::create(106, 0, JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token + "array index '" + reference_token +
...@@ -14362,16 +14283,14 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14362,16 +14283,14 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
JSON_CATCH(std::invalid_argument&) JSON_CATCH(std::invalid_argument&)
{ {
JSON_THROW(detail::parse_error::create( JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
109, 0, "array index '" + reference_token + "' is not a number"));
} }
break; break;
} }
default: default:
{ {
JSON_THROW(detail::out_of_range::create( JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
404, "unresolved reference token '" + reference_token + "'"));
} }
} }
} }
...@@ -14397,17 +14316,16 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14397,17 +14316,16 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
case detail::value_t::array: case detail::value_t::array:
{ {
if (reference_token == "-") if (JSON_UNLIKELY(reference_token == "-"))
{ {
// "-" cannot be used for const access // "-" cannot be used for const access
JSON_THROW(detail::out_of_range::create( JSON_THROW(detail::out_of_range::create(402,
402,
"array index '-' (" + std::to_string(ptr->m_value.array->size()) + "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
") is out of range")); ") is out of range"));
} }
// error condition (cf. RFC 6901, Sect. 4) // error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0') if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{ {
JSON_THROW(detail::parse_error::create(106, 0, JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token + "array index '" + reference_token +
...@@ -14422,16 +14340,14 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14422,16 +14340,14 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
JSON_CATCH(std::invalid_argument&) JSON_CATCH(std::invalid_argument&)
{ {
JSON_THROW(detail::parse_error::create( JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
109, 0, "array index '" + reference_token + "' is not a number"));
} }
break; break;
} }
default: default:
{ {
JSON_THROW(detail::out_of_range::create( JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
404, "unresolved reference token '" + reference_token + "'"));
} }
} }
} }
...@@ -14457,17 +14373,16 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14457,17 +14373,16 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
case detail::value_t::array: case detail::value_t::array:
{ {
if (reference_token == "-") if (JSON_UNLIKELY(reference_token == "-"))
{ {
// "-" always fails the range check // "-" always fails the range check
JSON_THROW(detail::out_of_range::create( JSON_THROW(detail::out_of_range::create(402,
402,
"array index '-' (" + std::to_string(ptr->m_value.array->size()) + "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
") is out of range")); ") is out of range"));
} }
// error condition (cf. RFC 6901, Sect. 4) // error condition (cf. RFC 6901, Sect. 4)
if (reference_token.size() > 1 and reference_token[0] == '0') if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{ {
JSON_THROW(detail::parse_error::create(106, 0, JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token + "array index '" + reference_token +
...@@ -14481,16 +14396,14 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14481,16 +14396,14 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
JSON_CATCH(std::invalid_argument&) JSON_CATCH(std::invalid_argument&)
{ {
JSON_THROW(detail::parse_error::create( JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
109, 0, "array index '" + reference_token + "' is not a number"));
} }
break; break;
} }
default: default:
{ {
JSON_THROW(detail::out_of_range::create( JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
404, "unresolved reference token '" + reference_token + "'"));
} }
} }
} }
...@@ -14536,8 +14449,7 @@ void json_pointer::flatten(const std::string& reference_string, ...@@ -14536,8 +14449,7 @@ void json_pointer::flatten(const std::string& reference_string,
// iterate object and use keys as reference string // iterate object and use keys as reference string
for (const auto& element : *value.m_value.object) for (const auto& element : *value.m_value.object)
{ {
flatten(reference_string + "/" + escape(element.first), element.second, flatten(reference_string + "/" + escape(element.first), element.second, result);
result);
} }
} }
break; break;
...@@ -14556,7 +14468,7 @@ NLOHMANN_BASIC_JSON_TPL_DECLARATION ...@@ -14556,7 +14468,7 @@ NLOHMANN_BASIC_JSON_TPL_DECLARATION
NLOHMANN_BASIC_JSON_TPL NLOHMANN_BASIC_JSON_TPL
json_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value) json_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value)
{ {
if (not value.is_object()) if (JSON_UNLIKELY(not value.is_object()))
{ {
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened")); JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
} }
...@@ -14566,16 +14478,15 @@ json_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value) ...@@ -14566,16 +14478,15 @@ json_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value)
// iterate the JSON object values // iterate the JSON object values
for (const auto& element : *value.m_value.object) for (const auto& element : *value.m_value.object)
{ {
if (not element.second.is_primitive()) if (JSON_UNLIKELY(not element.second.is_primitive()))
{ {
JSON_THROW(detail::type_error::create(315, "values in object must be primitive")); JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
} }
// assign value to reference pointed to by JSON pointer; Note // assign value to reference pointed to by JSON pointer; Note that if
// that if the JSON pointer is "" (i.e., points to the whole // the JSON pointer is "" (i.e., points to the whole value), function
// value), function get_and_create returns a reference to // get_and_create returns a reference to result itself. An assignment
// result itself. An assignment will then create a primitive // will then create a primitive value.
// value.
json_pointer(element.first).get_and_create(result) = element.second; json_pointer(element.first).get_and_create(result) = element.second;
} }
...@@ -14584,12 +14495,12 @@ json_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value) ...@@ -14584,12 +14495,12 @@ json_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value)
inline bool operator==(json_pointer const& lhs, json_pointer const& rhs) noexcept inline bool operator==(json_pointer const& lhs, json_pointer const& rhs) noexcept
{ {
return lhs.reference_tokens == rhs.reference_tokens; return (lhs.reference_tokens == rhs.reference_tokens);
} }
inline bool operator!=(json_pointer const& lhs, json_pointer const& rhs) noexcept inline bool operator!=(json_pointer const& lhs, json_pointer const& rhs) noexcept
{ {
return !(lhs == rhs); return not (lhs == rhs);
} }
} // namespace nlohmann } // namespace nlohmann
...@@ -14634,7 +14545,7 @@ struct hash<nlohmann::json> ...@@ -14634,7 +14545,7 @@ struct hash<nlohmann::json>
}; };
/// specialization for std::less<value_t> /// specialization for std::less<value_t>
template <> template<>
struct less<::nlohmann::detail::value_t> struct less<::nlohmann::detail::value_t>
{ {
/*! /*!
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment