mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-11-15 14:59:23 +01:00
Optimize deserializeMsgPack()
This commit is contained in:
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