mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	User can now use a JsonString as a key or a value
This commit is contained in:
		| @@ -28,6 +28,7 @@ HEAD | |||||||
| * `JsonDocument` now support the same operations as `JsonVariant`. | * `JsonDocument` now support the same operations as `JsonVariant`. | ||||||
|   Calling `JsonDocument::as<T>()` is not required anymore. |   Calling `JsonDocument::as<T>()` is not required anymore. | ||||||
| * Fixed example `JsonHttpClient.ino` | * Fixed example `JsonHttpClient.ino` | ||||||
|  | * User can now use a `JsonString` as a key or a value | ||||||
|  |  | ||||||
| > ### BREAKING CHANGES | > ### BREAKING CHANGES | ||||||
| >  | >  | ||||||
|   | |||||||
| @@ -24,13 +24,13 @@ class CollectionData { | |||||||
|  |  | ||||||
|   VariantData *add(MemoryPool *pool); |   VariantData *add(MemoryPool *pool); | ||||||
|  |  | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   VariantData *add(TKey key, MemoryPool *pool); |   VariantData *add(TAdaptedString key, MemoryPool *pool); | ||||||
|  |  | ||||||
|   void clear(); |   void clear(); | ||||||
|  |  | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   bool containsKey(const TKey &key) const; |   bool containsKey(const TAdaptedString &key) const; | ||||||
|  |  | ||||||
|   bool copyFrom(const CollectionData &src, MemoryPool *pool); |   bool copyFrom(const CollectionData &src, MemoryPool *pool); | ||||||
|  |  | ||||||
| @@ -39,8 +39,8 @@ class CollectionData { | |||||||
|  |  | ||||||
|   VariantData *get(size_t index) const; |   VariantData *get(size_t index) const; | ||||||
|  |  | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   VariantData *get(TKey key) const; |   VariantData *get(TAdaptedString key) const; | ||||||
|  |  | ||||||
|   VariantSlot *head() const { |   VariantSlot *head() const { | ||||||
|     return _head; |     return _head; | ||||||
| @@ -48,8 +48,8 @@ class CollectionData { | |||||||
|  |  | ||||||
|   void remove(size_t index); |   void remove(size_t index); | ||||||
|  |  | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   void remove(TKey key) { |   void remove(TAdaptedString key) { | ||||||
|     remove(getSlot(key)); |     remove(getSlot(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -62,8 +62,8 @@ class CollectionData { | |||||||
|  private: |  private: | ||||||
|   VariantSlot *getSlot(size_t index) const; |   VariantSlot *getSlot(size_t index) const; | ||||||
|  |  | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   VariantSlot *getSlot(TKey key) const; |   VariantSlot *getSlot(TAdaptedString key) const; | ||||||
|  |  | ||||||
|   VariantSlot *getPreviousSlot(VariantSlot *) const; |   VariantSlot *getPreviousSlot(VariantSlot *) const; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -29,8 +29,8 @@ inline VariantData* CollectionData::add(MemoryPool* pool) { | |||||||
|   return addSlot(pool)->data(); |   return addSlot(pool)->data(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TAdaptedString> | ||||||
| inline VariantData* CollectionData::add(TKey key, MemoryPool* pool) { | inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) { | ||||||
|   VariantSlot* slot = addSlot(pool); |   VariantSlot* slot = addSlot(pool); | ||||||
|   if (!slotSetKey(slot, key, pool)) return 0; |   if (!slotSetKey(slot, key, pool)) return 0; | ||||||
|   return slot->data(); |   return slot->data(); | ||||||
| @@ -41,8 +41,8 @@ inline void CollectionData::clear() { | |||||||
|   _tail = 0; |   _tail = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TAdaptedString> | ||||||
| inline bool CollectionData::containsKey(const TKey& key) const { | inline bool CollectionData::containsKey(const TAdaptedString& key) const { | ||||||
|   return getSlot(key) != 0; |   return getSlot(key) != 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -53,9 +53,9 @@ inline bool CollectionData::copyFrom(const CollectionData& src, | |||||||
|     VariantData* var; |     VariantData* var; | ||||||
|     if (s->key() != 0) { |     if (s->key() != 0) { | ||||||
|       if (s->ownsKey()) |       if (s->ownsKey()) | ||||||
|         var = add(RamStringWrapper(s->key()), pool); |         var = add(RamStringAdapter(s->key()), pool); | ||||||
|       else |       else | ||||||
|         var = add(ConstRamStringWrapper(s->key()), pool); |         var = add(ConstRamStringAdapter(s->key()), pool); | ||||||
|     } else { |     } else { | ||||||
|       var = add(pool); |       var = add(pool); | ||||||
|     } |     } | ||||||
| @@ -69,7 +69,7 @@ inline bool CollectionData::equalsObject(const CollectionData& other) const { | |||||||
|   size_t count = 0; |   size_t count = 0; | ||||||
|   for (VariantSlot* slot = _head; slot; slot = slot->next()) { |   for (VariantSlot* slot = _head; slot; slot = slot->next()) { | ||||||
|     VariantData* v1 = slot->data(); |     VariantData* v1 = slot->data(); | ||||||
|     VariantData* v2 = other.get(wrapString(slot->key())); |     VariantData* v2 = other.get(adaptString(slot->key())); | ||||||
|     if (!variantEquals(v1, v2)) return false; |     if (!variantEquals(v1, v2)) return false; | ||||||
|     count++; |     count++; | ||||||
|   } |   } | ||||||
| @@ -88,8 +88,8 @@ inline bool CollectionData::equalsArray(const CollectionData& other) const { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TAdaptedString> | ||||||
| inline VariantSlot* CollectionData::getSlot(TKey key) const { | inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const { | ||||||
|   VariantSlot* slot = _head; |   VariantSlot* slot = _head; | ||||||
|   while (slot) { |   while (slot) { | ||||||
|     if (key.equals(slot->key())) break; |     if (key.equals(slot->key())) break; | ||||||
| @@ -112,8 +112,8 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const { | |||||||
|   return 0; |   return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TAdaptedString> | ||||||
| inline VariantData* CollectionData::get(TKey key) const { | inline VariantData* CollectionData::get(TAdaptedString key) const { | ||||||
|   VariantSlot* slot = getSlot(key); |   VariantSlot* slot = getSlot(key); | ||||||
|   return slot ? slot->data() : 0; |   return slot ? slot->data() : 0; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -23,8 +23,8 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool, | |||||||
|   return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit); |   return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit); | ||||||
| } | } | ||||||
|  |  | ||||||
| // DeserializationError deserialize(JsonDocument& doc, TString input); | // deserialize(JsonDocument&, const std::string&); | ||||||
| // TString = const std::string&, const String& | // deserialize(JsonDocument&, const String&); | ||||||
| template <template <typename, typename> class TDeserializer, typename TString> | template <template <typename, typename> class TDeserializer, typename TString> | ||||||
| typename enable_if<!is_array<TString>::value, DeserializationError>::type | typename enable_if<!is_array<TString>::value, DeserializationError>::type | ||||||
| deserialize(JsonDocument &doc, const TString &input, | deserialize(JsonDocument &doc, const TString &input, | ||||||
| @@ -36,8 +36,9 @@ deserialize(JsonDocument &doc, const TString &input, | |||||||
|       .parse(doc.data()); |       .parse(doc.data()); | ||||||
| } | } | ||||||
| // | // | ||||||
| // DeserializationError deserialize(JsonDocument& doc, TChar* input); | // deserialize(JsonDocument&, char*); | ||||||
| // TChar* = char*, const char*, const __FlashStringHelper* | // deserialize(JsonDocument&, const char*); | ||||||
|  | // deserialize(JsonDocument&, const __FlashStringHelper*); | ||||||
| template <template <typename, typename> class TDeserializer, typename TChar> | template <template <typename, typename> class TDeserializer, typename TChar> | ||||||
| DeserializationError deserialize(JsonDocument &doc, TChar *input, | DeserializationError deserialize(JsonDocument &doc, TChar *input, | ||||||
|                                  NestingLimit nestingLimit) { |                                  NestingLimit nestingLimit) { | ||||||
| @@ -48,9 +49,9 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input, | |||||||
|       .parse(doc.data()); |       .parse(doc.data()); | ||||||
| } | } | ||||||
| // | // | ||||||
| // DeserializationError deserialize(JsonDocument& doc, TChar* input, size_t | // deserialize(JsonDocument&, char*, size_t); | ||||||
| // inputSize); | // deserialize(JsonDocument&, const char*, size_t); | ||||||
| // TChar* = char*, const char*, const __FlashStringHelper* | // deserialize(JsonDocument&, const __FlashStringHelper*, size_t); | ||||||
| template <template <typename, typename> class TDeserializer, typename TChar> | template <template <typename, typename> class TDeserializer, typename TChar> | ||||||
| DeserializationError deserialize(JsonDocument &doc, TChar *input, | DeserializationError deserialize(JsonDocument &doc, TChar *input, | ||||||
|                                  size_t inputSize, NestingLimit nestingLimit) { |                                  size_t inputSize, NestingLimit nestingLimit) { | ||||||
| @@ -61,8 +62,8 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input, | |||||||
|       .parse(doc.data()); |       .parse(doc.data()); | ||||||
| } | } | ||||||
| // | // | ||||||
| // DeserializationError deserialize(JsonDocument& doc, TStream input); | // deserialize(JsonDocument&, std::istream&); | ||||||
| // TStream = std::istream&, Stream& | // deserialize(JsonDocument&, Stream&); | ||||||
| template <template <typename, typename> class TDeserializer, typename TStream> | template <template <typename, typename> class TDeserializer, typename TStream> | ||||||
| DeserializationError deserialize(JsonDocument &doc, TStream &input, | DeserializationError deserialize(JsonDocument &doc, TStream &input, | ||||||
|                                  NestingLimit nestingLimit) { |                                  NestingLimit nestingLimit) { | ||||||
|   | |||||||
| @@ -86,13 +86,18 @@ class JsonDocument : public Visitable { | |||||||
|     return add().to<ArrayRef>(); |     return add().to<ArrayRef>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // createNestedArray(char*) | ||||||
|   ArrayRef createNestedArray(TKey* key) { |   // createNestedArray(const char*) | ||||||
|  |   // createNestedArray(const __FlashStringHelper*) | ||||||
|  |   template <typename TChar> | ||||||
|  |   ArrayRef createNestedArray(TChar* key) { | ||||||
|     return getOrCreate(key).template to<ArrayRef>(); |     return getOrCreate(key).template to<ArrayRef>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // createNestedArray(const std::string&) | ||||||
|   ArrayRef createNestedArray(const TKey& key) { |   // createNestedArray(const String&) | ||||||
|  |   template <typename TString> | ||||||
|  |   ArrayRef createNestedArray(const TString& key) { | ||||||
|     return getOrCreate(key).template to<ArrayRef>(); |     return getOrCreate(key).template to<ArrayRef>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -100,48 +105,57 @@ class JsonDocument : public Visitable { | |||||||
|     return add().to<ObjectRef>(); |     return add().to<ObjectRef>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // createNestedObject(char*) | ||||||
|   ObjectRef createNestedObject(TKey* key) { |   // createNestedObject(const char*) | ||||||
|  |   // createNestedObject(const __FlashStringHelper*) | ||||||
|  |   template <typename TChar> | ||||||
|  |   ObjectRef createNestedObject(TChar* key) { | ||||||
|     return getOrCreate(key).template to<ObjectRef>(); |     return getOrCreate(key).template to<ObjectRef>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // createNestedObject(const std::string&) | ||||||
|   ObjectRef createNestedObject(const TKey& key) { |   // createNestedObject(const String&) | ||||||
|  |   template <typename TString> | ||||||
|  |   ObjectRef createNestedObject(const TString& key) { | ||||||
|     return getOrCreate(key).template to<ObjectRef>(); |     return getOrCreate(key).template to<ObjectRef>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // MemberProxy operator[](TKey) |   // operator[](const std::string&) | ||||||
|   // TKey = const std::string&, const String& |   // operator[](const String&) | ||||||
|   template <typename TKey> |   template <typename TString> | ||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename enable_if<IsString<TKey>::value, |       typename enable_if<IsString<TString>::value, | ||||||
|                          MemberProxy<JsonDocument&, const TKey&> >::type |                          MemberProxy<JsonDocument&, const TString&> >::type | ||||||
|       operator[](const TKey& key) { |       operator[](const TString& key) { | ||||||
|     return MemberProxy<JsonDocument&, const TKey&>(*this, key); |     return MemberProxy<JsonDocument&, const TString&>(*this, key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // MemberProxy operator[](TKey); |   // operator[](char*) | ||||||
|   // TKey = const char*, const char[N], const __FlashStringHelper* |   // operator[](const char*) | ||||||
|   template <typename TKey> |   // operator[](const __FlashStringHelper*) | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey*>::value, |   template <typename TChar> | ||||||
|                                   MemberProxy<JsonDocument&, TKey*> >::type |   FORCE_INLINE typename enable_if<IsString<TChar*>::value, | ||||||
|   operator[](TKey* key) { |                                   MemberProxy<JsonDocument&, TChar*> >::type | ||||||
|     return MemberProxy<JsonDocument&, TKey*>(*this, key); |   operator[](TChar* key) { | ||||||
|  |     return MemberProxy<JsonDocument&, TChar*>(*this, key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // VariantConstRef operator[](TKey) const |   // operator[](const std::string&) const | ||||||
|   // TKey = const std::string&, const String& |   // operator[](const String&) const | ||||||
|   template <typename TKey> |   template <typename TString> | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantConstRef>::type |   FORCE_INLINE | ||||||
|   operator[](const TKey& key) const { |       typename enable_if<IsString<TString>::value, VariantConstRef>::type | ||||||
|  |       operator[](const TString& key) const { | ||||||
|     return getVariant()[key]; |     return getVariant()[key]; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // VariantConstRef operator[](TKey) const; |   // operator[](char*) const | ||||||
|   // TKey = const char*, const char[N], const __FlashStringHelper* |   // operator[](const char*) const | ||||||
|   template <typename TKey> |   // operator[](const __FlashStringHelper*) const | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey*>::value, VariantConstRef>::type |   template <typename TChar> | ||||||
|   operator[](TKey* key) const { |   FORCE_INLINE | ||||||
|  |       typename enable_if<IsString<TChar*>::value, VariantConstRef>::type | ||||||
|  |       operator[](TChar* key) const { | ||||||
|     return getVariant()[key]; |     return getVariant()[key]; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -157,43 +171,51 @@ class JsonDocument : public Visitable { | |||||||
|     return VariantRef(&_pool, _data.get(index)); |     return VariantRef(&_pool, _data.get(index)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // get(char*) const | ||||||
|   FORCE_INLINE VariantRef get(TKey* key) { |   // get(const char*) const | ||||||
|     return VariantRef(&_pool, _data.get(wrapString(key))); |   // get(const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|  |   FORCE_INLINE VariantRef get(TChar* key) { | ||||||
|  |     return VariantRef(&_pool, _data.get(adaptString(key))); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // get(const std::string&) const | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get( |   // get(const String&) const | ||||||
|       const TKey& key) { |   template <typename TString> | ||||||
|     return VariantRef(&_pool, _data.get(wrapString(key))); |   FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type | ||||||
|  |   get(const TString& key) { | ||||||
|  |     return VariantRef(&_pool, _data.get(adaptString(key))); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // getOrCreate(char*) | ||||||
|   FORCE_INLINE VariantRef getOrCreate(TKey* key) { |   // getOrCreate(const char*) | ||||||
|     return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool)); |   // getOrCreate(const __FlashStringHelper*) | ||||||
|  |   template <typename TChar> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(TChar* key) { | ||||||
|  |     return VariantRef(&_pool, _data.getOrCreate(adaptString(key), &_pool)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // getOrCreate(const std::string&) | ||||||
|   FORCE_INLINE VariantRef getOrCreate(const TKey& key) { |   // getOrCreate(const String&) | ||||||
|     return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool)); |   template <typename TString> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(const TString& key) { | ||||||
|  |     return VariantRef(&_pool, _data.getOrCreate(adaptString(key), &_pool)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE VariantRef add() { |   FORCE_INLINE VariantRef add() { | ||||||
|     return VariantRef(&_pool, _data.add(&_pool)); |     return VariantRef(&_pool, _data.add(&_pool)); | ||||||
|   } |   } | ||||||
|   // |  | ||||||
|   // bool add(TValue); |   template <typename TValue> | ||||||
|   // TValue = bool, long, int, short, float, double, serialized, VariantRef, |   FORCE_INLINE bool add(const TValue& value) { | ||||||
|   //          std::string, String, ObjectRef |  | ||||||
|   template <typename T> |  | ||||||
|   FORCE_INLINE bool add(const T& value) { |  | ||||||
|     return add().set(value); |     return add().set(value); | ||||||
|   } |   } | ||||||
|   // |  | ||||||
|   // bool add(TValue); |   // add(char*) const | ||||||
|   // TValue = char*, const char*, const __FlashStringHelper* |   // add(const char*) const | ||||||
|   template <typename T> |   // add(const __FlashStringHelper*) const | ||||||
|   FORCE_INLINE bool add(T* value) { |   template <typename TChar> | ||||||
|  |   FORCE_INLINE bool add(TChar* value) { | ||||||
|     return add().set(value); |     return add().set(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "../Strings/StringWrappers.hpp" | #include "../Strings/StringAdapters.hpp" | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| @@ -58,7 +58,7 @@ inline SerializedValue<T> serialized(T str) { | |||||||
|  |  | ||||||
| template <typename TChar> | template <typename TChar> | ||||||
| inline SerializedValue<TChar*> serialized(TChar* p) { | inline SerializedValue<TChar*> serialized(TChar* p) { | ||||||
|   return SerializedValue<TChar*>(p, wrapString(p).size()); |   return SerializedValue<TChar*>(p, adaptString(p).size()); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TChar> | template <typename TChar> | ||||||
|   | |||||||
| @@ -15,13 +15,13 @@ | |||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| template <typename TObject, typename TString> | template <typename TObject, typename TStringRef> | ||||||
| class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >, | class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >, | ||||||
|                     public Visitable { |                     public Visitable { | ||||||
|   typedef MemberProxy<TObject, TString> this_type; |   typedef MemberProxy<TObject, TStringRef> this_type; | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   FORCE_INLINE MemberProxy(TObject variant, TString key) |   FORCE_INLINE MemberProxy(TObject variant, TStringRef key) | ||||||
|       : _object(variant), _key(key) {} |       : _object(variant), _key(key) {} | ||||||
|  |  | ||||||
|   FORCE_INLINE operator VariantConstRef() const { |   FORCE_INLINE operator VariantConstRef() const { | ||||||
| @@ -33,22 +33,18 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >, | |||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Set the specified value |  | ||||||
|   // |  | ||||||
|   // operator=(const TValue&); |  | ||||||
|   // TValue = bool, char, long, int, short, float, double, |  | ||||||
|   //          std::string, String, ArrayRef, ObjectRef |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type |   FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type | ||||||
|   operator=(const TValue &src) { |   operator=(const TValue &src) { | ||||||
|     getOrCreateMember().set(src); |     getOrCreateMember().set(src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
|   // |  | ||||||
|   // operator=(TValue); |   // operator=(char*) const | ||||||
|   // TValue = char*, const char*, const __FlashStringHelper* |   // operator=(const char*) const | ||||||
|   template <typename TValue> |   // operator=(const __FlashStringHelper*) const | ||||||
|   FORCE_INLINE this_type &operator=(TValue *src) { |   template <typename TChar> | ||||||
|  |   FORCE_INLINE this_type &operator=(TChar *src) { | ||||||
|     getOrCreateMember().set(src); |     getOrCreateMember().set(src); | ||||||
|     return *this; |     return *this; | ||||||
|   } |   } | ||||||
| @@ -72,22 +68,17 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >, | |||||||
|     return getOrCreateMember().template to<TValue>(); |     return getOrCreateMember().template to<TValue>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Sets the specified value. |  | ||||||
|   // |  | ||||||
|   // bool set(const TValue&); |  | ||||||
|   // TValue = bool, char, long, int, short, float, double, serialized, |  | ||||||
|   // VariantRef, |  | ||||||
|   //          std::string, String, ArrayRef, ObjectRef |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set( |   FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set( | ||||||
|       const TValue &value) { |       const TValue &value) { | ||||||
|     return getOrCreateMember().set(value); |     return getOrCreateMember().set(value); | ||||||
|   } |   } | ||||||
|   // |  | ||||||
|   // bool set(TValue); |   // set(char*) const | ||||||
|   // TValue = char*, const char, const __FlashStringHelper* |   // set(const char*) const | ||||||
|   template <typename TValue> |   // set(const __FlashStringHelper*) const | ||||||
|   FORCE_INLINE bool set(const TValue *value) { |   template <typename TChar> | ||||||
|  |   FORCE_INLINE bool set(const TChar *value) { | ||||||
|     return getOrCreateMember().set(value); |     return getOrCreateMember().set(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -101,23 +92,33 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >, | |||||||
|     return getOrCreateMember().add(); |     return getOrCreateMember().add(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TNestedKey> |   // get(char*) const | ||||||
|   FORCE_INLINE VariantRef get(TNestedKey *key) const { |   // get(const char*) const | ||||||
|  |   // get(const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|  |   FORCE_INLINE VariantRef get(TChar *key) const { | ||||||
|     return getMember().get(key); |     return getMember().get(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TNestedKey> |   // get(const std::string&) const | ||||||
|   FORCE_INLINE VariantRef get(const TNestedKey &key) const { |   // get(const String&) const | ||||||
|  |   template <typename TString> | ||||||
|  |   FORCE_INLINE VariantRef get(const TString &key) const { | ||||||
|     return getMember().get(key); |     return getMember().get(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TNestedKey> |   // getOrCreate(char*) const | ||||||
|   FORCE_INLINE VariantRef getOrCreate(TNestedKey *key) const { |   // getOrCreate(const char*) const | ||||||
|  |   // getOrCreate(const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(TChar *key) const { | ||||||
|     return getOrCreateMember().getOrCreate(key); |     return getOrCreateMember().getOrCreate(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TNestedKey> |   // getOrCreate(const std::string&) const | ||||||
|   FORCE_INLINE VariantRef getOrCreate(const TNestedKey &key) const { |   // getOrCreate(const String&) const | ||||||
|  |   template <typename TString> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(const TString &key) const { | ||||||
|     return getOrCreateMember().getOrCreate(key); |     return getOrCreateMember().getOrCreate(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -131,7 +132,7 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   TObject _object; |   TObject _object; | ||||||
|   TString _key; |   TStringRef _key; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename TObject> | template <typename TObject> | ||||||
|   | |||||||
| @@ -16,8 +16,8 @@ void objectAccept(const CollectionData *obj, Visitor &visitor) { | |||||||
|     visitor.visitNull(); |     visitor.visitNull(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TAdaptedString> | ||||||
| inline bool objectContainsKey(const CollectionData *obj, TKey key) { | inline bool objectContainsKey(const CollectionData *obj, TAdaptedString key) { | ||||||
|   return obj && obj->containsKey(key); |   return obj && obj->containsKey(key); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -27,20 +27,20 @@ inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) { | |||||||
|   return lhs->equalsObject(*rhs); |   return lhs->equalsObject(*rhs); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TAdaptedString> | ||||||
| inline VariantData *objectGet(const CollectionData *obj, TKey key) { | inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) { | ||||||
|   if (!obj) return 0; |   if (!obj) return 0; | ||||||
|   return obj->get(key); |   return obj->get(key); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TAdaptedString> | ||||||
| void objectRemove(CollectionData *obj, TKey key) { | void objectRemove(CollectionData *obj, TAdaptedString key) { | ||||||
|   if (!obj) return; |   if (!obj) return; | ||||||
|   obj->remove(key); |   obj->remove(key); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TAdaptedString> | ||||||
| inline VariantData *objectGetOrCreate(CollectionData *obj, TKey key, | inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key, | ||||||
|                                       MemoryPool *pool) { |                                       MemoryPool *pool) { | ||||||
|   if (!obj) return 0; |   if (!obj) return 0; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,23 +17,22 @@ inline ArrayRef ObjectShortcuts<TObject>::createNestedArray( | |||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TObject> | template <typename TObject> | ||||||
| template <typename TString> | template <typename TChar> | ||||||
| inline ArrayRef ObjectShortcuts<TObject>::createNestedArray( | inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(TChar* key) const { | ||||||
|     TString* key) const { |  | ||||||
|   return impl()->getOrCreate(key).template to<ArrayRef>(); |   return impl()->getOrCreate(key).template to<ArrayRef>(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TObject> | template <typename TObject> | ||||||
| template <typename TKey> | template <typename TString> | ||||||
| ObjectRef ObjectShortcuts<TObject>::createNestedObject(const TKey& key) const { | inline ObjectRef ObjectShortcuts<TObject>::createNestedObject( | ||||||
|  |     const TString& key) const { | ||||||
|   return impl()->getOrCreate(key).template to<ObjectRef>(); |   return impl()->getOrCreate(key).template to<ObjectRef>(); | ||||||
| } | } | ||||||
| // |  | ||||||
| // ObjectRef createNestedObject(TKey); |  | ||||||
| // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* |  | ||||||
| template <typename TObject> | template <typename TObject> | ||||||
| template <typename TKey> | template <typename TChar> | ||||||
| ObjectRef ObjectShortcuts<TObject>::createNestedObject(TKey* key) const { | inline ObjectRef ObjectShortcuts<TObject>::createNestedObject( | ||||||
|  |     TChar* key) const { | ||||||
|   return impl()->getOrCreate(key).template to<ObjectRef>(); |   return impl()->getOrCreate(key).template to<ObjectRef>(); | ||||||
| } | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -26,20 +26,19 @@ class ObjectRefBase { | |||||||
|     objectAccept(_data, visitor); |     objectAccept(_data, visitor); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Tells weither the specified key is present and associated with a value. |   // containsKey(const std::string&) const | ||||||
|   // |   // containsKey(const String&) const | ||||||
|   // bool containsKey(TKey); |   template <typename TString> | ||||||
|   // TKey = const std::string&, const String& |   FORCE_INLINE bool containsKey(const TString& key) const { | ||||||
|   template <typename TKey> |     return objectContainsKey(_data, adaptString(key)); | ||||||
|   FORCE_INLINE bool containsKey(const TKey& key) const { |  | ||||||
|     return objectContainsKey(_data, wrapString(key)); |  | ||||||
|   } |   } | ||||||
|   // |  | ||||||
|   // bool containsKey(TKey); |   // containsKey(char*) const | ||||||
|   // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* |   // containsKey(const char*) const | ||||||
|   template <typename TKey> |   // containsKey(const __FlashStringHelper*) const | ||||||
|   FORCE_INLINE bool containsKey(TKey* key) const { |   template <typename TChar> | ||||||
|     return objectContainsKey(_data, wrapString(key)); |   FORCE_INLINE bool containsKey(TChar* key) const { | ||||||
|  |     return objectContainsKey(_data, adaptString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE bool isNull() const { |   FORCE_INLINE bool isNull() const { | ||||||
| @@ -83,41 +82,38 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>, | |||||||
|     return iterator(); |     return iterator(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // get(const std::string&) const | ||||||
|   // |   // get(const String&) const | ||||||
|   // TValue get<TValue>(TKey) const; |   template <typename TString> | ||||||
|   // TKey = const std::string&, const String& |   FORCE_INLINE VariantConstRef get(const TString& key) const { | ||||||
|   // TValue = bool, char, long, int, short, float, double, |     return get_impl(adaptString(key)); | ||||||
|   //          std::string, String, ArrayConstRef, ObjectConstRef |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE VariantConstRef get(const TKey& key) const { |  | ||||||
|     return get_impl(wrapString(key)); |  | ||||||
|   } |  | ||||||
|   // |  | ||||||
|   // TValue get<TValue>(TKey) const; |  | ||||||
|   // TKey = char*, const char*, const __FlashStringHelper* |  | ||||||
|   // TValue = bool, char, long, int, short, float, double, |  | ||||||
|   //          std::string, String, ArrayConstRef, ObjectConstRef |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE VariantConstRef get(TKey* key) const { |  | ||||||
|     return get_impl(wrapString(key)); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // |   // get(char*) const | ||||||
|   // VariantConstRef operator[](TKey) const; |   // get(const char*) const | ||||||
|   // TKey = const std::string&, const String& |   // get(const __FlashStringHelper*) const | ||||||
|   template <typename TKey> |   template <typename TChar> | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantConstRef>::type |   FORCE_INLINE VariantConstRef get(TChar* key) const { | ||||||
|   operator[](const TKey& key) const { |     return get_impl(adaptString(key)); | ||||||
|     return get_impl(wrapString(key)); |  | ||||||
|   } |   } | ||||||
|   // |  | ||||||
|   // VariantConstRef operator[](TKey) const; |   // operator[](const std::string&) const | ||||||
|   // TKey = const char*, const char[N], const __FlashStringHelper* |   // operator[](const String&) const | ||||||
|   template <typename TKey> |   template <typename TString> | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey*>::value, VariantConstRef>::type |   FORCE_INLINE | ||||||
|   operator[](TKey* key) const { |       typename enable_if<IsString<TString>::value, VariantConstRef>::type | ||||||
|     return get_impl(wrapString(key)); |       operator[](const TString& key) const { | ||||||
|  |     return get_impl(adaptString(key)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // operator[](char*) const | ||||||
|  |   // operator[](const char*) const | ||||||
|  |   // operator[](const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|  |   FORCE_INLINE | ||||||
|  |       typename enable_if<IsString<TChar*>::value, VariantConstRef>::type | ||||||
|  |       operator[](TChar* key) const { | ||||||
|  |     return get_impl(adaptString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE bool operator==(ObjectConstRef rhs) const { |   FORCE_INLINE bool operator==(ObjectConstRef rhs) const { | ||||||
| @@ -125,8 +121,8 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   FORCE_INLINE VariantConstRef get_impl(TKey key) const { |   FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const { | ||||||
|     return VariantConstRef(objectGet(_data, key)); |     return VariantConstRef(objectGet(_data, key)); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| @@ -170,30 +166,34 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | |||||||
|     return _data->copyFrom(*src._data, _pool); |     return _data->copyFrom(*src._data, _pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // get(const std::string&) const | ||||||
|   // |   // get(const String&) const | ||||||
|   // VariantRef get<TValue>(TKey) const; |   template <typename TString> | ||||||
|   // TKey = const std::string&, const String& |   FORCE_INLINE VariantRef get(const TString& key) const { | ||||||
|   template <typename TKey> |     return get_impl(adaptString(key)); | ||||||
|   FORCE_INLINE VariantRef get(const TKey& key) const { |  | ||||||
|     return get_impl(wrapString(key)); |  | ||||||
|   } |  | ||||||
|   // |  | ||||||
|   // VariantRef get<TValue>(TKey) const; |  | ||||||
|   // TKey = char*, const char*, const __FlashStringHelper* |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE VariantRef get(TKey* key) const { |  | ||||||
|     return get_impl(wrapString(key)); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // get(char*) const | ||||||
|   FORCE_INLINE VariantRef getOrCreate(TKey* key) const { |   // get(const char*) const | ||||||
|     return getOrCreate_impl(wrapString(key)); |   // get(const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|  |   FORCE_INLINE VariantRef get(TChar* key) const { | ||||||
|  |     return get_impl(adaptString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   // getOrCreate(const std::string&) const | ||||||
|   FORCE_INLINE VariantRef getOrCreate(const TKey& key) const { |   // getOrCreate(const String&) const | ||||||
|     return getOrCreate_impl(wrapString(key)); |   template <typename TString> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(const TString& key) const { | ||||||
|  |     return getOrCreate_impl(adaptString(key)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // getOrCreate(char*) const | ||||||
|  |   // getOrCreate(const char*) const | ||||||
|  |   // getOrCreate(const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(TChar* key) const { | ||||||
|  |     return getOrCreate_impl(adaptString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE bool operator==(ObjectRef rhs) const { |   FORCE_INLINE bool operator==(ObjectRef rhs) const { | ||||||
| @@ -205,30 +205,29 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | |||||||
|     _data->remove(it.internal()); |     _data->remove(it.internal()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Removes the specified key and the associated value. |   // remove(const std::string&) const | ||||||
|   // |   // remove(const String&) const | ||||||
|   // void remove(TKey); |   template <typename TString> | ||||||
|   // TKey = const std::string&, const String& |   FORCE_INLINE void remove(const TString& key) const { | ||||||
|   template <typename TKey> |     objectRemove(_data, adaptString(key)); | ||||||
|   FORCE_INLINE void remove(const TKey& key) const { |  | ||||||
|     objectRemove(_data, wrapString(key)); |  | ||||||
|   } |   } | ||||||
|   // |  | ||||||
|   // void remove(TKey); |   // remove(char*) const | ||||||
|   // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* |   // remove(const char*) const | ||||||
|   template <typename TKey> |   // remove(const __FlashStringHelper*) const | ||||||
|   FORCE_INLINE void remove(TKey* key) const { |   template <typename TChar> | ||||||
|     objectRemove(_data, wrapString(key)); |   FORCE_INLINE void remove(TChar* key) const { | ||||||
|  |     objectRemove(_data, adaptString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   FORCE_INLINE VariantRef get_impl(TKey key) const { |   FORCE_INLINE VariantRef get_impl(TAdaptedString key) const { | ||||||
|     return VariantRef(_pool, objectGet(_data, key)); |     return VariantRef(_pool, objectGet(_data, key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   FORCE_INLINE VariantRef getOrCreate_impl(TKey key) const { |   FORCE_INLINE VariantRef getOrCreate_impl(TAdaptedString key) const { | ||||||
|     return VariantRef(_pool, objectGetOrCreate(_data, key, _pool)); |     return VariantRef(_pool, objectGetOrCreate(_data, key, _pool)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,52 +6,52 @@ | |||||||
|  |  | ||||||
| #include "../Polyfills/attributes.hpp" | #include "../Polyfills/attributes.hpp" | ||||||
| #include "../Polyfills/type_traits.hpp" | #include "../Polyfills/type_traits.hpp" | ||||||
| #include "../Strings/StringWrappers.hpp" | #include "../Strings/StringAdapters.hpp" | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| template <typename TParent, typename TKey> | template <typename TParent, typename TStringRef> | ||||||
| class MemberProxy; | class MemberProxy; | ||||||
|  |  | ||||||
| template <typename TObject> | template <typename TObject> | ||||||
| class ObjectShortcuts { | class ObjectShortcuts { | ||||||
|  public: |  public: | ||||||
|   // MemberProxy operator[](TKey) const; |   // operator[](const std::string&) const | ||||||
|   // TKey = const std::string&, const String& |   // operator[](const String&) const | ||||||
|   template <typename TKey> |   template <typename TString> | ||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename enable_if<IsString<TKey>::value, |       typename enable_if<IsString<TString>::value, | ||||||
|                          MemberProxy<const TObject &, const TKey &> >::type |                          MemberProxy<const TObject &, const TString &> >::type | ||||||
|       operator[](const TKey &key) const; |       operator[](const TString &key) const; | ||||||
|   // |  | ||||||
|   // MemberProxy operator[](TKey) const; |  | ||||||
|   // TKey = const char*, const char[N], const __FlashStringHelper* |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey *>::value, |  | ||||||
|                                   MemberProxy<const TObject &, TKey *> >::type |  | ||||||
|   operator[](TKey *key) const; |  | ||||||
|  |  | ||||||
|   // Creates and adds a ArrayRef. |   // operator[](char*) const | ||||||
|   // |   // operator[](const char*) const | ||||||
|   // ArrayRef createNestedArray(TKey); |   // operator[](const __FlashStringHelper*) const | ||||||
|   // TKey = const std::string&, const String& |   template <typename TChar> | ||||||
|   template <typename TKey> |   FORCE_INLINE typename enable_if<IsString<TChar *>::value, | ||||||
|   FORCE_INLINE ArrayRef createNestedArray(const TKey &key) const; |                                   MemberProxy<const TObject &, TChar *> >::type | ||||||
|   // ArrayRef createNestedArray(TKey); |   operator[](TChar *key) const; | ||||||
|   // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* |  | ||||||
|   template <typename TKey> |  | ||||||
|   FORCE_INLINE ArrayRef createNestedArray(TKey *key) const; |  | ||||||
|  |  | ||||||
|   // Creates and adds a ObjectRef. |   // createNestedArray(const std::string&) const | ||||||
|   // |   // createNestedArray(const String&) const | ||||||
|   // ObjectRef createNestedObject(TKey); |   template <typename TString> | ||||||
|   // TKey = const std::string&, const String& |   FORCE_INLINE ArrayRef createNestedArray(const TString &key) const; | ||||||
|   template <typename TKey> |  | ||||||
|   ObjectRef createNestedObject(const TKey &key) const; |   // createNestedArray(char*) const | ||||||
|   // |   // createNestedArray(const char*) const | ||||||
|   // ObjectRef createNestedObject(TKey); |   // createNestedArray(const __FlashStringHelper*) const | ||||||
|   // TKey = char*, const char*, char[], const char[], const __FlashStringHelper* |   template <typename TChar> | ||||||
|   template <typename TKey> |   FORCE_INLINE ArrayRef createNestedArray(TChar *key) const; | ||||||
|   ObjectRef createNestedObject(TKey *key) const; |  | ||||||
|  |   // createNestedObject(const std::string&) const | ||||||
|  |   // createNestedObject(const String&) const | ||||||
|  |   template <typename TString> | ||||||
|  |   ObjectRef createNestedObject(const TString &key) const; | ||||||
|  |  | ||||||
|  |   // createNestedObject(char*) const | ||||||
|  |   // createNestedObject(const char*) const | ||||||
|  |   // createNestedObject(const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|  |   ObjectRef createNestedObject(TChar *key) const; | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   const TObject *impl() const { |   const TObject *impl() const { | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ class Pair { | |||||||
|  public: |  public: | ||||||
|   Pair(MemoryPool* pool, VariantSlot* slot) { |   Pair(MemoryPool* pool, VariantSlot* slot) { | ||||||
|     if (slot) { |     if (slot) { | ||||||
|       _key = slot->key(); |       _key = String(slot->key(), !slot->ownsKey()); | ||||||
|       _value = VariantRef(pool, slot->data()); |       _value = VariantRef(pool, slot->data()); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -35,7 +35,7 @@ class PairConst { | |||||||
|  public: |  public: | ||||||
|   PairConst(const VariantSlot* slot) { |   PairConst(const VariantSlot* slot) { | ||||||
|     if (slot) { |     if (slot) { | ||||||
|       _key = slot->key(); |       _key = String(slot->key(), !slot->ownsKey()); | ||||||
|       _value = VariantConstRef(slot->data()); |       _value = VariantConstRef(slot->data()); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -21,28 +21,28 @@ class VariantComparisons { | |||||||
|   template <typename T> |   template <typename T> | ||||||
|   friend typename enable_if<IsString<T *>::value, bool>::type operator==( |   friend typename enable_if<IsString<T *>::value, bool>::type operator==( | ||||||
|       T *lhs, TVariant rhs) { |       T *lhs, TVariant rhs) { | ||||||
|     return wrapString(lhs).equals(rhs.template as<const char *>()); |     return adaptString(lhs).equals(rhs.template as<const char *>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // std::string == TVariant |   // std::string == TVariant | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   friend typename enable_if<IsString<T>::value, bool>::type operator==( |   friend typename enable_if<IsString<T>::value, bool>::type operator==( | ||||||
|       const T &lhs, TVariant rhs) { |       const T &lhs, TVariant rhs) { | ||||||
|     return wrapString(lhs).equals(rhs.template as<const char *>()); |     return adaptString(lhs).equals(rhs.template as<const char *>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // TVariant == const char* |   // TVariant == const char* | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   friend typename enable_if<IsString<T *>::value, bool>::type operator==( |   friend typename enable_if<IsString<T *>::value, bool>::type operator==( | ||||||
|       TVariant lhs, T *rhs) { |       TVariant lhs, T *rhs) { | ||||||
|     return wrapString(rhs).equals(lhs.template as<const char *>()); |     return adaptString(rhs).equals(lhs.template as<const char *>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // TVariant == std::string |   // TVariant == std::string | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   friend typename enable_if<IsString<T>::value, bool>::type operator==( |   friend typename enable_if<IsString<T>::value, bool>::type operator==( | ||||||
|       TVariant lhs, const T &rhs) { |       TVariant lhs, const T &rhs) { | ||||||
|     return wrapString(rhs).equals(lhs.template as<const char *>()); |     return adaptString(rhs).equals(lhs.template as<const char *>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // bool/int/float == TVariant |   // bool/int/float == TVariant | ||||||
| @@ -63,28 +63,28 @@ class VariantComparisons { | |||||||
|   template <typename T> |   template <typename T> | ||||||
|   friend typename enable_if<IsString<T *>::value, bool>::type operator!=( |   friend typename enable_if<IsString<T *>::value, bool>::type operator!=( | ||||||
|       T *lhs, TVariant rhs) { |       T *lhs, TVariant rhs) { | ||||||
|     return !wrapString(lhs).equals(rhs.template as<const char *>()); |     return !adaptString(lhs).equals(rhs.template as<const char *>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // std::string != TVariant |   // std::string != TVariant | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   friend typename enable_if<IsString<T>::value, bool>::type operator!=( |   friend typename enable_if<IsString<T>::value, bool>::type operator!=( | ||||||
|       const T &lhs, TVariant rhs) { |       const T &lhs, TVariant rhs) { | ||||||
|     return !wrapString(lhs).equals(rhs.template as<const char *>()); |     return !adaptString(lhs).equals(rhs.template as<const char *>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // TVariant != const char* |   // TVariant != const char* | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   friend typename enable_if<IsString<T *>::value, bool>::type operator!=( |   friend typename enable_if<IsString<T *>::value, bool>::type operator!=( | ||||||
|       TVariant lhs, T *rhs) { |       TVariant lhs, T *rhs) { | ||||||
|     return !wrapString(rhs).equals(lhs.template as<const char *>()); |     return !adaptString(rhs).equals(lhs.template as<const char *>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // TVariant != std::string |   // TVariant != std::string | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   friend typename enable_if<IsString<T>::value, bool>::type operator!=( |   friend typename enable_if<IsString<T>::value, bool>::type operator!=( | ||||||
|       TVariant lhs, const T &rhs) { |       TVariant lhs, const T &rhs) { | ||||||
|     return !wrapString(rhs).equals(lhs.template as<const char *>()); |     return !adaptString(rhs).equals(lhs.template as<const char *>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // bool/int/float != TVariant |   // bool/int/float != TVariant | ||||||
|   | |||||||
| @@ -8,9 +8,9 @@ | |||||||
| 
 | 
 | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| 
 | 
 | ||||||
| class ArduinoStringWrapper { | class ArduinoStringAdapter { | ||||||
|  public: |  public: | ||||||
|   ArduinoStringWrapper(const ::String& str) : _str(&str) {} |   ArduinoStringAdapter(const ::String& str) : _str(&str) {} | ||||||
| 
 | 
 | ||||||
|   char* save(MemoryPool* pool) const { |   char* save(MemoryPool* pool) const { | ||||||
|     if (isNull()) return NULL; |     if (isNull()) return NULL; | ||||||
| @@ -40,6 +40,10 @@ class ArduinoStringWrapper { | |||||||
|     return _str->length(); |     return _str->length(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   bool isStatic() const { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  private: |  private: | ||||||
|   const ::String* _str; |   const ::String* _str; | ||||||
| }; | }; | ||||||
| @@ -50,8 +54,8 @@ struct IsString< ::String> : true_type {}; | |||||||
| template <> | template <> | ||||||
| struct IsString< ::StringSumHelper> : true_type {}; | struct IsString< ::StringSumHelper> : true_type {}; | ||||||
| 
 | 
 | ||||||
| inline ArduinoStringWrapper wrapString(const ::String& str) { | inline ArduinoStringAdapter adaptString(const ::String& str) { | ||||||
|   return ArduinoStringWrapper(str); |   return ArduinoStringAdapter(str); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE
 | }  // namespace ARDUINOJSON_NAMESPACE
 | ||||||
| @@ -9,9 +9,9 @@ | |||||||
| 
 | 
 | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| 
 | 
 | ||||||
| class ConstRamStringWrapper { | class ConstRamStringAdapter { | ||||||
|  public: |  public: | ||||||
|   ConstRamStringWrapper(const char* str = 0) : _str(str) {} |   ConstRamStringAdapter(const char* str = 0) : _str(str) {} | ||||||
| 
 | 
 | ||||||
|   bool equals(const char* expected) const { |   bool equals(const char* expected) const { | ||||||
|     const char* actual = _str; |     const char* actual = _str; | ||||||
| @@ -23,25 +23,29 @@ class ConstRamStringWrapper { | |||||||
|     return !_str; |     return !_str; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // template <typename TMemoryPool>
 |   template <typename TMemoryPool> | ||||||
|   // const char* save(TMemoryPool*) const {
 |   char* save(TMemoryPool*) const { | ||||||
|   //   return _str;
 |     return 0; | ||||||
|   // }
 |   } | ||||||
| 
 | 
 | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|     return strlen(_str); |     return strlen(_str); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const char* c_str() const { |   const char* data() const { | ||||||
|     return _str; |     return _str; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   bool isStatic() const { | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  protected: |  protected: | ||||||
|   const char* _str; |   const char* _str; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| inline ConstRamStringWrapper wrapString(const char* str) { | inline ConstRamStringAdapter adaptString(const char* str) { | ||||||
|   return ConstRamStringWrapper(str); |   return ConstRamStringAdapter(str); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE
 | }  // namespace ARDUINOJSON_NAMESPACE
 | ||||||
| @@ -6,9 +6,9 @@ | |||||||
| 
 | 
 | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| 
 | 
 | ||||||
| class FlashStringWrapper { | class FlashStringAdapter { | ||||||
|  public: |  public: | ||||||
|   FlashStringWrapper(const __FlashStringHelper* str) : _str(str) {} |   FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {} | ||||||
| 
 | 
 | ||||||
|   bool equals(const char* expected) const { |   bool equals(const char* expected) const { | ||||||
|     const char* actual = reinterpret_cast<const char*>(_str); |     const char* actual = reinterpret_cast<const char*>(_str); | ||||||
| @@ -28,16 +28,24 @@ class FlashStringWrapper { | |||||||
|     return dup; |     return dup; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   const char* data() const { | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|     return strlen_P(reinterpret_cast<const char*>(_str)); |     return strlen_P(reinterpret_cast<const char*>(_str)); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   bool isStatic() const { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  private: |  private: | ||||||
|   const __FlashStringHelper* _str; |   const __FlashStringHelper* _str; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| inline FlashStringWrapper wrapString(const __FlashStringHelper* str) { | inline FlashStringAdapter adaptString(const __FlashStringHelper* str) { | ||||||
|   return FlashStringWrapper(str); |   return FlashStringAdapter(str); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <> | template <> | ||||||
| @@ -4,13 +4,13 @@ | |||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "ConstRamStringWrapper.hpp" | #include "ConstRamStringAdapter.hpp" | ||||||
| 
 | 
 | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| 
 | 
 | ||||||
| class RamStringWrapper : public ConstRamStringWrapper { | class RamStringAdapter : public ConstRamStringAdapter { | ||||||
|  public: |  public: | ||||||
|   RamStringWrapper(const char* str) : ConstRamStringWrapper(str) {} |   RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {} | ||||||
| 
 | 
 | ||||||
|   char* save(MemoryPool* pool) const { |   char* save(MemoryPool* pool) const { | ||||||
|     if (!_str) return NULL; |     if (!_str) return NULL; | ||||||
| @@ -19,15 +19,19 @@ class RamStringWrapper : public ConstRamStringWrapper { | |||||||
|     if (dup) memcpy(dup, _str, n); |     if (dup) memcpy(dup, _str, n); | ||||||
|     return dup; |     return dup; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   bool isStatic() const { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename TChar> | template <typename TChar> | ||||||
| inline RamStringWrapper wrapString(const TChar* str) { | inline RamStringAdapter adaptString(const TChar* str) { | ||||||
|   return RamStringWrapper(reinterpret_cast<const char*>(str)); |   return RamStringAdapter(reinterpret_cast<const char*>(str)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline RamStringWrapper wrapString(char* str) { | inline RamStringAdapter adaptString(char* str) { | ||||||
|   return RamStringWrapper(str); |   return RamStringAdapter(str); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename TChar> | template <typename TChar> | ||||||
| @@ -6,9 +6,9 @@ | |||||||
| 
 | 
 | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| 
 | 
 | ||||||
| class SizedFlashStringWrapper { | class SizedFlashStringAdapter { | ||||||
|  public: |  public: | ||||||
|   SizedFlashStringWrapper(const __FlashStringHelper* str, size_t sz) |   SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz) | ||||||
|       : _str(str), _size(sz) {} |       : _str(str), _size(sz) {} | ||||||
| 
 | 
 | ||||||
|   bool equals(const char* expected) const { |   bool equals(const char* expected) const { | ||||||
| @@ -32,13 +32,17 @@ class SizedFlashStringWrapper { | |||||||
|     return strlen_P(reinterpret_cast<const char*>(_str)); |     return strlen_P(reinterpret_cast<const char*>(_str)); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   bool isStatic() const { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  private: |  private: | ||||||
|   const __FlashStringHelper* _str; |   const __FlashStringHelper* _str; | ||||||
|   size_t _size; |   size_t _size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| inline SizedFlashStringWrapper wrapString(const __FlashStringHelper* str, | inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str, | ||||||
|                                           size_t sz) { |                                            size_t sz) { | ||||||
|   return SizedFlashStringWrapper(str, sz); |   return SizedFlashStringAdapter(str, sz); | ||||||
| } | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE
 | }  // namespace ARDUINOJSON_NAMESPACE
 | ||||||
| @@ -8,9 +8,9 @@ | |||||||
| 
 | 
 | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| 
 | 
 | ||||||
| class SizedRamStringWrapper { | class SizedRamStringAdapter { | ||||||
|  public: |  public: | ||||||
|   SizedRamStringWrapper(const char* str, size_t n) : _str(str), _size(n) {} |   SizedRamStringAdapter(const char* str, size_t n) : _str(str), _size(n) {} | ||||||
| 
 | 
 | ||||||
|   bool equals(const char* expected) const { |   bool equals(const char* expected) const { | ||||||
|     const char* actual = reinterpret_cast<const char*>(_str); |     const char* actual = reinterpret_cast<const char*>(_str); | ||||||
| @@ -33,14 +33,18 @@ class SizedRamStringWrapper { | |||||||
|     return strlen(reinterpret_cast<const char*>(_str)); |     return strlen(reinterpret_cast<const char*>(_str)); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   bool isStatic() const { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  private: |  private: | ||||||
|   const char* _str; |   const char* _str; | ||||||
|   size_t _size; |   size_t _size; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| template <typename TChar> | template <typename TChar> | ||||||
| inline SizedRamStringWrapper wrapString(const TChar* str, size_t size) { | inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) { | ||||||
|   return SizedRamStringWrapper(reinterpret_cast<const char*>(str), size); |   return SizedRamStringAdapter(reinterpret_cast<const char*>(str), size); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE
 | }  // namespace ARDUINOJSON_NAMESPACE
 | ||||||
| @@ -8,9 +8,9 @@ | |||||||
| 
 | 
 | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| 
 | 
 | ||||||
| class StlStringWrapper { | class StlStringAdapter { | ||||||
|  public: |  public: | ||||||
|   StlStringWrapper(const std::string& str) : _str(&str) {} |   StlStringAdapter(const std::string& str) : _str(&str) {} | ||||||
| 
 | 
 | ||||||
|   char* save(MemoryPool* pool) const { |   char* save(MemoryPool* pool) const { | ||||||
|     size_t n = _str->length() + 1; |     size_t n = _str->length() + 1; | ||||||
| @@ -36,6 +36,10 @@ class StlStringWrapper { | |||||||
|     return _str->size(); |     return _str->size(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   bool isStatic() const { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  private: |  private: | ||||||
|   const std::string* _str; |   const std::string* _str; | ||||||
| }; | }; | ||||||
| @@ -43,8 +47,8 @@ class StlStringWrapper { | |||||||
| template <> | template <> | ||||||
| struct IsString<std::string> : true_type {}; | struct IsString<std::string> : true_type {}; | ||||||
| 
 | 
 | ||||||
| inline StlStringWrapper wrapString(const std::string& str) { | inline StlStringAdapter adaptString(const std::string& str) { | ||||||
|   return StlStringWrapper(str); |   return StlStringAdapter(str); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE
 | }  // namespace ARDUINOJSON_NAMESPACE
 | ||||||
| @@ -4,12 +4,15 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "ConstRamStringAdapter.hpp" | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| class String { | class String { | ||||||
|  public: |  public: | ||||||
|   String() : _data(0) {} |   String() : _data(0), _isStatic(true) {} | ||||||
|   String(const char* slot) : _data(slot) {} |   String(const char* data, bool isStaticData = true) | ||||||
|  |       : _data(data), _isStatic(isStaticData) {} | ||||||
|  |  | ||||||
|   const char* c_str() const { |   const char* c_str() const { | ||||||
|     return _data; |     return _data; | ||||||
| @@ -19,6 +22,10 @@ class String { | |||||||
|     return !_data; |     return !_data; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   bool isStatic() const { | ||||||
|  |     return _isStatic; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   friend bool operator==(String lhs, String rhs) { |   friend bool operator==(String lhs, String rhs) { | ||||||
|     if (lhs._data == rhs._data) return true; |     if (lhs._data == rhs._data) return true; | ||||||
|     if (!lhs._data) return false; |     if (!lhs._data) return false; | ||||||
| @@ -28,5 +35,31 @@ class String { | |||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   const char* _data; |   const char* _data; | ||||||
|  |   bool _isStatic; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | class StringAdapter : public RamStringAdapter { | ||||||
|  |  public: | ||||||
|  |   StringAdapter(const String& str) | ||||||
|  |       : RamStringAdapter(str.c_str()), _isStatic(str.isStatic()) {} | ||||||
|  |  | ||||||
|  |   bool isStatic() const { | ||||||
|  |     return _isStatic; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /*  const char* save(MemoryPool* pool) const { | ||||||
|  |       if (_isStatic) return c_str(); | ||||||
|  |       return RamStringAdapter::save(pool); | ||||||
|  |     }*/ | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   bool _isStatic; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct IsString<String> : true_type {}; | ||||||
|  |  | ||||||
|  | inline StringAdapter adaptString(const String& str) { | ||||||
|  |   return StringAdapter(str); | ||||||
|  | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -18,19 +18,19 @@ template <typename T> | |||||||
| struct IsString<T&> : IsString<T> {}; | struct IsString<T&> : IsString<T> {}; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE
 | }  // namespace ARDUINOJSON_NAMESPACE
 | ||||||
| 
 | 
 | ||||||
| #include "ConstRamStringWrapper.hpp" | #include "ConstRamStringAdapter.hpp" | ||||||
| #include "RamStringWrapper.hpp" | #include "RamStringAdapter.hpp" | ||||||
| #include "SizedRamStringWrapper.hpp" | #include "SizedRamStringAdapter.hpp" | ||||||
| 
 | 
 | ||||||
| #if ARDUINOJSON_ENABLE_STD_STRING | #if ARDUINOJSON_ENABLE_STD_STRING | ||||||
| #include "StlStringWrapper.hpp" | #include "StlStringAdapter.hpp" | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if ARDUINOJSON_ENABLE_ARDUINO_STRING | #if ARDUINOJSON_ENABLE_ARDUINO_STRING | ||||||
| #include "ArduinoStringWrapper.hpp" | #include "ArduinoStringAdapter.hpp" | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if ARDUINOJSON_ENABLE_PROGMEM | #if ARDUINOJSON_ENABLE_PROGMEM | ||||||
| #include "FlashStringWrapper.hpp" | #include "FlashStringAdapter.hpp" | ||||||
| #include "SizedFlashStringWrapper.hpp" | #include "SizedFlashStringAdapter.hpp" | ||||||
| #endif | #endif | ||||||
| @@ -6,24 +6,21 @@ | |||||||
|  |  | ||||||
| #include "../Memory/MemoryPool.hpp" | #include "../Memory/MemoryPool.hpp" | ||||||
| #include "../Polyfills/assert.hpp" | #include "../Polyfills/assert.hpp" | ||||||
| #include "../Strings/StringWrappers.hpp" | #include "../Strings/StringAdapters.hpp" | ||||||
| #include "VariantData.hpp" | #include "VariantData.hpp" | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TAdaptedString> | ||||||
| inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) { | inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) { | ||||||
|   if (!var) return false; |   if (!var) return false; | ||||||
|   char* dup = key.save(pool); |   if (key.isStatic()) { | ||||||
|   if (!dup) return false; |     var->setLinkedKey(key.data()); | ||||||
|   var->setOwnedKey(dup); |   } else { | ||||||
|   return true; |     char* dup = key.save(pool); | ||||||
| } |     if (!dup) return false; | ||||||
|  |     var->setOwnedKey(dup); | ||||||
| inline bool slotSetKey(VariantSlot* var, ConstRamStringWrapper key, |   } | ||||||
|                        MemoryPool*) { |  | ||||||
|   if (!var) return false; |  | ||||||
|   var->setLinkedKey(key.c_str()); |  | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -89,7 +89,7 @@ class VariantData { | |||||||
|       case VALUE_IS_OBJECT: |       case VALUE_IS_OBJECT: | ||||||
|         return toObject().copyFrom(src._content.asCollection, pool); |         return toObject().copyFrom(src._content.asCollection, pool); | ||||||
|       case VALUE_IS_OWNED_STRING: |       case VALUE_IS_OWNED_STRING: | ||||||
|         return setOwnedString(RamStringWrapper(src._content.asString), pool); |         return setOwnedString(RamStringAdapter(src._content.asString), pool); | ||||||
|       case VALUE_IS_OWNED_RAW: |       case VALUE_IS_OWNED_RAW: | ||||||
|         return setOwnedRaw( |         return setOwnedRaw( | ||||||
|             serialized(src._content.asRaw.data, src._content.asRaw.size), pool); |             serialized(src._content.asRaw.data, src._content.asRaw.size), pool); | ||||||
| @@ -186,7 +186,7 @@ class VariantData { | |||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) { |   bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) { | ||||||
|     char *dup = wrapString(value.data(), value.size()).save(pool); |     char *dup = adaptString(value.data(), value.size()).save(pool); | ||||||
|     if (dup) { |     if (dup) { | ||||||
|       setType(VALUE_IS_OWNED_RAW); |       setType(VALUE_IS_OWNED_RAW); | ||||||
|       _content.asRaw.data = dup; |       _content.asRaw.data = dup; | ||||||
| @@ -289,13 +289,13 @@ class VariantData { | |||||||
|     return isArray() ? _content.asCollection.get(index) : 0; |     return isArray() ? _content.asCollection.get(index) : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   VariantData *get(TKey key) const { |   VariantData *get(TAdaptedString key) const { | ||||||
|     return isObject() ? _content.asCollection.get(key) : 0; |     return isObject() ? _content.asCollection.get(key) : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TKey> |   template <typename TAdaptedString> | ||||||
|   VariantData *getOrCreate(TKey key, MemoryPool *pool) { |   VariantData *getOrCreate(TAdaptedString key, MemoryPool *pool) { | ||||||
|     if (isNull()) toObject(); |     if (isNull()) toObject(); | ||||||
|     if (!isObject()) return 0; |     if (!isObject()) return 0; | ||||||
|     VariantData *var = _content.asCollection.get(key); |     VariantData *var = _content.asCollection.get(key); | ||||||
|   | |||||||
| @@ -150,16 +150,16 @@ inline NO_INLINE VariantData *variantAdd(VariantData *var, MemoryPool *pool) { | |||||||
|   return var != 0 ? var->add(pool) : 0; |   return var != 0 ? var->add(pool) : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TChar> | ||||||
| NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TKey *key, | NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TChar *key, | ||||||
|                                           MemoryPool *pool) { |                                           MemoryPool *pool) { | ||||||
|   return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0; |   return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TString> | ||||||
| NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TKey &key, | NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TString &key, | ||||||
|                                           MemoryPool *pool) { |                                           MemoryPool *pool) { | ||||||
|   return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0; |   return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -110,24 +110,24 @@ inline VariantRef VariantRef::get(size_t index) const { | |||||||
|   return VariantRef(_pool, _data != 0 ? _data->get(index) : 0); |   return VariantRef(_pool, _data != 0 ? _data->get(index) : 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TChar> | ||||||
| inline VariantRef VariantRef::get(TKey *key) const { | inline VariantRef VariantRef::get(TChar *key) const { | ||||||
|   return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0); |   return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TString> | ||||||
| inline typename enable_if<IsString<TKey>::value, VariantRef>::type | inline typename enable_if<IsString<TString>::value, VariantRef>::type | ||||||
| VariantRef::get(const TKey &key) const { | VariantRef::get(const TString &key) const { | ||||||
|   return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0); |   return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TChar> | ||||||
| inline VariantRef VariantRef::getOrCreate(TKey *key) const { | inline VariantRef VariantRef::getOrCreate(TChar *key) const { | ||||||
|   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); |   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TKey> | template <typename TString> | ||||||
| inline VariantRef VariantRef::getOrCreate(const TKey &key) const { | inline VariantRef VariantRef::getOrCreate(const TString &key) const { | ||||||
|   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); |   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); | ||||||
| } | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -194,7 +194,7 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|   FORCE_INLINE bool set( |   FORCE_INLINE bool set( | ||||||
|       const T &value, |       const T &value, | ||||||
|       typename enable_if<IsString<T>::value>::type * = 0) const { |       typename enable_if<IsString<T>::value>::type * = 0) const { | ||||||
|     return variantSetOwnedString(_data, wrapString(value), _pool); |     return variantSetOwnedString(_data, adaptString(value), _pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(char*) |   // set(char*) | ||||||
| @@ -202,7 +202,7 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set( |   FORCE_INLINE bool set( | ||||||
|       T *value, typename enable_if<IsString<T *>::value>::type * = 0) const { |       T *value, typename enable_if<IsString<T *>::value>::type * = 0) const { | ||||||
|     return variantSetOwnedString(_data, wrapString(value), _pool); |     return variantSetOwnedString(_data, adaptString(value), _pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(const char*); |   // set(const char*); | ||||||
| @@ -285,20 +285,27 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|  |  | ||||||
|   FORCE_INLINE VariantRef get(size_t) const; |   FORCE_INLINE VariantRef get(size_t) const; | ||||||
|  |  | ||||||
|   template <typename TKey> |   // get(const char*) const | ||||||
|   FORCE_INLINE VariantRef get(TKey *) const; |   // get(const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|  |   FORCE_INLINE VariantRef get(TChar *) const; | ||||||
|  |  | ||||||
|   // get(const char*) |   // get(const std::string&) const | ||||||
|   // get(const __FlashStringHelper*) |   // get(const String&) const | ||||||
|   template <typename TKey> |   template <typename TString> | ||||||
|   FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get( |   FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type | ||||||
|       const TKey &) const; |   get(const TString &) const; | ||||||
|  |  | ||||||
|   template <typename TKey> |   // getOrCreate(char*) const | ||||||
|   FORCE_INLINE VariantRef getOrCreate(TKey *) const; |   // getOrCreate(const char*) const | ||||||
|  |   // getOrCreate(const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(TChar *) const; | ||||||
|  |  | ||||||
|   template <typename TKey> |   // getOrCreate(const std::string&) const | ||||||
|   FORCE_INLINE VariantRef getOrCreate(const TKey &) const; |   // getOrCreate(const String&) const | ||||||
|  |   template <typename TString> | ||||||
|  |   FORCE_INLINE VariantRef getOrCreate(const TString &) const; | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   MemoryPool *_pool; |   MemoryPool *_pool; | ||||||
| @@ -329,24 +336,24 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | |||||||
|  |  | ||||||
|   FORCE_INLINE VariantConstRef operator[](size_t index) const; |   FORCE_INLINE VariantConstRef operator[](size_t index) const; | ||||||
|  |  | ||||||
|   // |   // operator[](const std::string&) const | ||||||
|   // const VariantConstRef operator[](TKey) const; |   // operator[](const String&) const | ||||||
|   // TKey = const std::string&, const String& |  | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename enable_if<IsString<TString>::value, VariantConstRef>::type |       typename enable_if<IsString<TString>::value, VariantConstRef>::type | ||||||
|       operator[](const TString &key) const { |       operator[](const TString &key) const { | ||||||
|     return VariantConstRef(objectGet(variantAsObject(_data), wrapString(key))); |     return VariantConstRef(objectGet(variantAsObject(_data), adaptString(key))); | ||||||
|   } |   } | ||||||
|   // |  | ||||||
|   // VariantConstRef operator[](TKey); |   // operator[](char*) const | ||||||
|   // TKey = const char*, const char[N], const __FlashStringHelper* |   // operator[](const char*) const | ||||||
|   template <typename TString> |   // operator[](const __FlashStringHelper*) const | ||||||
|  |   template <typename TChar> | ||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename enable_if<IsString<TString *>::value, VariantConstRef>::type |       typename enable_if<IsString<TChar *>::value, VariantConstRef>::type | ||||||
|       operator[](TString *key) const { |       operator[](TChar *key) const { | ||||||
|     const CollectionData *obj = variantAsObject(_data); |     const CollectionData *obj = variantAsObject(_data); | ||||||
|     return VariantConstRef(obj ? obj->get(wrapString(key)) : 0); |     return VariantConstRef(obj ? obj->get(adaptString(key)) : 0); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -141,6 +141,18 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|     REQUIRE(expectedSize <= doc.memoryUsage()); |     REQUIRE(expectedSize <= doc.memoryUsage()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("should duplicate a non-static JsonString key") { | ||||||
|  |     obj[JsonString("hello", false)] = "world"; | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6); | ||||||
|  |     REQUIRE(expectedSize == doc.memoryUsage()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("should not duplicate a static JsonString key") { | ||||||
|  |     obj[JsonString("hello", true)] = "world"; | ||||||
|  |     const size_t expectedSize = JSON_OBJECT_SIZE(1); | ||||||
|  |     REQUIRE(expectedSize == doc.memoryUsage()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   SECTION("should ignore null key") { |   SECTION("should ignore null key") { | ||||||
|     // object must have a value to make a call to strcmp() |     // object must have a value to make a call to strcmp() | ||||||
|     obj["dummy"] = 42; |     obj["dummy"] = 42; | ||||||
|   | |||||||
| @@ -71,6 +71,26 @@ TEST_CASE("JsonVariant and strings") { | |||||||
|  |  | ||||||
|     REQUIRE(variant == "hello"); |     REQUIRE(variant == "hello"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("stores static JsonString by reference") { | ||||||
|  |     char str[16]; | ||||||
|  |  | ||||||
|  |     strcpy(str, "hello"); | ||||||
|  |     variant.set(JsonString(str, true)); | ||||||
|  |     strcpy(str, "world"); | ||||||
|  |  | ||||||
|  |     REQUIRE(variant == "hello"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("stores non-static JsonString by copy") { | ||||||
|  |     char str[16]; | ||||||
|  |  | ||||||
|  |     strcpy(str, "hello"); | ||||||
|  |     variant.set(JsonString(str, false)); | ||||||
|  |     strcpy(str, "world"); | ||||||
|  |  | ||||||
|  |     REQUIRE(variant == "hello"); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("JsonVariant with not enough memory") { | TEST_CASE("JsonVariant with not enough memory") { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user