forked from bblanchon/ArduinoJson
Optimize deserializeMsgPack()
This commit is contained in:
@ -4,6 +4,7 @@ ArduinoJson: change log
|
||||
* Add `ARDUINOJSON_STRING_LENGTH_SIZE` to the namespace name
|
||||
* Add MsgPack bin8/bin16/bin32 support (PR #2078 by @Sanae6)
|
||||
* Make string support even more generic (PR #2084 by @d-a-v)
|
||||
* Optimize `deserializeMsgPack()`
|
||||
|
||||
v7.0.4 (2024-03-12)
|
||||
------
|
||||
|
@ -228,12 +228,12 @@ TEST_CASE("deserializeMsgPack() under memory constaints") {
|
||||
checkError(0, "\x80", DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1}") {
|
||||
checkError(0, "\x81\xA1H\x01", DeserializationError::NoMemory);
|
||||
checkError(3, "\x81\xA1H\x01", DeserializationError::Ok);
|
||||
checkError(1, "\x81\xA1H\x01", DeserializationError::NoMemory);
|
||||
checkError(2, "\x81\xA1H\x01", DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1,W:2}") {
|
||||
checkError(3, "\x82\xA1H\x01\xA1W\x02", DeserializationError::NoMemory);
|
||||
checkError(5, "\x82\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
||||
checkError(2, "\x82\xA1H\x01\xA1W\x02", DeserializationError::NoMemory);
|
||||
checkError(3, "\x82\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,13 +242,13 @@ TEST_CASE("deserializeMsgPack() under memory constaints") {
|
||||
checkError(0, "\xDE\x00\x00", DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1}") {
|
||||
checkError(2, "\xDE\x00\x01\xA1H\x01", DeserializationError::NoMemory);
|
||||
checkError(3, "\xDE\x00\x01\xA1H\x01", DeserializationError::Ok);
|
||||
checkError(1, "\xDE\x00\x01\xA1H\x01", DeserializationError::NoMemory);
|
||||
checkError(2, "\xDE\x00\x01\xA1H\x01", DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1,W:2}") {
|
||||
checkError(3, "\xDE\x00\x02\xA1H\x01\xA1W\x02",
|
||||
checkError(2, "\xDE\x00\x02\xA1H\x01\xA1W\x02",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(5, "\xDE\x00\x02\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
||||
checkError(3, "\xDE\x00\x02\xA1H\x01\xA1W\x02", DeserializationError::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,14 +257,14 @@ TEST_CASE("deserializeMsgPack() under memory constaints") {
|
||||
checkError(0, "\xDF\x00\x00\x00\x00", DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1}") {
|
||||
checkError(2, "\xDF\x00\x00\x00\x01\xA1H\x01",
|
||||
checkError(1, "\xDF\x00\x00\x00\x01\xA1H\x01",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(3, "\xDF\x00\x00\x00\x01\xA1H\x01", DeserializationError::Ok);
|
||||
checkError(2, "\xDF\x00\x00\x00\x01\xA1H\x01", DeserializationError::Ok);
|
||||
}
|
||||
SECTION("{H:1,W:2}") {
|
||||
checkError(3, "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
||||
checkError(2, "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
||||
DeserializationError::NoMemory);
|
||||
checkError(5, "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
||||
checkError(3, "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02",
|
||||
DeserializationError::Ok);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
67
src/ArduinoJson/Memory/StringBuffer.hpp
Normal file
67
src/ArduinoJson/Memory/StringBuffer.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2024, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
class StringBuffer {
|
||||
public:
|
||||
StringBuffer(ResourceManager* resources) : resources_(resources) {}
|
||||
|
||||
~StringBuffer() {
|
||||
if (node_)
|
||||
resources_->destroyString(node_);
|
||||
}
|
||||
|
||||
char* reserve(size_t capacity) {
|
||||
if (node_ && capacity > node_->length) {
|
||||
// existing buffer is too small, we need to reallocate
|
||||
resources_->destroyString(node_);
|
||||
node_ = nullptr;
|
||||
}
|
||||
if (!node_)
|
||||
node_ = resources_->createString(capacity);
|
||||
if (!node_)
|
||||
return nullptr;
|
||||
size_ = capacity;
|
||||
node_->data[capacity] = 0; // null-terminate the string
|
||||
return node_->data;
|
||||
}
|
||||
|
||||
StringNode* save() {
|
||||
ARDUINOJSON_ASSERT(node_ != nullptr);
|
||||
node_->data[size_] = 0;
|
||||
auto node = resources_->getString(adaptString(node_->data, size_));
|
||||
if (node) {
|
||||
node->references++;
|
||||
return node;
|
||||
}
|
||||
|
||||
if (node_->length != size_) {
|
||||
node = resources_->resizeString(node_, size_);
|
||||
ARDUINOJSON_ASSERT(node != nullptr); // realloc to smaller can't fail
|
||||
} else {
|
||||
node = node_;
|
||||
}
|
||||
node_ = nullptr;
|
||||
resources_->saveString(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
JsonString str() const {
|
||||
ARDUINOJSON_ASSERT(node_ != nullptr);
|
||||
|
||||
return JsonString(node_->data, node_->length, JsonString::Copied);
|
||||
}
|
||||
|
||||
private:
|
||||
ResourceManager* resources_;
|
||||
StringNode* node_ = nullptr;
|
||||
size_t size_ = 0;
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <ArduinoJson/Deserialization/deserialize.hpp>
|
||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||
#include <ArduinoJson/Memory/StringBuffer.hpp>
|
||||
#include <ArduinoJson/MsgPack/endianness.hpp>
|
||||
#include <ArduinoJson/MsgPack/ieee754.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
@ -19,7 +20,7 @@ class MsgPackDeserializer {
|
||||
MsgPackDeserializer(ResourceManager* resources, TReader reader)
|
||||
: resources_(resources),
|
||||
reader_(reader),
|
||||
stringBuilder_(resources),
|
||||
stringBuffer_(resources),
|
||||
foundSomething_(false) {}
|
||||
|
||||
template <typename TFilter>
|
||||
@ -239,7 +240,7 @@ class MsgPackDeserializer {
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError::Code readBytes(uint8_t* p, size_t n) {
|
||||
DeserializationError::Code readBytes(void* p, size_t n) {
|
||||
if (reader_.readBytes(reinterpret_cast<char*>(p), n) == n)
|
||||
return DeserializationError::Ok;
|
||||
return DeserializationError::IncompleteInput;
|
||||
@ -247,7 +248,7 @@ class MsgPackDeserializer {
|
||||
|
||||
template <typename T>
|
||||
DeserializationError::Code readBytes(T& value) {
|
||||
return readBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
|
||||
return readBytes(&value, sizeof(value));
|
||||
}
|
||||
|
||||
DeserializationError::Code skipBytes(size_t n) {
|
||||
@ -379,28 +380,16 @@ class MsgPackDeserializer {
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
variant->setOwnedString(stringBuilder_.save());
|
||||
variant->setOwnedString(stringBuffer_.save());
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError::Code readString(size_t n) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
stringBuilder_.startString();
|
||||
for (; n; --n) {
|
||||
uint8_t c;
|
||||
|
||||
err = readBytes(c);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
stringBuilder_.append(static_cast<char>(c));
|
||||
}
|
||||
|
||||
if (!stringBuilder_.isValid())
|
||||
char* p = stringBuffer_.reserve(n);
|
||||
if (!p)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
return readBytes(p, n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -422,7 +411,7 @@ class MsgPackDeserializer {
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
variant->setBinary(stringBuilder_.save());
|
||||
variant->setBinary(stringBuffer_.save());
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
@ -517,7 +506,7 @@ class MsgPackDeserializer {
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
JsonString key = stringBuilder_.str();
|
||||
JsonString key = stringBuffer_.str();
|
||||
TFilter memberFilter = filter[key.c_str()];
|
||||
VariantData* member;
|
||||
|
||||
@ -525,7 +514,7 @@ class MsgPackDeserializer {
|
||||
ARDUINOJSON_ASSERT(object != 0);
|
||||
|
||||
// Save key in memory pool.
|
||||
auto savedKey = stringBuilder_.save();
|
||||
auto savedKey = stringBuffer_.save();
|
||||
|
||||
member = object->addMember(savedKey, resources_);
|
||||
if (!member)
|
||||
@ -582,7 +571,7 @@ class MsgPackDeserializer {
|
||||
|
||||
ResourceManager* resources_;
|
||||
TReader reader_;
|
||||
StringBuilder stringBuilder_;
|
||||
StringBuffer stringBuffer_;
|
||||
bool foundSomething_;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user