mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	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