forked from bblanchon/ArduinoJson
Remove member MsgPackDeserializer::_error
This reduces the code size by 54 bytes on AVR.
This commit is contained in:
@ -21,28 +21,26 @@ class MsgPackDeserializer {
|
||||
: _pool(&pool),
|
||||
_reader(reader),
|
||||
_stringStorage(stringStorage),
|
||||
_error(DeserializationError::Ok),
|
||||
_foundSomething(false) {}
|
||||
|
||||
template <typename TFilter>
|
||||
DeserializationError parse(VariantData &variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
parseVariant(&variant, filter, nestingLimit);
|
||||
return _foundSomething ? _error : DeserializationError::EmptyInput;
|
||||
DeserializationError::Code err;
|
||||
err = parseVariant(&variant, filter, nestingLimit);
|
||||
return _foundSomething ? err : DeserializationError::EmptyInput;
|
||||
}
|
||||
|
||||
private:
|
||||
bool invalidInput() {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TFilter>
|
||||
bool parseVariant(VariantData *variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code parseVariant(VariantData *variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
uint8_t code = 0; // TODO: why do we need to initialize this variable?
|
||||
if (!readByte(code))
|
||||
return false;
|
||||
err = readByte(code);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
_foundSomething = true;
|
||||
|
||||
@ -56,20 +54,20 @@ class MsgPackDeserializer {
|
||||
switch (code) {
|
||||
case 0xc0:
|
||||
// already null
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc1:
|
||||
return invalidInput();
|
||||
return DeserializationError::InvalidInput;
|
||||
|
||||
case 0xc2:
|
||||
if (allowValue)
|
||||
variant->setBoolean(false);
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc3:
|
||||
if (allowValue)
|
||||
variant->setBoolean(true);
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc4: // bin 8 (not supported)
|
||||
return skipString<uint8_t>();
|
||||
@ -221,157 +219,202 @@ class MsgPackDeserializer {
|
||||
if (allowValue)
|
||||
variant->setInteger(static_cast<int8_t>(code));
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool readByte(uint8_t &value) {
|
||||
DeserializationError::Code readByte(uint8_t &value) {
|
||||
int c = _reader.read();
|
||||
if (c < 0) {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (c < 0)
|
||||
return DeserializationError::IncompleteInput;
|
||||
value = static_cast<uint8_t>(c);
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool readBytes(uint8_t *p, size_t n) {
|
||||
DeserializationError::Code readBytes(uint8_t *p, size_t n) {
|
||||
if (_reader.readBytes(reinterpret_cast<char *>(p), n) == n)
|
||||
return true;
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
return DeserializationError::Ok;
|
||||
return DeserializationError::IncompleteInput;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readBytes(T &value) {
|
||||
DeserializationError::Code readBytes(T &value) {
|
||||
return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
|
||||
}
|
||||
|
||||
bool skipBytes(size_t n) {
|
||||
DeserializationError::Code skipBytes(size_t n) {
|
||||
for (; n; --n) {
|
||||
if (_reader.read() < 0) {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (_reader.read() < 0)
|
||||
return DeserializationError::IncompleteInput;
|
||||
}
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readInteger(T &value) {
|
||||
if (!readBytes(value))
|
||||
return false;
|
||||
DeserializationError::Code readInteger(T &value) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
err = readBytes(value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fixEndianess(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readInteger(VariantData *variant) {
|
||||
DeserializationError::Code readInteger(VariantData *variant) {
|
||||
DeserializationError::Code err;
|
||||
T value;
|
||||
if (!readInteger(value))
|
||||
return false;
|
||||
|
||||
err = readInteger(value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
variant->setInteger(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 4, bool>::type readFloat(
|
||||
VariantData *variant) {
|
||||
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
|
||||
readFloat(VariantData *variant) {
|
||||
DeserializationError::Code err;
|
||||
T value;
|
||||
if (!readBytes(value))
|
||||
return false;
|
||||
|
||||
err = readBytes(value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fixEndianess(value);
|
||||
variant->setFloat(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 8, bool>::type readDouble(
|
||||
VariantData *variant) {
|
||||
typename enable_if<sizeof(T) == 8, DeserializationError::Code>::type
|
||||
readDouble(VariantData *variant) {
|
||||
DeserializationError::Code err;
|
||||
T value;
|
||||
if (!readBytes(value))
|
||||
return false;
|
||||
|
||||
err = readBytes(value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fixEndianess(value);
|
||||
variant->setFloat(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 4, bool>::type readDouble(
|
||||
VariantData *variant) {
|
||||
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
|
||||
readDouble(VariantData *variant) {
|
||||
DeserializationError::Code err;
|
||||
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 false;
|
||||
|
||||
err = readBytes(i, 8);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
doubleToFloat(i, o);
|
||||
fixEndianess(value);
|
||||
variant->setFloat(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readString(VariantData *variant) {
|
||||
DeserializationError::Code readString(VariantData *variant) {
|
||||
DeserializationError::Code err;
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return readString(variant, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readString() {
|
||||
DeserializationError::Code readString() {
|
||||
DeserializationError::Code err;
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return readString(size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool skipString() {
|
||||
DeserializationError::Code skipString() {
|
||||
DeserializationError::Code err;
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return skipBytes(size);
|
||||
}
|
||||
|
||||
bool readString(VariantData *variant, size_t n) {
|
||||
if (!readString(n))
|
||||
return false;
|
||||
DeserializationError::Code readString(VariantData *variant, size_t n) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
err = readString(n);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
variant->setString(_stringStorage.save());
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool readString(size_t n) {
|
||||
DeserializationError::Code readString(size_t n) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
_stringStorage.startString();
|
||||
for (; n; --n) {
|
||||
uint8_t c;
|
||||
if (!readBytes(c))
|
||||
return false;
|
||||
|
||||
err = readBytes(c);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
_stringStorage.append(static_cast<char>(c));
|
||||
}
|
||||
if (!_stringStorage.isValid()) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!_stringStorage.isValid())
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename TSize, typename TFilter>
|
||||
bool readArray(VariantData *variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code readArray(VariantData *variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
TSize size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return readArray(variant, size, filter, nestingLimit);
|
||||
}
|
||||
|
||||
template <typename TFilter>
|
||||
bool readArray(VariantData *variant, size_t n, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
if (nestingLimit.reached()) {
|
||||
_error = DeserializationError::TooDeep;
|
||||
return false;
|
||||
}
|
||||
DeserializationError::Code readArray(VariantData *variant, size_t n,
|
||||
TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
if (nestingLimit.reached())
|
||||
return DeserializationError::TooDeep;
|
||||
|
||||
bool allowArray = filter.allowArray();
|
||||
|
||||
@ -384,43 +427,48 @@ class MsgPackDeserializer {
|
||||
|
||||
if (memberFilter.allow()) {
|
||||
value = array->addElement(_pool);
|
||||
if (!value) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
}
|
||||
if (!value)
|
||||
return DeserializationError::NoMemory;
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
if (!parseVariant(value, memberFilter, nestingLimit.decrement()))
|
||||
return false;
|
||||
err = parseVariant(value, memberFilter, nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename TSize, typename TFilter>
|
||||
bool readObject(VariantData *variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code readObject(VariantData *variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
TSize size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return readObject(variant, size, filter, nestingLimit);
|
||||
}
|
||||
|
||||
template <typename TFilter>
|
||||
bool readObject(VariantData *variant, size_t n, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
if (nestingLimit.reached()) {
|
||||
_error = DeserializationError::TooDeep;
|
||||
return false;
|
||||
}
|
||||
DeserializationError::Code readObject(VariantData *variant, size_t n,
|
||||
TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
if (nestingLimit.reached())
|
||||
return DeserializationError::TooDeep;
|
||||
|
||||
CollectionData *object = filter.allowObject() ? &variant->toObject() : 0;
|
||||
|
||||
for (; n; --n) {
|
||||
if (!readKey())
|
||||
return false;
|
||||
err = readKey();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
String key = _stringStorage.str();
|
||||
TFilter memberFilter = filter[key.c_str()];
|
||||
@ -434,10 +482,8 @@ class MsgPackDeserializer {
|
||||
key = _stringStorage.save();
|
||||
|
||||
VariantSlot *slot = object->addSlot(_pool);
|
||||
if (!slot) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
}
|
||||
if (!slot)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
slot->setKey(key);
|
||||
|
||||
@ -446,17 +492,21 @@ class MsgPackDeserializer {
|
||||
member = 0;
|
||||
}
|
||||
|
||||
if (!parseVariant(member, memberFilter, nestingLimit.decrement()))
|
||||
return false;
|
||||
err = parseVariant(member, memberFilter, nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool readKey() {
|
||||
DeserializationError::Code readKey() {
|
||||
DeserializationError::Code err;
|
||||
uint8_t code;
|
||||
if (!readByte(code))
|
||||
return false;
|
||||
|
||||
err = readByte(code);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((code & 0xe0) == 0xa0)
|
||||
return readString(code & 0x1f);
|
||||
@ -472,22 +522,25 @@ class MsgPackDeserializer {
|
||||
return readString<uint32_t>();
|
||||
|
||||
default:
|
||||
return invalidInput();
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool skipExt() {
|
||||
DeserializationError::Code skipExt() {
|
||||
DeserializationError::Code err;
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return skipBytes(size + 1U);
|
||||
}
|
||||
|
||||
MemoryPool *_pool;
|
||||
TReader _reader;
|
||||
TStringStorage _stringStorage;
|
||||
DeserializationError _error;
|
||||
bool _foundSomething;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user