forked from bblanchon/ArduinoJson
Added serializeMsgPack()
and measureMsgPack()
(closes #358)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@
|
||||
/fuzzing/*_fuzzer
|
||||
/fuzzing/*_fuzzer.options
|
||||
/fuzzing/*_fuzzer_seed_corpus.zip
|
||||
.vs/
|
||||
|
@ -10,7 +10,7 @@ HEAD
|
||||
* Added `deserializeJson()`
|
||||
* Added `serializeJson()` and `serializeJsonPretty()`
|
||||
* Added `measureJson()` and `measureJsonPretty()`
|
||||
* Added `deserializeMsgPack()` (issue #358)
|
||||
* Added `serializeMsgPack()`, `deserializeMsgPack()` and `measureMsgPack()` (issue #358)
|
||||
* Added example `MsgPackParser.ino` (issue #358)
|
||||
* Added support for non zero-terminated strings (issue #704)
|
||||
* Removed `JsonBuffer::parseArray()`, `parseObject()` and `parse()`
|
||||
|
@ -5,11 +5,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/StaticJsonDocument.hpp"
|
||||
#include "ArduinoJson/deserializeJson.hpp"
|
||||
#include "ArduinoJson/deserializeMsgPack.hpp"
|
||||
|
||||
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
||||
#include "ArduinoJson/Json/JsonSerializer.hpp"
|
||||
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
|
||||
#include "ArduinoJson/StaticJsonDocument.hpp"
|
||||
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
|
82
src/ArduinoJson/Deserialization/deserialize.hpp
Normal file
82
src/ArduinoJson/Deserialization/deserialize.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../StringStorage/StringStorage.hpp"
|
||||
#include "./ArduinoStreamReader.hpp"
|
||||
#include "./CharPointerReader.hpp"
|
||||
#include "./DeserializationError.hpp"
|
||||
#include "./FlashStringReader.hpp"
|
||||
#include "./IteratorReader.hpp"
|
||||
#include "./StdStreamReader.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <template <typename, typename> class TDeserializer,
|
||||
typename TJsonBuffer, typename TReader, typename TWriter>
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(TJsonBuffer *buffer,
|
||||
TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit) {
|
||||
return TDeserializer<TReader, TWriter>(buffer, reader, writer, nestingLimit);
|
||||
}
|
||||
|
||||
// DeserializationError deserialize(TDocument& doc, TString input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TString = const std::string&, const String&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TString>
|
||||
typename Internals::enable_if<!Internals::is_array<TString>::value,
|
||||
DeserializationError>::type
|
||||
deserialize(TDocument &doc, const TString &input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TChar>
|
||||
DeserializationError deserialize(TDocument &doc, TChar *input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input, size_t
|
||||
// inputSize);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TChar>
|
||||
DeserializationError deserialize(TDocument &doc, TChar *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(
|
||||
&doc.buffer(), makeReader(input, inputSize),
|
||||
makeStringStorage(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TStream input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TStream = std::istream&, Stream&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TStream>
|
||||
DeserializationError deserialize(TDocument &doc, TStream &input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -79,7 +79,7 @@ class DynamicJsonDocument {
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor visitor) const {
|
||||
void visit(Visitor& visitor) const {
|
||||
return _root.visit(visitor);
|
||||
}
|
||||
};
|
||||
|
@ -4,24 +4,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../DeserializationError.hpp"
|
||||
#include "../Deserialization/deserialize.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Reading/Reader.hpp"
|
||||
#include "./EscapeSequence.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
template <typename TReader, typename TStringStorage>
|
||||
class JsonDeserializer {
|
||||
public:
|
||||
JsonDeserializer(JsonBuffer *buffer, TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit)
|
||||
JsonDeserializer(JsonBuffer *buffer, TReader reader,
|
||||
TStringStorage stringStorage, uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
_reader(reader),
|
||||
_writer(writer),
|
||||
_stringStorage(stringStorage),
|
||||
_nestingLimit(nestingLimit),
|
||||
_loaded(false) {}
|
||||
DeserializationError parse(JsonVariant &variant) {
|
||||
@ -168,8 +167,8 @@ class JsonDeserializer {
|
||||
}
|
||||
|
||||
DeserializationError parseString(const char **result) {
|
||||
typename remove_reference<TWriter>::type::String str =
|
||||
_writer.startString();
|
||||
typename remove_reference<TStringStorage>::type::String str =
|
||||
_stringStorage.startString();
|
||||
|
||||
char c = current();
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
@ -285,19 +284,35 @@ class JsonDeserializer {
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
TReader _reader;
|
||||
TWriter _writer;
|
||||
TStringStorage _stringStorage;
|
||||
uint8_t _nestingLimit;
|
||||
char _current;
|
||||
bool _loaded;
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TReader, typename TWriter>
|
||||
JsonDeserializer<TReader, TWriter> makeJsonDeserializer(TJsonBuffer *buffer,
|
||||
TReader reader,
|
||||
TWriter writer,
|
||||
uint8_t nestingLimit) {
|
||||
return JsonDeserializer<TReader, TWriter>(buffer, reader, writer,
|
||||
nestingLimit);
|
||||
}
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, const TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput *input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
|
@ -4,37 +4,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Print/DummyPrint.hpp"
|
||||
#include "../Print/DynamicStringBuilder.hpp"
|
||||
#include "../Print/StaticStringBuilder.hpp"
|
||||
#include "./IndentedPrint.hpp"
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "./JsonWriter.hpp"
|
||||
#include "./Prettyfier.hpp"
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include "../Print/StreamPrintAdapter.hpp"
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename Writer>
|
||||
template <typename TPrint>
|
||||
class JsonSerializer {
|
||||
public:
|
||||
template <typename TSource>
|
||||
static void serialize(const TSource &source, Writer &writer) {
|
||||
source.visit(Visitor(&writer));
|
||||
}
|
||||
|
||||
struct Visitor {
|
||||
Visitor(Writer *writer) : _writer(writer) {}
|
||||
JsonSerializer(TPrint &destination) : _writer(destination) {}
|
||||
|
||||
void acceptFloat(JsonFloat value) {
|
||||
_writer->writeFloat(value);
|
||||
_writer.writeFloat(value);
|
||||
}
|
||||
|
||||
void acceptArray(const JsonArray &array) {
|
||||
_writer->beginArray();
|
||||
_writer.beginArray();
|
||||
|
||||
JsonArray::const_iterator it = array.begin();
|
||||
while (it != array.end()) {
|
||||
@ -43,141 +30,79 @@ class JsonSerializer {
|
||||
++it;
|
||||
if (it == array.end()) break;
|
||||
|
||||
_writer->writeComma();
|
||||
_writer.writeComma();
|
||||
}
|
||||
|
||||
_writer->endArray();
|
||||
_writer.endArray();
|
||||
}
|
||||
|
||||
void acceptObject(const JsonObject &object) {
|
||||
_writer->beginObject();
|
||||
_writer.beginObject();
|
||||
|
||||
JsonObject::const_iterator it = object.begin();
|
||||
while (it != object.end()) {
|
||||
_writer->writeString(it->key);
|
||||
_writer->writeColon();
|
||||
_writer.writeString(it->key);
|
||||
_writer.writeColon();
|
||||
it->value.visit(*this);
|
||||
|
||||
++it;
|
||||
if (it == object.end()) break;
|
||||
|
||||
_writer->writeComma();
|
||||
_writer.writeComma();
|
||||
}
|
||||
|
||||
_writer->endObject();
|
||||
_writer.endObject();
|
||||
}
|
||||
|
||||
void acceptString(const char *value) {
|
||||
_writer->writeString(value);
|
||||
_writer.writeString(value);
|
||||
}
|
||||
|
||||
void acceptRawJson(const char *value) {
|
||||
_writer->writeRaw(value);
|
||||
_writer.writeRaw(value);
|
||||
}
|
||||
|
||||
void acceptNegativeInteger(JsonUInt value) {
|
||||
_writer->writeRaw('-');
|
||||
_writer->writeInteger(value);
|
||||
_writer.writeRaw('-');
|
||||
_writer.writeInteger(value);
|
||||
}
|
||||
|
||||
void acceptPositiveInteger(JsonUInt value) {
|
||||
_writer->writeInteger(value);
|
||||
_writer.writeInteger(value);
|
||||
}
|
||||
|
||||
void acceptBoolean(bool value) {
|
||||
_writer->writeBoolean(value);
|
||||
_writer.writeBoolean(value);
|
||||
}
|
||||
|
||||
void acceptUndefined() {}
|
||||
|
||||
Writer *_writer;
|
||||
};
|
||||
size_t bytesWritten() const {
|
||||
return _writer.bytesWritten();
|
||||
}
|
||||
|
||||
private:
|
||||
JsonWriter<TPrint> _writer;
|
||||
};
|
||||
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
typename Internals::enable_if<
|
||||
!Internals::StringTraits<TDestination>::has_append, size_t>::type
|
||||
serializeJson(const TSource &source, TDestination &destination) {
|
||||
Internals::JsonWriter<TDestination> writer(destination);
|
||||
Internals::JsonSerializer<Internals::JsonWriter<TDestination> >::serialize(
|
||||
source, writer);
|
||||
return writer.bytesWritten();
|
||||
size_t serializeJson(TSource &source, TDestination &destination) {
|
||||
using namespace Internals;
|
||||
return serialize<JsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
template <typename TSource>
|
||||
std::ostream &serializeJson(const TSource &source, std::ostream &os) {
|
||||
Internals::StreamPrintAdapter adapter(os);
|
||||
serializeJson(source, adapter);
|
||||
return os;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJson(const TSource &source, char *buffer, size_t bufferSize) {
|
||||
Internals::StaticStringBuilder sb(buffer, bufferSize);
|
||||
return serializeJson(source, sb);
|
||||
}
|
||||
|
||||
template <typename TSource, size_t N>
|
||||
size_t serializeJson(const TSource &source, char (&buffer)[N]) {
|
||||
return serializeJson(source, buffer, N);
|
||||
}
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
typename Internals::enable_if<Internals::StringTraits<TDestination>::has_append,
|
||||
size_t>::type
|
||||
serializeJson(const TSource &source, TDestination &str) {
|
||||
Internals::DynamicStringBuilder<TDestination> sb(str);
|
||||
return serializeJson(source, sb);
|
||||
}
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
size_t serializeJsonPretty(const TSource &source,
|
||||
Internals::IndentedPrint<TDestination> &print) {
|
||||
Internals::Prettyfier<TDestination> p(print);
|
||||
return serializeJson(source, p);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJsonPretty(const TSource &source, char *buffer,
|
||||
size_t bufferSize) {
|
||||
Internals::StaticStringBuilder sb(buffer, bufferSize);
|
||||
return serializeJsonPretty(source, sb);
|
||||
}
|
||||
|
||||
template <typename TSource, size_t N>
|
||||
size_t serializeJsonPretty(const TSource &source, char (&buffer)[N]) {
|
||||
return serializeJsonPretty(source, buffer, N);
|
||||
}
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
typename Internals::enable_if<
|
||||
!Internals::StringTraits<TDestination>::has_append, size_t>::type
|
||||
serializeJsonPretty(const TSource &source, TDestination &print) {
|
||||
Internals::IndentedPrint<TDestination> indentedPrint(print);
|
||||
return serializeJsonPretty(source, indentedPrint);
|
||||
}
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
typename Internals::enable_if<Internals::StringTraits<TDestination>::has_append,
|
||||
size_t>::type
|
||||
serializeJsonPretty(const TSource &source, TDestination &str) {
|
||||
Internals::DynamicStringBuilder<TDestination> sb(str);
|
||||
return serializeJsonPretty(source, sb);
|
||||
using namespace Internals;
|
||||
return serialize<JsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJson(const TSource &source) {
|
||||
Internals::DummyPrint dp;
|
||||
return serializeJson(source, dp);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJsonPretty(const TSource &source) {
|
||||
Internals::DummyPrint dp;
|
||||
return serializeJsonPretty(source, dp);
|
||||
using namespace Internals;
|
||||
return measure<JsonSerializer>(source);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
|
57
src/ArduinoJson/Json/PrettyJsonSerializer.hpp
Normal file
57
src/ArduinoJson/Json/PrettyJsonSerializer.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "./IndentedPrint.hpp"
|
||||
#include "./JsonSerializer.hpp"
|
||||
#include "./Prettyfier.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TPrint>
|
||||
class PrettyJsonSerializer_Base {
|
||||
public:
|
||||
PrettyJsonSerializer_Base(TPrint &output)
|
||||
: _indentedPrint(output), _prettyfier(_indentedPrint) {}
|
||||
|
||||
protected:
|
||||
IndentedPrint<TPrint> _indentedPrint;
|
||||
Prettyfier<TPrint> _prettyfier;
|
||||
};
|
||||
|
||||
template <typename TPrint>
|
||||
class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>,
|
||||
public JsonSerializer<Prettyfier<TPrint> > {
|
||||
public:
|
||||
PrettyJsonSerializer(TPrint &output)
|
||||
: PrettyJsonSerializer_Base<TPrint>(output),
|
||||
JsonSerializer<Prettyfier<TPrint> >(
|
||||
PrettyJsonSerializer_Base<TPrint>::_prettyfier) {}
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
size_t serializeJsonPretty(TSource &source, TDestination &destination) {
|
||||
using namespace Internals;
|
||||
return serialize<PrettyJsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJsonPretty(const TSource &source, char *buffer,
|
||||
size_t bufferSize) {
|
||||
using namespace Internals;
|
||||
return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJsonPretty(const TSource &source) {
|
||||
using namespace Internals;
|
||||
return measure<PrettyJsonSerializer>(source);
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
@ -179,7 +179,7 @@ class JsonArray : public Internals::ReferenceType,
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor visitor) const {
|
||||
void visit(Visitor &visitor) const {
|
||||
return visitor.acceptArray(*this);
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor visitor) const {
|
||||
void visit(Visitor& visitor) const {
|
||||
return _array.get<JsonVariant>(_index).visit(visitor);
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,7 @@ class JsonObject : public Internals::ReferenceType,
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor visitor) const {
|
||||
void visit(Visitor& visitor) const {
|
||||
return visitor.acceptObject(*this);
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ class JsonObjectSubscript
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor visitor) const {
|
||||
void visit(Visitor& visitor) const {
|
||||
return _object.get<JsonVariant>(_key).visit(visitor);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
|
||||
_content.asInteger = static_cast<JsonUInt>(value);
|
||||
} else {
|
||||
_type = JSON_NEGATIVE_INTEGER;
|
||||
_content.asInteger = static_cast<JsonUInt>(-value);
|
||||
_content.asInteger = ~static_cast<JsonUInt>(value) + 1;
|
||||
}
|
||||
}
|
||||
// JsonVariant(unsigned short)
|
||||
@ -308,7 +308,7 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor visitor) const {
|
||||
void visit(Visitor &visitor) const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_FLOAT:
|
||||
|
@ -4,26 +4,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../DeserializationError.hpp"
|
||||
#include "../Deserialization/deserialize.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Reading/Reader.hpp"
|
||||
#include "../Writing/Writer.hpp"
|
||||
#include "./endianess.hpp"
|
||||
#include "./ieee754.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
template <typename TReader, typename TStringStorage>
|
||||
class MsgPackDeserializer {
|
||||
public:
|
||||
MsgPackDeserializer(JsonBuffer *buffer, TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit)
|
||||
MsgPackDeserializer(JsonBuffer *buffer, TReader reader,
|
||||
TStringStorage stringStorage, uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
_reader(reader),
|
||||
_writer(writer),
|
||||
_stringStorage(stringStorage),
|
||||
_nestingLimit(nestingLimit) {}
|
||||
|
||||
DeserializationError parse(JsonVariant &variant) {
|
||||
@ -221,8 +219,8 @@ class MsgPackDeserializer {
|
||||
}
|
||||
|
||||
DeserializationError readString(JsonVariant &variant, size_t n) {
|
||||
typename remove_reference<TWriter>::type::String str =
|
||||
_writer.startString();
|
||||
typename remove_reference<TStringStorage>::type::String str =
|
||||
_stringStorage.startString();
|
||||
for (; n; --n) {
|
||||
uint8_t c;
|
||||
if (!readBytes(c)) return DeserializationError::IncompleteInput;
|
||||
@ -295,15 +293,33 @@ class MsgPackDeserializer {
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
TReader _reader;
|
||||
TWriter _writer;
|
||||
TStringStorage _stringStorage;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TReader, typename TWriter>
|
||||
MsgPackDeserializer<TReader, TWriter> makeMsgPackDeserializer(
|
||||
TJsonBuffer *buffer, TReader reader, TWriter writer, uint8_t nestingLimit) {
|
||||
return MsgPackDeserializer<TReader, TWriter>(buffer, reader, writer,
|
||||
nestingLimit);
|
||||
}
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, const TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<MsgPackDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input) {
|
||||
using namespace Internals;
|
||||
return deserialize<MsgPackDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return deserialize<MsgPackDeserializer>(doc, input, inputSize);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<MsgPackDeserializer>(doc, input);
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
|
191
src/ArduinoJson/MsgPack/MsgPackSerializer.hpp
Normal file
191
src/ArduinoJson/MsgPack/MsgPackSerializer.hpp
Normal file
@ -0,0 +1,191 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "./endianess.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TPrint>
|
||||
class MsgPackSerializer {
|
||||
public:
|
||||
MsgPackSerializer(TPrint& output) : _output(&output), _bytesWritten(0) {}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 4>::type acceptFloat(T value32) {
|
||||
writeByte(0xCA);
|
||||
writeInteger(value32);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 8>::type acceptFloat(T value64) {
|
||||
float value32 = float(value64);
|
||||
if (value32 == value64) {
|
||||
writeByte(0xCA);
|
||||
writeInteger(value32);
|
||||
} else {
|
||||
writeByte(0xCB);
|
||||
writeInteger(value64);
|
||||
}
|
||||
}
|
||||
|
||||
void acceptArray(const JsonArray& array) {
|
||||
size_t n = array.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x90 + array.size()));
|
||||
} else if (n < 0x10000) {
|
||||
writeByte(0xDC);
|
||||
writeInteger(uint16_t(n));
|
||||
} else {
|
||||
writeByte(0xDD);
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
for (JsonArray::const_iterator it = array.begin(); it != array.end();
|
||||
++it) {
|
||||
it->visit(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void acceptObject(const JsonObject& object) {
|
||||
size_t n = object.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x80 + n));
|
||||
} else if (n < 0x10000) {
|
||||
writeByte(0xDE);
|
||||
writeInteger(uint16_t(n));
|
||||
} else {
|
||||
writeByte(0xDF);
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
for (JsonObject::const_iterator it = object.begin(); it != object.end();
|
||||
++it) {
|
||||
acceptString(it->key);
|
||||
it->value.visit(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void acceptString(const char* value) {
|
||||
if (!value) return writeByte(0xC0); // nil
|
||||
|
||||
size_t n = strlen(value);
|
||||
|
||||
if (n < 0x20) {
|
||||
writeByte(uint8_t(0xA0 + n));
|
||||
} else if (n < 0x100) {
|
||||
writeByte(0xD9);
|
||||
writeInteger(uint8_t(n));
|
||||
} else if (n < 0x10000) {
|
||||
writeByte(0xDA);
|
||||
writeInteger(uint16_t(n));
|
||||
} else {
|
||||
writeByte(0xDB);
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
writeBytes(reinterpret_cast<const uint8_t*>(value), n);
|
||||
}
|
||||
|
||||
void acceptRawJson(const char* /*value*/) {}
|
||||
|
||||
void acceptNegativeInteger(JsonUInt value) {
|
||||
JsonUInt negated = JsonUInt(~value + 1);
|
||||
if (value <= 0x20) {
|
||||
writeInteger(int8_t(negated));
|
||||
} else if (value <= 0x80) {
|
||||
writeByte(0xD0);
|
||||
writeInteger(int8_t(negated));
|
||||
} else if (value <= 0x8000) {
|
||||
writeByte(0xD1);
|
||||
writeInteger(int16_t(negated));
|
||||
} else if (value <= 0x80000000) {
|
||||
writeByte(0xD2);
|
||||
writeInteger(int32_t(negated));
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
else {
|
||||
writeByte(0xD3);
|
||||
writeInteger(int64_t(negated));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void acceptPositiveInteger(JsonUInt value) {
|
||||
if (value <= 0x7F) {
|
||||
writeInteger(uint8_t(value));
|
||||
} else if (value <= 0xFF) {
|
||||
writeByte(0xCC);
|
||||
writeInteger(uint8_t(value));
|
||||
} else if (value <= 0xFFFF) {
|
||||
writeByte(0xCD);
|
||||
writeInteger(uint16_t(value));
|
||||
} else if (value <= 0xFFFFFFFF) {
|
||||
writeByte(0xCE);
|
||||
writeInteger(uint32_t(value));
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
else {
|
||||
writeByte(0xCF);
|
||||
writeInteger(uint64_t(value));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void acceptBoolean(bool value) {
|
||||
writeByte(value ? 0xC3 : 0xC2);
|
||||
}
|
||||
|
||||
void acceptUndefined() {
|
||||
writeByte(0xC0);
|
||||
}
|
||||
|
||||
size_t bytesWritten() const {
|
||||
return _bytesWritten;
|
||||
}
|
||||
|
||||
private:
|
||||
void writeByte(uint8_t c) {
|
||||
_output->print(char(c));
|
||||
_bytesWritten++;
|
||||
}
|
||||
|
||||
void writeBytes(const uint8_t* c, size_t n) {
|
||||
for (; n > 0; --n, ++c) writeByte(*c);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void writeInteger(T value) {
|
||||
fixEndianess(value);
|
||||
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
|
||||
}
|
||||
|
||||
TPrint* _output;
|
||||
size_t _bytesWritten;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
|
||||
using namespace Internals;
|
||||
return serialize<MsgPackSerializer>(source, output);
|
||||
}
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
inline size_t serializeMsgPack(const TSource& source, TDestination* output,
|
||||
size_t size) {
|
||||
using namespace Internals;
|
||||
return serialize<MsgPackSerializer>(source, output, size);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
inline size_t measureMsgPack(const TSource& source) {
|
||||
using namespace Internals;
|
||||
return measure<MsgPackSerializer>(source);
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
@ -5,17 +5,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Polyfills/utility.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename T>
|
||||
inline void swap(T& a, T& b) {
|
||||
T t(a);
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
|
||||
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 8>) {
|
||||
swap(p[0], p[7]);
|
||||
swap(p[1], p[6]);
|
||||
|
16
src/ArduinoJson/Polyfills/utility.hpp
Normal file
16
src/ArduinoJson/Polyfills/utility.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename T>
|
||||
inline void swap(T& a, T& b) {
|
||||
T t(a);
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,11 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./ArduinoStreamReader.hpp"
|
||||
#include "./CharPointerReader.hpp"
|
||||
#include "./FlashStringReader.hpp"
|
||||
#include "./IteratorReader.hpp"
|
||||
#include "./StdStreamReader.hpp"
|
@ -7,7 +7,6 @@
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A dummy Print implementation used in measureJson()
|
||||
class DummyPrint {
|
||||
public:
|
||||
size_t print(char) {
|
@ -32,5 +32,5 @@ class StaticStringBuilder {
|
||||
char *end;
|
||||
char *p;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
21
src/ArduinoJson/Serialization/measure.hpp
Normal file
21
src/ArduinoJson/Serialization/measure.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./DummyPrint.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource>
|
||||
size_t measure(const TSource &source) {
|
||||
DummyPrint dp;
|
||||
TSerializer<DummyPrint> serializer(dp);
|
||||
source.visit(serializer);
|
||||
return serializer.bytesWritten();
|
||||
}
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
55
src/ArduinoJson/Serialization/serialize.hpp
Normal file
55
src/ArduinoJson/Serialization/serialize.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./DynamicStringBuilder.hpp"
|
||||
#include "./StaticStringBuilder.hpp"
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include "./StreamPrintAdapter.hpp"
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource,
|
||||
typename TPrint>
|
||||
typename enable_if<!StringTraits<TPrint>::has_append, size_t>::type serialize(
|
||||
const TSource &source, TPrint &destination) {
|
||||
TSerializer<TPrint> serializer(destination);
|
||||
source.visit(serializer);
|
||||
return serializer.bytesWritten();
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
template <template <typename> class TSerializer, typename TSource>
|
||||
size_t serialize(const TSource &source, std::ostream &os) {
|
||||
StreamPrintAdapter adapter(os);
|
||||
return serialize<TSerializer>(source, adapter);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource>
|
||||
size_t serialize(const TSource &source, char *buffer, size_t bufferSize) {
|
||||
StaticStringBuilder sb(buffer, bufferSize);
|
||||
return serialize<TSerializer>(source, sb);
|
||||
}
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource, size_t N>
|
||||
size_t serialize(const TSource &source, char (&buffer)[N]) {
|
||||
StaticStringBuilder sb(buffer, N);
|
||||
return serialize<TSerializer>(source, sb);
|
||||
}
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource,
|
||||
typename TString>
|
||||
typename enable_if<StringTraits<TString>::has_append, size_t>::type serialize(
|
||||
const TSource &source, TString &str) {
|
||||
DynamicStringBuilder<TString> sb(str);
|
||||
return serialize<TSerializer>(source, sb);
|
||||
}
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -76,7 +76,7 @@ class StaticJsonDocument {
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor visitor) const {
|
||||
void visit(Visitor& visitor) const {
|
||||
return _root.visit(visitor);
|
||||
}
|
||||
};
|
||||
|
@ -4,15 +4,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TJsonBuffer>
|
||||
class JsonBufferWriter {
|
||||
class StringCopier {
|
||||
public:
|
||||
JsonBufferWriter(TJsonBuffer& jb) : _jb(&jb) {}
|
||||
StringCopier(TJsonBuffer& jb) : _jb(&jb) {}
|
||||
|
||||
typedef typename TJsonBuffer::String String;
|
||||
|
@ -8,7 +8,7 @@ namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TChar>
|
||||
class StringWriter {
|
||||
class StringMover {
|
||||
public:
|
||||
class String {
|
||||
public:
|
||||
@ -28,7 +28,7 @@ class StringWriter {
|
||||
TChar* _startPtr;
|
||||
};
|
||||
|
||||
StringWriter(TChar* buffer) : _ptr(buffer) {}
|
||||
StringMover(TChar* buffer) : _ptr(buffer) {}
|
||||
|
||||
String startString() {
|
||||
return String(&_ptr);
|
||||
@ -37,5 +37,5 @@ class StringWriter {
|
||||
private:
|
||||
TChar* _ptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
44
src/ArduinoJson/StringStorage/StringStorage.hpp
Normal file
44
src/ArduinoJson/StringStorage/StringStorage.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./StringCopier.hpp"
|
||||
#include "./StringMover.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TJsonBuffer, typename TInput, typename Enable = void>
|
||||
struct StringStorage {
|
||||
typedef StringCopier<TJsonBuffer> type;
|
||||
|
||||
static type create(TJsonBuffer& jb, TInput&) {
|
||||
return type(jb);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct StringStorage<TJsonBuffer, TChar*,
|
||||
typename enable_if<!is_const<TChar>::value>::type> {
|
||||
typedef StringMover<TChar> type;
|
||||
|
||||
static type create(TJsonBuffer&, TChar* input) {
|
||||
return type(input);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TInput>
|
||||
typename StringStorage<TJsonBuffer, TInput>::type makeStringStorage(
|
||||
TJsonBuffer& jb, TInput& input) {
|
||||
return StringStorage<TJsonBuffer, TInput>::create(jb, input);
|
||||
}
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
typename StringStorage<TJsonBuffer, TChar*>::type makeStringStorage(
|
||||
TJsonBuffer& jb, TChar* input) {
|
||||
return StringStorage<TJsonBuffer, TChar*>::create(jb, input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,44 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./JsonBufferWriter.hpp"
|
||||
#include "./StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TJsonBuffer, typename TInput, typename Enable = void>
|
||||
struct Writer {
|
||||
typedef JsonBufferWriter<TJsonBuffer> type;
|
||||
|
||||
static type create(TJsonBuffer& jb, TInput&) {
|
||||
return type(jb);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct Writer<TJsonBuffer, TChar*,
|
||||
typename enable_if<!is_const<TChar>::value>::type> {
|
||||
typedef StringWriter<TChar> type;
|
||||
|
||||
static type create(TJsonBuffer&, TChar* input) {
|
||||
return type(input);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TInput>
|
||||
typename Writer<TJsonBuffer, TInput>::type makeWriter(TJsonBuffer& jb,
|
||||
TInput& input) {
|
||||
return Writer<TJsonBuffer, TInput>::create(jb, input);
|
||||
}
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
typename Writer<TJsonBuffer, TChar*>::type makeWriter(TJsonBuffer& jb,
|
||||
TChar* input) {
|
||||
return Writer<TJsonBuffer, TChar*>::create(jb, input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,58 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Json/JsonDeserializer.hpp"
|
||||
#include "Reading/Reader.hpp"
|
||||
#include "Writing/Writer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
// DeserializationError deserializeJson(TDocument& doc, TString input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TString = const std::string&, const String&
|
||||
template <typename TDocument, typename TString>
|
||||
typename Internals::enable_if<!Internals::is_array<TString>::value,
|
||||
DeserializationError>::type
|
||||
deserializeJson(TDocument &doc, const TString &input) {
|
||||
using namespace Internals;
|
||||
return makeJsonDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserializeJson(TDocument& doc, TChar* input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <typename TDocument, typename TChar>
|
||||
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>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserializeJson(TDocument& doc, TChar* input, size_t
|
||||
// inputSize); TDocument = DynamicJsonDocument, StaticJsonDocument TChar* =
|
||||
// char*, const char*, const FlashStringHelper*
|
||||
template <typename TDocument, typename TChar>
|
||||
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>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserializeJson(TDocument& doc, TStream input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TStream = std::istream&, Stream&
|
||||
template <typename TDocument, typename TStream>
|
||||
DeserializationError deserializeJson(TDocument &doc, TStream &input) {
|
||||
using namespace Internals;
|
||||
return makeJsonDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
} // namespace ArduinoJson
|
@ -1,63 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MsgPack/MsgPackDeserializer.hpp"
|
||||
#include "Reading/Reader.hpp"
|
||||
#include "Writing/Writer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
// DeserializationError deserializeMsgPack(TDocument& doc, TString input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TString = const std::string&, const String&
|
||||
template <typename TDocument, typename TString>
|
||||
typename Internals::enable_if<!Internals::is_array<TString>::value,
|
||||
DeserializationError>::type
|
||||
deserializeMsgPack(TDocument &doc, const TString &input) {
|
||||
using namespace Internals;
|
||||
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserializeMsgPack(TDocument& doc, TChar* input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <typename TDocument, typename TChar>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, TChar *input) {
|
||||
using namespace Internals;
|
||||
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserializeMsgPack(TDocument& doc, TChar* input, size_t
|
||||
// inputSize);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <typename TDocument, typename TChar>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, TChar *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input, inputSize),
|
||||
makeWriter(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserializeMsgPack(TDocument& doc, TStream input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TStream = std::istream&, Stream&
|
||||
template <typename TDocument, typename TStream>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, TStream &input) {
|
||||
using namespace Internals;
|
||||
return makeMsgPackDeserializer(&doc.buffer(), makeReader(input),
|
||||
makeWriter(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
} // namespace ArduinoJson
|
@ -73,6 +73,7 @@ add_subdirectory(JsonSerializer)
|
||||
add_subdirectory(JsonVariant)
|
||||
add_subdirectory(JsonWriter)
|
||||
add_subdirectory(Misc)
|
||||
add_subdirectory(MsgPack)
|
||||
add_subdirectory(MsgPackDeserializer)
|
||||
add_subdirectory(MsgPackSerializer)
|
||||
add_subdirectory(Polyfills)
|
||||
add_subdirectory(StaticJsonBuffer)
|
||||
|
@ -38,7 +38,13 @@ TEST_CASE("DeserializationError") {
|
||||
TEST_BOOLIFICATION(NotSupported, true);
|
||||
}
|
||||
|
||||
SECTION("ostream") {
|
||||
SECTION("ostream code") {
|
||||
std::stringstream s;
|
||||
s << DeserializationError(DeserializationError::InvalidInput);
|
||||
REQUIRE(s.str() == "InvalidInput");
|
||||
}
|
||||
|
||||
SECTION("ostream code") {
|
||||
std::stringstream s;
|
||||
s << DeserializationError::InvalidInput;
|
||||
REQUIRE(s.str() == "InvalidInput");
|
||||
|
@ -15,14 +15,14 @@ TEST_CASE("serialize JsonArray to std::string") {
|
||||
std::string json;
|
||||
serializeJson(array, json);
|
||||
|
||||
REQUIRE(std::string("[4,2]") == json);
|
||||
REQUIRE("[4,2]" == json);
|
||||
}
|
||||
|
||||
SECTION("serializeJsonPretty") {
|
||||
std::string json;
|
||||
serializeJsonPretty(array, json);
|
||||
|
||||
REQUIRE(std::string("[\r\n 4,\r\n 2\r\n]") == json);
|
||||
REQUIRE("[\r\n 4,\r\n 2\r\n]" == json);
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,13 +35,13 @@ TEST_CASE("serialize JsonObject to std::string") {
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
|
||||
REQUIRE(std::string("{\"key\":\"value\"}") == json);
|
||||
REQUIRE("{\"key\":\"value\"}" == json);
|
||||
}
|
||||
|
||||
SECTION("serializeJsonPretty") {
|
||||
std::string json;
|
||||
serializeJsonPretty(doc, json);
|
||||
|
||||
REQUIRE(std::string("{\r\n \"key\": \"value\"\r\n}") == json);
|
||||
REQUIRE("{\r\n \"key\": \"value\"\r\n}" == json);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <ArduinoJson/Json/JsonWriter.hpp>
|
||||
#include <ArduinoJson/Print/DynamicStringBuilder.hpp>
|
||||
#include <ArduinoJson/Serialization/DynamicStringBuilder.hpp>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <ArduinoJson/Json/JsonWriter.hpp>
|
||||
#include <ArduinoJson/Print/StaticStringBuilder.hpp>
|
||||
#include <ArduinoJson/Serialization/StaticStringBuilder.hpp>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
# Copyright Benoit Blanchon 2014-2018
|
||||
# MIT License
|
||||
|
||||
add_executable(MsgPackTests
|
||||
add_executable(MsgPackDeserializerTests
|
||||
deserializeArray.cpp
|
||||
deserializeObject.cpp
|
||||
deserializeStaticVariant.cpp
|
||||
@ -15,5 +15,5 @@ add_executable(MsgPackTests
|
||||
std_istream.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(MsgPackTests catch)
|
||||
add_test(MsgPack MsgPackTests)
|
||||
target_link_libraries(MsgPackDeserializerTests catch)
|
||||
add_test(MsgPackDeserializer MsgPackDeserializerTests)
|
@ -5,7 +5,7 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("deserializeMsgPack(JsonArray&)") {
|
||||
TEST_CASE("deserialize MsgPack array") {
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("fixarray") {
|
@ -16,7 +16,7 @@ static void check(const char* input, U expected) {
|
||||
REQUIRE(variant.as<T>() == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("deserializeMsgPack(JsonVariant&)") {
|
||||
TEST_CASE("deserialize MsgPack value") {
|
||||
SECTION("nil") {
|
||||
const char* nil = 0; // ArduinoJson uses a string for null
|
||||
check<const char*>("\xc0", nil);
|
14
test/MsgPackSerializer/CMakeLists.txt
Normal file
14
test/MsgPackSerializer/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2018
|
||||
# MIT License
|
||||
|
||||
add_executable(MsgPackSerializerTests
|
||||
destination_types.cpp
|
||||
measure.cpp
|
||||
serializeArray.cpp
|
||||
serializeObject.cpp
|
||||
serializeVariant.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(MsgPackSerializerTests catch)
|
||||
add_test(MsgPackSerializer MsgPackSerializerTests)
|
47
test/MsgPackSerializer/destination_types.cpp
Normal file
47
test/MsgPackSerializer/destination_types.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("serialize MsgPack to various destination types") {
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject &object = doc.to<JsonObject>();
|
||||
object["hello"] = "world";
|
||||
const char *expected_result = "\x81\xA5hello\xA5world";
|
||||
const size_t expected_length = 13;
|
||||
|
||||
SECTION("std::string") {
|
||||
std::string result;
|
||||
size_t len = serializeMsgPack(object, result);
|
||||
|
||||
REQUIRE(expected_result == result);
|
||||
REQUIRE(expected_length == len);
|
||||
}
|
||||
|
||||
/* SECTION("std::vector<char>") {
|
||||
std::vector<char> result;
|
||||
size_t len = serializeMsgPack(object, result);
|
||||
|
||||
REQUIRE(std::vector<char>(expected_result, expected_result + 13) ==
|
||||
result);
|
||||
REQUIRE(expected_length == len);
|
||||
} */
|
||||
|
||||
SECTION("char[]") {
|
||||
char result[64];
|
||||
size_t len = serializeMsgPack(object, result);
|
||||
|
||||
REQUIRE(std::string(expected_result) == result);
|
||||
REQUIRE(expected_length == len);
|
||||
}
|
||||
|
||||
SECTION("char*") {
|
||||
char result[64];
|
||||
size_t len = serializeMsgPack(object, result, 64);
|
||||
|
||||
REQUIRE(std::string(expected_result) == result);
|
||||
REQUIRE(expected_length == len);
|
||||
}
|
||||
}
|
14
test/MsgPackSerializer/measure.cpp
Normal file
14
test/MsgPackSerializer/measure.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
TEST_CASE("measureMsgPack()") {
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject &object = doc.to<JsonObject>();
|
||||
object["hello"] = "world";
|
||||
|
||||
REQUIRE(measureMsgPack(doc) == 13);
|
||||
}
|
60
test/MsgPackSerializer/serializeArray.cpp
Normal file
60
test/MsgPackSerializer/serializeArray.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void check(const JsonArray& array, const char* expected_data,
|
||||
size_t expected_len) {
|
||||
std::string expected(expected_data, expected_data + expected_len);
|
||||
std::string actual;
|
||||
size_t len = serializeMsgPack(array, actual);
|
||||
CAPTURE(array);
|
||||
REQUIRE(len == expected_len);
|
||||
REQUIRE(actual == expected);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
static void check(const JsonArray& array, const char (&expected_data)[N]) {
|
||||
const size_t expected_len = N - 1;
|
||||
check(array, expected_data, expected_len);
|
||||
}
|
||||
|
||||
// TODO: this function is used by the commented test
|
||||
// static void check(const JsonArray& array, const std::string& expected) {
|
||||
// check(array, expected.data(), expected.length());
|
||||
// }
|
||||
|
||||
TEST_CASE("serialize MsgPack array") {
|
||||
DynamicJsonDocument doc;
|
||||
JsonArray& array = doc.to<JsonArray>();
|
||||
|
||||
SECTION("empty") {
|
||||
check(array, "\x90");
|
||||
}
|
||||
|
||||
SECTION("fixarray") {
|
||||
array.add("hello");
|
||||
array.add("world");
|
||||
|
||||
check(array, "\x92\xA5hello\xA5world");
|
||||
}
|
||||
|
||||
SECTION("array 16") {
|
||||
for (int i = 0; i < 16; i++) array.add(i);
|
||||
|
||||
check(array,
|
||||
"\xDC\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D"
|
||||
"\x0E\x0F");
|
||||
}
|
||||
|
||||
// TODO: this test is too slow
|
||||
// SECTION("array 32") {
|
||||
// const char* nil = 0;
|
||||
// for (int i = 0; i < 65536; i++) array.add(nil);
|
||||
//
|
||||
// check(array,
|
||||
// std::string("\xDD\x00\x01\x00\x00", 5) + std::string(65536, 0xC0));
|
||||
// }
|
||||
}
|
73
test/MsgPackSerializer/serializeObject.cpp
Normal file
73
test/MsgPackSerializer/serializeObject.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <stdio.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
static void check(const JsonObject& object, const char* expected_data,
|
||||
size_t expected_len) {
|
||||
std::string expected(expected_data, expected_data + expected_len);
|
||||
std::string actual;
|
||||
size_t len = serializeMsgPack(object, actual);
|
||||
CAPTURE(object);
|
||||
REQUIRE(len == expected_len);
|
||||
REQUIRE(actual == expected);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
static void check(const JsonObject& object, const char (&expected_data)[N]) {
|
||||
const size_t expected_len = N - 1;
|
||||
check(object, expected_data, expected_len);
|
||||
}
|
||||
|
||||
// TODO: used by the commented test
|
||||
// static void check(const JsonObject& object, const std::string& expected) {
|
||||
// check(object, expected.data(), expected.length());
|
||||
//}
|
||||
|
||||
TEST_CASE("serialize MsgPack object") {
|
||||
DynamicJsonDocument doc;
|
||||
JsonObject& object = doc.to<JsonObject>();
|
||||
|
||||
SECTION("empty") {
|
||||
check(object, "\x80");
|
||||
}
|
||||
|
||||
SECTION("fixmap") {
|
||||
object["hello"] = "world";
|
||||
|
||||
check(object, "\x81\xA5hello\xA5world");
|
||||
}
|
||||
|
||||
SECTION("map 16") {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
char key[16];
|
||||
sprintf(key, "i%X", i);
|
||||
object[key] = i;
|
||||
}
|
||||
|
||||
check(object,
|
||||
"\xDE\x00\x10\xA2i0\x00\xA2i1\x01\xA2i2\x02\xA2i3\x03\xA2i4\x04\xA2i5"
|
||||
"\x05\xA2i6\x06\xA2i7\x07\xA2i8\x08\xA2i9\x09\xA2iA\x0A\xA2iB\x0B\xA2"
|
||||
"iC\x0C\xA2iD\x0D\xA2iE\x0E\xA2iF\x0F");
|
||||
}
|
||||
|
||||
// TODO: improve performance and uncomment
|
||||
// SECTION("map 32") {
|
||||
// std::string expected("\xDF\x00\x01\x00\x00", 5);
|
||||
//
|
||||
// for (int i = 0; i < 65536; ++i) {
|
||||
// char kv[16];
|
||||
// sprintf(kv, "%04x", i);
|
||||
// object[kv] = kv;
|
||||
// expected += '\xA4';
|
||||
// expected += kv;
|
||||
// expected += '\xA4';
|
||||
// expected += kv;
|
||||
// }
|
||||
//
|
||||
// check(object, expected);
|
||||
// }
|
||||
}
|
129
test/MsgPackSerializer/serializeVariant.cpp
Normal file
129
test/MsgPackSerializer/serializeVariant.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <catch.hpp>
|
||||
|
||||
void check(JsonVariant variant, const char* expected_data,
|
||||
size_t expected_len) {
|
||||
std::string expected(expected_data, expected_data + expected_len);
|
||||
std::string actual;
|
||||
size_t len = serializeMsgPack(variant, actual);
|
||||
CAPTURE(variant);
|
||||
REQUIRE(len == expected_len);
|
||||
REQUIRE(actual == expected);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
void check(JsonVariant variant, const char (&expected_data)[N]) {
|
||||
const size_t expected_len = N - 1;
|
||||
check(variant, expected_data, expected_len);
|
||||
}
|
||||
|
||||
void check(JsonVariant variant, const std::string& expected) {
|
||||
check(variant, expected.data(), expected.length());
|
||||
}
|
||||
|
||||
TEST_CASE("serialize MsgPack value") {
|
||||
SECTION("undefined") {
|
||||
check(JsonVariant(), "\xC0"); // we represent undefined as nil
|
||||
}
|
||||
|
||||
SECTION("nil") {
|
||||
const char* nil = 0; // ArduinoJson uses a string for null
|
||||
check(nil, "\xC0");
|
||||
}
|
||||
|
||||
SECTION("bool") {
|
||||
check(false, "\xC2");
|
||||
check(true, "\xC3");
|
||||
}
|
||||
|
||||
SECTION("positive fixint") {
|
||||
check(0, "\x00");
|
||||
check(127, "\x7F");
|
||||
}
|
||||
|
||||
SECTION("uint 8") {
|
||||
check(128, "\xCC\x80");
|
||||
check(255, "\xCC\xFF");
|
||||
}
|
||||
|
||||
SECTION("uint 16") {
|
||||
check(256, "\xCD\x01\x00");
|
||||
check(0xFFFF, "\xCD\xFF\xFF");
|
||||
}
|
||||
|
||||
SECTION("uint 32") {
|
||||
check(0x00010000U, "\xCE\x00\x01\x00\x00");
|
||||
check(0x12345678U, "\xCE\x12\x34\x56\x78");
|
||||
check(0xFFFFFFFFU, "\xCE\xFF\xFF\xFF\xFF");
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
SECTION("uint 64") {
|
||||
check(0x0001000000000000U, "\xCF\x00\x01\x00\x00\x00\x00\x00\x00");
|
||||
check(0x123456789ABCDEF0U, "\xCF\x12\x34\x56\x78\x9A\xBC\xDE\xF0");
|
||||
check(0xFFFFFFFFFFFFFFFFU, "\xCF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF");
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("negative fixint") {
|
||||
check(-1, "\xFF");
|
||||
check(-32, "\xE0");
|
||||
}
|
||||
|
||||
SECTION("int 8") {
|
||||
check(-33, "\xD0\xDF");
|
||||
check(-128, "\xD0\x80");
|
||||
}
|
||||
|
||||
SECTION("int 16") {
|
||||
check(-129, "\xD1\xFF\x7F");
|
||||
check(-32768, "\xD1\x80\x00");
|
||||
}
|
||||
|
||||
SECTION("int 32") {
|
||||
check(-32769, "\xD2\xFF\xFF\x7F\xFF");
|
||||
check(-2147483647 - 1, "\xD2\x80\x00\x00\x00");
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
SECTION("int 64") {
|
||||
check(int64_t(0xFEDCBA9876543210), "\xD3\xFE\xDC\xBA\x98\x76\x54\x32\x10");
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("float 32") {
|
||||
check(1.25, "\xCA\x3F\xA0\x00\x00");
|
||||
}
|
||||
|
||||
SECTION("float 64") {
|
||||
check(3.1415, "\xCB\x40\x09\x21\xCA\xC0\x83\x12\x6F");
|
||||
}
|
||||
|
||||
SECTION("fixstr") {
|
||||
check("", "\xA0");
|
||||
check("hello world hello world hello !",
|
||||
"\xBFhello world hello world hello !");
|
||||
}
|
||||
|
||||
SECTION("str 8") {
|
||||
check("hello world hello world hello !!",
|
||||
"\xD9\x20hello world hello world hello !!");
|
||||
}
|
||||
|
||||
SECTION("str 16") {
|
||||
std::string shortest(256, '?');
|
||||
check(shortest.c_str(), std::string("\xDA\x01\x00", 3) + shortest);
|
||||
|
||||
std::string longest(65535, '?');
|
||||
check(longest.c_str(), std::string("\xDA\xFF\xFF", 3) + longest);
|
||||
}
|
||||
|
||||
SECTION("str 32") {
|
||||
std::string shortest(65536, '?');
|
||||
check(shortest.c_str(), std::string("\xDB\x00\x01\x00\x00", 5) + shortest);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user