Merged MsgPackError and JsonError into DeserializationError.

Return NotSupported if the JSON input contains "\u".
This commit is contained in:
Benoit Blanchon
2018-05-15 18:23:09 +02:00
parent ccb54136a2
commit 4592f23260
38 changed files with 574 additions and 636 deletions

View File

@ -10,25 +10,33 @@
namespace ArduinoJson {
class JsonError {
class DeserializationError {
public:
enum Code { Ok, TooDeep, NoMemory, InvalidInput, IncompleteInput };
enum Code {
Ok,
IncompleteInput,
InvalidInput,
NoMemory,
NotSupported,
TooDeep
};
JsonError(Code code) : _code(code) {}
DeserializationError() {}
DeserializationError(Code code) : _code(code) {}
friend bool operator==(const JsonError& err, Code code) {
friend bool operator==(const DeserializationError& err, Code code) {
return err._code == code;
}
friend bool operator==(Code code, const JsonError& err) {
friend bool operator==(Code code, const DeserializationError& err) {
return err._code == code;
}
friend bool operator!=(const JsonError& err, Code code) {
friend bool operator!=(const DeserializationError& err, Code code) {
return err._code != code;
}
friend bool operator!=(Code code, const JsonError& err) {
friend bool operator!=(Code code, const DeserializationError& err) {
return err._code != code;
}
@ -48,6 +56,8 @@ class JsonError {
return "InvalidInput";
case IncompleteInput:
return "IncompleteInput";
case NotSupported:
return "NotSupported";
default:
return "???";
}
@ -58,13 +68,14 @@ class JsonError {
};
#if ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream& operator<<(std::ostream& s, const JsonError& e) {
inline std::ostream& operator<<(std::ostream& s,
const DeserializationError& e) {
s << e.c_str();
return s;
}
inline std::ostream& operator<<(std::ostream& s, JsonError::Code c) {
s << JsonError(c).c_str();
inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
s << DeserializationError(c).c_str();
return s;
}
#endif

View File

@ -4,7 +4,7 @@
#pragma once
#include "../../JsonError.hpp"
#include "../../DeserializationError.hpp"
#include "../../JsonVariant.hpp"
#include "../../Memory/JsonBuffer.hpp"
#include "../../Reading/Reader.hpp"
@ -24,8 +24,8 @@ class JsonDeserializer {
_writer(writer),
_nestingLimit(nestingLimit),
_loaded(false) {}
JsonError parse(JsonVariant &variant) {
JsonError err = skipSpacesAndComments();
DeserializationError parse(JsonVariant &variant) {
DeserializationError err = skipSpacesAndComments();
if (err) return err;
switch (current()) {
@ -64,22 +64,22 @@ class JsonDeserializer {
return true;
}
JsonError parseArray(JsonVariant &variant) {
if (_nestingLimit == 0) return JsonError::TooDeep;
DeserializationError parseArray(JsonVariant &variant) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return JsonError::NoMemory;
if (!array) return DeserializationError::NoMemory;
variant = array;
// Check opening braket
if (!eat('[')) return JsonError::InvalidInput;
if (!eat('[')) return DeserializationError::InvalidInput;
// Skip spaces
JsonError err = skipSpacesAndComments();
DeserializationError err = skipSpacesAndComments();
if (err) return err;
// Empty array?
if (eat(']')) return JsonError::Ok;
if (eat(']')) return DeserializationError::Ok;
// Read each value
for (;;) {
@ -89,34 +89,34 @@ class JsonDeserializer {
err = parse(value);
_nestingLimit++;
if (err) return err;
if (!array->add(value)) return JsonError::NoMemory;
if (!array->add(value)) return DeserializationError::NoMemory;
// 2 - Skip spaces
err = skipSpacesAndComments();
if (err) return err;
// 3 - More values?
if (eat(']')) return JsonError::Ok;
if (!eat(',')) return JsonError::InvalidInput;
if (eat(']')) return DeserializationError::Ok;
if (!eat(',')) return DeserializationError::InvalidInput;
}
}
JsonError parseObject(JsonVariant &variant) {
if (_nestingLimit == 0) return JsonError::TooDeep;
DeserializationError parseObject(JsonVariant &variant) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return JsonError::NoMemory;
if (!object) return DeserializationError::NoMemory;
variant = object;
// Check opening brace
if (!eat('{')) return JsonError::InvalidInput;
if (!eat('{')) return DeserializationError::InvalidInput;
// Skip spaces
JsonError err = skipSpacesAndComments();
DeserializationError err = skipSpacesAndComments();
if (err) return err;
// Empty object?
if (eat('}')) return JsonError::Ok;
if (eat('}')) return DeserializationError::Ok;
// Read each key value pair
for (;;) {
@ -130,7 +130,7 @@ class JsonDeserializer {
if (err) return err;
// Colon
if (!eat(':')) return JsonError::InvalidInput;
if (!eat(':')) return DeserializationError::InvalidInput;
// Parse value
JsonVariant value;
@ -138,15 +138,15 @@ class JsonDeserializer {
err = parse(value);
_nestingLimit++;
if (err) return err;
if (!object->set(key, value)) return JsonError::NoMemory;
if (!object->set(key, value)) return DeserializationError::NoMemory;
// Skip spaces
err = skipSpacesAndComments();
if (err) return err;
// More keys/values?
if (eat('}')) return JsonError::Ok;
if (!eat(',')) return JsonError::InvalidInput;
if (eat('}')) return DeserializationError::Ok;
if (!eat(',')) return DeserializationError::InvalidInput;
// Skip spaces
err = skipSpacesAndComments();
@ -154,24 +154,24 @@ class JsonDeserializer {
}
}
JsonError parseValue(JsonVariant &variant) {
DeserializationError parseValue(JsonVariant &variant) {
bool hasQuotes = isQuote(current());
const char *value;
JsonError error = parseString(&value);
DeserializationError error = parseString(&value);
if (error) return error;
if (hasQuotes) {
variant = value;
} else {
variant = RawJson(value);
}
return JsonError::Ok;
return DeserializationError::Ok;
}
JsonError parseString(const char **result) {
DeserializationError parseString(const char **result) {
typename RemoveReference<TWriter>::type::String str = _writer.startString();
char c = current();
if (c == '\0') return JsonError::IncompleteInput;
if (c == '\0') return DeserializationError::IncompleteInput;
if (isQuote(c)) { // quotes
move();
@ -181,14 +181,15 @@ class JsonDeserializer {
move();
if (c == stopChar) break;
if (c == '\0') return JsonError::IncompleteInput;
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == '\\') {
c = current();
if (c == 0) return JsonError::IncompleteInput;
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == 'u') return DeserializationError::NotSupported;
// replace char
c = Encoding::unescapeChar(c);
if (c == '\0') return JsonError::InvalidInput;
if (c == '\0') return DeserializationError::InvalidInput;
move();
}
@ -201,12 +202,12 @@ class JsonDeserializer {
c = current();
} while (canBeInNonQuotedString(c));
} else {
return JsonError::InvalidInput;
return DeserializationError::InvalidInput;
}
*result = str.c_str();
if (*result == NULL) return JsonError::NoMemory;
return JsonError::Ok;
if (*result == NULL) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
static inline bool isBetween(char c, char min, char max) {
@ -222,12 +223,12 @@ class JsonDeserializer {
return c == '\'' || c == '\"';
}
JsonError skipSpacesAndComments() {
DeserializationError skipSpacesAndComments() {
for (;;) {
switch (current()) {
// end of string
case '\0':
return JsonError::IncompleteInput;
return DeserializationError::IncompleteInput;
// spaces
case ' ':
@ -247,7 +248,7 @@ class JsonDeserializer {
bool wasStar = false;
for (;;) {
char c = current();
if (c == '\0') return JsonError::IncompleteInput;
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == '/' && wasStar) {
move();
break;
@ -264,19 +265,19 @@ class JsonDeserializer {
for (;;) {
move();
char c = current();
if (c == '\0') return JsonError::IncompleteInput;
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == '\n') break;
}
break;
// not a comment, just a '/'
default:
return JsonError::InvalidInput;
return DeserializationError::InvalidInput;
}
break;
default:
return JsonError::Ok;
return DeserializationError::Ok;
}
}
}

View File

@ -4,21 +4,18 @@
#pragma once
#include "../DeserializationError.hpp"
#include "../JsonVariant.hpp"
#include "../Memory/JsonBuffer.hpp"
#include "../Reading/Reader.hpp"
#include "../TypeTraits/IsConst.hpp"
#include "../Writing/Writer.hpp"
#include "./MsgPackError.hpp"
#include "./endianess.hpp"
#include "./ieee754.hpp"
namespace ArduinoJson {
namespace Internals {
// Parse JSON string to create JsonArrays and JsonObjects
// This internal class is not indended to be used directly.
// Instead, use JsonBuffer.parseArray() or .parseObject()
template <typename TReader, typename TWriter>
class MsgPackDeserializer {
public:
@ -29,18 +26,18 @@ class MsgPackDeserializer {
_writer(writer),
_nestingLimit(nestingLimit) {}
MsgPackError parse(JsonVariant &variant) {
DeserializationError parse(JsonVariant &variant) {
uint8_t code;
if (!readByte(code)) return MsgPackError::IncompleteInput;
if (!readByte(code)) return DeserializationError::IncompleteInput;
if ((code & 0x80) == 0) {
variant = code;
return MsgPackError::Ok;
return DeserializationError::Ok;
}
if ((code & 0xe0) == 0xe0) {
variant = static_cast<int8_t>(code);
return MsgPackError::Ok;
return DeserializationError::Ok;
}
if ((code & 0xe0) == 0xa0) {
@ -54,15 +51,15 @@ class MsgPackDeserializer {
switch (code) {
case 0xc0:
variant = static_cast<char *>(0);
return MsgPackError::Ok;
return DeserializationError::Ok;
case 0xc2:
variant = false;
return MsgPackError::Ok;
return DeserializationError::Ok;
case 0xc3:
variant = true;
return MsgPackError::Ok;
return DeserializationError::Ok;
case 0xcc:
return readInteger<uint8_t>(variant);
@ -94,7 +91,7 @@ class MsgPackDeserializer {
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
return readInteger<int64_t>(variant);
#else
if (!skip(4)) return MsgPackError::IncompleteInput;
if (!skip(4)) return DeserializationError::IncompleteInput;
return readInteger<int32_t>(variant);
#endif
@ -126,7 +123,7 @@ class MsgPackDeserializer {
return readObject<uint32_t>(variant);
default:
return MsgPackError::NotSupported;
return DeserializationError::NotSupported;
}
}
@ -176,123 +173,123 @@ class MsgPackDeserializer {
}
template <typename T>
MsgPackError readInteger(JsonVariant &variant) {
DeserializationError readInteger(JsonVariant &variant) {
T value;
if (!readInteger(value)) return MsgPackError::IncompleteInput;
if (!readInteger(value)) return DeserializationError::IncompleteInput;
variant = value;
return MsgPackError::Ok;
return DeserializationError::Ok;
}
template <typename T>
typename EnableIf<sizeof(T) == 4, MsgPackError>::type readFloat(
typename EnableIf<sizeof(T) == 4, DeserializationError>::type readFloat(
JsonVariant &variant) {
T value;
if (!readBytes(value)) return MsgPackError::IncompleteInput;
if (!readBytes(value)) return DeserializationError::IncompleteInput;
fixEndianess(value);
variant = value;
return MsgPackError::Ok;
return DeserializationError::Ok;
}
template <typename T>
typename EnableIf<sizeof(T) == 8, MsgPackError>::type readDouble(
typename EnableIf<sizeof(T) == 8, DeserializationError>::type readDouble(
JsonVariant &variant) {
T value;
if (!readBytes(value)) return MsgPackError::IncompleteInput;
if (!readBytes(value)) return DeserializationError::IncompleteInput;
fixEndianess(value);
variant = value;
return MsgPackError::Ok;
return DeserializationError::Ok;
}
template <typename T>
typename EnableIf<sizeof(T) == 4, MsgPackError>::type readDouble(
typename EnableIf<sizeof(T) == 4, DeserializationError>::type readDouble(
JsonVariant &variant) {
uint8_t i[8]; // input is 8 bytes
T value; // output is 4 bytes
uint8_t *o = reinterpret_cast<uint8_t *>(&value);
if (!readBytes(i, 8)) return MsgPackError::IncompleteInput;
if (!readBytes(i, 8)) return DeserializationError::IncompleteInput;
doubleToFloat(i, o);
fixEndianess(value);
variant = value;
return MsgPackError::Ok;
return DeserializationError::Ok;
}
template <typename T>
MsgPackError readString(JsonVariant &variant) {
DeserializationError readString(JsonVariant &variant) {
T size;
if (!readInteger(size)) return MsgPackError::IncompleteInput;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readString(variant, size);
}
MsgPackError readString(JsonVariant &variant, size_t n) {
DeserializationError readString(JsonVariant &variant, size_t n) {
typename RemoveReference<TWriter>::type::String str = _writer.startString();
for (; n; --n) {
uint8_t c;
if (!readBytes(c)) return MsgPackError::IncompleteInput;
if (!readBytes(c)) return DeserializationError::IncompleteInput;
str.append(static_cast<char>(c));
}
const char *s = str.c_str();
if (s == NULL) return MsgPackError::NoMemory;
if (s == NULL) return DeserializationError::NoMemory;
variant = s;
return MsgPackError::Ok;
return DeserializationError::Ok;
}
template <typename TSize>
MsgPackError readArray(JsonVariant &variant) {
DeserializationError readArray(JsonVariant &variant) {
TSize size;
if (!readInteger(size)) return MsgPackError::IncompleteInput;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readArray(variant, size);
}
MsgPackError readArray(JsonVariant &variant, size_t n) {
DeserializationError readArray(JsonVariant &variant, size_t n) {
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return MsgPackError::NoMemory;
if (!array) return DeserializationError::NoMemory;
variant = array;
return readArray(*array, n);
}
MsgPackError readArray(JsonArray &array, size_t n) {
if (_nestingLimit == 0) return MsgPackError::TooDeep;
DeserializationError readArray(JsonArray &array, size_t n) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {
JsonVariant variant;
MsgPackError err = parse(variant);
DeserializationError err = parse(variant);
if (err) return err;
if (!array.add(variant)) return MsgPackError::NoMemory;
if (!array.add(variant)) return DeserializationError::NoMemory;
}
++_nestingLimit;
return MsgPackError::Ok;
return DeserializationError::Ok;
}
template <typename TSize>
MsgPackError readObject(JsonVariant &variant) {
DeserializationError readObject(JsonVariant &variant) {
TSize size;
if (!readInteger(size)) return MsgPackError::IncompleteInput;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readObject(variant, size);
}
MsgPackError readObject(JsonVariant &variant, size_t n) {
DeserializationError readObject(JsonVariant &variant, size_t n) {
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return MsgPackError::NoMemory;
if (!object) return DeserializationError::NoMemory;
variant = object;
return readObject(*object, n);
}
MsgPackError readObject(JsonObject &object, size_t n) {
if (_nestingLimit == 0) return MsgPackError::TooDeep;
DeserializationError readObject(JsonObject &object, size_t n) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {
MsgPackError err;
DeserializationError err;
JsonVariant variant;
err = parse(variant);
if (err) return err;
const char *key = variant.as<char *>();
if (!key) return MsgPackError::NotSupported;
if (!key) return DeserializationError::NotSupported;
err = parse(variant);
if (err) return err;
if (!object.set(key, variant)) return MsgPackError::NoMemory;
if (!object.set(key, variant)) return DeserializationError::NoMemory;
}
++_nestingLimit;
return MsgPackError::Ok;
return DeserializationError::Ok;
}
JsonBuffer *_buffer;

View File

@ -1,74 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <ostream>
#endif
namespace ArduinoJson {
class MsgPackError {
public:
enum Code { Ok, NotSupported, NoMemory, TooDeep, IncompleteInput };
MsgPackError() {}
MsgPackError(Code code) : _code(code) {}
operator bool() const {
return _code != Ok;
}
friend bool operator==(const MsgPackError& err, Code code) {
return err._code == code;
}
friend bool operator==(Code code, const MsgPackError& err) {
return err._code == code;
}
friend bool operator!=(const MsgPackError& err, Code code) {
return err._code != code;
}
friend bool operator!=(Code code, const MsgPackError& err) {
return err._code != code;
}
const char* c_str() const {
switch (_code) {
case Ok:
return "Ok";
case NotSupported:
return "NotSupported";
case NoMemory:
return "NoMemory";
case TooDeep:
return "TooDeep";
case IncompleteInput:
return "IncompleteInput";
default:
return "???";
}
}
private:
Code _code;
};
#if ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream& operator<<(std::ostream& os, const MsgPackError& err) {
os << err.c_str();
return os;
}
inline std::ostream& operator<<(std::ostream& os, MsgPackError::Code code) {
os << MsgPackError(code).c_str();
return os;
}
#endif
} // namespace ArduinoJson

View File

@ -9,12 +9,12 @@
#include "Writing/Writer.hpp"
namespace ArduinoJson {
// JsonError deserializeJson(TDocument& doc, TString input);
// DeserializationError deserializeJson(TDocument& doc, TString input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = const std::string&, const String&
template <typename TDocument, typename TString>
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
JsonError>::type
DeserializationError>::type
deserializeJson(TDocument &doc, const TString &input) {
using namespace Internals;
return makeJsonDeserializer(&doc.buffer(), makeReader(input),
@ -22,33 +22,34 @@ deserializeJson(TDocument &doc, const TString &input) {
.parse(doc.template to<JsonVariant>());
}
//
// JsonError deserializeJson(TDocument& doc, TChar* input);
// DeserializationError deserializeJson(TDocument& doc, TChar* input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TChar* = char*, const char*, const FlashStringHelper*
template <typename TDocument, typename TChar>
JsonError deserializeJson(TDocument &doc, TChar *input) {
DeserializationError deserializeJson(TDocument &doc, TChar *input) {
using namespace Internals;
return makeJsonDeserializer(&doc.buffer(), makeReader(input),
makeWriter(doc.buffer(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
// JsonError deserializeJson(TDocument& doc, TChar* input, size_t inputSize);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TChar* = char*, const char*, const FlashStringHelper*
// DeserializationError deserializeJson(TDocument& doc, TChar* input, size_t
// inputSize); TDocument = DynamicJsonDocument, StaticJsonDocument TChar* =
// char*, const char*, const FlashStringHelper*
template <typename TDocument, typename TChar>
JsonError deserializeJson(TDocument &doc, TChar *input, size_t inputSize) {
DeserializationError deserializeJson(TDocument &doc, TChar *input,
size_t inputSize) {
using namespace Internals;
return makeJsonDeserializer(&doc.buffer(), makeReader(input, inputSize),
makeWriter(doc.buffer(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
// JsonError deserializeJson(TDocument& doc, TStream input);
// DeserializationError deserializeJson(TDocument& doc, TStream input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TStream = std::istream&, Stream&
template <typename TDocument, typename TStream>
JsonError deserializeJson(TDocument &doc, TStream &input) {
DeserializationError deserializeJson(TDocument &doc, TStream &input) {
using namespace Internals;
return makeJsonDeserializer(&doc.buffer(), makeReader(input),
makeWriter(doc.buffer(), input), doc.nestingLimit)

View File

@ -9,12 +9,12 @@
#include "Writing/Writer.hpp"
namespace ArduinoJson {
// MsgPackError deserializeMsgPack(TDocument& doc, TString input);
// DeserializationError deserializeMsgPack(TDocument& doc, TString input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = const std::string&, const String&
template <typename TDocument, typename TString>
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
MsgPackError>::type
DeserializationError>::type
deserializeMsgPack(TDocument &doc, const TString &input) {
using namespace Internals;
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input),
@ -23,11 +23,11 @@ deserializeMsgPack(TDocument &doc, const TString &input) {
.parse(doc.template to<JsonVariant>());
}
//
// MsgPackError deserializeMsgPack(TDocument& doc, TChar* input);
// DeserializationError deserializeMsgPack(TDocument& doc, TChar* input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TChar* = char*, const char*, const FlashStringHelper*
template <typename TDocument, typename TChar>
MsgPackError deserializeMsgPack(TDocument &doc, TChar *input) {
DeserializationError deserializeMsgPack(TDocument &doc, TChar *input) {
using namespace Internals;
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input),
makeWriter(doc.buffer(), input),
@ -35,13 +35,13 @@ MsgPackError deserializeMsgPack(TDocument &doc, TChar *input) {
.parse(doc.template to<JsonVariant>());
}
//
// MsgPackError deserializeMsgPack(TDocument& doc, TChar* input, size_t
// DeserializationError deserializeMsgPack(TDocument& doc, TChar* input, size_t
// inputSize);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TChar* = char*, const char*, const FlashStringHelper*
template <typename TDocument, typename TChar>
MsgPackError deserializeMsgPack(TDocument &doc, TChar *input,
size_t inputSize) {
DeserializationError deserializeMsgPack(TDocument &doc, TChar *input,
size_t inputSize) {
using namespace Internals;
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input, inputSize),
makeWriter(doc.buffer(), input),
@ -49,11 +49,11 @@ MsgPackError deserializeMsgPack(TDocument &doc, TChar *input,
.parse(doc.template to<JsonVariant>());
}
//
// MsgPackError deserializeMsgPack(TDocument& doc, TStream input);
// DeserializationError deserializeMsgPack(TDocument& doc, TStream input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TStream = std::istream&, Stream&
template <typename TDocument, typename TStream>
MsgPackError deserializeMsgPack(TDocument &doc, TStream &input) {
DeserializationError deserializeMsgPack(TDocument &doc, TStream &input) {
using namespace Internals;
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input),
makeWriter(doc.buffer(), input),