mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +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); | ||||
|   auto adapter = adaptString(str); | ||||
|  | ||||
|   CHECK(adapter.compare(NULL) > 0); | ||||
|   CHECK(adapter.compare("alpha") > 0); | ||||
|   CHECK(adapter.compare("bravo") == 0); | ||||
|   CHECK(adapter.compare("charlie") < 0); | ||||
|   CHECK(stringCompare(adapter, adaptString("alpha", 5)) > 0); | ||||
|   CHECK(stringCompare(adapter, adaptString("bravo", 5)) == 0); | ||||
|   CHECK(stringCompare(adapter, adaptString("charlie", 7)) < 0); | ||||
|  | ||||
|   CHECK(adapter.size() == 5); | ||||
| } | ||||
|   | ||||
| @@ -15,106 +15,75 @@ | ||||
|  | ||||
| using namespace ARDUINOJSON_NAMESPACE; | ||||
|  | ||||
| TEST_CASE("const char*") { | ||||
| TEST_CASE("ZeroTerminatedRamString") { | ||||
|   SECTION("null") { | ||||
|     StringAdapter<const char*> adapter(NULL); | ||||
|     ZeroTerminatedRamString s = adaptString(static_cast<const char*>(0)); | ||||
|  | ||||
|     CHECK(adapter.compare("bravo") < 0); | ||||
|     CHECK(adapter.compare(NULL) == 0); | ||||
|  | ||||
|     CHECK(adapter.size() == 0); | ||||
|     CHECK(s.isNull() == true); | ||||
|     CHECK(s.size() == 0); | ||||
|   } | ||||
|  | ||||
|   SECTION("non-null") { | ||||
|     StringAdapter<const char*> adapter("bravo"); | ||||
|     ZeroTerminatedRamString s = adaptString("bravo"); | ||||
|  | ||||
|     CHECK(adapter.compare(NULL) > 0); | ||||
|     CHECK(adapter.compare("alpha") > 0); | ||||
|     CHECK(adapter.compare("bravo") == 0); | ||||
|     CHECK(adapter.compare("charlie") < 0); | ||||
|  | ||||
|     CHECK(adapter.size() == 5); | ||||
|     CHECK(s.isNull() == false); | ||||
|     CHECK(s.size() == 5); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_CASE("const char* + size") { | ||||
| TEST_CASE("SizedRamString") { | ||||
|   SECTION("null") { | ||||
|     StringAdapter<const char*, true> adapter(NULL, 10); | ||||
|     SizedRamString s = adaptString(static_cast<const char*>(0), 10); | ||||
|  | ||||
|     CHECK(adapter.compare("bravo") < 0); | ||||
|     CHECK(adapter.compare(NULL) == 0); | ||||
|  | ||||
|     CHECK(adapter.size() == 10); | ||||
|     CHECK(s.isNull() == true); | ||||
|   } | ||||
|  | ||||
|   SECTION("non-null") { | ||||
|     StringAdapter<const char*, true> adapter("bravo", 5); | ||||
|     SizedRamString s = adaptString("bravo", 5); | ||||
|  | ||||
|     CHECK(adapter.compare(NULL) > 0); | ||||
|     CHECK(adapter.compare("alpha") > 0); | ||||
|     CHECK(adapter.compare("bravo") == 0); | ||||
|     CHECK(adapter.compare("charlie") < 0); | ||||
|  | ||||
|     CHECK(adapter.size() == 5); | ||||
|     CHECK(s.isNull() == false); | ||||
|     CHECK(s.size() == 5); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_CASE("const __FlashStringHelper*") { | ||||
| TEST_CASE("FlashString") { | ||||
|   SECTION("null") { | ||||
|     StringAdapter<const __FlashStringHelper*> adapter(NULL); | ||||
|     FlashString s = adaptString(static_cast<const __FlashStringHelper*>(0)); | ||||
|  | ||||
|     CHECK(adapter.compare("bravo") < 0); | ||||
|     CHECK(adapter.compare(NULL) == 0); | ||||
|  | ||||
|     CHECK(adapter.size() == 0); | ||||
|     CHECK(s.isNull() == true); | ||||
|     CHECK(s.size() == 0); | ||||
|   } | ||||
|  | ||||
|   SECTION("non-null") { | ||||
|     StringAdapter<const __FlashStringHelper*> adapter = adaptString(F("bravo")); | ||||
|     FlashString s = adaptString(F("bravo")); | ||||
|  | ||||
|     CHECK(adapter.compare(NULL) > 0); | ||||
|     CHECK(adapter.compare("alpha") > 0); | ||||
|     CHECK(adapter.compare("bravo") == 0); | ||||
|     CHECK(adapter.compare("charlie") < 0); | ||||
|  | ||||
|     CHECK(adapter.size() == 5); | ||||
|     CHECK(s.isNull() == false); | ||||
|     CHECK(s.size() == 5); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_CASE("std::string") { | ||||
|   std::string str("bravo"); | ||||
|   StringAdapter<std::string> adapter(str); | ||||
|   std::string orig("bravo"); | ||||
|   SizedRamString s = adaptString(orig); | ||||
|  | ||||
|   CHECK(adapter.compare(NULL) > 0); | ||||
|   CHECK(adapter.compare("alpha") > 0); | ||||
|   CHECK(adapter.compare("bravo") == 0); | ||||
|   CHECK(adapter.compare("charlie") < 0); | ||||
|  | ||||
|   CHECK(adapter.size() == 5); | ||||
|   CHECK(s.isNull() == false); | ||||
|   CHECK(s.size() == 5); | ||||
| } | ||||
|  | ||||
| TEST_CASE("Arduino String") { | ||||
|   ::String str("bravo"); | ||||
|   StringAdapter< ::String> adapter(str); | ||||
|   ::String orig("bravo"); | ||||
|   SizedRamString s = adaptString(orig); | ||||
|  | ||||
|   CHECK(adapter.compare(NULL) > 0); | ||||
|   CHECK(adapter.compare("alpha") > 0); | ||||
|   CHECK(adapter.compare("bravo") == 0); | ||||
|   CHECK(adapter.compare("charlie") < 0); | ||||
|  | ||||
|   CHECK(adapter.size() == 5); | ||||
|   CHECK(s.isNull() == false); | ||||
|   CHECK(s.size() == 5); | ||||
| } | ||||
|  | ||||
| TEST_CASE("custom_string") { | ||||
|   custom_string str("bravo"); | ||||
|   StringAdapter<custom_string> adapter(str); | ||||
|   custom_string orig("bravo"); | ||||
|   SizedRamString s = adaptString(orig); | ||||
|  | ||||
|   CHECK(adapter.compare(NULL) > 0); | ||||
|   CHECK(adapter.compare("alpha") > 0); | ||||
|   CHECK(adapter.compare("bravo") == 0); | ||||
|   CHECK(adapter.compare("charlie") < 0); | ||||
|  | ||||
|   CHECK(adapter.size() == 5); | ||||
|   CHECK(s.isNull() == false); | ||||
|   CHECK(s.size() == 5); | ||||
| } | ||||
|  | ||||
| TEST_CASE("IsString<T>") { | ||||
| @@ -142,3 +111,93 @@ TEST_CASE("IsString<T>") { | ||||
|     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 | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   VariantData *addMember(TAdaptedString key, MemoryPool *pool); | ||||
|   template <typename TAdaptedString, typename TStoragePolicy> | ||||
|   VariantData *addMember(TAdaptedString key, MemoryPool *pool, TStoragePolicy); | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   VariantData *getMember(TAdaptedString key) const; | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool); | ||||
|   template <typename TAdaptedString, typename TStoragePolicy> | ||||
|   VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool, | ||||
|                               TStoragePolicy); | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   void removeMember(TAdaptedString key) { | ||||
|   | ||||
| @@ -5,6 +5,8 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/Collection/CollectionData.hpp> | ||||
| #include <ArduinoJson/Strings/StoragePolicy.hpp> | ||||
| #include <ArduinoJson/Strings/StringAdapters.hpp> | ||||
| #include <ArduinoJson/Variant/VariantData.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
| @@ -34,11 +36,12 @@ inline VariantData* CollectionData::addElement(MemoryPool* pool) { | ||||
|   return slotData(addSlot(pool)); | ||||
| } | ||||
|  | ||||
| template <typename TAdaptedString> | ||||
| template <typename TAdaptedString, typename TStoragePolicy> | ||||
| inline VariantData* CollectionData::addMember(TAdaptedString key, | ||||
|                                               MemoryPool* pool) { | ||||
|                                               MemoryPool* pool, | ||||
|                                               TStoragePolicy storage) { | ||||
|   VariantSlot* slot = addSlot(pool); | ||||
|   if (!slotSetKey(slot, key, pool)) { | ||||
|   if (!slotSetKey(slot, key, pool, storage)) { | ||||
|     removeSlot(slot); | ||||
|     return 0; | ||||
|   } | ||||
| @@ -61,10 +64,8 @@ inline bool CollectionData::copyFrom(const CollectionData& src, | ||||
|   for (VariantSlot* s = src._head; s; s = s->next()) { | ||||
|     VariantData* var; | ||||
|     if (s->key() != 0) { | ||||
|       if (s->ownsKey()) | ||||
|         var = addMember(adaptString(const_cast<char*>(s->key())), pool); | ||||
|       else | ||||
|         var = addMember(adaptString(s->key()), pool); | ||||
|       String key(s->key(), !s->ownsKey()); | ||||
|       var = addMember(adaptString(key), pool, getStringStoragePolicy(key)); | ||||
|     } else { | ||||
|       var = addElement(pool); | ||||
|     } | ||||
| @@ -105,9 +106,11 @@ inline bool CollectionData::equalsArray(const CollectionData& other) const { | ||||
|  | ||||
| template <typename TAdaptedString> | ||||
| inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const { | ||||
|   if (key.isNull()) | ||||
|     return 0; | ||||
|   VariantSlot* slot = _head; | ||||
|   while (slot) { | ||||
|     if (key.compare(slot->key()) == 0) | ||||
|     if (stringEquals(key, adaptString(slot->key()))) | ||||
|       break; | ||||
|     slot = slot->next(); | ||||
|   } | ||||
| @@ -137,9 +140,9 @@ inline VariantData* CollectionData::getMember(TAdaptedString key) const { | ||||
|   return slot ? slot->data() : 0; | ||||
| } | ||||
|  | ||||
| template <typename TAdaptedString> | ||||
| inline VariantData* CollectionData::getOrAddMember(TAdaptedString key, | ||||
|                                                    MemoryPool* pool) { | ||||
| template <typename TAdaptedString, typename TStoragePolicy> | ||||
| inline VariantData* CollectionData::getOrAddMember( | ||||
|     TAdaptedString key, MemoryPool* pool, TStoragePolicy storage_policy) { | ||||
|   // ignore null key | ||||
|   if (key.isNull()) | ||||
|     return 0; | ||||
| @@ -149,7 +152,7 @@ inline VariantData* CollectionData::getOrAddMember(TAdaptedString key, | ||||
|   if (slot) | ||||
|     return slot->data(); | ||||
|  | ||||
|   return addMember(key, pool); | ||||
|   return addMember(key, pool, storage_policy); | ||||
| } | ||||
|  | ||||
| inline VariantData* CollectionData::getElement(size_t index) const { | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include <ArduinoJson/Memory/MemoryPool.hpp> | ||||
| #include <ArduinoJson/Object/MemberProxy.hpp> | ||||
| #include <ArduinoJson/Object/ObjectRef.hpp> | ||||
| #include <ArduinoJson/Strings/StoragePolicy.hpp> | ||||
| #include <ArduinoJson/Variant/VariantRef.hpp> | ||||
| #include <ArduinoJson/Variant/VariantTo.hpp> | ||||
|  | ||||
| @@ -244,14 +245,18 @@ class JsonDocument : public Visitable { | ||||
|   // getOrAddMember(const __FlashStringHelper*) | ||||
|   template <typename TChar> | ||||
|   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 String&) | ||||
|   template <typename TString> | ||||
|   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() { | ||||
|   | ||||
| @@ -60,7 +60,7 @@ class MemoryPool { | ||||
|   } | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   const char* saveString(const TAdaptedString& str) { | ||||
|   const char* saveString(TAdaptedString str) { | ||||
|     if (str.isNull()) | ||||
|       return CopiedString(); | ||||
|  | ||||
| @@ -74,7 +74,7 @@ class MemoryPool { | ||||
|  | ||||
|     char* newCopy = allocString(n + 1); | ||||
|     if (newCopy) { | ||||
|       str.copyTo(newCopy, n); | ||||
|       stringGetChars(str, newCopy, n); | ||||
|       newCopy[n] = 0;  // force null-terminator | ||||
|     } | ||||
|     return CopiedString(newCopy, n); | ||||
| @@ -165,22 +165,11 @@ class MemoryPool { | ||||
|   } | ||||
|  | ||||
| #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> | ||||
|   const char* findString(const TAdaptedString& str) const { | ||||
|     size_t n = str.size(); | ||||
|     for (char* next = _begin; next + n < _left; ++next) { | ||||
|       if (stringEquals(next, n, str)) | ||||
|       if (next[n] == '\0' && stringEquals(str, adaptString(next, n))) | ||||
|         return next; | ||||
|  | ||||
|       // jump to next terminator | ||||
|   | ||||
| @@ -40,12 +40,13 @@ void objectRemove(CollectionData *obj, TAdaptedString key) { | ||||
|   obj->removeMember(key); | ||||
| } | ||||
|  | ||||
| template <typename TAdaptedString> | ||||
| template <typename TAdaptedString, typename TStoragePolicy> | ||||
| inline VariantData *objectGetOrAddMember(CollectionData *obj, | ||||
|                                          TAdaptedString key, MemoryPool *pool) { | ||||
|                                          TAdaptedString key, MemoryPool *pool, | ||||
|                                          TStoragePolicy storage_policy) { | ||||
|   if (!obj) | ||||
|     return 0; | ||||
|  | ||||
|   return obj->getOrAddMember(key, pool); | ||||
|   return obj->getOrAddMember(key, pool, storage_policy); | ||||
| } | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -196,7 +196,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | ||||
|   template <typename TString> | ||||
|   FORCE_INLINE VariantRef getOrAddMember(const TString& key) const { | ||||
|     return VariantRef(_pool, | ||||
|                       objectGetOrAddMember(_data, adaptString(key), _pool)); | ||||
|                       objectGetOrAddMember(_data, adaptString(key), _pool, | ||||
|                                            getStringStoragePolicy(key))); | ||||
|   } | ||||
|  | ||||
|   // getOrAddMember(char*) const | ||||
| @@ -205,7 +206,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | ||||
|   template <typename TChar> | ||||
|   FORCE_INLINE VariantRef getOrAddMember(TChar* key) const { | ||||
|     return VariantRef(_pool, | ||||
|                       objectGetOrAddMember(_data, adaptString(key), _pool)); | ||||
|                       objectGetOrAddMember(_data, adaptString(key), _pool, | ||||
|                                            getStringStoragePolicy(key))); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE bool operator==(ObjectRef rhs) const { | ||||
|   | ||||
| @@ -65,6 +65,22 @@ inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) { | ||||
| } | ||||
| #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 | ||||
| inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) { | ||||
|   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 | ||||
|  | ||||
| #include <ArduinoJson/Memory/MemoryPool.hpp> | ||||
| #include <ArduinoJson/Strings/StoredString.hpp> | ||||
| #include <ArduinoJson/Strings/String.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| namespace storage_policies { | ||||
| struct store_by_address {}; | ||||
| struct store_by_copy {}; | ||||
| struct decide_at_runtime {}; | ||||
| }  // namespace storage_policies | ||||
| struct LinkStringStoragePolicy { | ||||
|   template <typename TAdaptedString, typename TCallback> | ||||
|   bool store(TAdaptedString str, MemoryPool *, TCallback callback) { | ||||
|     LinkedString storedString(str.data(), str.size()); | ||||
|     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 | ||||
|   | ||||
| @@ -4,12 +4,9 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/Polyfills/safe_strcmp.hpp> | ||||
| #include <ArduinoJson/Strings/StoragePolicy.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TStoragePolicy> | ||||
| template <bool linked> | ||||
| class StoredString { | ||||
|  public: | ||||
|   StoredString() : _data(0), _size(0) {} | ||||
| @@ -32,7 +29,7 @@ class StoredString { | ||||
|   size_t _size; | ||||
| }; | ||||
|  | ||||
| typedef StoredString<storage_policies::store_by_address> LinkedString; | ||||
| typedef StoredString<storage_policies::store_by_copy> CopiedString; | ||||
| typedef StoredString<true> LinkedString; | ||||
| typedef StoredString<false> CopiedString; | ||||
|  | ||||
| }  // 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 | ||||
|  | ||||
| #include <ArduinoJson/Strings/Adapters/ConstRamStringAdapter.hpp> | ||||
| #include <ArduinoJson/Strings/Adapters/JsonStringAdapter.hpp> | ||||
| #include <ArduinoJson/Strings/Adapters/RamStringAdapter.hpp> | ||||
| #include <ArduinoJson/Strings/Adapters/SizedRamStringAdapter.hpp> | ||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||
| #include <ArduinoJson/Strings/Adapters/JsonString.hpp> | ||||
| #include <ArduinoJson/Strings/Adapters/RamString.hpp> | ||||
|  | ||||
| #if ARDUINOJSON_ENABLE_STD_STRING | ||||
| #  include <ArduinoJson/Strings/Adapters/StdStringAdapter.hpp> | ||||
| #  include <ArduinoJson/Strings/Adapters/StdString.hpp> | ||||
| #endif | ||||
|  | ||||
| #if ARDUINOJSON_ENABLE_STRING_VIEW | ||||
| #  include <ArduinoJson/Strings/Adapters/StringViewAdapter.hpp> | ||||
| #  include <ArduinoJson/Strings/Adapters/StringView.hpp> | ||||
| #endif | ||||
|  | ||||
| #if ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||
| #  include <ArduinoJson/Strings/Adapters/ArduinoStringAdapter.hpp> | ||||
| #  include <ArduinoJson/Strings/Adapters/ArduinoString.hpp> | ||||
| #endif | ||||
|  | ||||
| #if ARDUINOJSON_ENABLE_PROGMEM | ||||
| #  include <ArduinoJson/Strings/Adapters/FlashStringAdapter.hpp> | ||||
| #  include <ArduinoJson/Strings/Adapters/SizedFlashStringAdapter.hpp> | ||||
| #  include <ArduinoJson/Strings/Adapters/FlashString.hpp> | ||||
| #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 <> | ||||
| struct Converter<const char*> { | ||||
|   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) { | ||||
| @@ -132,7 +133,8 @@ struct Converter<const char*> { | ||||
| template <> | ||||
| struct Converter<String> { | ||||
|   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) { | ||||
| @@ -151,7 +153,8 @@ inline typename enable_if<IsString<T>::value, bool>::type convertToJson( | ||||
|     const T& src, VariantRef dst) { | ||||
|   VariantData* data = getData(dst); | ||||
|   MemoryPool* pool = getPool(dst); | ||||
|   return variantSetString(data, adaptString(src), pool); | ||||
|   return variantSetString(data, adaptString(src), pool, | ||||
|                           getStringStoragePolicy(src)); | ||||
| } | ||||
|  | ||||
| template <> | ||||
|   | ||||
| @@ -9,40 +9,24 @@ | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TAdaptedString> | ||||
| inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) { | ||||
|   if (!var) | ||||
|     return false; | ||||
|   return slotSetKey(var, key, pool, typename TAdaptedString::storage_policy()); | ||||
| struct SlotKeySetter { | ||||
|   SlotKeySetter(VariantSlot* instance) : _instance(instance) {} | ||||
|  | ||||
|   template <typename TStoredString> | ||||
|   void operator()(TStoredString s) { | ||||
|     if (!s) | ||||
|       return; | ||||
|     ARDUINOJSON_ASSERT(_instance != 0); | ||||
|     _instance->setKey(s); | ||||
|   } | ||||
|  | ||||
| template <typename TAdaptedString> | ||||
|   VariantSlot* _instance; | ||||
| }; | ||||
|  | ||||
| template <typename TAdaptedString, typename TStoragePolicy> | ||||
| inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool, | ||||
|                        storage_policies::decide_at_runtime) { | ||||
|   if (key.isStatic()) { | ||||
|     return slotSetKey(var, key, pool, storage_policies::store_by_address()); | ||||
|   } else { | ||||
|     return slotSetKey(var, key, pool, storage_policies::store_by_copy()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template <typename TAdaptedString> | ||||
| 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> | ||||
| inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool, | ||||
|                        storage_policies::store_by_copy) { | ||||
|   CopiedString dup(pool->saveString(key), key.size()); | ||||
|   if (!dup) | ||||
|     return false; | ||||
|   ARDUINOJSON_ASSERT(var); | ||||
|   var->setKey(dup); | ||||
|   return true; | ||||
|                        TStoragePolicy storage) { | ||||
|   return storage.store(key, pool, SlotKeySetter(var)); | ||||
| } | ||||
|  | ||||
| inline size_t slotSize(const VariantSlot* var) { | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
| #include <ArduinoJson/Misc/Visitable.hpp> | ||||
| #include <ArduinoJson/Numbers/arithmeticCompare.hpp> | ||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||
| #include <ArduinoJson/Strings/StringAdapter.hpp> | ||||
| #include <ArduinoJson/Strings/StringAdapters.hpp> | ||||
| #include <ArduinoJson/Variant/Visitor.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
| @@ -23,12 +23,12 @@ struct Comparer; | ||||
| template <typename T> | ||||
| struct Comparer<T, typename enable_if<IsString<T>::value>::type> | ||||
|     : ComparerBase { | ||||
|   T rhs; | ||||
|   T rhs;  // TODO: store adapted string? | ||||
|  | ||||
|   explicit Comparer(T value) : rhs(value) {} | ||||
|  | ||||
|   CompareResult visitString(const char *lhs, size_t) { | ||||
|     int i = adaptString(rhs).compare(lhs); | ||||
|   CompareResult visitString(const char *lhs, size_t n) { | ||||
|     int i = stringCompare(adaptString(rhs), adaptString(lhs, n)); | ||||
|     if (i < 0) | ||||
|       return COMPARE_RESULT_GREATER; | ||||
|     else if (i > 0) | ||||
|   | ||||
| @@ -99,27 +99,7 @@ class VariantData { | ||||
|     return const_cast<VariantData *>(this)->asObject(); | ||||
|   } | ||||
|  | ||||
|   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 copyFrom(const VariantData &src, MemoryPool *pool); | ||||
|  | ||||
|   bool isArray() const { | ||||
|     return (_flags & VALUE_IS_ARRAY) != 0; | ||||
| @@ -242,11 +222,6 @@ class VariantData { | ||||
|     _content.asString.size = s.size(); | ||||
|   } | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   bool storeString(TAdaptedString value, MemoryPool *pool) { | ||||
|     return storeString(value, pool, typename TAdaptedString::storage_policy()); | ||||
|   } | ||||
|  | ||||
|   CollectionData &toArray() { | ||||
|     setType(VALUE_IS_ARRAY); | ||||
|     _content.asCollection.clear(); | ||||
| @@ -307,13 +282,14 @@ class VariantData { | ||||
|     return isObject() ? _content.asCollection.getMember(key) : 0; | ||||
|   } | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) { | ||||
|   template <typename TAdaptedString, typename TStoragePolicy> | ||||
|   VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool, | ||||
|                               TStoragePolicy storage_policy) { | ||||
|     if (isNull()) | ||||
|       toObject(); | ||||
|     if (!isObject()) | ||||
|       return 0; | ||||
|     return _content.asCollection.getOrAddMember(key, pool); | ||||
|     return _content.asCollection.getOrAddMember(key, pool, storage_policy); | ||||
|   } | ||||
|  | ||||
|   void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { | ||||
| @@ -327,46 +303,36 @@ class VariantData { | ||||
|     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: | ||||
|   void setType(uint8_t t) { | ||||
|     _flags &= OWNED_KEY_BIT; | ||||
|     _flags |= t; | ||||
|   } | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   inline bool storeString(TAdaptedString value, MemoryPool *pool, | ||||
|                           storage_policies::decide_at_runtime) { | ||||
|     if (value.isStatic()) | ||||
|       return storeString(value, pool, storage_policies::store_by_address()); | ||||
|   struct VariantStringSetter { | ||||
|     VariantStringSetter(VariantData *instance) : _instance(instance) {} | ||||
|  | ||||
|     template <typename TStoredString> | ||||
|     void operator()(TStoredString s) { | ||||
|       if (s) | ||||
|         _instance->setString(s); | ||||
|       else | ||||
|       return storeString(value, pool, storage_policies::store_by_copy()); | ||||
|         _instance->setNull(); | ||||
|     } | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   inline bool storeString(TAdaptedString value, MemoryPool *, | ||||
|                           storage_policies::store_by_address) { | ||||
|     if (value.isNull()) | ||||
|       setNull(); | ||||
|     else | ||||
|       setString(LinkedString(value.data(), value.size())); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   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; | ||||
|   } | ||||
|     VariantData *_instance; | ||||
|   }; | ||||
| }; | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/Polyfills/attributes.hpp> | ||||
| #include <ArduinoJson/Strings/StoragePolicy.hpp> | ||||
| #include <ArduinoJson/Variant/VariantData.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
| @@ -49,12 +50,10 @@ inline void variantSetNull(VariantData *var) { | ||||
|   var->setNull(); | ||||
| } | ||||
|  | ||||
| template <typename TAdaptedString> | ||||
| template <typename TAdaptedString, typename TStoragePolicy> | ||||
| inline bool variantSetString(VariantData *var, TAdaptedString value, | ||||
|                              MemoryPool *pool) { | ||||
|   if (!var) | ||||
|     return false; | ||||
|   return var->storeString(value, pool); | ||||
|                              MemoryPool *pool, TStoragePolicy storage_policy) { | ||||
|   return var != 0 ? var->storeString(value, pool, storage_policy) : 0; | ||||
| } | ||||
|  | ||||
| inline size_t variantSize(const VariantData *var) { | ||||
| @@ -87,14 +86,18 @@ inline NO_INLINE VariantData *variantGetOrAddElement(VariantData *var, | ||||
| template <typename TChar> | ||||
| NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key, | ||||
|                                              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> | ||||
| NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, | ||||
|                                              const TString &key, | ||||
|                                              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) { | ||||
|   | ||||
| @@ -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> | ||||
| inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type | ||||
| VariantRef::to() const { | ||||
| @@ -146,4 +168,15 @@ inline VariantConstRef operator|(VariantConstRef preferedValue, | ||||
| inline bool VariantRef::set(char value) const { | ||||
|   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 | ||||
|   | ||||
| @@ -7,7 +7,6 @@ | ||||
| #include <ArduinoJson/Polyfills/integer.hpp> | ||||
| #include <ArduinoJson/Polyfills/limits.hpp> | ||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||
| #include <ArduinoJson/Strings/StoragePolicy.hpp> | ||||
| #include <ArduinoJson/Strings/StoredString.hpp> | ||||
| #include <ArduinoJson/Variant/VariantContent.hpp> | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user