diff --git a/doc/examples/is_discarded.cpp b/doc/examples/is_discarded.cpp new file mode 100644 index 00000000..c71bf901 --- /dev/null +++ b/doc/examples/is_discarded.cpp @@ -0,0 +1,25 @@ +#include + +using namespace nlohmann; + +int main() +{ + // create JSON values + json j_null; + json j_boolean = true; + json j_number_integer = 17; + json j_number_float = 23.42; + json j_object = {{"one", 1}, {"two", 2}}; + json j_array = {1, 2, 4, 8, 16}; + json j_string = "Hello, world"; + + // call is_discarded() + std::cout << std::boolalpha; + std::cout << j_null.is_discarded() << '\n'; + std::cout << j_boolean.is_discarded() << '\n'; + std::cout << j_number_integer.is_discarded() << '\n'; + std::cout << j_number_float.is_discarded() << '\n'; + std::cout << j_object.is_discarded() << '\n'; + std::cout << j_array.is_discarded() << '\n'; + std::cout << j_string.is_discarded() << '\n'; +} diff --git a/doc/examples/is_discarded.link b/doc/examples/is_discarded.link new file mode 100644 index 00000000..389f90bb --- /dev/null +++ b/doc/examples/is_discarded.link @@ -0,0 +1 @@ +online \ No newline at end of file diff --git a/doc/examples/is_discarded.output b/doc/examples/is_discarded.output new file mode 100644 index 00000000..28f6ac44 --- /dev/null +++ b/doc/examples/is_discarded.output @@ -0,0 +1,7 @@ +false +false +false +false +false +false +false diff --git a/doc/examples/operator__equal__nullptr_t.cpp b/doc/examples/operator__equal__nullptr_t.cpp new file mode 100644 index 00000000..f3ce2fe2 --- /dev/null +++ b/doc/examples/operator__equal__nullptr_t.cpp @@ -0,0 +1,21 @@ +#include + +using namespace nlohmann; + +int main() +{ + // create several JSON values + json array = {1, 2, 3}; + json object = {{"A", "a"}, {"B", "b"}}; + json number = 17; + json string = "foo"; + json null; + + // output values and comparisons + std::cout << std::boolalpha; + std::cout << array << " == nullptr " << (array == nullptr) << '\n'; + std::cout << object << " == nullptr " << (object == nullptr) << '\n'; + std::cout << number << " == nullptr " << (number == nullptr) << '\n'; + std::cout << string << " == nullptr " << (string == nullptr) << '\n'; + std::cout << null << " == nullptr " << (null == nullptr) << '\n'; +} diff --git a/doc/examples/operator__equal__nullptr_t.link b/doc/examples/operator__equal__nullptr_t.link new file mode 100644 index 00000000..0ddbd47e --- /dev/null +++ b/doc/examples/operator__equal__nullptr_t.link @@ -0,0 +1 @@ +online \ No newline at end of file diff --git a/doc/examples/operator__equal__nullptr_t.output b/doc/examples/operator__equal__nullptr_t.output new file mode 100644 index 00000000..b7128e13 --- /dev/null +++ b/doc/examples/operator__equal__nullptr_t.output @@ -0,0 +1,5 @@ +[1,2,3] == nullptr false +{"A":"a","B":"b"} == nullptr false +17 == nullptr false +"foo" == nullptr false +null == nullptr true diff --git a/doc/examples/operator__notequal__nullptr_t.cpp b/doc/examples/operator__notequal__nullptr_t.cpp new file mode 100644 index 00000000..9a740d5d --- /dev/null +++ b/doc/examples/operator__notequal__nullptr_t.cpp @@ -0,0 +1,21 @@ +#include + +using namespace nlohmann; + +int main() +{ + // create several JSON values + json array = {1, 2, 3}; + json object = {{"A", "a"}, {"B", "b"}}; + json number = 17; + json string = "foo"; + json null; + + // output values and comparisons + std::cout << std::boolalpha; + std::cout << array << " != nullptr " << (array != nullptr) << '\n'; + std::cout << object << " != nullptr " << (object != nullptr) << '\n'; + std::cout << number << " != nullptr " << (number != nullptr) << '\n'; + std::cout << string << " != nullptr " << (string != nullptr) << '\n'; + std::cout << null << " != nullptr " << (null != nullptr) << '\n'; +} diff --git a/doc/examples/operator__notequal__nullptr_t.link b/doc/examples/operator__notequal__nullptr_t.link new file mode 100644 index 00000000..4d6ad55f --- /dev/null +++ b/doc/examples/operator__notequal__nullptr_t.link @@ -0,0 +1 @@ +online \ No newline at end of file diff --git a/doc/examples/operator__notequal__nullptr_t.output b/doc/examples/operator__notequal__nullptr_t.output new file mode 100644 index 00000000..0fc36dcf --- /dev/null +++ b/doc/examples/operator__notequal__nullptr_t.output @@ -0,0 +1,5 @@ +[1,2,3] != nullptr true +{"A":"a","B":"b"} != nullptr true +17 != nullptr true +"foo" != nullptr true +null != nullptr false diff --git a/src/json.hpp b/src/json.hpp index 76208d0d..cc3617c5 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -101,18 +101,24 @@ default; will be used in @ref number_float_t) @tparam AllocatorType type of the allocator to use (@c `std::allocator` by default) -@requirement This class satisfies the Container requirements (see -http://en.cppreference.com/w/cpp/concept/Container): -- basic_json() -- basic_json(const basic_json&) -- reference& operator=(basic_json) -- ~basic_json() -- iterator begin(), const_iterator begin(), const_iterator cbegin() -- iterator end(), const_iterator end(), const_iterator cend() -- bool operator==(const_reference, const_reference), bool operator!=(const_reference, const_reference) -- void swap(reference other) -- size_type size(), size_type max_size() -- bool empty() +@requirement The class satisfies the following concept requirements: +- Basic + - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible) + - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible) + - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable) + - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable) + - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible) +- Layout + - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType) +- Library-wide + - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable) + - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable) + - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable) + - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer) +- Container + - [Container](http://en.cppreference.com/w/cpp/concept/Container) + - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) @note ObjectType trick from http://stackoverflow.com/a/9860911 @@ -1904,11 +1910,16 @@ class basic_json This function returns true iff the JSON value was discarded during parsing with a callback function (see @ref parser_callback_t). + @note This function will always be `false` for JSON values after parsing. + That is, discarded values can only occur during parsing, but will be + removed when inside a structured value or replaced by null in other cases. + @return `true` if type is discarded, `false` otherwise. @complexity Constant. - @todo Add example. + @liveexample{The following code exemplifies @ref is_discarded for all JSON + types.,is_discarded} */ bool is_discarded() const noexcept { @@ -3948,6 +3959,36 @@ class basic_json return false; } + /*! + @brief comparison: equal + + The functions compares the given JSON value against a null pointer. As the + null pointer can be used to initialize a JSON value to null, a comparison + of JSON value @a v with a null pointer should be equivalent to call + `v.is_null()`. + + @param[in] v JSON value to consider + @return whether @a v is null + + @complexity Constant. + + @liveexample{The example compares several JSON types to the null pointer. + ,operator__equal__nullptr_t} + */ + friend bool operator==(const_reference v, std::nullptr_t) noexcept + { + return v.is_null(); + } + + /*! + @brief comparison: equal + @copydoc operator==(const_reference, std::nullptr_t) + */ + friend bool operator==(std::nullptr_t, const_reference v) noexcept + { + return v.is_null(); + } + /*! @brief comparison: not equal @@ -3969,6 +4010,36 @@ class basic_json return not (lhs == rhs); } + /*! + @brief comparison: not equal + + The functions compares the given JSON value against a null pointer. As the + null pointer can be used to initialize a JSON value to null, a comparison + of JSON value @a v with a null pointer should be equivalent to call + `not v.is_null()`. + + @param[in] v JSON value to consider + @return whether @a v is not null + + @complexity Constant. + + @liveexample{The example compares several JSON types to the null pointer. + ,operator__notequal__nullptr_t} + */ + friend bool operator!=(const_reference v, std::nullptr_t) noexcept + { + return not v.is_null(); + } + + /*! + @brief comparison: not equal + @copydoc operator!=(const_reference, std::nullptr_t) + */ + friend bool operator!=(std::nullptr_t, const_reference v) noexcept + { + return not v.is_null(); + } + /*! @brief comparison: less than diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index acf47b68..58666091 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -101,18 +101,24 @@ default; will be used in @ref number_float_t) @tparam AllocatorType type of the allocator to use (@c `std::allocator` by default) -@requirement This class satisfies the Container requirements (see -http://en.cppreference.com/w/cpp/concept/Container): -- basic_json() -- basic_json(const basic_json&) -- reference& operator=(basic_json) -- ~basic_json() -- iterator begin(), const_iterator begin(), const_iterator cbegin() -- iterator end(), const_iterator end(), const_iterator cend() -- bool operator==(const_reference, const_reference), bool operator!=(const_reference, const_reference) -- void swap(reference other) -- size_type size(), size_type max_size() -- bool empty() +@requirement The class satisfies the following concept requirements: +- Basic + - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible) + - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible) + - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible) + - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable) + - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable) + - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible) +- Layout + - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType) +- Library-wide + - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable) + - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable) + - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable) + - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer) +- Container + - [Container](http://en.cppreference.com/w/cpp/concept/Container) + - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) @note ObjectType trick from http://stackoverflow.com/a/9860911 @@ -1904,11 +1910,16 @@ class basic_json This function returns true iff the JSON value was discarded during parsing with a callback function (see @ref parser_callback_t). + @note This function will always be `false` for JSON values after parsing. + That is, discarded values can only occur during parsing, but will be + removed when inside a structured value or replaced by null in other cases. + @return `true` if type is discarded, `false` otherwise. @complexity Constant. - @todo Add example. + @liveexample{The following code exemplifies @ref is_discarded for all JSON + types.,is_discarded} */ bool is_discarded() const noexcept { @@ -3948,6 +3959,36 @@ class basic_json return false; } + /*! + @brief comparison: equal + + The functions compares the given JSON value against a null pointer. As the + null pointer can be used to initialize a JSON value to null, a comparison + of JSON value @a v with a null pointer should be equivalent to call + `v.is_null()`. + + @param[in] v JSON value to consider + @return whether @a v is null + + @complexity Constant. + + @liveexample{The example compares several JSON types to the null pointer. + ,operator__equal__nullptr_t} + */ + friend bool operator==(const_reference v, std::nullptr_t) noexcept + { + return v.is_null(); + } + + /*! + @brief comparison: equal + @copydoc operator==(const_reference, std::nullptr_t) + */ + friend bool operator==(std::nullptr_t, const_reference v) noexcept + { + return v.is_null(); + } + /*! @brief comparison: not equal @@ -3969,6 +4010,36 @@ class basic_json return not (lhs == rhs); } + /*! + @brief comparison: not equal + + The functions compares the given JSON value against a null pointer. As the + null pointer can be used to initialize a JSON value to null, a comparison + of JSON value @a v with a null pointer should be equivalent to call + `not v.is_null()`. + + @param[in] v JSON value to consider + @return whether @a v is not null + + @complexity Constant. + + @liveexample{The example compares several JSON types to the null pointer. + ,operator__notequal__nullptr_t} + */ + friend bool operator!=(const_reference v, std::nullptr_t) noexcept + { + return not v.is_null(); + } + + /*! + @brief comparison: not equal + @copydoc operator!=(const_reference, std::nullptr_t) + */ + friend bool operator!=(std::nullptr_t, const_reference v) noexcept + { + return not v.is_null(); + } + /*! @brief comparison: less than diff --git a/test/unit.cpp b/test/unit.cpp index 56ae526b..6f5f18f9 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -6803,6 +6803,11 @@ TEST_CASE("lexicographical comparison operators") CHECK( (j_discarded == j_values[i]) == false); CHECK( (j_discarded == j_discarded) == false); } + + // compare with null pointer + json j_null; + CHECK(j_null == nullptr); + CHECK(nullptr == j_null); } SECTION("comparison: not equal") @@ -6815,6 +6820,13 @@ TEST_CASE("lexicographical comparison operators") CHECK( (j_values[i] != j_values[j]) == not(j_values[i] == j_values[j]) ); } } + + // compare with null pointer + json j_null; + CHECK( (j_null != nullptr) == false); + CHECK( (nullptr != j_null) == false); + CHECK( (j_null != nullptr) == not(j_null == nullptr)); + CHECK( (nullptr != j_null) == not(nullptr == j_null)); } SECTION("comparison: less") @@ -8968,6 +8980,8 @@ TEST_CASE("concepts") // X::size_type must return an unsigned integer CHECK((std::is_unsigned::value)); // X::size_type can represent any non-negative value of X::difference_type + CHECK(std::numeric_limits::max() <= + std::numeric_limits::max()); // the expression "X u" has the post-condition "u.empty()" {