forked from bblanchon/ArduinoJson
Add CopiedString
and LinkedString
This commit is contained in:
@ -19,7 +19,8 @@ TEST_CASE("StringCopier") {
|
|||||||
str.append('\0');
|
str.append('\0');
|
||||||
|
|
||||||
REQUIRE(str.isValid() == true);
|
REQUIRE(str.isValid() == true);
|
||||||
REQUIRE(str.c_str() == std::string("hello"));
|
REQUIRE(std::string(str.str()) == "hello");
|
||||||
|
REQUIRE(pool.overflowed() == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Returns null when too small") {
|
SECTION("Returns null when too small") {
|
||||||
@ -49,7 +50,7 @@ static const char* addStringToPool(MemoryPool& pool, const char* s) {
|
|||||||
str.startString();
|
str.startString();
|
||||||
str.append(s);
|
str.append(s);
|
||||||
str.append('\0');
|
str.append('\0');
|
||||||
return str.save();
|
return str.save().c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("StringCopier::save() deduplicates strings") {
|
TEST_CASE("StringCopier::save() deduplicates strings") {
|
||||||
|
@ -19,7 +19,7 @@ static void testCodepoint(uint32_t codepoint, std::string expected) {
|
|||||||
Utf8::encodeCodepoint(codepoint, str);
|
Utf8::encodeCodepoint(codepoint, str);
|
||||||
|
|
||||||
str.append('\0');
|
str.append('\0');
|
||||||
REQUIRE(str.c_str() == expected);
|
REQUIRE(str.str().c_str() == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Utf8::encodeCodepoint()") {
|
TEST_CASE("Utf8::encodeCodepoint()") {
|
||||||
|
@ -231,12 +231,12 @@ class JsonDeserializer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *key = _stringStorage.c_str();
|
typename TStringStorage::string_type key = _stringStorage.str();
|
||||||
|
|
||||||
TFilter memberFilter = filter[key];
|
TFilter memberFilter = filter[key.c_str()];
|
||||||
|
|
||||||
if (memberFilter.allow()) {
|
if (memberFilter.allow()) {
|
||||||
VariantData *variant = object.getMember(adaptString(key));
|
VariantData *variant = object.getMember(adaptString(key.c_str()));
|
||||||
if (!variant) {
|
if (!variant) {
|
||||||
// Save key in memory pool.
|
// Save key in memory pool.
|
||||||
// This MUST be done before adding the slot.
|
// This MUST be done before adding the slot.
|
||||||
@ -249,7 +249,7 @@ class JsonDeserializer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->setKey(key, typename TStringStorage::storage_policy());
|
slot->setKey(key);
|
||||||
|
|
||||||
variant = slot->data();
|
variant = slot->data();
|
||||||
}
|
}
|
||||||
@ -345,8 +345,7 @@ class JsonDeserializer {
|
|||||||
_stringStorage.startString();
|
_stringStorage.startString();
|
||||||
if (!parseQuotedString())
|
if (!parseQuotedString())
|
||||||
return false;
|
return false;
|
||||||
const char *value = _stringStorage.save();
|
variant.setString(_stringStorage.save());
|
||||||
variant.setStringPointer(value, typename TStringStorage::storage_policy());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,8 +331,7 @@ class MsgPackDeserializer {
|
|||||||
bool readString(VariantData *variant, size_t n) {
|
bool readString(VariantData *variant, size_t n) {
|
||||||
if (!readString(n))
|
if (!readString(n))
|
||||||
return false;
|
return false;
|
||||||
variant->setStringPointer(_stringStorage.save(),
|
variant->setString(_stringStorage.save());
|
||||||
typename TStringStorage::storage_policy());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,8 +418,8 @@ class MsgPackDeserializer {
|
|||||||
if (!readKey())
|
if (!readKey())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const char *key = _stringStorage.c_str();
|
typename TStringStorage::string_type key = _stringStorage.str();
|
||||||
TFilter memberFilter = filter[key];
|
TFilter memberFilter = filter[key.c_str()];
|
||||||
VariantData *member;
|
VariantData *member;
|
||||||
|
|
||||||
if (memberFilter.allow()) {
|
if (memberFilter.allow()) {
|
||||||
@ -434,7 +433,7 @@ class MsgPackDeserializer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->setKey(key, typename TStringStorage::storage_policy());
|
slot->setKey(key);
|
||||||
|
|
||||||
member = slot->data();
|
member = slot->data();
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <ArduinoJson/Namespace.hpp>
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
|
|
||||||
#include <stdint.h> // int8_t
|
#include <stdint.h> // int8_t
|
||||||
|
#include <string.h> // strcmp
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ namespace ARDUINOJSON_NAMESPACE {
|
|||||||
|
|
||||||
class StringCopier {
|
class StringCopier {
|
||||||
public:
|
public:
|
||||||
|
typedef CopiedString string_type;
|
||||||
|
|
||||||
StringCopier(MemoryPool& pool) : _pool(&pool) {}
|
StringCopier(MemoryPool& pool) : _pool(&pool) {}
|
||||||
|
|
||||||
void startString() {
|
void startString() {
|
||||||
@ -17,7 +19,7 @@ class StringCopier {
|
|||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* save() {
|
string_type save() {
|
||||||
ARDUINOJSON_ASSERT(_ptr);
|
ARDUINOJSON_ASSERT(_ptr);
|
||||||
return _pool->saveStringFromFreeZone(_size);
|
return _pool->saveStringFromFreeZone(_size);
|
||||||
}
|
}
|
||||||
@ -47,12 +49,10 @@ class StringCopier {
|
|||||||
return _ptr != 0;
|
return _ptr != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* c_str() {
|
string_type str() const {
|
||||||
return _ptr;
|
return _ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef storage_policies::store_by_copy storage_policy;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryPool* _pool;
|
MemoryPool* _pool;
|
||||||
|
|
||||||
|
@ -5,19 +5,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
#include <ArduinoJson/Strings/StoredString.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
class StringMover {
|
class StringMover {
|
||||||
public:
|
public:
|
||||||
|
typedef LinkedString string_type;
|
||||||
|
|
||||||
StringMover(char* ptr) : _writePtr(ptr) {}
|
StringMover(char* ptr) : _writePtr(ptr) {}
|
||||||
|
|
||||||
void startString() {
|
void startString() {
|
||||||
_startPtr = _writePtr;
|
_startPtr = _writePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* save() const {
|
FORCE_INLINE string_type save() {
|
||||||
return _startPtr;
|
return _startPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,12 +31,10 @@ class StringMover {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* c_str() const {
|
string_type str() const {
|
||||||
return _startPtr;
|
return string_type(_startPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef storage_policies::store_by_address storage_policy;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* _writePtr;
|
char* _writePtr;
|
||||||
char* _startPtr;
|
char* _startPtr;
|
||||||
|
32
src/ArduinoJson/Strings/StoredString.hpp
Normal file
32
src/ArduinoJson/Strings/StoredString.hpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2021
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
|
||||||
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename TStoragePolicy>
|
||||||
|
class StoredString {
|
||||||
|
public:
|
||||||
|
StoredString(const char* p) : _data(p) {}
|
||||||
|
|
||||||
|
operator const char*() const {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* c_str() const {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef StoredString<storage_policies::store_by_address> LinkedString;
|
||||||
|
typedef StoredString<storage_policies::store_by_copy> CopiedString;
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -173,7 +173,7 @@ struct Converter<SerializedValue<T>,
|
|||||||
VariantData* data = getData(dst);
|
VariantData* data = getData(dst);
|
||||||
MemoryPool* pool = getPool(dst);
|
MemoryPool* pool = getPool(dst);
|
||||||
if (data)
|
if (data)
|
||||||
data->setOwnedRaw(src, pool);
|
data->storeOwnedRaw(src, pool);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ class MemoryPoolPrint : public Print {
|
|||||||
pool->getFreeZone(&_string, &_capacity);
|
pool->getFreeZone(&_string, &_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* c_str() {
|
CopiedString str() {
|
||||||
_string[_size++] = 0;
|
_string[_size++] = 0;
|
||||||
ARDUINOJSON_ASSERT(_size <= _capacity);
|
ARDUINOJSON_ASSERT(_size <= _capacity);
|
||||||
return _pool->saveStringFromFreeZone(_size);
|
return _pool->saveStringFromFreeZone(_size);
|
||||||
@ -250,7 +250,7 @@ inline void convertToJson(const ::Printable& src, VariantRef dst) {
|
|||||||
data->setNull();
|
data->setNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
data->setStringPointer(print.c_str(), storage_policies::store_by_copy());
|
data->setString(print.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,18 +30,18 @@ template <typename TAdaptedString>
|
|||||||
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
|
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
|
||||||
storage_policies::store_by_address) {
|
storage_policies::store_by_address) {
|
||||||
ARDUINOJSON_ASSERT(var);
|
ARDUINOJSON_ASSERT(var);
|
||||||
var->setKey(key.data(), storage_policies::store_by_address());
|
var->setKey(LinkedString(key.data()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
|
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
|
||||||
storage_policies::store_by_copy) {
|
storage_policies::store_by_copy) {
|
||||||
const char* dup = pool->saveString(key);
|
CopiedString dup = pool->saveString(key);
|
||||||
if (!dup)
|
if (!dup)
|
||||||
return false;
|
return false;
|
||||||
ARDUINOJSON_ASSERT(var);
|
ARDUINOJSON_ASSERT(var);
|
||||||
var->setKey(dup, storage_policies::store_by_copy());
|
var->setKey(dup);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,10 +104,10 @@ class VariantData {
|
|||||||
case VALUE_IS_OBJECT:
|
case VALUE_IS_OBJECT:
|
||||||
return toObject().copyFrom(src._content.asCollection, pool);
|
return toObject().copyFrom(src._content.asCollection, pool);
|
||||||
case VALUE_IS_OWNED_STRING:
|
case VALUE_IS_OWNED_STRING:
|
||||||
return setString(adaptString(const_cast<char *>(src._content.asString)),
|
return storeString(
|
||||||
pool);
|
adaptString(const_cast<char *>(src._content.asString)), pool);
|
||||||
case VALUE_IS_OWNED_RAW:
|
case VALUE_IS_OWNED_RAW:
|
||||||
return setOwnedRaw(
|
return storeOwnedRaw(
|
||||||
serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
|
serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
|
||||||
default:
|
default:
|
||||||
setType(src.type());
|
setType(src.type());
|
||||||
@ -194,7 +194,7 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
|
bool storeOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
|
||||||
const char *dup = pool->saveString(adaptString(value.data(), value.size()));
|
const char *dup = pool->saveString(adaptString(value.data(), value.size()));
|
||||||
if (dup) {
|
if (dup) {
|
||||||
setType(VALUE_IS_OWNED_RAW);
|
setType(VALUE_IS_OWNED_RAW);
|
||||||
@ -223,20 +223,20 @@ class VariantData {
|
|||||||
setType(VALUE_IS_NULL);
|
setType(VALUE_IS_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStringPointer(const char *s, storage_policies::store_by_copy) {
|
void setString(CopiedString s) {
|
||||||
ARDUINOJSON_ASSERT(s != 0);
|
ARDUINOJSON_ASSERT(s);
|
||||||
setType(VALUE_IS_OWNED_STRING);
|
setType(VALUE_IS_OWNED_STRING);
|
||||||
_content.asString = s;
|
_content.asString = s.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStringPointer(const char *s, storage_policies::store_by_address) {
|
void setString(LinkedString s) {
|
||||||
ARDUINOJSON_ASSERT(s != 0);
|
ARDUINOJSON_ASSERT(s);
|
||||||
setType(VALUE_IS_LINKED_STRING);
|
setType(VALUE_IS_LINKED_STRING);
|
||||||
_content.asString = s;
|
_content.asString = s.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
bool setString(TAdaptedString value, MemoryPool *pool) {
|
bool storeString(TAdaptedString value, MemoryPool *pool) {
|
||||||
return storeString(value, pool, typename TAdaptedString::storage_policy());
|
return storeString(value, pool, typename TAdaptedString::storage_policy());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +342,7 @@ class VariantData {
|
|||||||
if (value.isNull())
|
if (value.isNull())
|
||||||
setNull();
|
setNull();
|
||||||
else
|
else
|
||||||
setStringPointer(value.data(), storage_policies::store_by_address());
|
setString(LinkedString(value.data()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +358,7 @@ class VariantData {
|
|||||||
setNull();
|
setNull();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
setStringPointer(copy, storage_policies::store_by_copy());
|
setString(CopiedString(copy));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -54,7 +54,7 @@ inline bool variantSetString(VariantData *var, TAdaptedString value,
|
|||||||
MemoryPool *pool) {
|
MemoryPool *pool) {
|
||||||
if (!var)
|
if (!var)
|
||||||
return false;
|
return false;
|
||||||
return var->setString(value, pool);
|
return var->storeString(value, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t variantSize(const VariantData *var) {
|
inline size_t variantSize(const VariantData *var) {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <ArduinoJson/Polyfills/limits.hpp>
|
#include <ArduinoJson/Polyfills/limits.hpp>
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
|
#include <ArduinoJson/Strings/StoredString.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
@ -77,16 +78,16 @@ class VariantSlot {
|
|||||||
_next = VariantSlotDiff(slot - this);
|
_next = VariantSlotDiff(slot - this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setKey(const char* k, storage_policies::store_by_copy) {
|
void setKey(CopiedString k) {
|
||||||
ARDUINOJSON_ASSERT(k != NULL);
|
ARDUINOJSON_ASSERT(k);
|
||||||
_flags |= OWNED_KEY_BIT;
|
_flags |= OWNED_KEY_BIT;
|
||||||
_key = k;
|
_key = k.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setKey(const char* k, storage_policies::store_by_address) {
|
void setKey(LinkedString k) {
|
||||||
ARDUINOJSON_ASSERT(k != NULL);
|
ARDUINOJSON_ASSERT(k);
|
||||||
_flags &= VALUE_MASK;
|
_flags &= VALUE_MASK;
|
||||||
_key = k;
|
_key = k.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* key() const {
|
const char* key() const {
|
||||||
|
Reference in New Issue
Block a user