forked from bblanchon/ArduinoJson
Added DeserializationError::EmptyInput
This commit is contained in:
@ -6,6 +6,7 @@ HEAD
|
|||||||
|
|
||||||
* Added a build failure when nullptr is defined as a macro (issue #1355)
|
* 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 `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)
|
* Fixed `JsonVariant::set((char*)0)` which returned false instead of true (issue #1368)
|
||||||
|
|
||||||
v6.16.1 (2020-08-04)
|
v6.16.1 (2020-08-04)
|
||||||
|
@ -30,20 +30,22 @@ void testBoolification(DeserializationError error, bool expected) {
|
|||||||
TEST_CASE("DeserializationError") {
|
TEST_CASE("DeserializationError") {
|
||||||
SECTION("c_str()") {
|
SECTION("c_str()") {
|
||||||
TEST_STRINGIFICATION(Ok);
|
TEST_STRINGIFICATION(Ok);
|
||||||
TEST_STRINGIFICATION(TooDeep);
|
TEST_STRINGIFICATION(EmptyInput);
|
||||||
TEST_STRINGIFICATION(NoMemory);
|
|
||||||
TEST_STRINGIFICATION(InvalidInput);
|
|
||||||
TEST_STRINGIFICATION(IncompleteInput);
|
TEST_STRINGIFICATION(IncompleteInput);
|
||||||
|
TEST_STRINGIFICATION(InvalidInput);
|
||||||
|
TEST_STRINGIFICATION(NoMemory);
|
||||||
TEST_STRINGIFICATION(NotSupported);
|
TEST_STRINGIFICATION(NotSupported);
|
||||||
|
TEST_STRINGIFICATION(TooDeep);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("as boolean") {
|
SECTION("as boolean") {
|
||||||
TEST_BOOLIFICATION(Ok, false);
|
TEST_BOOLIFICATION(Ok, false);
|
||||||
TEST_BOOLIFICATION(TooDeep, true);
|
TEST_BOOLIFICATION(EmptyInput, true);
|
||||||
TEST_BOOLIFICATION(NoMemory, true);
|
|
||||||
TEST_BOOLIFICATION(InvalidInput, true);
|
|
||||||
TEST_BOOLIFICATION(IncompleteInput, true);
|
TEST_BOOLIFICATION(IncompleteInput, true);
|
||||||
|
TEST_BOOLIFICATION(InvalidInput, true);
|
||||||
|
TEST_BOOLIFICATION(NoMemory, true);
|
||||||
TEST_BOOLIFICATION(NotSupported, true);
|
TEST_BOOLIFICATION(NotSupported, true);
|
||||||
|
TEST_BOOLIFICATION(TooDeep, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("ostream DeserializationError") {
|
SECTION("ostream DeserializationError") {
|
||||||
@ -58,13 +60,6 @@ TEST_CASE("DeserializationError") {
|
|||||||
REQUIRE(s.str() == "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") {
|
SECTION("switch") {
|
||||||
DeserializationError err = DeserializationError::InvalidInput;
|
DeserializationError err = DeserializationError::InvalidInput;
|
||||||
switch (err.code()) {
|
switch (err.code()) {
|
||||||
|
@ -27,7 +27,13 @@ TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
|
|||||||
SECTION("Empty input") {
|
SECTION("Empty input") {
|
||||||
DeserializationError err = deserializeJson(doc, "");
|
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") {
|
SECTION("issue #628") {
|
||||||
|
@ -373,16 +373,22 @@ TEST_CASE("Comments in objects") {
|
|||||||
TEST_CASE("Comments alone") {
|
TEST_CASE("Comments alone") {
|
||||||
DynamicJsonDocument doc(2048);
|
DynamicJsonDocument doc(2048);
|
||||||
|
|
||||||
SECTION("Just a trailing comment") {
|
SECTION("Just a trailing comment with no line break") {
|
||||||
DeserializationError err = deserializeJson(doc, "// comment");
|
DeserializationError err = deserializeJson(doc, "// comment");
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
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") {
|
SECTION("Just a block comment") {
|
||||||
DeserializationError err = deserializeJson(doc, "/*comment*/");
|
DeserializationError err = deserializeJson(doc, "/*comment*/");
|
||||||
|
|
||||||
REQUIRE(err == DeserializationError::IncompleteInput);
|
REQUIRE(err == DeserializationError::EmptyInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Just a slash") {
|
SECTION("Just a slash") {
|
||||||
|
@ -10,6 +10,7 @@ add_executable(MsgPackDeserializerTests
|
|||||||
doubleToFloat.cpp
|
doubleToFloat.cpp
|
||||||
incompleteInput.cpp
|
incompleteInput.cpp
|
||||||
input_types.cpp
|
input_types.cpp
|
||||||
|
misc.cpp
|
||||||
nestingLimit.cpp
|
nestingLimit.cpp
|
||||||
notSupported.cpp
|
notSupported.cpp
|
||||||
)
|
)
|
||||||
|
24
extras/tests/MsgPackDeserializer/misc.cpp
Normal file
24
extras/tests/MsgPackDeserializer/misc.cpp
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ class DeserializationError {
|
|||||||
public:
|
public:
|
||||||
enum Code {
|
enum Code {
|
||||||
Ok,
|
Ok,
|
||||||
|
EmptyInput,
|
||||||
IncompleteInput,
|
IncompleteInput,
|
||||||
InvalidInput,
|
InvalidInput,
|
||||||
NoMemory,
|
NoMemory,
|
||||||
@ -77,22 +78,12 @@ class DeserializationError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char* c_str() const {
|
const char* c_str() const {
|
||||||
switch (_code) {
|
static const char* messages[] = {
|
||||||
case Ok:
|
"Ok", "EmptyInput", "IncompleteInput", "InvalidInput",
|
||||||
return "Ok";
|
"NoMemory", "NotSupported", "TooDeep"};
|
||||||
case TooDeep:
|
ARDUINOJSON_ASSERT(static_cast<size_t>(_code) <
|
||||||
return "TooDeep";
|
sizeof(messages) / sizeof(messages[0]));
|
||||||
case NoMemory:
|
return messages[_code];
|
||||||
return "NoMemory";
|
|
||||||
case InvalidInput:
|
|
||||||
return "InvalidInput";
|
|
||||||
case IncompleteInput:
|
|
||||||
return "IncompleteInput";
|
|
||||||
case NotSupported:
|
|
||||||
return "NotSupported";
|
|
||||||
default:
|
|
||||||
return "???";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -23,6 +23,7 @@ class JsonDeserializer {
|
|||||||
JsonDeserializer(MemoryPool &pool, TReader reader,
|
JsonDeserializer(MemoryPool &pool, TReader reader,
|
||||||
TStringStorage stringStorage)
|
TStringStorage stringStorage)
|
||||||
: _stringStorage(stringStorage),
|
: _stringStorage(stringStorage),
|
||||||
|
_foundSomething(false),
|
||||||
_latch(reader),
|
_latch(reader),
|
||||||
_pool(&pool),
|
_pool(&pool),
|
||||||
_error(DeserializationError::Ok) {}
|
_error(DeserializationError::Ok) {}
|
||||||
@ -34,7 +35,7 @@ class JsonDeserializer {
|
|||||||
|
|
||||||
if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
|
if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
|
||||||
// We don't detect trailing characters earlier, so we need to check now
|
// We don't detect trailing characters earlier, so we need to check now
|
||||||
_error = DeserializationError::InvalidInput;
|
return DeserializationError::InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _error;
|
return _error;
|
||||||
@ -559,7 +560,8 @@ class JsonDeserializer {
|
|||||||
switch (current()) {
|
switch (current()) {
|
||||||
// end of string
|
// end of string
|
||||||
case '\0':
|
case '\0':
|
||||||
_error = DeserializationError::IncompleteInput;
|
_error = _foundSomething ? DeserializationError::IncompleteInput
|
||||||
|
: DeserializationError::EmptyInput;
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// spaces
|
// spaces
|
||||||
@ -619,12 +621,14 @@ class JsonDeserializer {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
_foundSomething = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TStringStorage _stringStorage;
|
TStringStorage _stringStorage;
|
||||||
|
bool _foundSomething;
|
||||||
Latch<TReader> _latch;
|
Latch<TReader> _latch;
|
||||||
MemoryPool *_pool;
|
MemoryPool *_pool;
|
||||||
char _buffer[64]; // using a member instead of a local variable because it
|
char _buffer[64]; // using a member instead of a local variable because it
|
||||||
|
@ -21,22 +21,23 @@ class MsgPackDeserializer {
|
|||||||
: _pool(&pool),
|
: _pool(&pool),
|
||||||
_reader(reader),
|
_reader(reader),
|
||||||
_stringStorage(stringStorage),
|
_stringStorage(stringStorage),
|
||||||
_error(DeserializationError::Ok) {}
|
_error(DeserializationError::Ok),
|
||||||
|
_foundSomething(false) {}
|
||||||
|
|
||||||
// TODO: add support for filter
|
// TODO: add support for filter
|
||||||
DeserializationError parse(VariantData &variant, AllowAllFilter,
|
DeserializationError parse(VariantData &variant, AllowAllFilter,
|
||||||
NestingLimit nestingLimit) {
|
NestingLimit nestingLimit) {
|
||||||
parseVariant(variant, nestingLimit);
|
parseVariant(variant, nestingLimit);
|
||||||
return _error;
|
return _foundSomething ? _error : DeserializationError::EmptyInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool parseVariant(VariantData &variant, NestingLimit nestingLimit) {
|
bool parseVariant(VariantData &variant, NestingLimit nestingLimit) {
|
||||||
uint8_t code;
|
uint8_t code;
|
||||||
if (!readByte(code)) {
|
if (!readByte(code))
|
||||||
_error = DeserializationError::IncompleteInput;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
_foundSomething = true;
|
||||||
|
|
||||||
if ((code & 0x80) == 0) {
|
if ((code & 0x80) == 0) {
|
||||||
variant.setUnsignedInteger(code);
|
variant.setUnsignedInteger(code);
|
||||||
@ -345,6 +346,7 @@ class MsgPackDeserializer {
|
|||||||
TReader _reader;
|
TReader _reader;
|
||||||
TStringStorage _stringStorage;
|
TStringStorage _stringStorage;
|
||||||
DeserializationError _error;
|
DeserializationError _error;
|
||||||
|
bool _foundSomething;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TInput>
|
template <typename TInput>
|
||||||
|
Reference in New Issue
Block a user