Added StaticJsonDocument and DynamicJsonDocument.

Removed StaticJsonArray and DynamicJsonArray.
Removed StaticJsonObject and DynamicJsonObject.
Removed StaticJsonVariant and DynamicJsonVariant.
This commit is contained in:
Benoit Blanchon
2018-04-17 21:27:45 +02:00
parent a13b9e8bdc
commit 1feb92679d
100 changed files with 1696 additions and 1844 deletions

View File

@ -4,18 +4,14 @@
#pragma once
#include "ArduinoJson/DynamicJsonArray.hpp"
#include "ArduinoJson/DynamicJsonObject.hpp"
#include "ArduinoJson/DynamicJsonVariant.hpp"
#include "ArduinoJson/DynamicJsonDocument.hpp"
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
#include "ArduinoJson/StaticJsonArray.hpp"
#include "ArduinoJson/StaticJsonObject.hpp"
#include "ArduinoJson/StaticJsonVariant.hpp"
#include "ArduinoJson/StaticJsonDocument.hpp"
#include "ArduinoJson/deserializeJson.hpp"
#include "ArduinoJson/deserializeMsgPack.hpp"
#include "ArduinoJson/Json/Deserialization/JsonParserImpl.hpp"
#include "ArduinoJson/Json/Serialization/JsonSerializerImpl.hpp"
#include "ArduinoJson/Json/Deserialization/JsonDeserializer.hpp"
#include "ArduinoJson/Json/Serialization/JsonSerializer.hpp"
#include "ArduinoJson/JsonArrayImpl.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp"

View File

@ -1,32 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonArray : public JsonArray {
DynamicJsonBuffer _buffer;
public:
DynamicJsonArray() : JsonArray(&_buffer) {}
DynamicJsonArray(size_t capacity)
: JsonArray(&_buffer), _buffer(capacity - sizeof(JsonArray)) {}
void clear() {
Internals::List<JsonVariant>::clear();
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size() + sizeof(JsonArray);
}
DynamicJsonBuffer& buffer() {
return _buffer;
}
};
} // namespace ArduinoJson

View File

@ -0,0 +1,83 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "JsonObject.hpp"
#include "JsonVariant.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonDocument {
Internals::DynamicJsonBuffer _buffer;
JsonVariant _root;
public:
DynamicJsonDocument() {}
DynamicJsonDocument(size_t capacity) : _buffer(capacity) {}
template <typename T>
bool is() const {
return _root.is<T>();
}
template <typename T>
typename Internals::JsonVariantAs<T>::type as() const {
return _root.as<T>();
}
// JsonObject& to<JsonObject>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonObject>::value,
JsonObject&>::type
to() {
clear();
JsonObject* object = new (&_buffer) JsonObject(&_buffer);
if (!object) return JsonObject::invalid();
_root = object;
return *object;
}
// JsonArray& to<JsonArray>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonArray>::value,
JsonArray&>::type
to() {
clear();
JsonArray* array = new (&_buffer) JsonArray(&_buffer);
if (!array) return JsonArray::invalid();
_root = array;
return *array;
}
// JsonVariant& to<JsonVariant>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonVariant>::value,
T&>::type
to() {
clear();
return _root;
}
Internals::DynamicJsonBuffer& buffer() {
return _buffer;
}
void clear() {
_buffer.clear();
_root = JsonVariant();
}
size_t memoryUsage() const {
return _buffer.size();
}
template <typename Visitor>
void visit(Visitor visitor) const {
return _root.visit(visitor);
}
};
} // namespace ArduinoJson

View File

@ -1,32 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonObject.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonObject : public JsonObject {
DynamicJsonBuffer _buffer;
public:
DynamicJsonObject() : JsonObject(&_buffer) {}
DynamicJsonObject(size_t capacity)
: JsonObject(&_buffer), _buffer(capacity - sizeof(JsonObject)) {}
DynamicJsonBuffer& buffer() {
return _buffer;
}
void clear() {
Internals::List<JsonPair>::clear();
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size() + sizeof(JsonObject);
}
};
} // namespace ArduinoJson

