forked from bblanchon/ArduinoJson
Inverted dependency between MemoryPool and string adapters.
Inserted a null after each raw string in the pool.
This commit is contained in:
@ -102,13 +102,13 @@ TEST_CASE("JsonArray::add()") {
|
|||||||
|
|
||||||
SECTION("should duplicate char*") {
|
SECTION("should duplicate char*") {
|
||||||
array.add(const_cast<char*>("world"));
|
array.add(const_cast<char*>("world"));
|
||||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
REQUIRE(expectedSize == doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string") {
|
SECTION("should duplicate std::string") {
|
||||||
array.add(std::string("world"));
|
array.add(std::string("world"));
|
||||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
REQUIRE(expectedSize == doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,13 +119,13 @@ TEST_CASE("JsonArray::operator[]") {
|
|||||||
|
|
||||||
SECTION("should duplicate char*") {
|
SECTION("should duplicate char*") {
|
||||||
array[0] = const_cast<char*>("world");
|
array[0] = const_cast<char*>("world");
|
||||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
REQUIRE(expectedSize == doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string") {
|
SECTION("should duplicate std::string") {
|
||||||
array[0] = std::string("world");
|
array[0] = std::string("world");
|
||||||
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
REQUIRE(expectedSize == doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ TEST_CASE("deserialize JSON array with a StaticJsonDocument") {
|
|||||||
|
|
||||||
deserializeJson(doc, " [ \"1234567\" ] ");
|
deserializeJson(doc, " [ \"1234567\" ] ");
|
||||||
|
|
||||||
REQUIRE(JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(8) == doc.memoryUsage());
|
REQUIRE(JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(7) == doc.memoryUsage());
|
||||||
// note: we use a string of 8 bytes to be sure that the StaticMemoryPool
|
// note: we use a string of 8 bytes to be sure that the StaticMemoryPool
|
||||||
// will not insert bytes to enforce alignement
|
// will not insert bytes to enforce alignement
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,8 @@ TEST_CASE("BasicJsonDocument::shrinkToFit()") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("owned raw") {
|
SECTION("owned raw") {
|
||||||
doc.set(serialized(std::string("[{},123]")));
|
doc.set(serialized(std::string("[{},12]")));
|
||||||
testShrinkToFit(doc, "[{},123]", 8);
|
testShrinkToFit(doc, "[{},12]", 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("linked key") {
|
SECTION("linked key") {
|
||||||
|
@ -107,43 +107,43 @@ TEST_CASE("JsonObject::operator[]") {
|
|||||||
|
|
||||||
SECTION("should duplicate char* value") {
|
SECTION("should duplicate char* value") {
|
||||||
obj["hello"] = const_cast<char*>("world");
|
obj["hello"] = const_cast<char*>("world");
|
||||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
REQUIRE(expectedSize == doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate char* key") {
|
SECTION("should duplicate char* key") {
|
||||||
obj[const_cast<char*>("hello")] = "world";
|
obj[const_cast<char*>("hello")] = "world";
|
||||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
REQUIRE(expectedSize == doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate char* key&value") {
|
SECTION("should duplicate char* key&value") {
|
||||||
obj[const_cast<char*>("hello")] = const_cast<char*>("world");
|
obj[const_cast<char*>("hello")] = const_cast<char*>("world");
|
||||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize <= doc.memoryUsage());
|
REQUIRE(expectedSize <= doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string value") {
|
SECTION("should duplicate std::string value") {
|
||||||
obj["hello"] = std::string("world");
|
obj["hello"] = std::string("world");
|
||||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
REQUIRE(expectedSize == doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string key") {
|
SECTION("should duplicate std::string key") {
|
||||||
obj[std::string("hello")] = "world";
|
obj[std::string("hello")] = "world";
|
||||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
REQUIRE(expectedSize == doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate std::string key&value") {
|
SECTION("should duplicate std::string key&value") {
|
||||||
obj[std::string("hello")] = std::string("world");
|
obj[std::string("hello")] = std::string("world");
|
||||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize <= doc.memoryUsage());
|
REQUIRE(expectedSize <= doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("should duplicate a non-static JsonString key") {
|
SECTION("should duplicate a non-static JsonString key") {
|
||||||
obj[JsonString("hello", false)] = "world";
|
obj[JsonString("hello", false)] = "world";
|
||||||
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
|
const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
|
||||||
REQUIRE(expectedSize == doc.memoryUsage());
|
REQUIRE(expectedSize == doc.memoryUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,20 +47,20 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
var1.set(str);
|
var1.set(str);
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
|
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
|
||||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
|
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("stores std::string by copy") {
|
SECTION("stores std::string by copy") {
|
||||||
var1.set(std::string("hello!!"));
|
var1.set(std::string("hello!!"));
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
|
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
|
||||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
|
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("stores Serialized<const char*> by reference") {
|
SECTION("stores Serialized<const char*> by reference") {
|
||||||
var1.set(serialized("hello!!", JSON_STRING_SIZE(8)));
|
var1.set(serialized("hello!!", 8));
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == 0);
|
REQUIRE(doc1.memoryUsage() == 0);
|
||||||
@ -69,18 +69,18 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
|
|||||||
|
|
||||||
SECTION("stores Serialized<char*> by copy") {
|
SECTION("stores Serialized<char*> by copy") {
|
||||||
char str[] = "hello!!";
|
char str[] = "hello!!";
|
||||||
var1.set(serialized(str, 8));
|
var1.set(serialized(str, 7));
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
|
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
|
||||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
|
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("stores Serialized<std::string> by copy") {
|
SECTION("stores Serialized<std::string> by copy") {
|
||||||
var1.set(serialized(std::string("hello!!!")));
|
var1.set(serialized(std::string("hello!!")));
|
||||||
var2.set(var1);
|
var2.set(var1);
|
||||||
|
|
||||||
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
|
REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
|
||||||
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
|
REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,6 @@ TEST_CASE("StringBuilder") {
|
|||||||
str.append('h');
|
str.append('h');
|
||||||
str.complete();
|
str.complete();
|
||||||
|
|
||||||
REQUIRE(JSON_STRING_SIZE(2) == pool.size());
|
REQUIRE(JSON_STRING_SIZE(1) == pool.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,19 +30,19 @@ TEST_CASE("MemoryPool::size()") {
|
|||||||
SECTION("Decreases after freezeString()") {
|
SECTION("Decreases after freezeString()") {
|
||||||
StringSlot a = pool.allocExpandableString();
|
StringSlot a = pool.allocExpandableString();
|
||||||
pool.freezeString(a, 1);
|
pool.freezeString(a, 1);
|
||||||
REQUIRE(pool.size() == JSON_STRING_SIZE(1));
|
REQUIRE(pool.size() == 1);
|
||||||
|
|
||||||
StringSlot b = pool.allocExpandableString();
|
StringSlot b = pool.allocExpandableString();
|
||||||
pool.freezeString(b, 1);
|
pool.freezeString(b, 1);
|
||||||
REQUIRE(pool.size() == 2 * JSON_STRING_SIZE(1));
|
REQUIRE(pool.size() == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Increases after allocFrozenString()") {
|
SECTION("Increases after allocFrozenString()") {
|
||||||
pool.allocFrozenString(0);
|
pool.allocFrozenString(1);
|
||||||
REQUIRE(pool.size() == JSON_STRING_SIZE(0));
|
REQUIRE(pool.size() == 1);
|
||||||
|
|
||||||
pool.allocFrozenString(0);
|
pool.allocFrozenString(2);
|
||||||
REQUIRE(pool.size() == 2 * JSON_STRING_SIZE(0));
|
REQUIRE(pool.size() == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Doesn't grow when memory pool is full") {
|
SECTION("Doesn't grow when memory pool is full") {
|
||||||
|
@ -145,4 +145,12 @@ TEST_CASE("IsString<T>") {
|
|||||||
SECTION("const __FlashStringHelper*") {
|
SECTION("const __FlashStringHelper*") {
|
||||||
CHECK(IsString<const __FlashStringHelper*>::value == true);
|
CHECK(IsString<const __FlashStringHelper*>::value == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("const char*") {
|
||||||
|
CHECK(IsString<const char*>::value == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("const char[]") {
|
||||||
|
CHECK(IsString<const char[8]>::value == true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
template <size_t Capacity>
|
template <size_t Capacity>
|
||||||
static void check(const char* input, DeserializationError expected) {
|
static void check(const char* input, DeserializationError expected) {
|
||||||
StaticJsonDocument<Capacity> variant;
|
StaticJsonDocument<Capacity> doc;
|
||||||
|
|
||||||
DeserializationError error = deserializeMsgPack(variant, input);
|
DeserializationError error = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
CAPTURE(input);
|
CAPTURE(input);
|
||||||
REQUIRE(error == expected);
|
REQUIRE(error == expected);
|
||||||
@ -17,7 +17,7 @@ static void check(const char* input, DeserializationError expected) {
|
|||||||
|
|
||||||
template <size_t Size>
|
template <size_t Size>
|
||||||
static void checkString(const char* input, DeserializationError expected) {
|
static void checkString(const char* input, DeserializationError expected) {
|
||||||
check<JSON_STRING_SIZE(Size)>(input, expected);
|
check<Size>(input, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("deserializeMsgPack(StaticJsonDocument&)") {
|
TEST_CASE("deserializeMsgPack(StaticJsonDocument&)") {
|
||||||
|
@ -60,6 +60,19 @@ class MemoryPool {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
char* saveString(const TAdaptedString& str) {
|
||||||
|
if (str.isNull())
|
||||||
|
return 0;
|
||||||
|
size_t n = str.size();
|
||||||
|
char* dup = allocFrozenString(n + 1);
|
||||||
|
if (dup) {
|
||||||
|
str.copyTo(dup, n);
|
||||||
|
dup[n] = 0; // force null-terminator
|
||||||
|
}
|
||||||
|
return dup;
|
||||||
|
}
|
||||||
|
|
||||||
StringSlot allocExpandableString() {
|
StringSlot allocExpandableString() {
|
||||||
StringSlot s;
|
StringSlot s;
|
||||||
s.value = _left;
|
s.value = _left;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
|
|
||||||
#define JSON_STRING_SIZE(SIZE) (SIZE)
|
#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
@ -16,14 +16,8 @@ class ArduinoStringAdapter {
|
|||||||
public:
|
public:
|
||||||
ArduinoStringAdapter(const ::String& str) : _str(&str) {}
|
ArduinoStringAdapter(const ::String& str) : _str(&str) {}
|
||||||
|
|
||||||
char* save(MemoryPool* pool) const {
|
void copyTo(char* p, size_t n) const {
|
||||||
if (isNull())
|
memcpy(p, _str->c_str(), n);
|
||||||
return NULL;
|
|
||||||
size_t n = _str->length() + 1;
|
|
||||||
char* dup = pool->allocFrozenString(n);
|
|
||||||
if (dup)
|
|
||||||
memcpy(dup, _str->c_str(), n);
|
|
||||||
return dup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
@ -45,7 +39,7 @@ class ArduinoStringAdapter {
|
|||||||
return _str->length();
|
return _str->length();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef storage_policy::store_by_copy storage_policy;
|
typedef storage_policies::store_by_copy storage_policy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ::String* _str;
|
const ::String* _str;
|
||||||
|
@ -39,12 +39,18 @@ class ConstRamStringAdapter {
|
|||||||
return _str;
|
return _str;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef storage_policy::store_by_address storage_policy;
|
typedef storage_policies::store_by_address storage_policy;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const char* _str;
|
const char* _str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IsString<const char*> : true_type {};
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
struct IsString<const char[N]> : true_type {};
|
||||||
|
|
||||||
inline ConstRamStringAdapter adaptString(const char* str) {
|
inline ConstRamStringAdapter adaptString(const char* str) {
|
||||||
return ConstRamStringAdapter(str);
|
return ConstRamStringAdapter(str);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
|
||||||
#include <ArduinoJson/Polyfills/pgmspace.hpp>
|
#include <ArduinoJson/Polyfills/pgmspace.hpp>
|
||||||
#include <ArduinoJson/Strings/IsString.hpp>
|
#include <ArduinoJson/Strings/IsString.hpp>
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
@ -33,14 +32,8 @@ class FlashStringAdapter {
|
|||||||
return !_str;
|
return !_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* save(MemoryPool* pool) const {
|
void copyTo(char* p, size_t n) const {
|
||||||
if (!_str)
|
memcpy_P(p, reinterpret_cast<const char*>(_str), n);
|
||||||
return NULL;
|
|
||||||
size_t n = size() + 1; // copy the terminator
|
|
||||||
char* dup = pool->allocFrozenString(n);
|
|
||||||
if (dup)
|
|
||||||
memcpy_P(dup, reinterpret_cast<const char*>(_str), n);
|
|
||||||
return dup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
@ -49,7 +42,7 @@ class FlashStringAdapter {
|
|||||||
return strlen_P(reinterpret_cast<const char*>(_str));
|
return strlen_P(reinterpret_cast<const char*>(_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef storage_policy::store_by_copy storage_policy;
|
typedef storage_policies::store_by_copy storage_policy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const __FlashStringHelper* _str;
|
const __FlashStringHelper* _str;
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
|
||||||
#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
|
#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
|
||||||
#include <ArduinoJson/Strings/IsString.hpp>
|
#include <ArduinoJson/Strings/IsString.hpp>
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
@ -15,17 +14,11 @@ class RamStringAdapter : public ConstRamStringAdapter {
|
|||||||
public:
|
public:
|
||||||
RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
|
RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
|
||||||
|
|
||||||
char* save(MemoryPool* pool) const {
|
void copyTo(char* p, size_t n) const {
|
||||||
if (!_str)
|
memcpy(p, _str, n);
|
||||||
return NULL;
|
|
||||||
size_t n = size() + 1;
|
|
||||||
char* dup = pool->allocFrozenString(n);
|
|
||||||
if (dup)
|
|
||||||
memcpy(dup, _str, n);
|
|
||||||
return dup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef ARDUINOJSON_NAMESPACE::storage_policy::store_by_copy storage_policy;
|
typedef ARDUINOJSON_NAMESPACE::storage_policies::store_by_copy storage_policy;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
|
@ -33,20 +33,15 @@ class SizedFlashStringAdapter {
|
|||||||
return !_str;
|
return !_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* save(MemoryPool* pool) const {
|
void copyTo(char* p, size_t n) const {
|
||||||
if (!_str)
|
memcpy_P(p, reinterpret_cast<const char*>(_str), n);
|
||||||
return NULL;
|
|
||||||
char* dup = pool->allocFrozenString(_size);
|
|
||||||
if (dup)
|
|
||||||
memcpy_P(dup, reinterpret_cast<const char*>(_str), _size);
|
|
||||||
return dup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef storage_policy::store_by_copy storage_policy;
|
typedef storage_policies::store_by_copy storage_policy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const __FlashStringHelper* _str;
|
const __FlashStringHelper* _str;
|
||||||
|
@ -28,20 +28,15 @@ class SizedRamStringAdapter {
|
|||||||
return !_str;
|
return !_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* save(MemoryPool* pool) const {
|
void copyTo(char* p, size_t n) const {
|
||||||
if (!_str)
|
memcpy(p, _str, n);
|
||||||
return NULL;
|
|
||||||
char* dup = pool->allocFrozenString(_size);
|
|
||||||
if (dup)
|
|
||||||
memcpy(dup, _str, _size);
|
|
||||||
return dup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef storage_policy::store_by_copy storage_policy;
|
typedef storage_policies::store_by_copy storage_policy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* _str;
|
const char* _str;
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
#include <ArduinoJson/Strings/IsString.hpp>
|
#include <ArduinoJson/Strings/IsString.hpp>
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
@ -18,12 +17,8 @@ class StlStringAdapter {
|
|||||||
public:
|
public:
|
||||||
StlStringAdapter(const TString& str) : _str(&str) {}
|
StlStringAdapter(const TString& str) : _str(&str) {}
|
||||||
|
|
||||||
char* save(MemoryPool* pool) const {
|
void copyTo(char* p, size_t n) const {
|
||||||
size_t n = _str->length() + 1;
|
memcpy(p, _str->c_str(), n);
|
||||||
char* dup = pool->allocFrozenString(n);
|
|
||||||
if (dup)
|
|
||||||
memcpy(dup, _str->c_str(), n);
|
|
||||||
return dup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
@ -46,7 +41,7 @@ class StlStringAdapter {
|
|||||||
return _str->size();
|
return _str->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef storage_policy::store_by_copy storage_policy;
|
typedef storage_policies::store_by_copy storage_policy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const TString* _str;
|
const TString* _str;
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
namespace storage_policy {
|
namespace storage_policies {
|
||||||
struct store_by_address {};
|
struct store_by_address {};
|
||||||
struct store_by_copy {};
|
struct store_by_copy {};
|
||||||
struct decide_at_runtime {};
|
struct decide_at_runtime {};
|
||||||
} // namespace storage_policy
|
} // namespace storage_policies
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -38,8 +38,6 @@ class String {
|
|||||||
return strcmp(lhs._data, rhs._data) == 0;
|
return strcmp(lhs._data, rhs._data) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef storage_policy::decide_at_runtime storage_policy;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* _data;
|
const char* _data;
|
||||||
bool _isStatic;
|
bool _isStatic;
|
||||||
@ -54,11 +52,7 @@ class StringAdapter : public RamStringAdapter {
|
|||||||
return _isStatic;
|
return _isStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* save(MemoryPool* pool) const {
|
typedef storage_policies::decide_at_runtime storage_policy;
|
||||||
if (_isStatic)
|
|
||||||
return data();
|
|
||||||
return RamStringAdapter::save(pool);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _isStatic;
|
bool _isStatic;
|
||||||
|
@ -18,17 +18,17 @@ inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
|
|||||||
|
|
||||||
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_policy::decide_at_runtime) {
|
storage_policies::decide_at_runtime) {
|
||||||
if (key.isStatic()) {
|
if (key.isStatic()) {
|
||||||
return slotSetKey(var, key, pool, storage_policy::store_by_address());
|
return slotSetKey(var, key, pool, storage_policies::store_by_address());
|
||||||
} else {
|
} else {
|
||||||
return slotSetKey(var, key, pool, storage_policy::store_by_copy());
|
return slotSetKey(var, key, pool, storage_policies::store_by_copy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
|
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
|
||||||
storage_policy::store_by_address) {
|
storage_policies::store_by_address) {
|
||||||
ARDUINOJSON_ASSERT(var);
|
ARDUINOJSON_ASSERT(var);
|
||||||
var->setLinkedKey(make_not_null(key.data()));
|
var->setLinkedKey(make_not_null(key.data()));
|
||||||
return true;
|
return true;
|
||||||
@ -36,8 +36,8 @@ inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
|
|||||||
|
|
||||||
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_policy::store_by_copy) {
|
storage_policies::store_by_copy) {
|
||||||
const char* dup = key.save(pool);
|
const char* dup = pool->saveString(key);
|
||||||
if (!dup)
|
if (!dup)
|
||||||
return false;
|
return false;
|
||||||
ARDUINOJSON_ASSERT(var);
|
ARDUINOJSON_ASSERT(var);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||||
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
||||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||||
#include <ArduinoJson/Polyfills/gsl/not_null.hpp>
|
#include <ArduinoJson/Polyfills/gsl/not_null.hpp>
|
||||||
@ -191,7 +192,7 @@ class VariantData {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
|
bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
|
||||||
char *dup = adaptString(value.data(), value.size()).save(pool);
|
char *dup = pool->saveString(adaptString(value.data(), value.size()));
|
||||||
if (dup) {
|
if (dup) {
|
||||||
setType(VALUE_IS_OWNED_RAW);
|
setType(VALUE_IS_OWNED_RAW);
|
||||||
_content.asRaw.data = dup;
|
_content.asRaw.data = dup;
|
||||||
@ -265,9 +266,9 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename TAdaptedString>
|
||||||
bool setOwnedString(T value, MemoryPool *pool) {
|
bool setOwnedString(TAdaptedString value, MemoryPool *pool) {
|
||||||
return setOwnedString(value.save(pool));
|
return setOwnedString(pool->saveString(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionData &toArray() {
|
CollectionData &toArray() {
|
||||||
|
@ -119,11 +119,44 @@ inline bool variantSetOwnedString(VariantData *var, char *value) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename TAdaptedString>
|
||||||
inline bool variantSetOwnedString(VariantData *var, T value, MemoryPool *pool) {
|
inline bool variantSetOwnedString(VariantData *var, TAdaptedString value,
|
||||||
|
MemoryPool *pool) {
|
||||||
return var != 0 && var->setOwnedString(value, pool);
|
return var != 0 && var->setOwnedString(value, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
inline bool variantSetString(VariantData *var, TAdaptedString value,
|
||||||
|
MemoryPool *pool,
|
||||||
|
storage_policies::decide_at_runtime) {
|
||||||
|
if (value.isStatic())
|
||||||
|
return variantSetString(var, value, pool,
|
||||||
|
storage_policies::store_by_address());
|
||||||
|
else
|
||||||
|
return variantSetString(var, value, pool,
|
||||||
|
storage_policies::store_by_copy());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
inline bool variantSetString(VariantData *var, TAdaptedString value,
|
||||||
|
MemoryPool *pool) {
|
||||||
|
return variantSetString(var, value, pool,
|
||||||
|
typename TAdaptedString::storage_policy());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
inline bool variantSetString(VariantData *var, TAdaptedString value,
|
||||||
|
MemoryPool *, storage_policies::store_by_address) {
|
||||||
|
return variantSetLinkedString(var, value.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
inline bool variantSetString(VariantData *var, TAdaptedString value,
|
||||||
|
MemoryPool *pool,
|
||||||
|
storage_policies::store_by_copy) {
|
||||||
|
return variantSetOwnedString(var, value, pool);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool variantSetInteger(VariantData *var, T value) {
|
inline bool variantSetInteger(VariantData *var, T value) {
|
||||||
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
|
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||||
#include <ArduinoJson/Misc/Visitable.hpp>
|
#include <ArduinoJson/Misc/Visitable.hpp>
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantAs.hpp>
|
#include <ArduinoJson/Variant/VariantAs.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantFunctions.hpp>
|
#include <ArduinoJson/Variant/VariantFunctions.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantOperators.hpp>
|
#include <ArduinoJson/Variant/VariantOperators.hpp>
|
||||||
@ -213,20 +214,15 @@ class VariantRef : public VariantRefBase<VariantData>,
|
|||||||
FORCE_INLINE bool set(
|
FORCE_INLINE bool set(
|
||||||
const T &value,
|
const T &value,
|
||||||
typename enable_if<IsString<T>::value>::type * = 0) const {
|
typename enable_if<IsString<T>::value>::type * = 0) const {
|
||||||
return variantSetOwnedString(_data, adaptString(value), _pool);
|
return variantSetString(_data, adaptString(value), _pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set(char*)
|
// set(char*)
|
||||||
// set(const __FlashStringHelper*)
|
// set(const __FlashStringHelper*)
|
||||||
|
// set(const char*)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE bool set(
|
FORCE_INLINE bool set(
|
||||||
T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
|
T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
|
||||||
return variantSetOwnedString(_data, adaptString(value), _pool);
|
return variantSetString(_data, adaptString(value), _pool);
|
||||||
}
|
|
||||||
|
|
||||||
// set(const char*);
|
|
||||||
FORCE_INLINE bool set(const char *value) const {
|
|
||||||
return variantSetLinkedString(_data, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set(VariantRef)
|
// set(VariantRef)
|
||||||
@ -247,6 +243,14 @@ class VariantRef : public VariantRefBase<VariantData>,
|
|||||||
return variantSetInteger(_data, static_cast<Integer>(value));
|
return variantSetInteger(_data, static_cast<Integer>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ARDUINOJSON_HAS_NULLPTR
|
||||||
|
// set(nullptr_t)
|
||||||
|
FORCE_INLINE bool set(decltype(nullptr)) const {
|
||||||
|
variantSetNull(_data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE typename VariantAs<T>::type as() const {
|
FORCE_INLINE typename VariantAs<T>::type as() const {
|
||||||
return variantAs<typename VariantAs<T>::type>(_data, _pool);
|
return variantAs<typename VariantAs<T>::type>(_data, _pool);
|
||||||
|
Reference in New Issue
Block a user