Просмотр исходного кода

Added DeserializationError::EmptyInput

Benoit Blanchon 5 лет назад
Родитель
Сommit
c907ca6e5d

+ 1 - 0
CHANGELOG.md

@@ -6,6 +6,7 @@ HEAD
 
 * Added a build failure when nullptr is defined as a macro (issue #1355)
 * Added `JsonDocument::overflowed()` which tells if the memory pool was too small (issue #1358)
+* Added `DeserializationError::EmptyInput` which tells if the input was empty
 * Fixed `JsonVariant::set((char*)0)` which returned false instead of true (issue #1368)
 
 v6.16.1 (2020-08-04)

+ 8 - 13
extras/tests/JsonDeserializer/DeserializationError.cpp

@@ -30,20 +30,22 @@ void testBoolification(DeserializationError error, bool expected) {
 TEST_CASE("DeserializationError") {
   SECTION("c_str()") {
     TEST_STRINGIFICATION(Ok);
-    TEST_STRINGIFICATION(TooDeep);
-    TEST_STRINGIFICATION(NoMemory);
-    TEST_STRINGIFICATION(InvalidInput);
+    TEST_STRINGIFICATION(EmptyInput);
     TEST_STRINGIFICATION(IncompleteInput);
+    TEST_STRINGIFICATION(InvalidInput);
+    TEST_STRINGIFICATION(NoMemory);
     TEST_STRINGIFICATION(NotSupported);
+    TEST_STRINGIFICATION(TooDeep);
   }
 
   SECTION("as boolean") {
     TEST_BOOLIFICATION(Ok, false);
-    TEST_BOOLIFICATION(TooDeep, true);
-    TEST_BOOLIFICATION(NoMemory, true);
-    TEST_BOOLIFICATION(InvalidInput, true);
+    TEST_BOOLIFICATION(EmptyInput, true);
     TEST_BOOLIFICATION(IncompleteInput, true);
+    TEST_BOOLIFICATION(InvalidInput, true);
+    TEST_BOOLIFICATION(NoMemory, true);
     TEST_BOOLIFICATION(NotSupported, true);
+    TEST_BOOLIFICATION(TooDeep, true);
   }
 
   SECTION("ostream DeserializationError") {
@@ -58,13 +60,6 @@ TEST_CASE("DeserializationError") {
     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()) {

+ 7 - 1
extras/tests/JsonDeserializer/misc.cpp

@@ -27,7 +27,13 @@ TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
     SECTION("Empty input") {
       DeserializationError err = deserializeJson(doc, "");
 
-      REQUIRE(err == DeserializationError::IncompleteInput);
+      REQUIRE(err == DeserializationError::EmptyInput);
+    }
+
+    SECTION("Only spaces") {
+      DeserializationError err = deserializeJson(doc, "  \t\n\r");
+
+      REQUIRE(err == DeserializationError::EmptyInput);
     }
 
     SECTION("issue #628") {

+ 8 - 2
extras/tests/MixedConfiguration/enable_comments_1.cpp

@@ -373,16 +373,22 @@ TEST_CASE("Comments in objects") {
 TEST_CASE("Comments alone") {
   DynamicJsonDocument doc(2048);
 
-  SECTION("Just a trailing comment") {
+  SECTION("Just a trailing comment with no line break") {
     DeserializationError err = deserializeJson(doc, "// comment");
 
     REQUIRE(err == DeserializationError::IncompleteInput);
   }
 
+  SECTION("Just a trailing comment with no a break") {
+    DeserializationError err = deserializeJson(doc, "// comment\n");
+
+    REQUIRE(err == DeserializationError::EmptyInput);
+  }
+
   SECTION("Just a block comment") {
     DeserializationError err = deserializeJson(doc, "/*comment*/");
 
-    REQUIRE(err == DeserializationError::IncompleteInput);
+    REQUIRE(err == DeserializationError::EmptyInput);
   }
 
   SECTION("Just a slash") {

+ 1 - 0
extras/tests/MsgPackDeserializer/CMakeLists.txt

@@ -10,6 +10,7 @@ add_executable(MsgPackDeserializerTests
 	doubleToFloat.cpp
 	incompleteInput.cpp
 	input_types.cpp
+	misc.cpp
 	nestingLimit.cpp
 	notSupported.cpp
 )

+ 24 - 0
extras/tests/MsgPackDeserializer/misc.cpp

@@ -0,0 +1,24 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2020
+// MIT License
+
+#include <ArduinoJson.h>
+#include <catch.hpp>
+
+TEST_CASE("deserializeMsgPack() returns EmptyInput") {
+  StaticJsonDocument<100> doc;
+
+  SECTION("from sized buffer") {
+    DeserializationError err = deserializeMsgPack(doc, "", 0);
+
+    REQUIRE(err == DeserializationError::EmptyInput);
+  }
+
+  SECTION("from stream") {
+    std::istringstream input("");
+
+    DeserializationError err = deserializeMsgPack(doc, input);
+
+    REQUIRE(err == DeserializationError::EmptyInput);
+  }
+}

+ 7 - 16
src/ArduinoJson/Deserialization/DeserializationError.hpp

@@ -20,6 +20,7 @@ class DeserializationError {
  public:
   enum Code {
     Ok,
+    EmptyInput,
     IncompleteInput,
     InvalidInput,
     NoMemory,
@@ -77,22 +78,12 @@ class DeserializationError {
   }
 
   const char* c_str() const {
-    switch (_code) {
-      case Ok:
-        return "Ok";
-      case TooDeep:
-        return "TooDeep";
-      case NoMemory:
-        return "NoMemory";
-      case InvalidInput:
-        return "InvalidInput";
-      case IncompleteInput:
-        return "IncompleteInput";
-      case NotSupported:
-        return "NotSupported";
-      default:
-        return "???";
-    }
+    static const char* messages[] = {
+        "Ok",       "EmptyInput",   "IncompleteInput", "InvalidInput",
+        "NoMemory", "NotSupported", "TooDeep"};
+    ARDUINOJSON_ASSERT(static_cast<size_t>(_code) <
+                       sizeof(messages) / sizeof(messages[0]));
+    return messages[_code];
   }
 
  private:

+ 6 - 2
src/ArduinoJson/Json/JsonDeserializer.hpp

@@ -23,6 +23,7 @@ class JsonDeserializer {
   JsonDeserializer(MemoryPool &pool, TReader reader,
                    TStringStorage stringStorage)
       : _stringStorage(stringStorage),
+        _foundSomething(false),
         _latch(reader),
         _pool(&pool),
         _error(DeserializationError::Ok) {}
@@ -34,7 +35,7 @@ class JsonDeserializer {
 
     if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
       // We don't detect trailing characters earlier, so we need to check now
-      _error = DeserializationError::InvalidInput;
+      return DeserializationError::InvalidInput;
     }
 
     return _error;
@@ -559,7 +560,8 @@ class JsonDeserializer {
       switch (current()) {
         // end of string
         case '\0':
-          _error = DeserializationError::IncompleteInput;
+          _error = _foundSomething ? DeserializationError::IncompleteInput
+                                   : DeserializationError::EmptyInput;
           return false;
 
         // spaces
@@ -619,12 +621,14 @@ class JsonDeserializer {
 #endif
 
         default:
+          _foundSomething = true;
           return true;
       }
     }
   }
 
   TStringStorage _stringStorage;
+  bool _foundSomething;
   Latch<TReader> _latch;
   MemoryPool *_pool;
   char _buffer[64];  // using a member instead of a local variable because it

+ 7 - 5
src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp

@@ -21,22 +21,23 @@ class MsgPackDeserializer {
       : _pool(&pool),
         _reader(reader),
         _stringStorage(stringStorage),
-        _error(DeserializationError::Ok) {}
+        _error(DeserializationError::Ok),
+        _foundSomething(false) {}
 
   // TODO: add support for filter
   DeserializationError parse(VariantData &variant, AllowAllFilter,
                              NestingLimit nestingLimit) {
     parseVariant(variant, nestingLimit);
-    return _error;
+    return _foundSomething ? _error : DeserializationError::EmptyInput;
   }
 
  private:
   bool parseVariant(VariantData &variant, NestingLimit nestingLimit) {
     uint8_t code;
-    if (!readByte(code)) {
-      _error = DeserializationError::IncompleteInput;
+    if (!readByte(code))
       return false;
-    }
+
+    _foundSomething = true;
 
     if ((code & 0x80) == 0) {
       variant.setUnsignedInteger(code);
@@ -345,6 +346,7 @@ class MsgPackDeserializer {
   TReader _reader;
   TStringStorage _stringStorage;
   DeserializationError _error;
+  bool _foundSomething;
 };
 
 template <typename TInput>