فهرست منبع

Added `DeserializationError::code()` to be used in switch statements (closes #846)

Benoit Blanchon 7 سال پیش
والد
کامیت
0a97d4c825
3فایلهای تغییر یافته به همراه131 افزوده شده و 15 حذف شده
  1. 2 1
      CHANGELOG.md
  2. 42 12
      src/ArduinoJson/Deserialization/DeserializationError.hpp
  3. 87 2
      test/JsonDeserializer/DeserializationError.cpp

+ 2 - 1
CHANGELOG.md

@@ -9,7 +9,8 @@ HEAD
 * Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)`
 * Replaced `T JsonObject::get<T>(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)
 -----------

+ 42 - 12
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==(Code code, const DeserializationError& err) {
-    return err._code == code;
+  friend bool operator!=(const DeserializationError& lhs,
+                         const DeserializationError& rhs) {
+    return lhs._code != rhs._code;
   }
 
-  friend bool operator!=(const DeserializationError& err, Code code) {
-    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!=(Code code, const DeserializationError& err) {
-    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<bool>(err) == value;
+  }
+  friend bool operator==(const DeserializationError& err, bool value) {
+    return static_cast<bool>(err) == value;
+  }
+  friend bool operator!=(bool value, const DeserializationError& err) {
+    return static_cast<bool>(err) != value;
+  }
+  friend bool operator!=(const DeserializationError& err, bool value) {
+    return static_cast<bool>(err) != value;
   }
 
-  operator bool() const {
-    return _code != Ok;
+  // Returns internal enum, useful for switch statement
+  Code code() const {
+    return _code;
   }
 
   const char* c_str() const {

+ 87 - 2
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<DeserializationError::Code*>(&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);
+    }
+  }
 }