cleanup and improvement of branch coverage

This commit is contained in:
Niels 2016-08-30 23:44:15 +02:00
parent 463ffb21bc
commit a485aa8d27
4 changed files with 265 additions and 291 deletions

View file

@ -1164,11 +1164,10 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class CompatibleObjectType, typename template<class CompatibleObjectType, typename std::enable_if<
std::enable_if< std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
= 0>
basic_json(const CompatibleObjectType& val) basic_json(const CompatibleObjectType& val)
: m_type(value_t::object) : m_type(value_t::object)
{ {
@ -1229,16 +1228,15 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class CompatibleArrayType, typename template<class CompatibleArrayType, typename std::enable_if<
std::enable_if< not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
= 0>
basic_json(const CompatibleArrayType& val) basic_json(const CompatibleArrayType& val)
: m_type(value_t::array) : m_type(value_t::array)
{ {
@ -1324,10 +1322,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class CompatibleStringType, typename template<class CompatibleStringType, typename std::enable_if<
std::enable_if< std::is_constructible<string_t, CompatibleStringType>::value, int>::type
std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
= 0>
basic_json(const CompatibleStringType& val) basic_json(const CompatibleStringType& val)
: basic_json(string_t(val)) : basic_json(string_t(val))
{ {
@ -1377,8 +1374,7 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename T, template<typename T, typename std::enable_if<
typename std::enable_if<
not (std::is_same<T, int>::value) not (std::is_same<T, int>::value)
and std::is_same<T, number_integer_t>::value and std::is_same<T, number_integer_t>::value
, int>::type , int>::type
@ -1477,8 +1473,7 @@ class basic_json
@since version 2.0.0 @since version 2.0.0
*/ */
template<typename T, template<typename T, typename std::enable_if<
typename std::enable_if<
not (std::is_same<T, int>::value) not (std::is_same<T, int>::value)
and std::is_same<T, number_unsigned_t>::value and std::is_same<T, number_unsigned_t>::value
, int>::type , int>::type
@ -1509,13 +1504,11 @@ class basic_json
@since version 2.0.0 @since version 2.0.0
*/ */
template <typename CompatibleNumberUnsignedType, typename template<typename CompatibleNumberUnsignedType, typename std::enable_if<
std::enable_if < std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, CompatibleNumberUnsignedType>::type
not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, = 0>
CompatibleNumberUnsignedType>::type
= 0>
basic_json(const CompatibleNumberUnsignedType val) noexcept basic_json(const CompatibleNumberUnsignedType val) noexcept
: m_type(value_t::number_unsigned), : m_type(value_t::number_unsigned),
m_value(static_cast<number_unsigned_t>(val)) m_value(static_cast<number_unsigned_t>(val))
@ -1591,11 +1584,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename CompatibleNumberFloatType, typename = typename template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
std::enable_if<
std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
std::is_floating_point<CompatibleNumberFloatType>::value>::type std::is_floating_point<CompatibleNumberFloatType>::value>::type>
>
basic_json(const CompatibleNumberFloatType val) noexcept basic_json(const CompatibleNumberFloatType val) noexcept
: basic_json(number_float_t(val)) : basic_json(number_float_t(val))
{ {
@ -1672,8 +1663,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
basic_json(std::initializer_list<basic_json> init, basic_json(std::initializer_list<basic_json> init,
bool type_deduction = true, const bool type_deduction = true,
value_t manual_type = value_t::array) const value_t manual_type = value_t::array)
{ {
// check if each element is an array with two elements whose first // check if each element is an array with two elements whose first
// element is a string // element is a string
@ -1862,12 +1853,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class InputIT, typename template<class InputIT, typename = typename std::enable_if<
std::enable_if< std::is_same<InputIT, typename basic_json_t::iterator>::value or
std::is_same<InputIT, typename basic_json_t::iterator>::value or std::is_same<InputIT, typename basic_json_t::const_iterator>::value>::type>
std::is_same<InputIT, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
basic_json(InputIT first, InputIT last) basic_json(InputIT first, InputIT last)
{ {
assert(first.m_object != nullptr); assert(first.m_object != nullptr);
@ -2616,11 +2604,10 @@ class basic_json
////////////////// //////////////////
/// get an object (explicit) /// get an object (explicit)
template <class T, typename template<class T, typename std::enable_if<
std::enable_if< std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
std::is_convertible<typename object_t::key_type, typename T::key_type>::value and std::is_convertible<basic_json_t, typename T::mapped_type>::value
std::is_convertible<basic_json_t, typename T::mapped_type>::value , int>::type = 0>
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
if (is_object()) if (is_object())
@ -2647,14 +2634,13 @@ class basic_json
} }
/// get an array (explicit) /// get an array (explicit)
template <class T, typename template<class T, typename std::enable_if<
std::enable_if< std::is_convertible<basic_json_t, typename T::value_type>::value and
std::is_convertible<basic_json_t, typename T::value_type>::value and not std::is_same<basic_json_t, typename T::value_type>::value and
not std::is_same<basic_json_t, typename T::value_type>::value and not std::is_arithmetic<T>::value and
not std::is_arithmetic<T>::value and not std::is_convertible<std::string, T>::value and
not std::is_convertible<std::string, T>::value and not has_mapped_type<T>::value
not has_mapped_type<T>::value , int>::type = 0>
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
if (is_array()) if (is_array())
@ -2674,11 +2660,10 @@ class basic_json
} }
/// get an array (explicit) /// get an array (explicit)
template <class T, typename template<class T, typename std::enable_if<
std::enable_if< std::is_convertible<basic_json_t, T>::value and
std::is_convertible<basic_json_t, T>::value and not std::is_same<basic_json_t, T>::value
not std::is_same<basic_json_t, T>::value , int>::type = 0>
, int>::type = 0>
std::vector<T> get_impl(std::vector<T>*) const std::vector<T> get_impl(std::vector<T>*) const
{ {
if (is_array()) if (is_array())
@ -2699,11 +2684,10 @@ class basic_json
} }
/// get an array (explicit) /// get an array (explicit)
template <class T, typename template<class T, typename std::enable_if<
std::enable_if< std::is_same<basic_json, typename T::value_type>::value and
std::is_same<basic_json, typename T::value_type>::value and not has_mapped_type<T>::value
not has_mapped_type<T>::value , int>::type = 0>
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
if (is_array()) if (is_array())
@ -2730,10 +2714,9 @@ class basic_json
} }
/// get a string (explicit) /// get a string (explicit)
template <typename T, typename template<typename T, typename std::enable_if<
std::enable_if< std::is_convertible<string_t, T>::value
std::is_convertible<string_t, T>::value , int>::type = 0>
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
if (is_string()) if (is_string())
@ -2747,10 +2730,8 @@ class basic_json
} }
/// get a number (explicit) /// get a number (explicit)
template<typename T, typename template<typename T, typename std::enable_if<
std::enable_if< std::is_arithmetic<T>::value, int>::type = 0>
std::is_arithmetic<T>::value
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
switch (m_type) switch (m_type)
@ -2939,10 +2920,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename ValueType, typename template<typename ValueType, typename = typename std::enable_if<
std::enable_if< not std::is_pointer<ValueType>::value>::type>
not std::is_pointer<ValueType>::value
, int>::type = 0>
ValueType get() const ValueType get() const
{ {
return get_impl(static_cast<ValueType*>(nullptr)); return get_impl(static_cast<ValueType*>(nullptr));
@ -2975,10 +2954,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename PointerType, typename template<typename PointerType, typename = typename std::enable_if<
std::enable_if< std::is_pointer<PointerType>::value>::type>
std::is_pointer<PointerType>::value
, int>::type = 0>
PointerType get() noexcept PointerType get() noexcept
{ {
// delegate the call to get_ptr // delegate the call to get_ptr
@ -2989,10 +2966,8 @@ class basic_json
@brief get a pointer value (explicit) @brief get a pointer value (explicit)
@copydoc get() @copydoc get()
*/ */
template<typename PointerType, typename template<typename PointerType, typename = typename std::enable_if<
std::enable_if< std::is_pointer<PointerType>::value>::type>
std::is_pointer<PointerType>::value
, int>::type = 0>
constexpr const PointerType get() const noexcept constexpr const PointerType get() const noexcept
{ {
// delegate the call to get_ptr // delegate the call to get_ptr
@ -3025,10 +3000,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename PointerType, typename template<typename PointerType, typename = typename std::enable_if<
std::enable_if< std::is_pointer<PointerType>::value>::type>
std::is_pointer<PointerType>::value
, int>::type = 0>
PointerType get_ptr() noexcept PointerType get_ptr() noexcept
{ {
// get the type of the PointerType (remove pointer and const) // get the type of the PointerType (remove pointer and const)
@ -3054,11 +3027,9 @@ class basic_json
@brief get a pointer value (implicit) @brief get a pointer value (implicit)
@copydoc get_ptr() @copydoc get_ptr()
*/ */
template<typename PointerType, typename template<typename PointerType, typename = typename std::enable_if<
std::enable_if<
std::is_pointer<PointerType>::value std::is_pointer<PointerType>::value
and std::is_const<typename std::remove_pointer<PointerType>::type>::value and std::is_const<typename std::remove_pointer<PointerType>::type>::value>::type>
, int>::type = 0>
constexpr const PointerType get_ptr() const noexcept constexpr const PointerType get_ptr() const noexcept
{ {
// get the type of the PointerType (remove pointer and const) // get the type of the PointerType (remove pointer and const)
@ -3106,10 +3077,8 @@ class basic_json
@since version 1.1.0 @since version 1.1.0
*/ */
template<typename ReferenceType, typename template<typename ReferenceType, typename = typename std::enable_if<
std::enable_if< std::is_reference<ReferenceType>::value>::type>
std::is_reference<ReferenceType>::value
, int>::type = 0>
ReferenceType get_ref() ReferenceType get_ref()
{ {
// delegate call to get_ref_impl // delegate call to get_ref_impl
@ -3120,11 +3089,9 @@ class basic_json
@brief get a reference value (implicit) @brief get a reference value (implicit)
@copydoc get_ref() @copydoc get_ref()
*/ */
template<typename ReferenceType, typename template<typename ReferenceType, typename = typename std::enable_if<
std::enable_if<
std::is_reference<ReferenceType>::value std::is_reference<ReferenceType>::value
and std::is_const<typename std::remove_reference<ReferenceType>::type>::value and std::is_const<typename std::remove_reference<ReferenceType>::type>::value>::type>
, int>::type = 0>
ReferenceType get_ref() const ReferenceType get_ref() const
{ {
// delegate call to get_ref_impl // delegate call to get_ref_impl
@ -3159,14 +3126,13 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template < typename ValueType, typename template < typename ValueType, typename = typename std::enable_if <
std::enable_if <
not std::is_pointer<ValueType>::value not std::is_pointer<ValueType>::value
and not std::is_same<ValueType, typename string_t::value_type>::value and not std::is_same<ValueType, typename string_t::value_type>::value
#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#endif #endif
, int >::type = 0 > >::type >
operator ValueType() const operator ValueType() const
{ {
// delegate the call to get<>() const // delegate the call to get<>() const
@ -3752,10 +3718,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class ValueType, typename template<class ValueType, typename = typename std::enable_if<
std::enable_if< std::is_convertible<basic_json_t, ValueType>::value>::type>
std::is_convertible<basic_json_t, ValueType>::value
, int>::type = 0>
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
@ -3828,10 +3792,8 @@ class basic_json
@since version 2.0.2 @since version 2.0.2
*/ */
template <class ValueType, typename template<class ValueType, typename = typename std::enable_if<
std::enable_if< std::is_convertible<basic_json_t, ValueType>::value>::type>
std::is_convertible<basic_json_t, ValueType>::value
, int>::type = 0>
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
@ -3992,12 +3954,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class InteratorType, typename template<class InteratorType, typename = typename std::enable_if<
std::enable_if< std::is_same<InteratorType, typename basic_json_t::iterator>::value or
std::is_same<InteratorType, typename basic_json_t::iterator>::value or std::is_same<InteratorType, typename basic_json_t::const_iterator>::value>::type>
std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
InteratorType erase(InteratorType pos) InteratorType erase(InteratorType pos)
{ {
// make sure iterator fits the current value // make sure iterator fits the current value
@ -4101,12 +4060,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class InteratorType, typename template<class InteratorType, typename = typename std::enable_if<
std::enable_if< std::is_same<InteratorType, typename basic_json_t::iterator>::value or
std::is_same<InteratorType, typename basic_json_t::iterator>::value or std::is_same<InteratorType, typename basic_json_t::const_iterator>::value>::type>
std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
InteratorType erase(InteratorType first, InteratorType last) InteratorType erase(InteratorType first, InteratorType last)
{ {
// make sure iterator fits the current value // make sure iterator fits the current value
@ -6267,7 +6223,7 @@ class basic_json
const unsigned int current_indent = 0) const const unsigned int current_indent = 0) const
{ {
// variable to hold indentation for recursive calls // variable to hold indentation for recursive calls
unsigned int new_indent = current_indent; auto new_indent = current_indent;
switch (m_type) switch (m_type)
{ {
@ -7561,7 +7517,7 @@ class basic_json
const std::size_t codepoint2 = 0) const std::size_t codepoint2 = 0)
{ {
// calculate the code point from the given code points // calculate the code point from the given code points
std::size_t codepoint = codepoint1; auto codepoint = codepoint1;
// check if codepoint1 is a high surrogate // check if codepoint1 is a high surrogate
if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF) if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
@ -9524,7 +9480,7 @@ basic_json_parser_63:
auto reference_token = reference_string.substr(start, slash - start); auto reference_token = reference_string.substr(start, slash - start);
// check reference tokens are properly escaped // check reference tokens are properly escaped
for (size_t pos = reference_token.find_first_of("~"); for (auto pos = reference_token.find_first_of("~");
pos != std::string::npos; pos != std::string::npos;
pos = reference_token.find_first_of("~", pos + 1)) pos = reference_token.find_first_of("~", pos + 1))
{ {
@ -9569,7 +9525,7 @@ basic_json_parser_63:
assert(not f.empty()); assert(not f.empty());
for ( for (
size_t pos = s.find(f); // find first occurrence of f auto pos = s.find(f); // find first occurrence of f
pos != std::string::npos; // make sure f was found pos != std::string::npos; // make sure f was found
s.replace(pos, f.size(), t), // replace with t s.replace(pos, f.size(), t), // replace with t
pos = s.find(f, pos + t.size()) // find next occurrence of f pos = s.find(f, pos + t.size()) // find next occurrence of f
@ -9969,7 +9925,7 @@ basic_json_parser_63:
else else
{ {
// make sure the top element of the pointer exists // make sure the top element of the pointer exists
json_pointer top_pointer = ptr.top(); auto top_pointer = ptr.top();
if (top_pointer != ptr) if (top_pointer != ptr)
{ {
basic_json& x = result.at(top_pointer); basic_json& x = result.at(top_pointer);
@ -10377,7 +10333,7 @@ namespace std
@since version 1.0.0 @since version 1.0.0
*/ */
template <> template<>
inline void swap(nlohmann::json& j1, inline void swap(nlohmann::json& j1,
nlohmann::json& j2) noexcept( nlohmann::json& j2) noexcept(
is_nothrow_move_constructible<nlohmann::json>::value and is_nothrow_move_constructible<nlohmann::json>::value and
@ -10388,7 +10344,7 @@ inline void swap(nlohmann::json& j1,
} }
/// hash value for JSON objects /// hash value for JSON objects
template <> template<>
struct hash<nlohmann::json> struct hash<nlohmann::json>
{ {
/*! /*!

View file

@ -1164,11 +1164,10 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class CompatibleObjectType, typename template<class CompatibleObjectType, typename std::enable_if<
std::enable_if< std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type = 0>
= 0>
basic_json(const CompatibleObjectType& val) basic_json(const CompatibleObjectType& val)
: m_type(value_t::object) : m_type(value_t::object)
{ {
@ -1229,16 +1228,15 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class CompatibleArrayType, typename template<class CompatibleArrayType, typename std::enable_if<
std::enable_if< not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type = 0>
= 0>
basic_json(const CompatibleArrayType& val) basic_json(const CompatibleArrayType& val)
: m_type(value_t::array) : m_type(value_t::array)
{ {
@ -1324,10 +1322,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class CompatibleStringType, typename template<class CompatibleStringType, typename std::enable_if<
std::enable_if< std::is_constructible<string_t, CompatibleStringType>::value, int>::type
std::is_constructible<string_t, CompatibleStringType>::value, int>::type = 0>
= 0>
basic_json(const CompatibleStringType& val) basic_json(const CompatibleStringType& val)
: basic_json(string_t(val)) : basic_json(string_t(val))
{ {
@ -1377,8 +1374,7 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename T, template<typename T, typename std::enable_if<
typename std::enable_if<
not (std::is_same<T, int>::value) not (std::is_same<T, int>::value)
and std::is_same<T, number_integer_t>::value and std::is_same<T, number_integer_t>::value
, int>::type , int>::type
@ -1477,8 +1473,7 @@ class basic_json
@since version 2.0.0 @since version 2.0.0
*/ */
template<typename T, template<typename T, typename std::enable_if<
typename std::enable_if<
not (std::is_same<T, int>::value) not (std::is_same<T, int>::value)
and std::is_same<T, number_unsigned_t>::value and std::is_same<T, number_unsigned_t>::value
, int>::type , int>::type
@ -1509,13 +1504,11 @@ class basic_json
@since version 2.0.0 @since version 2.0.0
*/ */
template <typename CompatibleNumberUnsignedType, typename template<typename CompatibleNumberUnsignedType, typename std::enable_if<
std::enable_if < std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, CompatibleNumberUnsignedType>::type
not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, = 0>
CompatibleNumberUnsignedType>::type
= 0>
basic_json(const CompatibleNumberUnsignedType val) noexcept basic_json(const CompatibleNumberUnsignedType val) noexcept
: m_type(value_t::number_unsigned), : m_type(value_t::number_unsigned),
m_value(static_cast<number_unsigned_t>(val)) m_value(static_cast<number_unsigned_t>(val))
@ -1591,11 +1584,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename CompatibleNumberFloatType, typename = typename template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
std::enable_if<
std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
std::is_floating_point<CompatibleNumberFloatType>::value>::type std::is_floating_point<CompatibleNumberFloatType>::value>::type>
>
basic_json(const CompatibleNumberFloatType val) noexcept basic_json(const CompatibleNumberFloatType val) noexcept
: basic_json(number_float_t(val)) : basic_json(number_float_t(val))
{ {
@ -1672,8 +1663,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
basic_json(std::initializer_list<basic_json> init, basic_json(std::initializer_list<basic_json> init,
bool type_deduction = true, const bool type_deduction = true,
value_t manual_type = value_t::array) const value_t manual_type = value_t::array)
{ {
// check if each element is an array with two elements whose first // check if each element is an array with two elements whose first
// element is a string // element is a string
@ -1862,12 +1853,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class InputIT, typename template<class InputIT, typename = typename std::enable_if<
std::enable_if< std::is_same<InputIT, typename basic_json_t::iterator>::value or
std::is_same<InputIT, typename basic_json_t::iterator>::value or std::is_same<InputIT, typename basic_json_t::const_iterator>::value>::type>
std::is_same<InputIT, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
basic_json(InputIT first, InputIT last) basic_json(InputIT first, InputIT last)
{ {
assert(first.m_object != nullptr); assert(first.m_object != nullptr);
@ -2616,11 +2604,10 @@ class basic_json
////////////////// //////////////////
/// get an object (explicit) /// get an object (explicit)
template <class T, typename template<class T, typename std::enable_if<
std::enable_if< std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
std::is_convertible<typename object_t::key_type, typename T::key_type>::value and std::is_convertible<basic_json_t, typename T::mapped_type>::value
std::is_convertible<basic_json_t, typename T::mapped_type>::value , int>::type = 0>
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
if (is_object()) if (is_object())
@ -2647,14 +2634,13 @@ class basic_json
} }
/// get an array (explicit) /// get an array (explicit)
template <class T, typename template<class T, typename std::enable_if<
std::enable_if< std::is_convertible<basic_json_t, typename T::value_type>::value and
std::is_convertible<basic_json_t, typename T::value_type>::value and not std::is_same<basic_json_t, typename T::value_type>::value and
not std::is_same<basic_json_t, typename T::value_type>::value and not std::is_arithmetic<T>::value and
not std::is_arithmetic<T>::value and not std::is_convertible<std::string, T>::value and
not std::is_convertible<std::string, T>::value and not has_mapped_type<T>::value
not has_mapped_type<T>::value , int>::type = 0>
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
if (is_array()) if (is_array())
@ -2674,11 +2660,10 @@ class basic_json
} }
/// get an array (explicit) /// get an array (explicit)
template <class T, typename template<class T, typename std::enable_if<
std::enable_if< std::is_convertible<basic_json_t, T>::value and
std::is_convertible<basic_json_t, T>::value and not std::is_same<basic_json_t, T>::value
not std::is_same<basic_json_t, T>::value , int>::type = 0>
, int>::type = 0>
std::vector<T> get_impl(std::vector<T>*) const std::vector<T> get_impl(std::vector<T>*) const
{ {
if (is_array()) if (is_array())
@ -2699,11 +2684,10 @@ class basic_json
} }
/// get an array (explicit) /// get an array (explicit)
template <class T, typename template<class T, typename std::enable_if<
std::enable_if< std::is_same<basic_json, typename T::value_type>::value and
std::is_same<basic_json, typename T::value_type>::value and not has_mapped_type<T>::value
not has_mapped_type<T>::value , int>::type = 0>
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
if (is_array()) if (is_array())
@ -2730,10 +2714,9 @@ class basic_json
} }
/// get a string (explicit) /// get a string (explicit)
template <typename T, typename template<typename T, typename std::enable_if<
std::enable_if< std::is_convertible<string_t, T>::value
std::is_convertible<string_t, T>::value , int>::type = 0>
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
if (is_string()) if (is_string())
@ -2747,10 +2730,8 @@ class basic_json
} }
/// get a number (explicit) /// get a number (explicit)
template<typename T, typename template<typename T, typename std::enable_if<
std::enable_if< std::is_arithmetic<T>::value, int>::type = 0>
std::is_arithmetic<T>::value
, int>::type = 0>
T get_impl(T*) const T get_impl(T*) const
{ {
switch (m_type) switch (m_type)
@ -2939,10 +2920,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename ValueType, typename template<typename ValueType, typename = typename std::enable_if<
std::enable_if< not std::is_pointer<ValueType>::value>::type>
not std::is_pointer<ValueType>::value
, int>::type = 0>
ValueType get() const ValueType get() const
{ {
return get_impl(static_cast<ValueType*>(nullptr)); return get_impl(static_cast<ValueType*>(nullptr));
@ -2975,10 +2954,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename PointerType, typename template<typename PointerType, typename = typename std::enable_if<
std::enable_if< std::is_pointer<PointerType>::value>::type>
std::is_pointer<PointerType>::value
, int>::type = 0>
PointerType get() noexcept PointerType get() noexcept
{ {
// delegate the call to get_ptr // delegate the call to get_ptr
@ -2989,10 +2966,8 @@ class basic_json
@brief get a pointer value (explicit) @brief get a pointer value (explicit)
@copydoc get() @copydoc get()
*/ */
template<typename PointerType, typename template<typename PointerType, typename = typename std::enable_if<
std::enable_if< std::is_pointer<PointerType>::value>::type>
std::is_pointer<PointerType>::value
, int>::type = 0>
constexpr const PointerType get() const noexcept constexpr const PointerType get() const noexcept
{ {
// delegate the call to get_ptr // delegate the call to get_ptr
@ -3025,10 +3000,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template<typename PointerType, typename template<typename PointerType, typename = typename std::enable_if<
std::enable_if< std::is_pointer<PointerType>::value>::type>
std::is_pointer<PointerType>::value
, int>::type = 0>
PointerType get_ptr() noexcept PointerType get_ptr() noexcept
{ {
// get the type of the PointerType (remove pointer and const) // get the type of the PointerType (remove pointer and const)
@ -3054,11 +3027,9 @@ class basic_json
@brief get a pointer value (implicit) @brief get a pointer value (implicit)
@copydoc get_ptr() @copydoc get_ptr()
*/ */
template<typename PointerType, typename template<typename PointerType, typename = typename std::enable_if<
std::enable_if<
std::is_pointer<PointerType>::value std::is_pointer<PointerType>::value
and std::is_const<typename std::remove_pointer<PointerType>::type>::value and std::is_const<typename std::remove_pointer<PointerType>::type>::value>::type>
, int>::type = 0>
constexpr const PointerType get_ptr() const noexcept constexpr const PointerType get_ptr() const noexcept
{ {
// get the type of the PointerType (remove pointer and const) // get the type of the PointerType (remove pointer and const)
@ -3106,10 +3077,8 @@ class basic_json
@since version 1.1.0 @since version 1.1.0
*/ */
template<typename ReferenceType, typename template<typename ReferenceType, typename = typename std::enable_if<
std::enable_if< std::is_reference<ReferenceType>::value>::type>
std::is_reference<ReferenceType>::value
, int>::type = 0>
ReferenceType get_ref() ReferenceType get_ref()
{ {
// delegate call to get_ref_impl // delegate call to get_ref_impl
@ -3120,11 +3089,9 @@ class basic_json
@brief get a reference value (implicit) @brief get a reference value (implicit)
@copydoc get_ref() @copydoc get_ref()
*/ */
template<typename ReferenceType, typename template<typename ReferenceType, typename = typename std::enable_if<
std::enable_if<
std::is_reference<ReferenceType>::value std::is_reference<ReferenceType>::value
and std::is_const<typename std::remove_reference<ReferenceType>::type>::value and std::is_const<typename std::remove_reference<ReferenceType>::type>::value>::type>
, int>::type = 0>
ReferenceType get_ref() const ReferenceType get_ref() const
{ {
// delegate call to get_ref_impl // delegate call to get_ref_impl
@ -3159,14 +3126,13 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template < typename ValueType, typename template < typename ValueType, typename = typename std::enable_if <
std::enable_if <
not std::is_pointer<ValueType>::value not std::is_pointer<ValueType>::value
and not std::is_same<ValueType, typename string_t::value_type>::value and not std::is_same<ValueType, typename string_t::value_type>::value
#ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015 #ifndef _MSC_VER // Fix for issue #167 operator<< abiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#endif #endif
, int >::type = 0 > >::type >
operator ValueType() const operator ValueType() const
{ {
// delegate the call to get<>() const // delegate the call to get<>() const
@ -3752,10 +3718,8 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class ValueType, typename template<class ValueType, typename = typename std::enable_if<
std::enable_if< std::is_convertible<basic_json_t, ValueType>::value>::type>
std::is_convertible<basic_json_t, ValueType>::value
, int>::type = 0>
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
@ -3828,10 +3792,8 @@ class basic_json
@since version 2.0.2 @since version 2.0.2
*/ */
template <class ValueType, typename template<class ValueType, typename = typename std::enable_if<
std::enable_if< std::is_convertible<basic_json_t, ValueType>::value>::type>
std::is_convertible<basic_json_t, ValueType>::value
, int>::type = 0>
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
@ -3992,12 +3954,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class InteratorType, typename template<class InteratorType, typename = typename std::enable_if<
std::enable_if< std::is_same<InteratorType, typename basic_json_t::iterator>::value or
std::is_same<InteratorType, typename basic_json_t::iterator>::value or std::is_same<InteratorType, typename basic_json_t::const_iterator>::value>::type>
std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
InteratorType erase(InteratorType pos) InteratorType erase(InteratorType pos)
{ {
// make sure iterator fits the current value // make sure iterator fits the current value
@ -4101,12 +4060,9 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
template <class InteratorType, typename template<class InteratorType, typename = typename std::enable_if<
std::enable_if< std::is_same<InteratorType, typename basic_json_t::iterator>::value or
std::is_same<InteratorType, typename basic_json_t::iterator>::value or std::is_same<InteratorType, typename basic_json_t::const_iterator>::value>::type>
std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
, int>::type
= 0>
InteratorType erase(InteratorType first, InteratorType last) InteratorType erase(InteratorType first, InteratorType last)
{ {
// make sure iterator fits the current value // make sure iterator fits the current value
@ -6267,7 +6223,7 @@ class basic_json
const unsigned int current_indent = 0) const const unsigned int current_indent = 0) const
{ {
// variable to hold indentation for recursive calls // variable to hold indentation for recursive calls
unsigned int new_indent = current_indent; auto new_indent = current_indent;
switch (m_type) switch (m_type)
{ {
@ -7561,7 +7517,7 @@ class basic_json
const std::size_t codepoint2 = 0) const std::size_t codepoint2 = 0)
{ {
// calculate the code point from the given code points // calculate the code point from the given code points
std::size_t codepoint = codepoint1; auto codepoint = codepoint1;
// check if codepoint1 is a high surrogate // check if codepoint1 is a high surrogate
if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF) if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
@ -8821,7 +8777,7 @@ class basic_json
auto reference_token = reference_string.substr(start, slash - start); auto reference_token = reference_string.substr(start, slash - start);
// check reference tokens are properly escaped // check reference tokens are properly escaped
for (size_t pos = reference_token.find_first_of("~"); for (auto pos = reference_token.find_first_of("~");
pos != std::string::npos; pos != std::string::npos;
pos = reference_token.find_first_of("~", pos + 1)) pos = reference_token.find_first_of("~", pos + 1))
{ {
@ -8866,7 +8822,7 @@ class basic_json
assert(not f.empty()); assert(not f.empty());
for ( for (
size_t pos = s.find(f); // find first occurrence of f auto pos = s.find(f); // find first occurrence of f
pos != std::string::npos; // make sure f was found pos != std::string::npos; // make sure f was found
s.replace(pos, f.size(), t), // replace with t s.replace(pos, f.size(), t), // replace with t
pos = s.find(f, pos + t.size()) // find next occurrence of f pos = s.find(f, pos + t.size()) // find next occurrence of f
@ -9266,7 +9222,7 @@ class basic_json
else else
{ {
// make sure the top element of the pointer exists // make sure the top element of the pointer exists
json_pointer top_pointer = ptr.top(); auto top_pointer = ptr.top();
if (top_pointer != ptr) if (top_pointer != ptr)
{ {
basic_json& x = result.at(top_pointer); basic_json& x = result.at(top_pointer);
@ -9674,7 +9630,7 @@ namespace std
@since version 1.0.0 @since version 1.0.0
*/ */
template <> template<>
inline void swap(nlohmann::json& j1, inline void swap(nlohmann::json& j1,
nlohmann::json& j2) noexcept( nlohmann::json& j2) noexcept(
is_nothrow_move_constructible<nlohmann::json>::value and is_nothrow_move_constructible<nlohmann::json>::value and
@ -9685,7 +9641,7 @@ inline void swap(nlohmann::json& j1,
} }
/// hash value for JSON objects /// hash value for JSON objects
template <> template<>
struct hash<nlohmann::json> struct hash<nlohmann::json>
{ {
/*! /*!

View file

@ -64,6 +64,22 @@ TEST_CASE("const_iterator class")
json::const_iterator it2(&j); json::const_iterator it2(&j);
it2 = it; it2 = it;
} }
SECTION("copy constructor from non-const iterator")
{
SECTION("create from uninitialized iterator")
{
const json::iterator it {};
json::const_iterator cit(it);
}
SECTION("create from initialized iterator")
{
json j;
const json::iterator it = j.begin();
json::const_iterator cit(it);
}
}
} }
SECTION("initialization") SECTION("initialization")

View file

@ -33,41 +33,87 @@ using nlohmann::json;
TEST_CASE("deserialization") TEST_CASE("deserialization")
{ {
SECTION("stream") SECTION("successful deserialization")
{ {
std::stringstream ss; SECTION("stream")
ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; {
json j = json::parse(ss); std::stringstream ss;
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
json j = json::parse(ss);
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
SECTION("string")
{
json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}]";
json j = json::parse(s);
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
SECTION("operator<<")
{
std::stringstream ss;
ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
json j;
j << ss;
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
SECTION("operator>>")
{
std::stringstream ss;
ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
json j;
ss >> j;
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
SECTION("user-defined string literal")
{
CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
} }
SECTION("string") SECTION("successful deserialization")
{ {
auto s = "[\"foo\",1,2,3,false,{\"one\":1}]"; SECTION("stream")
json j = json::parse(s); {
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); std::stringstream ss;
} ss << "[\"foo\",1,2,3,false,{\"one\":1}";
CHECK_THROWS_AS(json::parse(ss), std::invalid_argument);
CHECK_THROWS_WITH(json::parse(ss), "parse error - unexpected end of input");
}
SECTION("operator<<") SECTION("string")
{ {
std::stringstream ss; json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}";
ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; CHECK_THROWS_AS(json::parse(s), std::invalid_argument);
json j; CHECK_THROWS_WITH(json::parse(s), "parse error - unexpected end of input; expected ']'");
j << ss; }
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
}
SECTION("operator>>") SECTION("operator<<")
{ {
std::stringstream ss; std::stringstream ss;
ss << "[\"foo\",1,2,3,false,{\"one\":1}]"; ss << "[\"foo\",1,2,3,false,{\"one\":1}";
json j; json j;
ss >> j; CHECK_THROWS_AS(j << ss, std::invalid_argument);
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input");
} }
SECTION("user-defined string literal") SECTION("operator>>")
{ {
CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}})); std::stringstream ss;
ss << "[\"foo\",1,2,3,false,{\"one\":1}";
json j;
CHECK_THROWS_AS(ss >> j, std::invalid_argument);
CHECK_THROWS_WITH(ss >> j, "parse error - unexpected end of input");
}
SECTION("user-defined string literal")
{
CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, std::invalid_argument);
CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json,
"parse error - unexpected end of input; expected ']'");
}
} }
} }