diff --git a/CHANGELOG.md b/CHANGELOG.md index 2656ba8a..34627dc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ HEAD * Replaced `T JsonArray::get(i)` with `JsonVariant JsonArray::get(i)` * Replaced `T JsonObject::get(k)` with `JsonVariant JsonObject::get(k)` * Added `JSON_STRING_SIZE()` -* Replacing or removing a value now releases the memory. +* Replacing or removing a value now releases the memory +* Added `DeserializationError::code()` to be used in switch statements (issue #846) v6.5.0-beta (2018-10-13) ----------- diff --git a/src/ArduinoJson/Deserialization/DeserializationError.hpp b/src/ArduinoJson/Deserialization/DeserializationError.hpp index 92a868b6..0bfce9ee 100644 --- a/src/ArduinoJson/Deserialization/DeserializationError.hpp +++ b/src/ArduinoJson/Deserialization/DeserializationError.hpp @@ -11,6 +11,10 @@ namespace ARDUINOJSON_NAMESPACE { class DeserializationError { + // safe bool idiom + typedef void (DeserializationError::*bool_type)() const; + void safeBoolHelper() const {} + public: enum Code { Ok, @@ -22,26 +26,52 @@ class DeserializationError { }; DeserializationError() {} - DeserializationError(Code code) : _code(code) {} + DeserializationError(Code c) : _code(c) {} - friend bool operator==(const DeserializationError& err, Code code) { - return err._code == code; + // Compare with DeserializationError + friend bool operator==(const DeserializationError& lhs, + const DeserializationError& rhs) { + return lhs._code == rhs._code; + } + friend bool operator!=(const DeserializationError& lhs, + const DeserializationError& rhs) { + return lhs._code != rhs._code; } - friend bool operator==(Code code, const DeserializationError& err) { - return err._code == code; + // Compare with Code + friend bool operator==(const DeserializationError& lhs, Code rhs) { + return lhs._code == rhs; + } + friend bool operator==(Code lhs, const DeserializationError& rhs) { + return lhs == rhs._code; + } + friend bool operator!=(const DeserializationError& lhs, Code rhs) { + return lhs._code != rhs; + } + friend bool operator!=(Code lhs, const DeserializationError& rhs) { + return lhs != rhs._code; } - friend bool operator!=(const DeserializationError& err, Code code) { - return err._code != code; + // Behaves like a bool + operator bool_type() const { + return _code != Ok ? &DeserializationError::safeBoolHelper : 0; + } + friend bool operator==(bool value, const DeserializationError& err) { + return static_cast(err) == value; + } + friend bool operator==(const DeserializationError& err, bool value) { + return static_cast(err) == value; + } + friend bool operator!=(bool value, const DeserializationError& err) { + return static_cast(err) != value; + } + friend bool operator!=(const DeserializationError& err, bool value) { + return static_cast(err) != value; } - friend bool operator!=(Code code, const DeserializationError& err) { - return err._code != code; - } - - operator bool() const { - return _code != Ok; + // Returns internal enum, useful for switch statement + Code code() const { + return _code; } const char* c_str() const { diff --git a/test/JsonDeserializer/DeserializationError.cpp b/test/JsonDeserializer/DeserializationError.cpp index f455f629..2ef451b1 100644 --- a/test/JsonDeserializer/DeserializationError.cpp +++ b/test/JsonDeserializer/DeserializationError.cpp @@ -10,7 +10,15 @@ void testStringification(DeserializationError error, std::string expected) { } void testBoolification(DeserializationError error, bool expected) { + // DeserializationError on left-hand side CHECK(error == expected); + CHECK(error != !expected); + CHECK(!error == !expected); + + // DeserializationError on right-hand side + CHECK(expected == error); + CHECK(!expected != error); + CHECK(!expected == !error); } #define TEST_STRINGIFICATION(symbol) \ @@ -38,15 +46,92 @@ TEST_CASE("DeserializationError") { TEST_BOOLIFICATION(NotSupported, true); } - SECTION("ostream code") { + SECTION("ostream DeserializationError") { std::stringstream s; s << DeserializationError(DeserializationError::InvalidInput); REQUIRE(s.str() == "InvalidInput"); } - SECTION("ostream code") { + SECTION("ostream DeserializationError::Code") { std::stringstream s; s << DeserializationError::InvalidInput; REQUIRE(s.str() == "InvalidInput"); } + + SECTION("out of range") { + int code = 666; + DeserializationError err( + *reinterpret_cast(&code)); + REQUIRE(err.c_str() == std::string("???")); + } + + SECTION("switch") { + DeserializationError err = DeserializationError::InvalidInput; + switch (err.code()) { + case DeserializationError::InvalidInput: + SUCCEED(); + break; + default: + FAIL(); + break; + } + } + + SECTION("Comparisons") { + DeserializationError invalidInput(DeserializationError::InvalidInput); + DeserializationError ok(DeserializationError::Ok); + + SECTION("DeserializationError == bool") { + REQUIRE(invalidInput == true); + REQUIRE(ok == false); + } + + SECTION("bool == DeserializationError") { + REQUIRE(true == invalidInput); + REQUIRE(false == ok); + } + + SECTION("DeserializationError != bool") { + REQUIRE(invalidInput != false); + REQUIRE(ok != true); + } + + SECTION("bool != DeserializationError") { + REQUIRE(false != invalidInput); + REQUIRE(true != ok); + } + + SECTION("Negations") { + REQUIRE(!invalidInput == false); + REQUIRE(!ok == true); + } + + SECTION("DeserializationError == Code") { + REQUIRE(invalidInput == DeserializationError::InvalidInput); + REQUIRE(ok == DeserializationError::Ok); + } + + SECTION("Code == DeserializationError") { + REQUIRE(DeserializationError::InvalidInput == invalidInput); + REQUIRE(DeserializationError::Ok == ok); + } + + SECTION("DeserializationError != Code") { + REQUIRE(invalidInput != DeserializationError::Ok); + REQUIRE(ok != DeserializationError::InvalidInput); + } + + SECTION("Code != DeserializationError") { + REQUIRE(DeserializationError::Ok != invalidInput); + REQUIRE(DeserializationError::InvalidInput != ok); + } + + SECTION("DeserializationError == DeserializationError") { + REQUIRE_FALSE(invalidInput == ok); + } + + SECTION("DeserializationError != DeserializationError") { + REQUIRE(invalidInput != ok); + } + } }