View File

@ -1,45 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariant.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonVariant : public JsonVariant {
DynamicJsonBuffer _buffer;
public:
DynamicJsonVariant() : JsonVariant() {}
DynamicJsonVariant(size_t capacity) : JsonVariant(), _buffer(capacity) {}
template <typename T>
DynamicJsonVariant& operator=(const T& value) {
_buffer.clear();
JsonVariant::operator=(value);
return *this;
}
template <typename T>
DynamicJsonVariant& operator=(const T* value) {
_buffer.clear();
JsonVariant::operator=(value);
return *this;
}
DynamicJsonBuffer& buffer() {
return _buffer;
}
void clear() {
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size();
}
};
} // namespace ArduinoJson

View File

@ -0,0 +1,218 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../../JsonError.hpp"
#include "../../JsonVariant.hpp"
#include "../../Memory/JsonBuffer.hpp"
#include "../../Strings/StringWriter.hpp"
#include "../../TypeTraits/IsConst.hpp"
#include "../Encoding.hpp"
#include "./Comments.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename TReader, typename TWriter>
class JsonDeserializer {
public:
JsonDeserializer(JsonBuffer *buffer, TReader reader, TWriter writer,
uint8_t nestingLimit)
: _buffer(buffer),
_reader(reader),
_writer(writer),
_nestingLimit(nestingLimit) {}
JsonError parse(JsonVariant &variant) {
skipSpacesAndComments(_reader);
switch (_reader.current()) {
case '[':
return parseArray(variant);
case '{':
return parseObject(variant);
default:
return parseValue(variant);
}
}
private:
JsonDeserializer &operator=(const JsonDeserializer &); // non-copiable
static bool eat(TReader &reader, char charToSkip) {
skipSpacesAndComments(reader);
if (reader.current() != charToSkip) return false;
reader.move();
return true;
}
FORCE_INLINE bool eat(char charToSkip) {
return eat(_reader, charToSkip);
}
JsonError parseArray(JsonVariant &variant) {
if (_nestingLimit == 0) return JsonError::TooDeep;
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return JsonError::NoMemory;
variant = array;
// Check opening braket
if (!eat('[')) return JsonError::InvalidInput;
if (eat(']')) return JsonError::Ok;
// Read each value
for (;;) {
// 1 - Parse value
JsonVariant value;
_nestingLimit--;
JsonError error = parse(value);
_nestingLimit++;
if (error != JsonError::Ok) return error;
if (!array->add(value)) return JsonError::NoMemory;
// 2 - More values?
if (eat(']')) return JsonError::Ok;
if (!eat(',')) return JsonError::InvalidInput;
}
}
JsonError parseObject(JsonVariant &variant) {
if (_nestingLimit == 0) return JsonError::TooDeep;
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return JsonError::NoMemory;
variant = object;
// Check opening brace
if (!eat('{')) return JsonError::InvalidInput;
if (eat('}')) return JsonError::Ok;
// Read each key value pair
for (;;) {
// 1 - Parse key
const char *key;
JsonError error = parseString(&key);
if (error) return error;
if (!eat(':')) return JsonError::InvalidInput;
// 2 - Parse value
JsonVariant value;
_nestingLimit--;
error = parse(value);
_nestingLimit++;
if (error != JsonError::Ok) return error;
if (!object->set(key, value)) return JsonError::NoMemory;
// 3 - More keys/values?
if (eat('}')) return JsonError::Ok;
if (!eat(',')) return JsonError::InvalidInput;
}
}
JsonError parseValue(JsonVariant &variant) {
bool hasQuotes = isQuote(_reader.current());
const char *value;
JsonError error = parseString(&value);
if (error) return error;
if (hasQuotes) {
variant = value;
} else {
variant = RawJson(value);
}
return JsonError::Ok;
}
JsonError parseString(const char **result) {
typename RemoveReference<TWriter>::type::String str = _writer.startString();
skipSpacesAndComments(_reader);
char c = _reader.current();
if (isQuote(c)) { // quotes
_reader.move();
char stopChar = c;
for (;;) {
c = _reader.current();
if (c == '\0') break;
_reader.move();
if (c == stopChar) break;
if (c == '\\') {
// replace char
c = Encoding::unescapeChar(_reader.current());
if (c == '\0') return JsonError::InvalidInput;
_reader.move();
}
str.append(c);
}
} else if (canBeInNonQuotedString(c)) { // no quotes
do {
_reader.move();
str.append(c);
c = _reader.current();
} while (canBeInNonQuotedString(c));
} else {
return JsonError::InvalidInput;
}
*result = str.c_str();
if (*result == NULL) return JsonError::NoMemory;
return JsonError::Ok;
}
static inline bool isBetween(char c, char min, char max) {
return min <= c && c <= max;
}
static inline bool canBeInNonQuotedString(char c) {
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
}
static inline bool isQuote(char c) {
return c == '\'' || c == '\"';
}
JsonBuffer *_buffer;
TReader _reader;
TWriter _writer;
uint8_t _nestingLimit;
};
template <typename TJsonBuffer, typename TString, typename Enable = void>
struct JsonParserBuilder {
typedef typename StringTraits<TString>::Reader InputReader;
typedef JsonDeserializer<InputReader, TJsonBuffer &> TParser;
static TParser makeParser(TJsonBuffer *buffer, TString &json,
uint8_t nestingLimit) {
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
}
};
template <typename TJsonBuffer, typename TChar>
struct JsonParserBuilder<TJsonBuffer, TChar *,
typename EnableIf<!IsConst<TChar>::value>::type> {
typedef typename StringTraits<TChar *>::Reader TReader;
typedef StringWriter<TChar> TWriter;
typedef JsonDeserializer<TReader, TWriter> TParser;
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
uint8_t nestingLimit) {
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
}
};
template <typename TJsonBuffer, typename TString>
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
nestingLimit);
}
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,95 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../../JsonError.hpp"
#include "../../JsonVariant.hpp"
#include "../../Memory/JsonBuffer.hpp"
#include "../../Strings/StringWriter.hpp"
#include "../../TypeTraits/IsConst.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 JsonParser {
public:
JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer,
uint8_t nestingLimit)
: _buffer(buffer),
_reader(reader),
_writer(writer),
_nestingLimit(nestingLimit) {}
JsonError parse(JsonArray &destination);
JsonError parse(JsonObject &destination);
JsonError parse(JsonVariant &destination);
private:
JsonParser &operator=(const JsonParser &); // non-copiable
static bool eat(TReader &, char charToSkip);
FORCE_INLINE bool eat(char charToSkip) {
return eat(_reader, charToSkip);
}
const char *parseString();
JsonError parseArray(JsonVariant &variant);
JsonError parseObject(JsonVariant &variant);
JsonError parseValue(JsonVariant &variant);
static inline bool isBetween(char c, char min, char max) {
return min <= c && c <= max;
}
static inline bool canBeInNonQuotedString(char c) {
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
}
static inline bool isQuote(char c) {
return c == '\'' || c == '\"';
}
JsonBuffer *_buffer;
TReader _reader;
TWriter _writer;
uint8_t _nestingLimit;
};
template <typename TJsonBuffer, typename TString, typename Enable = void>
struct JsonParserBuilder {
typedef typename StringTraits<TString>::Reader InputReader;
typedef JsonParser<InputReader, TJsonBuffer &> TParser;
static TParser makeParser(TJsonBuffer *buffer, TString &json,
uint8_t nestingLimit) {
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
}
};
template <typename TJsonBuffer, typename TChar>
struct JsonParserBuilder<TJsonBuffer, TChar *,
typename EnableIf<!IsConst<TChar>::value>::type> {
typedef typename StringTraits<TChar *>::Reader TReader;
typedef StringWriter<TChar> TWriter;
typedef JsonParser<TReader, TWriter> TParser;
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
uint8_t nestingLimit) {
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
}
};
template <typename TJsonBuffer, typename TString>
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
nestingLimit);
}
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,166 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Encoding.hpp"
#include "Comments.hpp"
#include "JsonParser.hpp"
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
TReader &reader, char charToSkip) {
skipSpacesAndComments(reader);
if (reader.current() != charToSkip) return false;
reader.move();
return true;
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parse(JsonArray &array) {
if (_nestingLimit == 0) return JsonError::TooDeep;
// Check opening braket
if (!eat('[')) return JsonError::OpeningBracketExpected;
if (eat(']')) return JsonError::Ok;
// Read each value
for (;;) {
// 1 - Parse value
JsonVariant value;
_nestingLimit--;
JsonError error = parse(value);
_nestingLimit++;
if (error != JsonError::Ok) return error;
if (!array.add(value)) return JsonError::NoMemory;
// 2 - More values?
if (eat(']')) return JsonError::Ok;
if (!eat(',')) return JsonError::ClosingBracketExpected;
}
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parse(
JsonObject &object) {
if (_nestingLimit == 0) return JsonError::TooDeep;
// Check opening brace
if (!eat('{')) return JsonError::OpeningBraceExpected;
if (eat('}')) return JsonError::Ok;
// Read each key value pair
for (;;) {
// 1 - Parse key
const char *key = parseString();
if (!key) return JsonError::NoMemory;
if (!eat(':')) return JsonError::ColonExpected;
// 2 - Parse value
JsonVariant value;
_nestingLimit--;
JsonError error = parse(value);
_nestingLimit++;
if (error != JsonError::Ok) return error;
if (!object.set(key, value)) return JsonError::NoMemory;
// 3 - More keys/values?
if (eat('}')) return JsonError::Ok;
if (!eat(',')) return JsonError::ClosingBraceExpected;
}
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parse(
JsonVariant &variant) {
skipSpacesAndComments(_reader);
switch (_reader.current()) {
case '[':
return parseArray(variant);
case '{':
return parseObject(variant);
default:
return parseValue(variant);
}
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray(
JsonVariant &variant) {
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return JsonError::NoMemory;
variant = array;
return parse(*array);
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject(
JsonVariant &variant) {
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return JsonError::NoMemory;
variant = object;
return parse(*object);
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseValue(
JsonVariant &variant) {
bool hasQuotes = isQuote(_reader.current());
const char *value = parseString();
if (value == NULL) return JsonError::NoMemory;
if (hasQuotes) {
variant = value;
} else {
variant = RawJson(value);
}
return JsonError::Ok;
}
template <typename TReader, typename TWriter>
inline const char *
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
typename RemoveReference<TWriter>::type::String str = _writer.startString();
skipSpacesAndComments(_reader);
char c = _reader.current();
if (isQuote(c)) { // quotes
_reader.move();
char stopChar = c;
for (;;) {
c = _reader.current();
if (c == '\0') break;
_reader.move();
if (c == stopChar) break;
if (c == '\\') {
// replace char
c = Encoding::unescapeChar(_reader.current());
if (c == '\0') break;
_reader.move();
}
str.append(c);
}
} else { // no quotes
for (;;) {
if (!canBeInNonQuotedString(c)) break;
_reader.move();
str.append(c);
c = _reader.current();
}
}
return str.c_str();
}

View File

@ -16,26 +16,15 @@
#endif
namespace ArduinoJson {
class JsonArray;
class JsonObject;
class JsonVariant;
namespace Internals {
class JsonArraySubscript;
template <typename TKey>
class JsonObjectSubscript;
template <typename Writer>
class JsonSerializer {
public:
static void serialize(const JsonArray &, Writer &);
static void serialize(const JsonArraySubscript &, Writer &);
static void serialize(const JsonObject &, Writer &);
template <typename TKey>
static void serialize(const JsonObjectSubscript<TKey> &, Writer &);
static void serialize(const JsonVariant &, Writer &);
template <typename TSource>
static void serialize(const TSource &source, Writer &writer) {
source.visit(Visitor(&writer));
}
struct Visitor {
Visitor(Writer *writer) : _writer(writer) {}
@ -44,12 +33,38 @@ class JsonSerializer {
_writer->writeFloat(value);
}
void acceptArray(const JsonArray &value) {
serialize(value, *_writer);
void acceptArray(const JsonArray &array) {
_writer->beginArray();
JsonArray::const_iterator it = array.begin();
while (it != array.end()) {
it->visit(*this);
++it;
if (it == array.end()) break;
_writer->writeComma();
}
_writer->endArray();
}
void acceptObject(const JsonObject &value) {
serialize(value, *_writer);
void acceptObject(const JsonObject &object) {
_writer->beginObject();
JsonObject::const_iterator it = object.begin();
while (it != object.end()) {
_writer->writeString(it->key);
_writer->writeColon();
it->value.visit(*this);
++it;
if (it == object.end()) break;
_writer->writeComma();
}
_writer->endObject();
}
void acceptString(const char *value) {

View File

@ -1,69 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../../JsonArray.hpp"
#include "../../JsonArraySubscript.hpp"
#include "../../JsonObject.hpp"
#include "../../JsonObjectSubscript.hpp"
#include "../../JsonVariant.hpp"
#include "JsonSerializer.hpp"
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonArray& array, Writer& writer) {
writer.beginArray();
JsonArray::const_iterator it = array.begin();
while (it != array.end()) {
serialize(*it, writer);
++it;
if (it == array.end()) break;
writer.writeComma();
}
writer.endArray();
}
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonArraySubscript& arraySubscript, Writer& writer) {
serialize(arraySubscript.as<JsonVariant>(), writer);
}
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonObject& object, Writer& writer) {
writer.beginObject();
JsonObject::const_iterator it = object.begin();
while (it != object.end()) {
writer.writeString(it->key);
writer.writeColon();
serialize(it->value, writer);
++it;
if (it == object.end()) break;
writer.writeComma();
}
writer.endObject();
}
template <typename Writer>
template <typename TKey>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonObjectSubscript<TKey>& objectSubscript, Writer& writer) {
serialize(objectSubscript.template as<JsonVariant>(), writer);
}
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonVariant& variant, Writer& writer) {
variant.visit(Visitor(&writer));
}

View File

@ -180,6 +180,11 @@ class JsonArray : public Internals::ReferenceType,
}
}
template <typename Visitor>
void visit(Visitor visitor) const {
return visitor.acceptArray(*this);
}
private:
template <typename TValueRef>
bool set_impl(size_t index, TValueRef value) {

View File

@ -74,6 +74,11 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
return _array.set(_index, value);
}
template <typename Visitor>
void visit(Visitor visitor) const {
return _array.get<JsonVariant>(_index).visit(visitor);
}
private:
JsonArray& _array;
const size_t _index;

View File

@ -8,16 +8,7 @@ namespace ArduinoJson {
class JsonError {
public:
enum Code {
Ok,
OpeningBraceExpected,
ClosingBraceExpected,
OpeningBracketExpected,
ClosingBracketExpected,
ColonExpected,
TooDeep,
NoMemory
};
enum Code { Ok, TooDeep, NoMemory, InvalidInput };
JsonError(Code code) : _code(code) {}
@ -45,20 +36,12 @@ class JsonError {
switch (_code) {
case Ok:
return "Ok";
case OpeningBraceExpected:
return "OpeningBraceExpected";
case ClosingBraceExpected:
return "ClosingBraceExpected";
case OpeningBracketExpected:
return "OpeningBracketExpected";
case ClosingBracketExpected:
return "ClosingBracketExpected";
case ColonExpected:
return "ColonExpected";
case TooDeep:
return "TooDeep";
case NoMemory:
return "NoMemory";
case InvalidInput:
return "InvalidInput";
default:
return "???";
}
@ -73,6 +56,11 @@ inline std::ostream& operator<<(std::ostream& s, const JsonError& e) {
s << e.c_str();
return s;
}
inline std::ostream& operator<<(std::ostream& s, JsonError::Code c) {
s << JsonError(c).c_str();
return s;
}
#endif
} // namespace ArduinoJson

View File

@ -229,6 +229,11 @@ class JsonObject : public Internals::ReferenceType,
return instance;
}
template <typename Visitor>
void visit(Visitor visitor) const {
return visitor.acceptObject(*this);
}
private:
// Returns the list node that matches the specified key.
template <typename TStringRef>

View File

@ -82,6 +82,11 @@ class JsonObjectSubscript
return _object.set(_key, value);
}
template <typename Visitor>
void visit(Visitor visitor) const {
return _object.get<JsonVariant>(_key).visit(visitor);
}
private:
JsonObject& _object;
TStringRef _key;

View File

@ -151,6 +151,12 @@ class DynamicJsonBufferBase : public JsonBuffer {
Block* _head;
size_t _nextBlockCapacity;
};
// Implements a JsonBuffer with dynamic memory allocation.
// You are strongly encouraged to consider using StaticJsonBuffer which is much
// more suitable for embedded systems.
typedef Internals::DynamicJsonBufferBase<Internals::DefaultAllocator>
DynamicJsonBuffer;
} // namespace Internals
#if defined(__clang__)
@ -160,10 +166,4 @@ class DynamicJsonBufferBase : public JsonBuffer {
#pragma GCC diagnostic pop
#endif
#endif
// Implements a JsonBuffer with dynamic memory allocation.
// You are strongly encouraged to consider using StaticJsonBuffer which is much
// more suitable for embedded systems.
typedef Internals::DynamicJsonBufferBase<Internals::DefaultAllocator>
DynamicJsonBuffer;
} // namespace ArduinoJson

View File

@ -92,7 +92,6 @@ class StaticJsonBufferBase : public JsonBuffer {
size_t _capacity;
size_t _size;
};
} // namespace Internals
#if defined(__clang__)
#pragma clang diagnostic push
@ -118,6 +117,7 @@ class StaticJsonBuffer : public Internals::StaticJsonBufferBase {
private:
char _buffer[ACTUAL_CAPACITY];
};
} // namespace Internals
} // namespace ArduinoJson
#if defined(__clang__)

View File

@ -28,40 +28,6 @@ class MsgPackDeserializer {
_writer(writer),
_nestingLimit(nestingLimit) {}
MsgPackError parse(JsonArray &array) {
uint8_t c = readOne();
size_t n;
if ((c & 0xF0) == 0x90) {
n = c & 0x0F;
} else if (c == 0xdc) {
n = readInteger<uint16_t>();
} else if (c == 0xdd) {
n = readInteger<uint32_t>();
} else {
return MsgPackError::NotAnArray;
}
return readArray(array, n);
}
MsgPackError parse(JsonObject &object) {
uint8_t c = readOne();
size_t n;
if ((c & 0xf0) == 0x80) {
n = c & 0x0f;
} else if (c == 0xde) {
n = readInteger<uint16_t>();
} else if (c == 0xdf) {
n = readInteger<uint32_t>();
} else {
return MsgPackError::NotAnObject;
}
return readObject(object, n);
}
MsgPackError parse(JsonVariant &variant) {
uint8_t c = readOne();

View File

@ -8,7 +8,7 @@ namespace ArduinoJson {
class MsgPackError {
public:
enum Code { Ok, NotSupported, NoMemory, NotAnArray, NotAnObject, TooDeep };
enum Code { Ok, NotSupported, NoMemory, TooDeep };
MsgPackError() {}
@ -42,10 +42,6 @@ class MsgPackError {
return "NotSupported";
case NoMemory:
return "NoMemory";
case NotAnArray:
return "NotAnArray";
case NotAnObject:
return "NotAnObject";
case TooDeep:
return "TooDeep";
default:
@ -62,6 +58,11 @@ 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

@ -1,32 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "Memory/StaticJsonBuffer.hpp"
namespace ArduinoJson {
template <size_t CAPACITY>
class StaticJsonArray : public JsonArray {
StaticJsonBuffer<CAPACITY - sizeof(JsonArray)> _buffer;
public:
StaticJsonArray() : JsonArray(&_buffer) {}
void clear() {
Internals::List<JsonVariant>::clear();
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size() + sizeof(JsonArray);
}
Internals::StaticJsonBufferBase& buffer() {
return _buffer;
}
};
} // namespace ArduinoJson

View File

@ -0,0 +1,80 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariant.hpp"
#include "Memory/StaticJsonBuffer.hpp"
namespace ArduinoJson {
template <size_t CAPACITY = sizeof(JsonVariant)>
class StaticJsonDocument {
Internals::StaticJsonBuffer<CAPACITY> _buffer;
JsonVariant _root;
public:
Internals::StaticJsonBufferBase& buffer() {
return _buffer;
}
template <typename T>
bool is() const {
return _root.is<T>();
}
template <typename T>
typename Internals::JsonVariantAs<T>::type as() const {
return _root.as<T>();
}
// JsonObject& to<JsonObject>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonObject>::value,
JsonObject&>::type
to() {
clear();
JsonObject* object = new (&_buffer) JsonObject(&_buffer);
if (!object) return JsonObject::invalid();
_root = object;
return *object;
}
// JsonArray& to<JsonArray>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonArray>::value,
JsonArray&>::type
to() {
clear();
JsonArray* array = new (&_buffer) JsonArray(&_buffer);
if (!array) return JsonArray::invalid();
_root = array;
return *array;
}
// JsonVariant to<JsonVariant>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonVariant>::value,
T&>::type
to() {
clear();
return _root;
}
void clear() {
_buffer.clear();
_root = JsonVariant();
}
size_t memoryUsage() const {
return _buffer.size();
}
template <typename Visitor>
void visit(Visitor visitor) const {
return _root.visit(visitor);
}
};
} // namespace ArduinoJson

View File

@ -1,32 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonObject.hpp"
#include "Memory/StaticJsonBuffer.hpp"
namespace ArduinoJson {
template <size_t CAPACITY>
class StaticJsonObject : public JsonObject {
StaticJsonBuffer<CAPACITY - sizeof(JsonObject)> _buffer;
public:
StaticJsonObject() : JsonObject(&_buffer) {}
void clear() {
Internals::List<JsonPair>::clear();
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size() + sizeof(JsonObject);
}
Internals::StaticJsonBufferBase& buffer() {
return _buffer;
}
};
} // namespace ArduinoJson

View File

@ -1,43 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariant.hpp"
#include "Memory/StaticJsonBuffer.hpp"
namespace ArduinoJson {
template <size_t CAPACITY = sizeof(JsonVariant)>
class StaticJsonVariant : public JsonVariant {
StaticJsonBuffer<CAPACITY> _buffer;
public:
template <typename T>
StaticJsonVariant& operator=(const T& value) {
_buffer.clear();
JsonVariant::operator=(value);
return *this;
}
template <typename T>
StaticJsonVariant& operator=(const T* value) {
_buffer.clear();
JsonVariant::operator=(value);
return *this;
}
Internals::StaticJsonBufferBase& buffer() {
return _buffer;
}
void clear() {
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size();
}
};
} // namespace ArduinoJson

View File

@ -4,6 +4,8 @@
#pragma once
#include <stdlib.h> // for size_t
namespace ArduinoJson {
namespace Internals {

View File

@ -4,43 +4,40 @@
#pragma once
#include "Json/Deserialization/JsonParser.hpp"
#include "Json/Deserialization/JsonDeserializer.hpp"
namespace ArduinoJson {
// JsonError deserializeJson(TDestination& destination, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant
// JsonError deserializeJson(TDocument& doc, TString json);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = const std::string&, const String&
template <typename TDestination, typename TString>
template <typename TDocument, typename TString>
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
JsonError>::type
deserializeJson(TDestination &destination, const TString &json,
deserializeJson(TDocument &doc, const TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear();
return Internals::makeParser(&destination.buffer(), json, nestingLimit)
.parse(destination);
return Internals::makeParser(&doc.buffer(), json, nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
// JsonError deserializeJson(TDestination& destination, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant
// JsonError deserializeJson(TDocument& doc, TString json);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = const char*, const char[N], const FlashStringHelper*
template <typename TDestination, typename TString>
template <typename TDocument, typename TString>
JsonError deserializeJson(
TDestination &destination, TString *json,
TDocument &doc, TString *json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear();
return Internals::makeParser(&destination.buffer(), json, nestingLimit)
.parse(destination);
return Internals::makeParser(&doc.buffer(), json, nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
// JsonError deserializeJson(TDestination& destination, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant
// JsonError deserializeJson(TDocument& doc, TString json);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = std::istream&, Stream&
template <typename TDestination, typename TString>
template <typename TDocument, typename TString>
JsonError deserializeJson(
TDestination &destination, TString &json,
TDocument &doc, TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear();
return Internals::makeParser(&destination.buffer(), json, nestingLimit)
.parse(destination);
return Internals::makeParser(&doc.buffer(), json, nestingLimit)
.parse(doc.template to<JsonVariant>());
}
} // namespace ArduinoJson

View File

@ -7,43 +7,37 @@
#include "MsgPack/MsgPackDeserializer.hpp"
namespace ArduinoJson {
// MsgPackError deserializeMsgPack(TDestination& destination, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant
// MsgPackError deserializeMsgPack(TDocument& doc, TString json);
// TDocument = DynamicJsonArray | StaticJsonArray
// TString = const std::string&, const String&
template <typename TDestination, typename TString>
template <typename TDocument, typename TString>
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
MsgPackError>::type
deserializeMsgPack(TDestination &destination, const TString &json,
deserializeMsgPack(TDocument &doc, const TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear();
return Internals::makeMsgPackDeserializer(&destination.buffer(), json,
nestingLimit)
.parse(destination);
return Internals::makeMsgPackDeserializer(&doc.buffer(), json, nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
// MsgPackError deserializeMsgPack(TDestination& destination, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant
// MsgPackError deserializeMsgPack(TDocument& doc, TString json);
// TDocument = DynamicJsonArray | StaticJsonArray
// TString = const char*, const char[N], const FlashStringHelper*
template <typename TDestination, typename TString>
template <typename TDocument, typename TString>
MsgPackError deserializeMsgPack(
TDestination &destination, TString *json,
TDocument &doc, TString *json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear();
return Internals::makeMsgPackDeserializer(&destination.buffer(), json,
nestingLimit)
.parse(destination);
return Internals::makeMsgPackDeserializer(&doc.buffer(), json, nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
// MsgPackError deserializeMsgPack(TDestination& destination, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant
// MsgPackError deserializeMsgPack(TDocument& doc, TString json);
// TDocument = DynamicJsonArray | StaticJsonArray
// TString = std::istream&, Stream&
template <typename TDestination, typename TString>
template <typename TDocument, typename TString>
MsgPackError deserializeMsgPack(
TDestination &destination, TString &json,
TDocument &doc, TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear();
return Internals::makeMsgPackDeserializer(&destination.buffer(), json,
nestingLimit)
.parse(destination);
return Internals::makeMsgPackDeserializer(&doc.buffer(), json, nestingLimit)
.parse(doc.template to<JsonVariant>());
}
} // namespace ArduinoJson