Extracted VariantData and CollectionData classes

This commit is contained in:
Benoit Blanchon
2018-12-07 09:16:58 +01:00
parent 1ad97ebf85
commit b77b203935
45 changed files with 1129 additions and 1007 deletions

View File

@@ -7,7 +7,7 @@
#include "../Deserialization/deserialize.hpp"
#include "../Memory/MemoryPool.hpp"
#include "../Polyfills/type_traits.hpp"
#include "../Variant/VariantRef.hpp"
#include "../Variant/VariantData.hpp"
#include "endianess.hpp"
#include "ieee754.hpp"
@@ -17,27 +17,28 @@ template <typename TReader, typename TStringStorage>
class MsgPackDeserializer {
typedef typename remove_reference<TStringStorage>::type::StringBuilder
StringBuilder;
typedef typename StringBuilder::StringType StringType;
typedef const char *StringType;
public:
MsgPackDeserializer(MemoryPool &memoryPool, TReader reader,
MsgPackDeserializer(MemoryPool &pool, TReader reader,
TStringStorage stringStorage, uint8_t nestingLimit)
: _memoryPool(&memoryPool),
: _pool(&pool),
_reader(reader),
_stringStorage(stringStorage),
_nestingLimit(nestingLimit) {}
DeserializationError parse(VariantRef variant) {
DeserializationError parse(VariantData &variant) {
uint8_t code;
if (!readByte(code)) return DeserializationError::IncompleteInput;
if ((code & 0x80) == 0) {
variant.set(code);
variant.setUnsignedInteger(code);
return DeserializationError::Ok;
}
if ((code & 0xe0) == 0xe0) {
variant.set(static_cast<int8_t>(code));
// TODO: add setNegativeInteger()
variant.setSignedInteger(static_cast<int8_t>(code));
return DeserializationError::Ok;
}
@@ -45,9 +46,13 @@ class MsgPackDeserializer {
return readString(variant, code & 0x1f);
}
if ((code & 0xf0) == 0x90) return readArray(variant, code & 0x0F);
if ((code & 0xf0) == 0x90) {
return readArray(variant.toArray(), code & 0x0F);
}
if ((code & 0xf0) == 0x80) return readObject(variant, code & 0x0F);
if ((code & 0xf0) == 0x80) {
return readObject(variant.toObject(), code & 0x0F);
}
switch (code) {
case 0xc0:
@@ -55,11 +60,11 @@ class MsgPackDeserializer {
return DeserializationError::Ok;
case 0xc2:
variant.set(false);
variant.setBoolean(false);
return DeserializationError::Ok;
case 0xc3:
variant.set(true);
variant.setBoolean(true);
return DeserializationError::Ok;
case 0xcc:
@@ -112,16 +117,16 @@ class MsgPackDeserializer {
return readString<uint32_t>(variant);
case 0xdc:
return readArray<uint16_t>(variant);
return readArray<uint16_t>(variant.toArray());
case 0xdd:
return readArray<uint32_t>(variant);
return readArray<uint32_t>(variant.toArray());
case 0xde:
return readObject<uint16_t>(variant);
return readObject<uint16_t>(variant.toObject());
case 0xdf:
return readObject<uint32_t>(variant);
return readObject<uint32_t>(variant.toObject());
default:
return DeserializationError::NotSupported;
@@ -174,48 +179,48 @@ class MsgPackDeserializer {
}
template <typename T>
DeserializationError readInteger(VariantRef variant) {
DeserializationError readInteger(VariantData &variant) {
T value;
if (!readInteger(value)) return DeserializationError::IncompleteInput;
variant.set(value);
variant.setInteger(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, DeserializationError>::type readFloat(
VariantRef variant) {
VariantData &variant) {
T value;
if (!readBytes(value)) return DeserializationError::IncompleteInput;
fixEndianess(value);
variant.set(value);
variant.setFloat(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 8, DeserializationError>::type readDouble(
VariantRef variant) {
VariantData &variant) {
T value;
if (!readBytes(value)) return DeserializationError::IncompleteInput;
fixEndianess(value);
variant.set(value);
variant.setFloat(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, DeserializationError>::type readDouble(
VariantRef variant) {
VariantData &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 DeserializationError::IncompleteInput;
doubleToFloat(i, o);
fixEndianess(value);
variant.set(value);
variant.setFloat(value);
return DeserializationError::Ok;
}
template <typename T>
DeserializationError readString(VariantRef variant) {
DeserializationError readString(VariantData &variant) {
T size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readString(variant, size);
@@ -228,46 +233,40 @@ class MsgPackDeserializer {
return readString(str, size);
}
DeserializationError readString(VariantRef variant, size_t n) {
DeserializationError readString(VariantData &variant, size_t n) {
StringType s;
DeserializationError err = readString(s, n);
if (!err) variant.set(s);
if (!err) variant.setOwnedString(s);
return err;
}
DeserializationError readString(StringType &s, size_t n) {
DeserializationError readString(StringType &result, size_t n) {
StringBuilder builder = _stringStorage.startString();
for (; n; --n) {
uint8_t c;
if (!readBytes(c)) return DeserializationError::IncompleteInput;
builder.append(static_cast<char>(c));
}
s = builder.complete();
if (s.isNull()) return DeserializationError::NoMemory;
result = builder.complete();
if (!result) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
template <typename TSize>
DeserializationError readArray(VariantRef variant) {
DeserializationError readArray(CollectionData &array) {
TSize size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readArray(variant, size);
return readArray(array, size);
}
DeserializationError readArray(VariantRef variant, size_t n) {
ArrayRef array = variant.to<ArrayRef>();
if (array.isNull()) return DeserializationError::NoMemory;
return readArray(array, n);
}
DeserializationError readArray(ArrayRef array, size_t n) {
DeserializationError readArray(CollectionData &array, size_t n) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {
VariantRef value = array.add();
if (value.isInvalid()) return DeserializationError::NoMemory;
VariantData *value = array.add(_pool);
if (!value) return DeserializationError::NoMemory;
DeserializationError err = parse(value);
DeserializationError err = parse(*value);
if (err) return err;
}
++_nestingLimit;
@@ -275,31 +274,25 @@ class MsgPackDeserializer {
}
template <typename TSize>
DeserializationError readObject(VariantRef variant) {
DeserializationError readObject(CollectionData &object) {
TSize size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readObject(variant, size);
return readObject(object, size);
}
DeserializationError readObject(VariantRef variant, size_t n) {
ObjectRef object = variant.to<ObjectRef>();
if (object.isNull()) return DeserializationError::NoMemory;
return readObject(object, n);
}
DeserializationError readObject(ObjectRef object, size_t n) {
DeserializationError readObject(CollectionData &object, size_t n) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {
VariantSlot *slot = object.addSlot(_pool);
if (!slot) return DeserializationError::NoMemory;
StringType key;
DeserializationError err = parseKey(key);
if (err) return err;
slot->setOwnedKey(key);
VariantRef value = object.set(key);
if (value.isInvalid()) return DeserializationError::NoMemory;
err = parse(value);
err = parse(*slot->data());
if (err) return err;
}
++_nestingLimit;
@@ -327,7 +320,7 @@ class MsgPackDeserializer {
}
}
MemoryPool *_memoryPool;
MemoryPool *_pool;
TReader _reader;
TStringStorage _stringStorage;
uint8_t _nestingLimit;

View File

@@ -7,7 +7,7 @@
#include "../Polyfills/type_traits.hpp"
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "../Variant/VariantRef.hpp"
#include "../Variant/VariantData.hpp"
#include "endianess.hpp"
namespace ARDUINOJSON_NAMESPACE {
@@ -35,7 +35,7 @@ class MsgPackSerializer {
}
}
void visitArray(ArrayConstRef array) {
void visitArray(const CollectionData& array) {
size_t n = array.size();
if (n < 0x10) {
writeByte(uint8_t(0x90 + array.size()));
@@ -46,12 +46,12 @@ class MsgPackSerializer {
writeByte(0xDD);
writeInteger(uint32_t(n));
}
for (ArrayConstRef::iterator it = array.begin(); it != array.end(); ++it) {
it->accept(*this);
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
slot->data()->accept(*this);
}
}
void visitObject(ObjectConstRef object) {
void visitObject(const CollectionData& object) {
size_t n = object.size();
if (n < 0x10) {
writeByte(uint8_t(0x80 + n));
@@ -62,10 +62,9 @@ class MsgPackSerializer {
writeByte(0xDF);
writeInteger(uint32_t(n));
}
for (ObjectConstRef::iterator it = object.begin(); it != object.end();
++it) {
visitString(it->key());
it->value().accept(*this);
for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
visitString(slot->key());
slot->data()->accept(*this);
}
}