Remove member MsgPackDeserializer::_error

This reduces the code size by 54 bytes on AVR.
This commit is contained in:
Benoit Blanchon
2022-07-29 10:51:47 +02:00
parent a6da4ad452
commit dde9e9fc26

View File

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