forked from bblanchon/ArduinoJson
Separate string adapter from storage policy
This commit is contained in:
@ -92,10 +92,9 @@ TEST_CASE("StringViewAdapter") {
|
|||||||
std::string_view str("bravoXXX", 5);
|
std::string_view str("bravoXXX", 5);
|
||||||
auto adapter = adaptString(str);
|
auto adapter = adaptString(str);
|
||||||
|
|
||||||
CHECK(adapter.compare(NULL) > 0);
|
CHECK(stringCompare(adapter, adaptString("alpha", 5)) > 0);
|
||||||
CHECK(adapter.compare("alpha") > 0);
|
CHECK(stringCompare(adapter, adaptString("bravo", 5)) == 0);
|
||||||
CHECK(adapter.compare("bravo") == 0);
|
CHECK(stringCompare(adapter, adaptString("charlie", 7)) < 0);
|
||||||
CHECK(adapter.compare("charlie") < 0);
|
|
||||||
|
|
||||||
CHECK(adapter.size() == 5);
|
CHECK(adapter.size() == 5);
|
||||||
}
|
}
|
||||||
|
@ -15,106 +15,75 @@
|
|||||||
|
|
||||||
using namespace ARDUINOJSON_NAMESPACE;
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
TEST_CASE("const char*") {
|
TEST_CASE("ZeroTerminatedRamString") {
|
||||||
SECTION("null") {
|
SECTION("null") {
|
||||||
StringAdapter<const char*> adapter(NULL);
|
ZeroTerminatedRamString s = adaptString(static_cast<const char*>(0));
|
||||||
|
|
||||||
CHECK(adapter.compare("bravo") < 0);
|
CHECK(s.isNull() == true);
|
||||||
CHECK(adapter.compare(NULL) == 0);
|
CHECK(s.size() == 0);
|
||||||
|
|
||||||
CHECK(adapter.size() == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-null") {
|
SECTION("non-null") {
|
||||||
StringAdapter<const char*> adapter("bravo");
|
ZeroTerminatedRamString s = adaptString("bravo");
|
||||||
|
|
||||||
CHECK(adapter.compare(NULL) > 0);
|
CHECK(s.isNull() == false);
|
||||||
CHECK(adapter.compare("alpha") > 0);
|
CHECK(s.size() == 5);
|
||||||
CHECK(adapter.compare("bravo") == 0);
|
|
||||||
CHECK(adapter.compare("charlie") < 0);
|
|
||||||
|
|
||||||
CHECK(adapter.size() == 5);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("const char* + size") {
|
TEST_CASE("SizedRamString") {
|
||||||
SECTION("null") {
|
SECTION("null") {
|
||||||
StringAdapter<const char*, true> adapter(NULL, 10);
|
SizedRamString s = adaptString(static_cast<const char*>(0), 10);
|
||||||
|
|
||||||
CHECK(adapter.compare("bravo") < 0);
|
CHECK(s.isNull() == true);
|
||||||
CHECK(adapter.compare(NULL) == 0);
|
|
||||||
|
|
||||||
CHECK(adapter.size() == 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-null") {
|
SECTION("non-null") {
|
||||||
StringAdapter<const char*, true> adapter("bravo", 5);
|
SizedRamString s = adaptString("bravo", 5);
|
||||||
|
|
||||||
CHECK(adapter.compare(NULL) > 0);
|
CHECK(s.isNull() == false);
|
||||||
CHECK(adapter.compare("alpha") > 0);
|
CHECK(s.size() == 5);
|
||||||
CHECK(adapter.compare("bravo") == 0);
|
|
||||||
CHECK(adapter.compare("charlie") < 0);
|
|
||||||
|
|
||||||
CHECK(adapter.size() == 5);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("const __FlashStringHelper*") {
|
TEST_CASE("FlashString") {
|
||||||
SECTION("null") {
|
SECTION("null") {
|
||||||
StringAdapter<const __FlashStringHelper*> adapter(NULL);
|
FlashString s = adaptString(static_cast<const __FlashStringHelper*>(0));
|
||||||
|
|
||||||
CHECK(adapter.compare("bravo") < 0);
|
CHECK(s.isNull() == true);
|
||||||
CHECK(adapter.compare(NULL) == 0);
|
CHECK(s.size() == 0);
|
||||||
|
|
||||||
CHECK(adapter.size() == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-null") {
|
SECTION("non-null") {
|
||||||
StringAdapter<const __FlashStringHelper*> adapter = adaptString(F("bravo"));
|
FlashString s = adaptString(F("bravo"));
|
||||||
|
|
||||||
CHECK(adapter.compare(NULL) > 0);
|
CHECK(s.isNull() == false);
|
||||||
CHECK(adapter.compare("alpha") > 0);
|
CHECK(s.size() == 5);
|
||||||
CHECK(adapter.compare("bravo") == 0);
|
|
||||||
CHECK(adapter.compare("charlie") < 0);
|
|
||||||
|
|
||||||
CHECK(adapter.size() == 5);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("std::string") {
|
TEST_CASE("std::string") {
|
||||||
std::string str("bravo");
|
std::string orig("bravo");
|
||||||
StringAdapter<std::string> adapter(str);
|
SizedRamString s = adaptString(orig);
|
||||||
|
|
||||||
CHECK(adapter.compare(NULL) > 0);
|
CHECK(s.isNull() == false);
|
||||||
CHECK(adapter.compare("alpha") > 0);
|
CHECK(s.size() == 5);
|
||||||
CHECK(adapter.compare("bravo") == 0);
|
|
||||||
CHECK(adapter.compare("charlie") < 0);
|
|
||||||
|
|
||||||
CHECK(adapter.size() == 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Arduino String") {
|
TEST_CASE("Arduino String") {
|
||||||
::String str("bravo");
|
::String orig("bravo");
|
||||||
StringAdapter< ::String> adapter(str);
|
SizedRamString s = adaptString(orig);
|
||||||
|
|
||||||
CHECK(adapter.compare(NULL) > 0);
|
CHECK(s.isNull() == false);
|
||||||
CHECK(adapter.compare("alpha") > 0);
|
CHECK(s.size() == 5);
|
||||||
CHECK(adapter.compare("bravo") == 0);
|
|
||||||
CHECK(adapter.compare("charlie") < 0);
|
|
||||||
|
|
||||||
CHECK(adapter.size() == 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("custom_string") {
|
TEST_CASE("custom_string") {
|
||||||
custom_string str("bravo");
|
custom_string orig("bravo");
|
||||||
StringAdapter<custom_string> adapter(str);
|
SizedRamString s = adaptString(orig);
|
||||||
|
|
||||||
CHECK(adapter.compare(NULL) > 0);
|
CHECK(s.isNull() == false);
|
||||||
CHECK(adapter.compare("alpha") > 0);
|
CHECK(s.size() == 5);
|
||||||
CHECK(adapter.compare("bravo") == 0);
|
|
||||||
CHECK(adapter.compare("charlie") < 0);
|
|
||||||
|
|
||||||
CHECK(adapter.size() == 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("IsString<T>") {
|
TEST_CASE("IsString<T>") {
|
||||||
@ -142,3 +111,93 @@ TEST_CASE("IsString<T>") {
|
|||||||
CHECK(IsString<const char[8]>::value == true);
|
CHECK(IsString<const char[8]>::value == true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("stringCompare") {
|
||||||
|
SECTION("ZeroTerminatedRamString vs ZeroTerminatedRamString") {
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString("alpha")) > 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString("bravo")) == 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString("charlie")) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ZeroTerminatedRamString vs SizedRamString") {
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString("alpha?", 5)) > 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString("bravo?", 4)) > 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString("bravo?", 5)) == 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString("bravo?", 6)) < 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString("charlie?", 7)) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("SizedRamString vs SizedRamString") {
|
||||||
|
// clang-format off
|
||||||
|
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("alpha?", 5)) > 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo?", 5)) == 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("charlie?", 7)) < 0);
|
||||||
|
|
||||||
|
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo!", 4)) > 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo!", 5)) == 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo!", 5), adaptString("bravo!", 6)) < 0);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("FlashString vs FlashString") {
|
||||||
|
// clang-format off
|
||||||
|
CHECK(stringCompare(adaptString(F("bravo")), adaptString(F("alpha"))) > 0);
|
||||||
|
CHECK(stringCompare(adaptString(F("bravo")), adaptString(F("bravo"))) == 0);
|
||||||
|
CHECK(stringCompare(adaptString(F("bravo")), adaptString(F("charlie"))) < 0);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("FlashString vs SizedRamString") {
|
||||||
|
// clang-format off
|
||||||
|
CHECK(stringCompare(adaptString(F("bravo")), adaptString("alpha?", 5)) > 0);
|
||||||
|
CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo?", 5)) == 0);
|
||||||
|
CHECK(stringCompare(adaptString(F("bravo")), adaptString("charlie?", 7)) < 0);
|
||||||
|
|
||||||
|
CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo!", 4)) > 0);
|
||||||
|
CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo!", 5)) == 0);
|
||||||
|
CHECK(stringCompare(adaptString(F("bravo")), adaptString("bravo!", 6)) < 0);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ZeroTerminatedRamString vs FlashString") {
|
||||||
|
// clang-format off
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString(F("alpha?"), 5)) > 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString(F("bravo?"), 4)) > 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString(F("bravo?"), 5)) == 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString(F("bravo?"), 6)) < 0);
|
||||||
|
CHECK(stringCompare(adaptString("bravo"), adaptString(F("charlie?"), 7)) < 0);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("stringEquals()") {
|
||||||
|
SECTION("ZeroTerminatedRamString vs ZeroTerminatedRamString") {
|
||||||
|
CHECK(stringEquals(adaptString("bravo"), adaptString("brav")) == false);
|
||||||
|
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo")) == true);
|
||||||
|
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!")) == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ZeroTerminatedRamString vs SizedRamString") {
|
||||||
|
// clang-format off
|
||||||
|
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!", 4)) == false);
|
||||||
|
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!", 5)) == true);
|
||||||
|
CHECK(stringEquals(adaptString("bravo"), adaptString("bravo!", 6)) == false);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("FlashString vs SizedRamString") {
|
||||||
|
// clang-format off
|
||||||
|
CHECK(stringEquals(adaptString(F("bravo")), adaptString("bravo!", 4)) == false);
|
||||||
|
CHECK(stringEquals(adaptString(F("bravo")), adaptString("bravo!", 5)) == true);
|
||||||
|
CHECK(stringEquals(adaptString(F("bravo")), adaptString("bravo!", 6)) == false);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("SizedRamString vs SizedRamString") {
|
||||||
|
// clang-format off
|
||||||
|
CHECK(stringEquals(adaptString("bravo?", 5), adaptString("bravo!", 4)) == false);
|
||||||
|
CHECK(stringEquals(adaptString("bravo?", 5), adaptString("bravo!", 5)) == true);
|
||||||
|
CHECK(stringEquals(adaptString("bravo?", 5), adaptString("bravo!", 6)) == false);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,14 +40,15 @@ class CollectionData {
|
|||||||
|
|
||||||
// Object only
|
// Object only
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString, typename TStoragePolicy>
|
||||||
VariantData *addMember(TAdaptedString key, MemoryPool *pool);
|
VariantData *addMember(TAdaptedString key, MemoryPool *pool, TStoragePolicy);
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
VariantData *getMember(TAdaptedString key) const;
|
VariantData *getMember(TAdaptedString key) const;
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString, typename TStoragePolicy>
|
||||||
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool);
|
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool,
|
||||||
|
TStoragePolicy);
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
void removeMember(TAdaptedString key) {
|
void removeMember(TAdaptedString key) {
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Collection/CollectionData.hpp>
|
#include <ArduinoJson/Collection/CollectionData.hpp>
|
||||||
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
@ -34,11 +36,12 @@ inline VariantData* CollectionData::addElement(MemoryPool* pool) {
|
|||||||
return slotData(addSlot(pool));
|
return slotData(addSlot(pool));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString, typename TStoragePolicy>
|
||||||
inline VariantData* CollectionData::addMember(TAdaptedString key,
|
inline VariantData* CollectionData::addMember(TAdaptedString key,
|
||||||
MemoryPool* pool) {
|
MemoryPool* pool,
|
||||||
|
TStoragePolicy storage) {
|
||||||
VariantSlot* slot = addSlot(pool);
|
VariantSlot* slot = addSlot(pool);
|
||||||
if (!slotSetKey(slot, key, pool)) {
|
if (!slotSetKey(slot, key, pool, storage)) {
|
||||||
removeSlot(slot);
|
removeSlot(slot);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -61,10 +64,8 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
|
|||||||
for (VariantSlot* s = src._head; s; s = s->next()) {
|
for (VariantSlot* s = src._head; s; s = s->next()) {
|
||||||
VariantData* var;
|
VariantData* var;
|
||||||
if (s->key() != 0) {
|
if (s->key() != 0) {
|
||||||
if (s->ownsKey())
|
String key(s->key(), !s->ownsKey());
|
||||||
var = addMember(adaptString(const_cast<char*>(s->key())), pool);
|
var = addMember(adaptString(key), pool, getStringStoragePolicy(key));
|
||||||
else
|
|
||||||
var = addMember(adaptString(s->key()), pool);
|
|
||||||
} else {
|
} else {
|
||||||
var = addElement(pool);
|
var = addElement(pool);
|
||||||
}
|
}
|
||||||
@ -105,9 +106,11 @@ inline bool CollectionData::equalsArray(const CollectionData& other) const {
|
|||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
|
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
|
||||||
|
if (key.isNull())
|
||||||
|
return 0;
|
||||||
VariantSlot* slot = _head;
|
VariantSlot* slot = _head;
|
||||||
while (slot) {
|
while (slot) {
|
||||||
if (key.compare(slot->key()) == 0)
|
if (stringEquals(key, adaptString(slot->key())))
|
||||||
break;
|
break;
|
||||||
slot = slot->next();
|
slot = slot->next();
|
||||||
}
|
}
|
||||||
@ -137,9 +140,9 @@ inline VariantData* CollectionData::getMember(TAdaptedString key) const {
|
|||||||
return slot ? slot->data() : 0;
|
return slot ? slot->data() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString, typename TStoragePolicy>
|
||||||
inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
|
inline VariantData* CollectionData::getOrAddMember(
|
||||||
MemoryPool* pool) {
|
TAdaptedString key, MemoryPool* pool, TStoragePolicy storage_policy) {
|
||||||
// ignore null key
|
// ignore null key
|
||||||
if (key.isNull())
|
if (key.isNull())
|
||||||
return 0;
|
return 0;
|
||||||
@ -149,7 +152,7 @@ inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
|
|||||||
if (slot)
|
if (slot)
|
||||||
return slot->data();
|
return slot->data();
|
||||||
|
|
||||||
return addMember(key, pool);
|
return addMember(key, pool, storage_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VariantData* CollectionData::getElement(size_t index) const {
|
inline VariantData* CollectionData::getElement(size_t index) const {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||||
#include <ArduinoJson/Object/MemberProxy.hpp>
|
#include <ArduinoJson/Object/MemberProxy.hpp>
|
||||||
#include <ArduinoJson/Object/ObjectRef.hpp>
|
#include <ArduinoJson/Object/ObjectRef.hpp>
|
||||||
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantRef.hpp>
|
#include <ArduinoJson/Variant/VariantRef.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantTo.hpp>
|
#include <ArduinoJson/Variant/VariantTo.hpp>
|
||||||
|
|
||||||
@ -244,14 +245,18 @@ class JsonDocument : public Visitable {
|
|||||||
// getOrAddMember(const __FlashStringHelper*)
|
// getOrAddMember(const __FlashStringHelper*)
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
FORCE_INLINE VariantRef getOrAddMember(TChar* key) {
|
FORCE_INLINE VariantRef getOrAddMember(TChar* key) {
|
||||||
return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
|
return VariantRef(&_pool,
|
||||||
|
_data.getOrAddMember(adaptString(key), &_pool,
|
||||||
|
getStringStoragePolicy(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// getOrAddMember(const std::string&)
|
// getOrAddMember(const std::string&)
|
||||||
// getOrAddMember(const String&)
|
// getOrAddMember(const String&)
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
FORCE_INLINE VariantRef getOrAddMember(const TString& key) {
|
FORCE_INLINE VariantRef getOrAddMember(const TString& key) {
|
||||||
return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
|
return VariantRef(&_pool,
|
||||||
|
_data.getOrAddMember(adaptString(key), &_pool,
|
||||||
|
getStringStoragePolicy(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE VariantRef addElement() {
|
FORCE_INLINE VariantRef addElement() {
|
||||||
|
@ -60,7 +60,7 @@ class MemoryPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
const char* saveString(const TAdaptedString& str) {
|
const char* saveString(TAdaptedString str) {
|
||||||
if (str.isNull())
|
if (str.isNull())
|
||||||
return CopiedString();
|
return CopiedString();
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ class MemoryPool {
|
|||||||
|
|
||||||
char* newCopy = allocString(n + 1);
|
char* newCopy = allocString(n + 1);
|
||||||
if (newCopy) {
|
if (newCopy) {
|
||||||
str.copyTo(newCopy, n);
|
stringGetChars(str, newCopy, n);
|
||||||
newCopy[n] = 0; // force null-terminator
|
newCopy[n] = 0; // force null-terminator
|
||||||
}
|
}
|
||||||
return CopiedString(newCopy, n);
|
return CopiedString(newCopy, n);
|
||||||
@ -165,22 +165,11 @@ class MemoryPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
|
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
|
||||||
template <typename TAdaptedString>
|
|
||||||
static bool stringEquals(const char* p, size_t n, const TAdaptedString& s) {
|
|
||||||
if (p[n]) // check terminator first
|
|
||||||
return false;
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
if (p[i] != s[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
const char* findString(const TAdaptedString& str) const {
|
const char* findString(const TAdaptedString& str) const {
|
||||||
size_t n = str.size();
|
size_t n = str.size();
|
||||||
for (char* next = _begin; next + n < _left; ++next) {
|
for (char* next = _begin; next + n < _left; ++next) {
|
||||||
if (stringEquals(next, n, str))
|
if (next[n] == '\0' && stringEquals(str, adaptString(next, n)))
|
||||||
return next;
|
return next;
|
||||||
|
|
||||||
// jump to next terminator
|
// jump to next terminator
|
||||||
|
@ -40,12 +40,13 @@ void objectRemove(CollectionData *obj, TAdaptedString key) {
|
|||||||
obj->removeMember(key);
|
obj->removeMember(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString, typename TStoragePolicy>
|
||||||
inline VariantData *objectGetOrAddMember(CollectionData *obj,
|
inline VariantData *objectGetOrAddMember(CollectionData *obj,
|
||||||
TAdaptedString key, MemoryPool *pool) {
|
TAdaptedString key, MemoryPool *pool,
|
||||||
|
TStoragePolicy storage_policy) {
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return obj->getOrAddMember(key, pool);
|
return obj->getOrAddMember(key, pool, storage_policy);
|
||||||
}
|
}
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -196,7 +196,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
|
|||||||
template <typename TString>
|
template <typename TString>
|
||||||
FORCE_INLINE VariantRef getOrAddMember(const TString& key) const {
|
FORCE_INLINE VariantRef getOrAddMember(const TString& key) const {
|
||||||
return VariantRef(_pool,
|
return VariantRef(_pool,
|
||||||
objectGetOrAddMember(_data, adaptString(key), _pool));
|
objectGetOrAddMember(_data, adaptString(key), _pool,
|
||||||
|
getStringStoragePolicy(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// getOrAddMember(char*) const
|
// getOrAddMember(char*) const
|
||||||
@ -205,7 +206,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
|
|||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
FORCE_INLINE VariantRef getOrAddMember(TChar* key) const {
|
FORCE_INLINE VariantRef getOrAddMember(TChar* key) const {
|
||||||
return VariantRef(_pool,
|
return VariantRef(_pool,
|
||||||
objectGetOrAddMember(_data, adaptString(key), _pool));
|
objectGetOrAddMember(_data, adaptString(key), _pool,
|
||||||
|
getStringStoragePolicy(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE bool operator==(ObjectRef rhs) const {
|
FORCE_INLINE bool operator==(ObjectRef rhs) const {
|
||||||
|
@ -65,6 +65,22 @@ inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef memcmp_P
|
||||||
|
inline int memcmp_P(const void* a, ARDUINOJSON_NAMESPACE::pgm_p b, size_t n) {
|
||||||
|
const uint8_t* p1 = reinterpret_cast<const uint8_t*>(a);
|
||||||
|
const char* p2 = b.address;
|
||||||
|
ARDUINOJSON_ASSERT(p1 != NULL);
|
||||||
|
ARDUINOJSON_ASSERT(p2 != NULL);
|
||||||
|
while (n-- > 0) {
|
||||||
|
uint8_t v1 = *p1++;
|
||||||
|
uint8_t v2 = pgm_read_byte(p2++);
|
||||||
|
if (v1 != v2)
|
||||||
|
return v1 - v2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef memcpy_P
|
#ifndef memcpy_P
|
||||||
inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) {
|
inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) {
|
||||||
uint8_t* d = reinterpret_cast<uint8_t*>(dst);
|
uint8_t* d = reinterpret_cast<uint8_t*>(dst);
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
|
|
||||||
#include <stdint.h> // int8_t
|
|
||||||
#include <string.h> // strcmp
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
inline int safe_strcmp(const char* a, const char* b) {
|
|
||||||
if (a == b)
|
|
||||||
return 0;
|
|
||||||
if (!a)
|
|
||||||
return -1;
|
|
||||||
if (!b)
|
|
||||||
return 1;
|
|
||||||
return strcmp(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int safe_strncmp(const char* a, const char* b, size_t n) {
|
|
||||||
if (a == b)
|
|
||||||
return 0;
|
|
||||||
if (!a)
|
|
||||||
return -1;
|
|
||||||
if (!b)
|
|
||||||
return 1;
|
|
||||||
return strncmp(a, b, n);
|
|
||||||
}
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
24
src/ArduinoJson/Strings/Adapters/ArduinoString.hpp
Normal file
24
src/ArduinoJson/Strings/Adapters/ArduinoString.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2021
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||||
|
#include <ArduinoJson/Strings/IsString.hpp>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
inline SizedRamString adaptString(const ::String& s) {
|
||||||
|
return SizedRamString(s.c_str(), s.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IsString< ::String> : true_type {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IsString< ::StringSumHelper> : true_type {};
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,56 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class StringAdapter< ::String> {
|
|
||||||
public:
|
|
||||||
StringAdapter(const ::String& str) : _str(&str) {}
|
|
||||||
|
|
||||||
void copyTo(char* p, size_t n) const {
|
|
||||||
memcpy(p, _str->c_str(), n);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() const {
|
|
||||||
// Arduino's String::c_str() can return NULL
|
|
||||||
return !_str->c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
int compare(const char* other) const {
|
|
||||||
// Arduino's String::c_str() can return NULL
|
|
||||||
const char* me = _str->c_str();
|
|
||||||
return safe_strcmp(me, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
|
||||||
ARDUINOJSON_ASSERT(_str != 0);
|
|
||||||
return _str->operator[](static_cast<unsigned int>(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const {
|
|
||||||
return _str->length();
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef storage_policies::store_by_copy storage_policy;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const ::String* _str;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class StringAdapter< ::StringSumHelper> : public StringAdapter< ::String> {
|
|
||||||
public:
|
|
||||||
StringAdapter(const ::String& s) : StringAdapter< ::String>(s) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
@ -1,58 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stddef.h> // size_t
|
|
||||||
#include <string.h> // strcmp
|
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
|
||||||
#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class StringAdapter<const char*> {
|
|
||||||
public:
|
|
||||||
StringAdapter(const char* str = 0) : _str(str) {}
|
|
||||||
|
|
||||||
int compare(const char* other) const {
|
|
||||||
return safe_strcmp(_str, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() const {
|
|
||||||
return !_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const {
|
|
||||||
if (!_str)
|
|
||||||
return 0;
|
|
||||||
return strlen(_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
|
||||||
ARDUINOJSON_ASSERT(_str != 0);
|
|
||||||
ARDUINOJSON_ASSERT(i <= size());
|
|
||||||
return _str[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* data() const {
|
|
||||||
return _str;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef storage_policies::store_by_address storage_policy;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const char* _str;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int N>
|
|
||||||
class StringAdapter<const char[N]> : public StringAdapter<const char*> {
|
|
||||||
public:
|
|
||||||
StringAdapter(const char* s) : StringAdapter<const char*>(s) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
80
src/ArduinoJson/Strings/Adapters/FlashString.hpp
Normal file
80
src/ArduinoJson/Strings/Adapters/FlashString.hpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2021
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include <ArduinoJson/Polyfills/pgmspace.hpp>
|
||||||
|
#include <ArduinoJson/Strings/IsString.hpp>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
class FlashString {
|
||||||
|
public:
|
||||||
|
static const size_t typeSortKey = 1;
|
||||||
|
|
||||||
|
FlashString(const __FlashStringHelper* str, size_t sz)
|
||||||
|
: _str(reinterpret_cast<const char*>(str)), _size(sz) {}
|
||||||
|
|
||||||
|
bool isNull() const {
|
||||||
|
return !_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
char operator[](size_t i) const {
|
||||||
|
ARDUINOJSON_ASSERT(_str != 0);
|
||||||
|
ARDUINOJSON_ASSERT(i <= _size);
|
||||||
|
return static_cast<char>(pgm_read_byte(_str + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool stringEquals(FlashString a, SizedRamString b) {
|
||||||
|
ARDUINOJSON_ASSERT(a.typeSortKey < b.typeSortKey);
|
||||||
|
ARDUINOJSON_ASSERT(!a.isNull());
|
||||||
|
ARDUINOJSON_ASSERT(!b.isNull());
|
||||||
|
if (a.size() != b.size())
|
||||||
|
return false;
|
||||||
|
return ::memcmp_P(b.data(), a._str, a._size) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend int stringCompare(FlashString a, SizedRamString b) {
|
||||||
|
ARDUINOJSON_ASSERT(a.typeSortKey < b.typeSortKey);
|
||||||
|
ARDUINOJSON_ASSERT(!a.isNull());
|
||||||
|
ARDUINOJSON_ASSERT(!b.isNull());
|
||||||
|
size_t minsize = a.size() < b.size() ? a.size() : b.size();
|
||||||
|
int res = ::memcmp_P(b.data(), a._str, minsize);
|
||||||
|
if (res)
|
||||||
|
return -res;
|
||||||
|
if (a.size() < b.size())
|
||||||
|
return -1;
|
||||||
|
if (a.size() > b.size())
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void stringGetChars(FlashString s, char* p, size_t n) {
|
||||||
|
ARDUINOJSON_ASSERT(s.size() <= n);
|
||||||
|
::memcpy_P(p, s._str, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* _str;
|
||||||
|
size_t _size;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline FlashString adaptString(const __FlashStringHelper* s) {
|
||||||
|
return FlashString(s, s ? strlen_P(reinterpret_cast<const char*>(s)) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FlashString adaptString(const __FlashStringHelper* s, size_t n) {
|
||||||
|
return FlashString(s, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IsString<const __FlashStringHelper*> : true_type {};
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,55 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/pgmspace.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class StringAdapter<const __FlashStringHelper*> {
|
|
||||||
public:
|
|
||||||
StringAdapter(const __FlashStringHelper* str) : _str(str) {}
|
|
||||||
|
|
||||||
int compare(const char* other) const {
|
|
||||||
if (!other && !_str)
|
|
||||||
return 0;
|
|
||||||
if (!_str)
|
|
||||||
return -1;
|
|
||||||
if (!other)
|
|
||||||
return 1;
|
|
||||||
return -strcmp_P(other, reinterpret_cast<const char*>(_str));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() const {
|
|
||||||
return !_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyTo(char* p, size_t n) const {
|
|
||||||
memcpy_P(p, reinterpret_cast<const char*>(_str), n);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const {
|
|
||||||
if (!_str)
|
|
||||||
return 0;
|
|
||||||
return strlen_P(reinterpret_cast<const char*>(_str));
|
|
||||||
}
|
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
|
||||||
ARDUINOJSON_ASSERT(_str != 0);
|
|
||||||
ARDUINOJSON_ASSERT(i <= size());
|
|
||||||
return static_cast<char>(
|
|
||||||
pgm_read_byte(reinterpret_cast<const char*>(_str) + i));
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef storage_policies::store_by_copy storage_policy;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const __FlashStringHelper* _str;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
20
src/ArduinoJson/Strings/Adapters/JsonString.hpp
Normal file
20
src/ArduinoJson/Strings/Adapters/JsonString.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2021
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||||
|
#include <ArduinoJson/Strings/IsString.hpp>
|
||||||
|
#include <ArduinoJson/Strings/String.hpp>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
inline SizedRamString adaptString(const String& s) {
|
||||||
|
return SizedRamString(s.c_str(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IsString<String> : true_type {};
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,27 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Strings/Adapters/RamStringAdapter.hpp>
|
|
||||||
#include <ArduinoJson/Strings/String.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class StringAdapter<String> : public StringAdapter<char*> {
|
|
||||||
public:
|
|
||||||
StringAdapter(const String& str)
|
|
||||||
: StringAdapter<char*>(str.c_str()), _isStatic(str.isStatic()) {}
|
|
||||||
|
|
||||||
bool isStatic() const {
|
|
||||||
return _isStatic;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef storage_policies::decide_at_runtime storage_policy;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool _isStatic;
|
|
||||||
};
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
119
src/ArduinoJson/Strings/Adapters/RamString.hpp
Normal file
119
src/ArduinoJson/Strings/Adapters/RamString.hpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2021
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h> // size_t
|
||||||
|
#include <string.h> // strcmp
|
||||||
|
|
||||||
|
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||||
|
#include <ArduinoJson/Strings/IsString.hpp>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
class ZeroTerminatedRamString {
|
||||||
|
public:
|
||||||
|
static const size_t typeSortKey = 3;
|
||||||
|
|
||||||
|
ZeroTerminatedRamString(const char* str) : _str(str) {}
|
||||||
|
|
||||||
|
bool isNull() const {
|
||||||
|
return !_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return _str ? ::strlen(_str) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char operator[](size_t i) const {
|
||||||
|
ARDUINOJSON_ASSERT(_str != 0);
|
||||||
|
ARDUINOJSON_ASSERT(i <= size());
|
||||||
|
return _str[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* data() const {
|
||||||
|
return _str;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend int stringCompare(ZeroTerminatedRamString a,
|
||||||
|
ZeroTerminatedRamString b) {
|
||||||
|
ARDUINOJSON_ASSERT(!a.isNull());
|
||||||
|
ARDUINOJSON_ASSERT(!b.isNull());
|
||||||
|
return ::strcmp(a._str, b._str);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool stringEquals(ZeroTerminatedRamString a,
|
||||||
|
ZeroTerminatedRamString b) {
|
||||||
|
return stringCompare(a, b) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char* _str;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IsString<char*> : true_type {};
|
||||||
|
|
||||||
|
inline ZeroTerminatedRamString adaptString(const char* s) {
|
||||||
|
return ZeroTerminatedRamString(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IsString<unsigned char*> : true_type {};
|
||||||
|
|
||||||
|
inline ZeroTerminatedRamString adaptString(const unsigned char* s) {
|
||||||
|
return adaptString(reinterpret_cast<const char*>(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IsString<signed char*> : true_type {};
|
||||||
|
|
||||||
|
inline ZeroTerminatedRamString adaptString(const signed char* s) {
|
||||||
|
return adaptString(reinterpret_cast<const char*>(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
class SizedRamString {
|
||||||
|
public:
|
||||||
|
static const size_t typeSortKey = 2;
|
||||||
|
|
||||||
|
SizedRamString(const char* str, size_t sz) : _str(str), _size(sz) {}
|
||||||
|
|
||||||
|
bool isNull() const {
|
||||||
|
return !_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
char operator[](size_t i) const {
|
||||||
|
ARDUINOJSON_ASSERT(_str != 0);
|
||||||
|
ARDUINOJSON_ASSERT(i <= size());
|
||||||
|
return _str[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* data() const {
|
||||||
|
return _str;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const char* _str;
|
||||||
|
size_t _size;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline SizedRamString adaptString(const char* s, size_t n) {
|
||||||
|
return SizedRamString(s, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
struct IsString<char[N]> : true_type {};
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
struct IsString<const char[N]> : true_type {};
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
inline SizedRamString adaptString(char s[N]) {
|
||||||
|
return SizedRamString(s, strlen(s));
|
||||||
|
}
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,29 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <typename TChar>
|
|
||||||
class StringAdapter<TChar*, false,
|
|
||||||
typename enable_if<sizeof(TChar) == 1 &&
|
|
||||||
!is_same<TChar, void>::value>::type>
|
|
||||||
: public StringAdapter<const char*> {
|
|
||||||
public:
|
|
||||||
StringAdapter(const TChar* str)
|
|
||||||
: StringAdapter<const char*>(reinterpret_cast<const char*>(str)) {}
|
|
||||||
|
|
||||||
void copyTo(char* p, size_t n) const {
|
|
||||||
memcpy(p, _str, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef ARDUINOJSON_NAMESPACE::storage_policies::store_by_copy storage_policy;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
@ -1,56 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class StringAdapter<const __FlashStringHelper*, true> {
|
|
||||||
public:
|
|
||||||
StringAdapter(const __FlashStringHelper* str, size_t sz)
|
|
||||||
: _str(str), _size(sz) {}
|
|
||||||
|
|
||||||
int compare(const char* other) const {
|
|
||||||
if (!other && !_str)
|
|
||||||
return 0;
|
|
||||||
if (!_str)
|
|
||||||
return -1;
|
|
||||||
if (!other)
|
|
||||||
return 1;
|
|
||||||
return -strncmp_P(other, reinterpret_cast<const char*>(_str), _size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() const {
|
|
||||||
return !_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyTo(char* p, size_t n) const {
|
|
||||||
memcpy_P(p, reinterpret_cast<const char*>(_str), n);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: not covered by the tests
|
|
||||||
char operator[](size_t i) const {
|
|
||||||
ARDUINOJSON_ASSERT(_str != 0);
|
|
||||||
ARDUINOJSON_ASSERT(i <= _size);
|
|
||||||
return static_cast<char>(
|
|
||||||
pgm_read_byte(reinterpret_cast<const char*>(_str) + i));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const {
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef storage_policies::store_by_copy storage_policy;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const __FlashStringHelper* _str;
|
|
||||||
size_t _size;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
@ -1,49 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
|
||||||
|
|
||||||
#include <string.h> // strcmp
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <typename TChar>
|
|
||||||
class StringAdapter<TChar*, true> {
|
|
||||||
public:
|
|
||||||
StringAdapter(const char* str, size_t n) : _str(str), _size(n) {}
|
|
||||||
|
|
||||||
int compare(const char* other) const {
|
|
||||||
return safe_strncmp(_str, other, _size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() const {
|
|
||||||
return !_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyTo(char* p, size_t n) const {
|
|
||||||
memcpy(p, _str, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const {
|
|
||||||
return _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
|
||||||
ARDUINOJSON_ASSERT(_str != 0);
|
|
||||||
ARDUINOJSON_ASSERT(i <= _size);
|
|
||||||
return _str[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef storage_policies::store_by_copy storage_policy;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char* _str;
|
|
||||||
size_t _size;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
23
src/ArduinoJson/Strings/Adapters/StdString.hpp
Normal file
23
src/ArduinoJson/Strings/Adapters/StdString.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2021
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename TCharTraits, typename TAllocator>
|
||||||
|
inline SizedRamString adaptString(
|
||||||
|
const std::basic_string<char, TCharTraits, TAllocator>& s) {
|
||||||
|
return SizedRamString(s.c_str(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TCharTraits, typename TAllocator>
|
||||||
|
struct IsString<std::basic_string<char, TCharTraits, TAllocator> > : true_type {
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,51 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <typename TCharTraits, typename TAllocator>
|
|
||||||
class StringAdapter<std::basic_string<char, TCharTraits, TAllocator> > {
|
|
||||||
public:
|
|
||||||
typedef std::basic_string<char, TCharTraits, TAllocator> string_type;
|
|
||||||
|
|
||||||
StringAdapter(const string_type& str) : _str(&str) {}
|
|
||||||
|
|
||||||
void copyTo(char* p, size_t n) const {
|
|
||||||
memcpy(p, _str->c_str(), n);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int compare(const char* other) const {
|
|
||||||
if (!other)
|
|
||||||
return 1;
|
|
||||||
return _str->compare(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
|
||||||
ARDUINOJSON_ASSERT(i <= size());
|
|
||||||
return _str->operator[](i);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const {
|
|
||||||
return _str->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef storage_policies::store_by_copy storage_policy;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const string_type* _str;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
20
src/ArduinoJson/Strings/Adapters/StringView.hpp
Normal file
20
src/ArduinoJson/Strings/Adapters/StringView.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2021
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
inline SizedRamString adaptString(const std::string_view& s) {
|
||||||
|
return SizedRamString(s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct IsString<std::string_view> : true_type {};
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,49 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class StringAdapter<std::string_view> {
|
|
||||||
public:
|
|
||||||
StringAdapter(std::string_view str) : _str(str) {}
|
|
||||||
|
|
||||||
void copyTo(char* p, size_t n) const {
|
|
||||||
memcpy(p, _str.data(), n);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNull() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int compare(const char* other) const {
|
|
||||||
if (!other)
|
|
||||||
return 1;
|
|
||||||
return _str.compare(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
|
||||||
ARDUINOJSON_ASSERT(i <= size());
|
|
||||||
return _str[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const {
|
|
||||||
return _str.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef storage_policies::store_by_copy storage_policy;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string_view _str;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
17
src/ArduinoJson/Strings/IsString.hpp
Normal file
17
src/ArduinoJson/Strings/IsString.hpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2021
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename T, typename Enable = void>
|
||||||
|
struct IsString : false_type {};
|
||||||
|
|
||||||
|
template <typename TChar>
|
||||||
|
struct IsString<const TChar*> : IsString<TChar*> {};
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -4,12 +4,56 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||||
|
#include <ArduinoJson/Strings/StoredString.hpp>
|
||||||
|
#include <ArduinoJson/Strings/String.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
namespace storage_policies {
|
struct LinkStringStoragePolicy {
|
||||||
struct store_by_address {};
|
template <typename TAdaptedString, typename TCallback>
|
||||||
struct store_by_copy {};
|
bool store(TAdaptedString str, MemoryPool *, TCallback callback) {
|
||||||
struct decide_at_runtime {};
|
LinkedString storedString(str.data(), str.size());
|
||||||
} // namespace storage_policies
|
callback(storedString);
|
||||||
|
return !str.isNull();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CopyStringStoragePolicy {
|
||||||
|
typedef CopiedString TResult;
|
||||||
|
|
||||||
|
template <typename TAdaptedString, typename TCallback>
|
||||||
|
bool store(TAdaptedString str, MemoryPool *pool, TCallback callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
class LinkOrCopyStringStoragePolicy : LinkStringStoragePolicy,
|
||||||
|
CopyStringStoragePolicy {
|
||||||
|
public:
|
||||||
|
LinkOrCopyStringStoragePolicy(bool link) : _link(link) {}
|
||||||
|
|
||||||
|
template <typename TAdaptedString, typename TCallback>
|
||||||
|
bool store(TAdaptedString str, MemoryPool *pool, TCallback callback) {
|
||||||
|
if (_link)
|
||||||
|
return LinkStringStoragePolicy::store(str, pool, callback);
|
||||||
|
else
|
||||||
|
return CopyStringStoragePolicy::store(str, pool, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _link;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline CopyStringStoragePolicy getStringStoragePolicy(const T &) {
|
||||||
|
return CopyStringStoragePolicy();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LinkStringStoragePolicy getStringStoragePolicy(const char *) {
|
||||||
|
return LinkStringStoragePolicy();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LinkOrCopyStringStoragePolicy getStringStoragePolicy(const String &s) {
|
||||||
|
return LinkOrCopyStringStoragePolicy(s.isStatic());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -4,12 +4,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
|
|
||||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TStoragePolicy>
|
template <bool linked>
|
||||||
class StoredString {
|
class StoredString {
|
||||||
public:
|
public:
|
||||||
StoredString() : _data(0), _size(0) {}
|
StoredString() : _data(0), _size(0) {}
|
||||||
@ -32,7 +29,7 @@ class StoredString {
|
|||||||
size_t _size;
|
size_t _size;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef StoredString<storage_policies::store_by_address> LinkedString;
|
typedef StoredString<true> LinkedString;
|
||||||
typedef StoredString<storage_policies::store_by_copy> CopiedString;
|
typedef StoredString<false> CopiedString;
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
// ArduinoJson - https://arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2021
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
template <typename T, bool bounded = false, typename Enable = void>
|
|
||||||
class StringAdapter;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline StringAdapter<T, false> adaptString(const T& str) {
|
|
||||||
return StringAdapter<T, false>(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline StringAdapter<T, true> adaptString(const T& str, size_t sz) {
|
|
||||||
return StringAdapter<T, true>(str, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Enable = void>
|
|
||||||
struct IsString : false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct IsString<
|
|
||||||
T, typename make_void<typename StringAdapter<T>::storage_policy>::type>
|
|
||||||
: true_type {};
|
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
@ -4,24 +4,85 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Strings/Adapters/ConstRamStringAdapter.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
#include <ArduinoJson/Strings/Adapters/JsonStringAdapter.hpp>
|
#include <ArduinoJson/Strings/Adapters/JsonString.hpp>
|
||||||
#include <ArduinoJson/Strings/Adapters/RamStringAdapter.hpp>
|
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||||
#include <ArduinoJson/Strings/Adapters/SizedRamStringAdapter.hpp>
|
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STRING
|
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||||
# include <ArduinoJson/Strings/Adapters/StdStringAdapter.hpp>
|
# include <ArduinoJson/Strings/Adapters/StdString.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STRING_VIEW
|
#if ARDUINOJSON_ENABLE_STRING_VIEW
|
||||||
# include <ArduinoJson/Strings/Adapters/StringViewAdapter.hpp>
|
# include <ArduinoJson/Strings/Adapters/StringView.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||||
# include <ArduinoJson/Strings/Adapters/ArduinoStringAdapter.hpp>
|
# include <ArduinoJson/Strings/Adapters/ArduinoString.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||||
# include <ArduinoJson/Strings/Adapters/FlashStringAdapter.hpp>
|
# include <ArduinoJson/Strings/Adapters/FlashString.hpp>
|
||||||
# include <ArduinoJson/Strings/Adapters/SizedFlashStringAdapter.hpp>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename TAdaptedString1, typename TAdaptedString2>
|
||||||
|
typename enable_if<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey,
|
||||||
|
int>::type
|
||||||
|
stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) {
|
||||||
|
ARDUINOJSON_ASSERT(!s1.isNull());
|
||||||
|
ARDUINOJSON_ASSERT(!s2.isNull());
|
||||||
|
size_t size1 = s1.size();
|
||||||
|
size_t size2 = s2.size();
|
||||||
|
size_t n = size1 < size2 ? size1 : size2;
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
if (s1[i] != s2[i])
|
||||||
|
return s1[i] - s2[i];
|
||||||
|
}
|
||||||
|
if (size1 < size2)
|
||||||
|
return -1;
|
||||||
|
if (size1 > size2)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString1, typename TAdaptedString2>
|
||||||
|
typename enable_if<
|
||||||
|
(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), int>::type
|
||||||
|
stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) {
|
||||||
|
return -stringCompare(s2, s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString1, typename TAdaptedString2>
|
||||||
|
typename enable_if<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey,
|
||||||
|
bool>::type
|
||||||
|
stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) {
|
||||||
|
ARDUINOJSON_ASSERT(!s1.isNull());
|
||||||
|
ARDUINOJSON_ASSERT(!s2.isNull());
|
||||||
|
size_t size1 = s1.size();
|
||||||
|
size_t size2 = s2.size();
|
||||||
|
if (size1 != size2)
|
||||||
|
return false;
|
||||||
|
for (size_t i = 0; i < size1; i++) {
|
||||||
|
if (s1[i] != s2[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString1, typename TAdaptedString2>
|
||||||
|
typename enable_if<
|
||||||
|
(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), bool>::type
|
||||||
|
stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) {
|
||||||
|
return stringEquals(s2, s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString>
|
||||||
|
static void stringGetChars(TAdaptedString s, char* p, size_t n) {
|
||||||
|
ARDUINOJSON_ASSERT(s.size() <= n);
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
p[i] = s[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -115,7 +115,8 @@ struct Converter<T, typename enable_if<is_floating_point<T>::value>::type> {
|
|||||||
template <>
|
template <>
|
||||||
struct Converter<const char*> {
|
struct Converter<const char*> {
|
||||||
static void toJson(const char* src, VariantRef dst) {
|
static void toJson(const char* src, VariantRef dst) {
|
||||||
variantSetString(getData(dst), adaptString(src), getPool(dst));
|
variantSetString(getData(dst), adaptString(src), getPool(dst),
|
||||||
|
getStringStoragePolicy(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* fromJson(VariantConstRef src) {
|
static const char* fromJson(VariantConstRef src) {
|
||||||
@ -132,7 +133,8 @@ struct Converter<const char*> {
|
|||||||
template <>
|
template <>
|
||||||
struct Converter<String> {
|
struct Converter<String> {
|
||||||
static void toJson(String src, VariantRef dst) {
|
static void toJson(String src, VariantRef dst) {
|
||||||
variantSetString(getData(dst), adaptString(src), getPool(dst));
|
variantSetString(getData(dst), adaptString(src), getPool(dst),
|
||||||
|
getStringStoragePolicy(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
static String fromJson(VariantConstRef src) {
|
static String fromJson(VariantConstRef src) {
|
||||||
@ -151,7 +153,8 @@ inline typename enable_if<IsString<T>::value, bool>::type convertToJson(
|
|||||||
const T& src, VariantRef dst) {
|
const T& src, VariantRef dst) {
|
||||||
VariantData* data = getData(dst);
|
VariantData* data = getData(dst);
|
||||||
MemoryPool* pool = getPool(dst);
|
MemoryPool* pool = getPool(dst);
|
||||||
return variantSetString(data, adaptString(src), pool);
|
return variantSetString(data, adaptString(src), pool,
|
||||||
|
getStringStoragePolicy(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -9,40 +9,24 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
struct SlotKeySetter {
|
||||||
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
|
SlotKeySetter(VariantSlot* instance) : _instance(instance) {}
|
||||||
if (!var)
|
|
||||||
return false;
|
|
||||||
return slotSetKey(var, key, pool, typename TAdaptedString::storage_policy());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TStoredString>
|
||||||
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
|
void operator()(TStoredString s) {
|
||||||
storage_policies::decide_at_runtime) {
|
if (!s)
|
||||||
if (key.isStatic()) {
|
return;
|
||||||
return slotSetKey(var, key, pool, storage_policies::store_by_address());
|
ARDUINOJSON_ASSERT(_instance != 0);
|
||||||
} else {
|
_instance->setKey(s);
|
||||||
return slotSetKey(var, key, pool, storage_policies::store_by_copy());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
VariantSlot* _instance;
|
||||||
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
|
};
|
||||||
storage_policies::store_by_address) {
|
|
||||||
ARDUINOJSON_ASSERT(var);
|
|
||||||
var->setKey(LinkedString(key.data(), key.size()));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString, typename TStoragePolicy>
|
||||||
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
|
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
|
||||||
storage_policies::store_by_copy) {
|
TStoragePolicy storage) {
|
||||||
CopiedString dup(pool->saveString(key), key.size());
|
return storage.store(key, pool, SlotKeySetter(var));
|
||||||
if (!dup)
|
|
||||||
return false;
|
|
||||||
ARDUINOJSON_ASSERT(var);
|
|
||||||
var->setKey(dup);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t slotSize(const VariantSlot* var) {
|
inline size_t slotSize(const VariantSlot* var) {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include <ArduinoJson/Misc/Visitable.hpp>
|
#include <ArduinoJson/Misc/Visitable.hpp>
|
||||||
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
|
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <ArduinoJson/Variant/Visitor.hpp>
|
#include <ArduinoJson/Variant/Visitor.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
@ -23,12 +23,12 @@ struct Comparer;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct Comparer<T, typename enable_if<IsString<T>::value>::type>
|
struct Comparer<T, typename enable_if<IsString<T>::value>::type>
|
||||||
: ComparerBase {
|
: ComparerBase {
|
||||||
T rhs;
|
T rhs; // TODO: store adapted string?
|
||||||
|
|
||||||
explicit Comparer(T value) : rhs(value) {}
|
explicit Comparer(T value) : rhs(value) {}
|
||||||
|
|
||||||
CompareResult visitString(const char *lhs, size_t) {
|
CompareResult visitString(const char *lhs, size_t n) {
|
||||||
int i = adaptString(rhs).compare(lhs);
|
int i = stringCompare(adaptString(rhs), adaptString(lhs, n));
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
return COMPARE_RESULT_GREATER;
|
return COMPARE_RESULT_GREATER;
|
||||||
else if (i > 0)
|
else if (i > 0)
|
||||||
|
@ -99,27 +99,7 @@ class VariantData {
|
|||||||
return const_cast<VariantData *>(this)->asObject();
|
return const_cast<VariantData *>(this)->asObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool copyFrom(const VariantData &src, MemoryPool *pool) {
|
bool copyFrom(const VariantData &src, MemoryPool *pool);
|
||||||
switch (src.type()) {
|
|
||||||
case VALUE_IS_ARRAY:
|
|
||||||
return toArray().copyFrom(src._content.asCollection, pool);
|
|
||||||
case VALUE_IS_OBJECT:
|
|
||||||
return toObject().copyFrom(src._content.asCollection, pool);
|
|
||||||
case VALUE_IS_OWNED_STRING:
|
|
||||||
return storeString(
|
|
||||||
adaptString(const_cast<char *>(src._content.asString.data),
|
|
||||||
src._content.asString.size),
|
|
||||||
pool);
|
|
||||||
case VALUE_IS_OWNED_RAW:
|
|
||||||
return storeOwnedRaw(
|
|
||||||
serialized(src._content.asString.data, src._content.asString.size),
|
|
||||||
pool);
|
|
||||||
default:
|
|
||||||
setType(src.type());
|
|
||||||
_content = src._content;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isArray() const {
|
bool isArray() const {
|
||||||
return (_flags & VALUE_IS_ARRAY) != 0;
|
return (_flags & VALUE_IS_ARRAY) != 0;
|
||||||
@ -242,11 +222,6 @@ class VariantData {
|
|||||||
_content.asString.size = s.size();
|
_content.asString.size = s.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
|
||||||
bool storeString(TAdaptedString value, MemoryPool *pool) {
|
|
||||||
return storeString(value, pool, typename TAdaptedString::storage_policy());
|
|
||||||
}
|
|
||||||
|
|
||||||
CollectionData &toArray() {
|
CollectionData &toArray() {
|
||||||
setType(VALUE_IS_ARRAY);
|
setType(VALUE_IS_ARRAY);
|
||||||
_content.asCollection.clear();
|
_content.asCollection.clear();
|
||||||
@ -307,13 +282,14 @@ class VariantData {
|
|||||||
return isObject() ? _content.asCollection.getMember(key) : 0;
|
return isObject() ? _content.asCollection.getMember(key) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString, typename TStoragePolicy>
|
||||||
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) {
|
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool,
|
||||||
|
TStoragePolicy storage_policy) {
|
||||||
if (isNull())
|
if (isNull())
|
||||||
toObject();
|
toObject();
|
||||||
if (!isObject())
|
if (!isObject())
|
||||||
return 0;
|
return 0;
|
||||||
return _content.asCollection.getOrAddMember(key, pool);
|
return _content.asCollection.getOrAddMember(key, pool, storage_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
|
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
|
||||||
@ -327,46 +303,36 @@ class VariantData {
|
|||||||
return _flags & VALUE_MASK;
|
return _flags & VALUE_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TAdaptedString, typename TStoragePolicy>
|
||||||
|
inline bool storeString(TAdaptedString value, MemoryPool *pool,
|
||||||
|
TStoragePolicy storage) {
|
||||||
|
if (value.isNull()) {
|
||||||
|
setNull();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage.store(value, pool, VariantStringSetter(this));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setType(uint8_t t) {
|
void setType(uint8_t t) {
|
||||||
_flags &= OWNED_KEY_BIT;
|
_flags &= OWNED_KEY_BIT;
|
||||||
_flags |= t;
|
_flags |= t;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
struct VariantStringSetter {
|
||||||
inline bool storeString(TAdaptedString value, MemoryPool *pool,
|
VariantStringSetter(VariantData *instance) : _instance(instance) {}
|
||||||
storage_policies::decide_at_runtime) {
|
|
||||||
if (value.isStatic())
|
|
||||||
return storeString(value, pool, storage_policies::store_by_address());
|
|
||||||
else
|
|
||||||
return storeString(value, pool, storage_policies::store_by_copy());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TStoredString>
|
||||||
inline bool storeString(TAdaptedString value, MemoryPool *,
|
void operator()(TStoredString s) {
|
||||||
storage_policies::store_by_address) {
|
if (s)
|
||||||
if (value.isNull())
|
_instance->setString(s);
|
||||||
setNull();
|
else
|
||||||
else
|
_instance->setNull();
|
||||||
setString(LinkedString(value.data(), value.size()));
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
VariantData *_instance;
|
||||||
inline bool storeString(TAdaptedString value, MemoryPool *pool,
|
};
|
||||||
storage_policies::store_by_copy) {
|
|
||||||
if (value.isNull()) {
|
|
||||||
setNull();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const char *copy = pool->saveString(value);
|
|
||||||
if (!copy) {
|
|
||||||
setNull();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
setString(CopiedString(copy, value.size()));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/attributes.hpp>
|
#include <ArduinoJson/Polyfills/attributes.hpp>
|
||||||
|
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
@ -49,12 +50,10 @@ inline void variantSetNull(VariantData *var) {
|
|||||||
var->setNull();
|
var->setNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString, typename TStoragePolicy>
|
||||||
inline bool variantSetString(VariantData *var, TAdaptedString value,
|
inline bool variantSetString(VariantData *var, TAdaptedString value,
|
||||||
MemoryPool *pool) {
|
MemoryPool *pool, TStoragePolicy storage_policy) {
|
||||||
if (!var)
|
return var != 0 ? var->storeString(value, pool, storage_policy) : 0;
|
||||||
return false;
|
|
||||||
return var->storeString(value, pool);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t variantSize(const VariantData *var) {
|
inline size_t variantSize(const VariantData *var) {
|
||||||
@ -87,14 +86,18 @@ inline NO_INLINE VariantData *variantGetOrAddElement(VariantData *var,
|
|||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key,
|
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key,
|
||||||
MemoryPool *pool) {
|
MemoryPool *pool) {
|
||||||
return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
|
return var != 0 ? var->getOrAddMember(adaptString(key), pool,
|
||||||
|
getStringStoragePolicy(key))
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var,
|
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var,
|
||||||
const TString &key,
|
const TString &key,
|
||||||
MemoryPool *pool) {
|
MemoryPool *pool) {
|
||||||
return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
|
return var != 0 ? var->getOrAddMember(adaptString(key), pool,
|
||||||
|
getStringStoragePolicy(key))
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool variantIsNull(const VariantData *var) {
|
inline bool variantIsNull(const VariantData *var) {
|
||||||
|
@ -81,6 +81,28 @@ inline String VariantData::asString() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool VariantData::copyFrom(const VariantData &src, MemoryPool *pool) {
|
||||||
|
switch (src.type()) {
|
||||||
|
case VALUE_IS_ARRAY:
|
||||||
|
return toArray().copyFrom(src._content.asCollection, pool);
|
||||||
|
case VALUE_IS_OBJECT:
|
||||||
|
return toObject().copyFrom(src._content.asCollection, pool);
|
||||||
|
case VALUE_IS_OWNED_STRING: {
|
||||||
|
String value = src.asString();
|
||||||
|
return storeString(adaptString(value), pool,
|
||||||
|
getStringStoragePolicy(value));
|
||||||
|
}
|
||||||
|
case VALUE_IS_OWNED_RAW:
|
||||||
|
return storeOwnedRaw(
|
||||||
|
serialized(src._content.asString.data, src._content.asString.size),
|
||||||
|
pool);
|
||||||
|
default:
|
||||||
|
setType(src.type());
|
||||||
|
_content = src._content;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type
|
inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type
|
||||||
VariantRef::to() const {
|
VariantRef::to() const {
|
||||||
@ -146,4 +168,15 @@ inline VariantConstRef operator|(VariantConstRef preferedValue,
|
|||||||
inline bool VariantRef::set(char value) const {
|
inline bool VariantRef::set(char value) const {
|
||||||
return set<signed char>(value);
|
return set<signed char>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: move somewhere else
|
||||||
|
template <typename TAdaptedString, typename TCallback>
|
||||||
|
bool CopyStringStoragePolicy::store(TAdaptedString str, MemoryPool *pool,
|
||||||
|
TCallback callback) {
|
||||||
|
const char *copy = pool->saveString(str);
|
||||||
|
CopiedString storedString(copy, str.size());
|
||||||
|
callback(storedString);
|
||||||
|
return copy != 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <ArduinoJson/Polyfills/integer.hpp>
|
#include <ArduinoJson/Polyfills/integer.hpp>
|
||||||
#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/StoredString.hpp>
|
#include <ArduinoJson/Strings/StoredString.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user