diff --git a/docs/examples/json_pointer__operator__equal.cpp b/docs/examples/json_pointer__operator__equal.cpp new file mode 100644 index 000000000..dce6df03c --- /dev/null +++ b/docs/examples/json_pointer__operator__equal.cpp @@ -0,0 +1,19 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // different JSON pointers + json::json_pointer ptr0; + json::json_pointer ptr1(""); + json::json_pointer ptr2("/foo"); + + // compare JSON pointers + std::cout << std::boolalpha + << "\"" << ptr0 << "\" == \"" << ptr0 << "\": " << (ptr0 == ptr0) << '\n' + << "\"" << ptr0 << "\" == \"" << ptr1 << "\": " << (ptr0 == ptr1) << '\n' + << "\"" << ptr1 << "\" == \"" << ptr2 << "\": " << (ptr1 == ptr2) << '\n' + << "\"" << ptr2 << "\" == \"" << ptr2 << "\": " << (ptr2 == ptr2) << std::endl; +} diff --git a/docs/examples/json_pointer__operator__equal.output b/docs/examples/json_pointer__operator__equal.output new file mode 100644 index 000000000..9a7612580 --- /dev/null +++ b/docs/examples/json_pointer__operator__equal.output @@ -0,0 +1,4 @@ +"" == "": true +"" == "": true +"" == "/foo": false +"/foo" == "/foo": true diff --git a/docs/examples/json_pointer__operator__equal_stringtype.cpp b/docs/examples/json_pointer__operator__equal_stringtype.cpp new file mode 100644 index 000000000..af8ec5a29 --- /dev/null +++ b/docs/examples/json_pointer__operator__equal_stringtype.cpp @@ -0,0 +1,33 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + // different JSON pointers + json::json_pointer ptr0; + json::json_pointer ptr1(""); + json::json_pointer ptr2("/foo"); + + // different strings + std::string str0(""); + std::string str1("/foo"); + std::string str2("bar"); + + // compare JSON pointers and strings + std::cout << std::boolalpha + << "\"" << ptr0 << "\" == \"" << str0 << "\": " << (ptr0 == str0) << '\n' + << "\"" << str0 << "\" == \"" << ptr1 << "\": " << (str0 == ptr1) << '\n' + << "\"" << ptr2 << "\" == \"" << str1 << "\": " << (ptr2 == str1) << std::endl; + + try + { + std::cout << "\"" << str2 << "\" == \"" << ptr2 << "\": " << (str2 == ptr2) << std::endl; + } + catch (const json::parse_error& ex) + { + std::cout << ex.what() << std::endl; + } +} diff --git a/docs/examples/json_pointer__operator__equal_stringtype.output b/docs/examples/json_pointer__operator__equal_stringtype.output new file mode 100644 index 000000000..7fb299d3d --- /dev/null +++ b/docs/examples/json_pointer__operator__equal_stringtype.output @@ -0,0 +1,4 @@ +"" == "": true +"" == "": true +"/foo" == "/foo": true +"bar" == "/foo": [json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'bar' diff --git a/docs/examples/json_pointer__operator__notequal.cpp b/docs/examples/json_pointer__operator__notequal.cpp new file mode 100644 index 000000000..9bbdd5310 --- /dev/null +++ b/docs/examples/json_pointer__operator__notequal.cpp @@ -0,0 +1,19 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // different JSON pointers + json::json_pointer ptr0; + json::json_pointer ptr1(""); + json::json_pointer ptr2("/foo"); + + // compare JSON pointers + std::cout << std::boolalpha + << "\"" << ptr0 << "\" != \"" << ptr0 << "\": " << (ptr0 != ptr0) << '\n' + << "\"" << ptr0 << "\" != \"" << ptr1 << "\": " << (ptr0 != ptr1) << '\n' + << "\"" << ptr1 << "\" != \"" << ptr2 << "\": " << (ptr1 != ptr2) << '\n' + << "\"" << ptr2 << "\" != \"" << ptr2 << "\": " << (ptr2 != ptr2) << std::endl; +} diff --git a/docs/examples/json_pointer__operator__notequal.output b/docs/examples/json_pointer__operator__notequal.output new file mode 100644 index 000000000..de891f0c6 --- /dev/null +++ b/docs/examples/json_pointer__operator__notequal.output @@ -0,0 +1,4 @@ +"" != "": false +"" != "": false +"" != "/foo": true +"/foo" != "/foo": false diff --git a/docs/examples/json_pointer__operator__notequal_stringtype.cpp b/docs/examples/json_pointer__operator__notequal_stringtype.cpp new file mode 100644 index 000000000..b9b898728 --- /dev/null +++ b/docs/examples/json_pointer__operator__notequal_stringtype.cpp @@ -0,0 +1,32 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // different JSON pointers + json::json_pointer ptr0; + json::json_pointer ptr1(""); + json::json_pointer ptr2("/foo"); + + // different strings + std::string str0(""); + std::string str1("/foo"); + std::string str2("bar"); + + // compare JSON pointers and strings + std::cout << std::boolalpha + << "\"" << ptr0 << "\" != \"" << str0 << "\": " << (ptr0 != str0) << '\n' + << "\"" << str0 << "\" != \"" << ptr1 << "\": " << (str0 != ptr1) << '\n' + << "\"" << ptr2 << "\" != \"" << str1 << "\": " << (ptr2 != str1) << std::endl; + + try + { + std::cout << "\"" << str2 << "\" != \"" << ptr2 << "\": " << (str2 != ptr2) << std::endl; + } + catch (const json::parse_error& ex) + { + std::cout << ex.what() << std::endl; + } +} diff --git a/docs/examples/json_pointer__operator__notequal_stringtype.output b/docs/examples/json_pointer__operator__notequal_stringtype.output new file mode 100644 index 000000000..61331b752 --- /dev/null +++ b/docs/examples/json_pointer__operator__notequal_stringtype.output @@ -0,0 +1,4 @@ +"" != "": false +"" != "": false +"/foo" != "/foo": false +"bar" != "/foo": [json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'bar' diff --git a/docs/mkdocs/docs/api/json_pointer/index.md b/docs/mkdocs/docs/api/json_pointer/index.md index 75b536c1c..22e246405 100644 --- a/docs/mkdocs/docs/api/json_pointer/index.md +++ b/docs/mkdocs/docs/api/json_pointer/index.md @@ -29,6 +29,8 @@ are the base for JSON patches. - [(constructor)](json_pointer.md) - [**to_string**](to_string.md) - return a string representation of the JSON pointer - [**operator string_t**](operator_string_t.md) - return a string representation of the JSON pointer +- [**operator==**](operator_eq.md) - compare: equal +- [**operator!=**](operator_ne.md) - compare: not equal - [**operator/=**](operator_slasheq.md) - append to the end of the JSON pointer - [**operator/**](operator_slash.md) - create JSON Pointer by appending - [**parent_pointer**](parent_pointer.md) - returns the parent of this JSON pointer diff --git a/docs/mkdocs/docs/api/json_pointer/operator_eq.md b/docs/mkdocs/docs/api/json_pointer/operator_eq.md new file mode 100644 index 000000000..a877f4b2a --- /dev/null +++ b/docs/mkdocs/docs/api/json_pointer/operator_eq.md @@ -0,0 +1,107 @@ +# nlohmann::json_pointer::operator== + +```cpp +// until C++20 +template +bool operator==( + const json_pointer& lhs, + const json_pointer& rhs) noexcept; // (1) + +template +bool operator==( + const json_pointer& lhs, + const StringType& rhs); // (2) + +template +bool operator==( + const StringType& lhs, + const json_pointer& rhs); // (2) + +// since C++20 +class json_pointer { + template + bool operator==( + const json_pointer& rhs) const noexcept; // (1) + + bool operator==(const string_t& rhs) const; // (2) +}; +``` + +1. Compares two JSON pointers for equality by comparing their reference tokens. + +2. Compares a JSON pointer and a string or a string and a JSON pointer for equality by converting the string to a JSON + pointer and comparing the JSON pointers according to 1. + +## Template parameters + +`RefStringTypeLhs`, `RefStringTypeRhs` +: the string type of the left-hand side or right-hand side JSON pointer, respectively + +`StringType` +: the string type derived from the `json_pointer` operand ([`json_pointer::string_t`](string_t.md)) + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether the values `lhs`/`*this` and `rhs` are equal + +## Exception safety + +1. No-throw guarantee: this function never throws exceptions. +2. Strong exception safety: if an exception occurs, the original value stays intact. + +## Exceptions + +1. (none) +2. The function can throw the following exceptions: + - Throws [parse_error.107](../../home/exceptions.md#jsonexceptionparse_error107) if the given JSON pointer `s` is + nonempty and does not begin with a slash (`/`); see example below. + - Throws [parse_error.108](../../home/exceptions.md#jsonexceptionparse_error108) if a tilde (`~`) in the given JSON + pointer `s` is not followed by `0` (representing `~`) or `1` (representing `/`); see example below. + +## Complexity + +Constant if `lhs` and `rhs` differ in the number of reference tokens, otherwise linear in the number of reference +tokens. + +## Examples + +??? example "Example: (1) Comparing JSON pointers" + + The example demonstrates comparing JSON pointers. + + ```cpp + --8<-- "examples/json_pointer__operator__equal.cpp" + ``` + + Output: + + ``` + --8<-- "examples/json_pointer__operator__equal.output" + ``` + +??? example "Example: (2) Comparing JSON pointers and strings" + + The example demonstrates comparing JSON pointers and strings, and when doing so may raise an exception. + + ```cpp + --8<-- "examples/json_pointer__operator__equal_stringtype.cpp" + ``` + + Output: + + ``` + --8<-- "examples/json_pointer__operator__equal_stringtype.output" + ``` + +## Version history + +1. Added in version 2.1.0. Added C++20 member functions in version 3.11.2. +2. Added in version 3.11.2. diff --git a/docs/mkdocs/docs/api/json_pointer/operator_ne.md b/docs/mkdocs/docs/api/json_pointer/operator_ne.md new file mode 100644 index 000000000..05b09ce45 --- /dev/null +++ b/docs/mkdocs/docs/api/json_pointer/operator_ne.md @@ -0,0 +1,105 @@ +# nlohmann::json_pointer::operator!= + +```cpp +// until C++20 +template +bool operator!=( + const json_pointer& lhs, + const json_pointer& rhs) noexcept; // (1) + +template +bool operator!=( + const json_pointer& lhs, + const StringType& rhs); // (2) + +template +bool operator!=( + const StringType& lhs, + const json_pointer& rhs); // (2) +``` + +1. Compares two JSON pointers for inequality by comparing their reference tokens. + +2. Compares a JSON pointer and a string or a string and a JSON pointer for inequality by converting the string to a + JSON pointer and comparing the JSON pointers according to 1. + +## Template parameters + +`RefStringTypeLhs`, `RefStringTypeRhs` +: the string type of the left-hand side or right-hand side JSON pointer, respectively + +`StringType` +: the string type derived from the `json_pointer` operand ([`json_pointer::string_t`](string_t.md)) + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether the values `lhs`/`*this` and `rhs` are not equal + +## Exception safety + +1. No-throw guarantee: this function never throws exceptions. +2. Strong exception safety: if an exception occurs, the original value stays intact. + +## Exceptions + +1. (none) +2. The function can throw the following exceptions: + - Throws [parse_error.107](../../home/exceptions.md#jsonexceptionparse_error107) if the given JSON pointer `s` is + nonempty and does not begin with a slash (`/`); see example below. + - Throws [parse_error.108](../../home/exceptions.md#jsonexceptionparse_error108) if a tilde (`~`) in the given JSON + pointer `s` is not followed by `0` (representing `~`) or `1` (representing `/`); see example below. + +## Complexity + +Constant if `lhs` and `rhs` differ in the number of reference tokens, otherwise linear in the number of reference +tokens. + +## Notes + +!!! note "Operator overload resolution" + + Since C++20 overload resolution will consider the _rewritten candidate_ generated from + [`operator==`](operator_eq.md). + +## Examples + +??? example "Example: (1) Comparing JSON pointers" + + The example demonstrates comparing JSON pointers. + + ```cpp + --8<-- "examples/json_pointer__operator__notequal.cpp" + ``` + + Output: + + ``` + --8<-- "examples/json_pointer__operator__notequal.output" + ``` + +??? example "Example: (2) Comparing JSON pointers and strings" + + The example demonstrates comparing JSON pointers and strings, and when doing so may raise an exception. + + ```cpp + --8<-- "examples/json_pointer__operator__notequal_stringtype.cpp" + ``` + + Output: + + ``` + --8<-- "examples/json_pointer__operator__notequal_stringtype.output" + ``` + +## Version history + +1. Added in version 2.1.0. +2. Added in version 3.11.2. diff --git a/docs/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml index 65182adbf..f88784f3e 100644 --- a/docs/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -209,6 +209,8 @@ nav: - 'back': api/json_pointer/back.md - 'empty': api/json_pointer/empty.md - 'operator string_t': api/json_pointer/operator_string_t.md + - 'operator==': api/json_pointer/operator_eq.md + - 'operator!=': api/json_pointer/operator_ne.md - 'operator/': api/json_pointer/operator_slash.md - 'operator/=': api/json_pointer/operator_slasheq.md - 'parent_pointer': api/json_pointer/parent_pointer.md diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 5b7632676..28de45028 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -846,55 +846,118 @@ class json_pointer return result; } - /*! - @brief compares two JSON pointers for equality + public: +#ifdef JSON_HAS_CPP_20 + /// @brief compares two JSON pointers for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + bool operator==(const json_pointer& rhs) const noexcept + { + return reference_tokens == rhs.reference_tokens; + } - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is equal to @a rhs - - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ + /// @brief compares JSON pointer and string for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + bool operator==(const string_t& rhs) const + { + return *this == json_pointer(rhs); + } +#else + /// @brief compares two JSON pointers for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept; + friend bool operator==(const json_pointer& lhs, + const json_pointer& rhs) noexcept; - /*! - @brief compares two JSON pointers for inequality + /// @brief compares JSON pointer and string for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(const json_pointer& lhs, + const StringType& rhs); - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is not equal @a rhs + /// @brief compares string and JSON pointer for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(const StringType& lhs, + const json_pointer& rhs); - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ + /// @brief compares two JSON pointers for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept; + friend bool operator!=(const json_pointer& lhs, + const json_pointer& rhs) noexcept; + /// @brief compares JSON pointer and string for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const json_pointer& lhs, + const StringType& rhs); + + /// @brief compares string and JSON pointer for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const StringType& lhs, + const json_pointer& rhs); +#endif + + private: /// the reference tokens std::vector reference_tokens; }; +#ifndef JSON_HAS_CPP_20 // functions cannot be defined inside class due to ODR violations template -inline bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept +inline bool operator==(const json_pointer& lhs, + const json_pointer& rhs) noexcept { return lhs.reference_tokens == rhs.reference_tokens; } +template::string_t> +inline bool operator==(const json_pointer& lhs, + const StringType& rhs) +{ + return lhs == json_pointer(rhs); +} + +template::string_t> +inline bool operator==(const StringType& lhs, + const json_pointer& rhs) +{ + return json_pointer(lhs) == rhs; +} + template -inline bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept +inline bool operator!=(const json_pointer& lhs, + const json_pointer& rhs) noexcept { return !(lhs == rhs); } +template::string_t> +inline bool operator!=(const json_pointer& lhs, + const StringType& rhs) +{ + return !(lhs == rhs); +} + +template::string_t> +inline bool operator!=(const StringType& lhs, + const json_pointer& rhs) +{ + return !(lhs == rhs); +} +#endif + NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/json_fwd.hpp b/include/nlohmann/json_fwd.hpp index c7ad23660..be197359c 100644 --- a/include/nlohmann/json_fwd.hpp +++ b/include/nlohmann/json_fwd.hpp @@ -51,7 +51,7 @@ class basic_json; /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document /// @sa https://json.nlohmann.me/api/json_pointer/ -template +template class json_pointer; /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 4d86493e1..beee0136c 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -3373,7 +3373,7 @@ NLOHMANN_JSON_NAMESPACE_END /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document /// @sa https://json.nlohmann.me/api/json_pointer/ - template + template class json_pointer; /*! @@ -14448,57 +14448,120 @@ class json_pointer return result; } - /*! - @brief compares two JSON pointers for equality + public: +#ifdef JSON_HAS_CPP_20 + /// @brief compares two JSON pointers for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + bool operator==(const json_pointer& rhs) const noexcept + { + return reference_tokens == rhs.reference_tokens; + } - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is equal to @a rhs - - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ + /// @brief compares JSON pointer and string for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + bool operator==(const string_t& rhs) const + { + return *this == json_pointer(rhs); + } +#else + /// @brief compares two JSON pointers for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept; + friend bool operator==(const json_pointer& lhs, + const json_pointer& rhs) noexcept; - /*! - @brief compares two JSON pointers for inequality + /// @brief compares JSON pointer and string for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(const json_pointer& lhs, + const StringType& rhs); - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is not equal @a rhs + /// @brief compares string and JSON pointer for equality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(const StringType& lhs, + const json_pointer& rhs); - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ + /// @brief compares two JSON pointers for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept; + friend bool operator!=(const json_pointer& lhs, + const json_pointer& rhs) noexcept; + /// @brief compares JSON pointer and string for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const json_pointer& lhs, + const StringType& rhs); + + /// @brief compares string and JSON pointer for inequality + /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(const StringType& lhs, + const json_pointer& rhs); +#endif + + private: /// the reference tokens std::vector reference_tokens; }; +#ifndef JSON_HAS_CPP_20 // functions cannot be defined inside class due to ODR violations template -inline bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept +inline bool operator==(const json_pointer& lhs, + const json_pointer& rhs) noexcept { return lhs.reference_tokens == rhs.reference_tokens; } +template::string_t> +inline bool operator==(const json_pointer& lhs, + const StringType& rhs) +{ + return lhs == json_pointer(rhs); +} + +template::string_t> +inline bool operator==(const StringType& lhs, + const json_pointer& rhs) +{ + return json_pointer(lhs) == rhs; +} + template -inline bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept +inline bool operator!=(const json_pointer& lhs, + const json_pointer& rhs) noexcept { return !(lhs == rhs); } +template::string_t> +inline bool operator!=(const json_pointer& lhs, + const StringType& rhs) +{ + return !(lhs == rhs); +} + +template::string_t> +inline bool operator!=(const StringType& lhs, + const json_pointer& rhs) +{ + return !(lhs == rhs); +} +#endif + NLOHMANN_JSON_NAMESPACE_END // #include diff --git a/tests/src/unit-json_pointer.cpp b/tests/src/unit-json_pointer.cpp index 93559eb31..f6e2b00c0 100644 --- a/tests/src/unit-json_pointer.cpp +++ b/tests/src/unit-json_pointer.cpp @@ -651,11 +651,50 @@ TEST_CASE("JSON pointers") SECTION("equality comparison") { - auto ptr1 = json::json_pointer("/foo/bar"); - auto ptr2 = json::json_pointer("/foo/bar"); + const char* ptr_cpstring = "/foo/bar"; + const char ptr_castring[] = "/foo/bar"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays) + std::string ptr_string{"/foo/bar"}; + auto ptr1 = json::json_pointer(ptr_string); + auto ptr2 = json::json_pointer(ptr_string); + + // build with C++20 to test rewritten candidates + // JSON_HAS_CPP_20 CHECK(ptr1 == ptr2); + + CHECK(ptr1 == "/foo/bar"); + CHECK(ptr1 == ptr_cpstring); + CHECK(ptr1 == ptr_castring); + CHECK(ptr1 == ptr_string); + + CHECK("/foo/bar" == ptr1); + CHECK(ptr_cpstring == ptr1); + CHECK(ptr_castring == ptr1); + CHECK(ptr_string == ptr1); + CHECK_FALSE(ptr1 != ptr2); + + CHECK_FALSE(ptr1 != "/foo/bar"); + CHECK_FALSE(ptr1 != ptr_cpstring); + CHECK_FALSE(ptr1 != ptr_castring); + CHECK_FALSE(ptr1 != ptr_string); + + CHECK_FALSE("/foo/bar" != ptr1); + CHECK_FALSE(ptr_cpstring != ptr1); + CHECK_FALSE(ptr_castring != ptr1); + CHECK_FALSE(ptr_string != ptr1); + + SECTION("exceptions") + { + CHECK_THROWS_WITH_AS(ptr1 == "foo", + "[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo'", json::parse_error&); + CHECK_THROWS_WITH_AS("foo" == ptr1, + "[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo'", json::parse_error&); + CHECK_THROWS_WITH_AS(ptr1 == "/~~", + "[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'", json::parse_error&); + CHECK_THROWS_WITH_AS("/~~" == ptr1, + "[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'", json::parse_error&); + } } SECTION("backwards compatibility and mixing") @@ -676,9 +715,10 @@ TEST_CASE("JSON pointers") CHECK(std::is_same::value); CHECK(std::is_same::value); - json_ptr_str ptr{"/foo/0"}; - json_ptr_j ptr_j{"/foo/0"}; - json_ptr_oj ptr_oj{"/foo/0"}; + std::string ptr_string{"/foo/0"}; + json_ptr_str ptr{ptr_string}; + json_ptr_j ptr_j{ptr_string}; + json_ptr_oj ptr_oj{ptr_string}; CHECK(j.contains(ptr)); CHECK(j.contains(ptr_j)); @@ -697,5 +737,25 @@ TEST_CASE("JSON pointers") CHECK(ptr == ptr_oj); CHECK_FALSE(ptr != ptr_j); CHECK_FALSE(ptr != ptr_oj); + + SECTION("equality comparison") + { + // build with C++20 to test rewritten candidates + // JSON_HAS_CPP_20 + + CHECK(ptr == ptr_j); + CHECK(ptr == ptr_oj); + CHECK(ptr_j == ptr); + CHECK(ptr_j == ptr_oj); + CHECK(ptr_oj == ptr_j); + CHECK(ptr_oj == ptr); + + CHECK_FALSE(ptr != ptr_j); + CHECK_FALSE(ptr != ptr_oj); + CHECK_FALSE(ptr_j != ptr); + CHECK_FALSE(ptr_j != ptr_oj); + CHECK_FALSE(ptr_oj != ptr_j); + CHECK_FALSE(ptr_oj != ptr); + } } }