فهرست منبع

User can now use a JsonString as a key or a value

Benoit Blanchon 7 سال پیش
والد
کامیت
b184af6d00
29فایلهای تغییر یافته به همراه509 افزوده شده و 385 حذف شده
  1. 1 0
      CHANGELOG.md
  2. 10 10
      src/ArduinoJson/Collection/CollectionData.hpp
  3. 11 11
      src/ArduinoJson/Collection/CollectionImpl.hpp
  4. 10 9
      src/ArduinoJson/Deserialization/deserialize.hpp
  5. 82 60
      src/ArduinoJson/Document/JsonDocument.hpp
  6. 2 2
      src/ArduinoJson/Misc/SerializedValue.hpp
  7. 35 34
      src/ArduinoJson/Object/MemberProxy.hpp
  8. 8 8
      src/ArduinoJson/Object/ObjectFunctions.hpp
  9. 9 10
      src/ArduinoJson/Object/ObjectImpl.hpp
  10. 86 87
      src/ArduinoJson/Object/ObjectRef.hpp
  11. 38 38
      src/ArduinoJson/Object/ObjectShortcuts.hpp
  12. 2 2
      src/ArduinoJson/Object/Pair.hpp
  13. 8 8
      src/ArduinoJson/Operators/VariantComparisons.hpp
  14. 8 4
      src/ArduinoJson/Strings/ArduinoStringAdapter.hpp
  15. 13 9
      src/ArduinoJson/Strings/ConstRamStringAdapter.hpp
  16. 12 4
      src/ArduinoJson/Strings/FlashStringAdapter.hpp
  17. 11 7
      src/ArduinoJson/Strings/RamStringAdapter.hpp
  18. 9 5
      src/ArduinoJson/Strings/SizedFlashStringAdapter.hpp
  19. 8 4
      src/ArduinoJson/Strings/SizedRamStringAdapter.hpp
  20. 8 4
      src/ArduinoJson/Strings/StlStringAdapter.hpp
  21. 35 2
      src/ArduinoJson/Strings/String.hpp
  22. 7 7
      src/ArduinoJson/Strings/StringAdapters.hpp
  23. 10 13
      src/ArduinoJson/Variant/SlotFunctions.hpp
  24. 6 6
      src/ArduinoJson/Variant/VariantData.hpp
  25. 6 6
      src/ArduinoJson/Variant/VariantFunctions.hpp
  26. 11 11
      src/ArduinoJson/Variant/VariantImpl.hpp
  27. 31 24
      src/ArduinoJson/Variant/VariantRef.hpp
  28. 12 0
      test/JsonObject/subscript.cpp
  29. 20 0
      test/JsonVariant/set.cpp

+ 1 - 0
CHANGELOG.md

@@ -28,6 +28,7 @@ HEAD
 * `JsonDocument` now support the same operations as `JsonVariant`.
   Calling `JsonDocument::as<T>()` is not required anymore.
 * Fixed example `JsonHttpClient.ino`
+* User can now use a `JsonString` as a key or a value
 
 > ### BREAKING CHANGES
 > 

+ 10 - 10
src/ArduinoJson/Collection/CollectionData.hpp

@@ -24,13 +24,13 @@ class CollectionData {
 
   VariantData *add(MemoryPool *pool);
 
-  template <typename TKey>
-  VariantData *add(TKey key, MemoryPool *pool);
+  template <typename TAdaptedString>
+  VariantData *add(TAdaptedString key, MemoryPool *pool);
 
   void clear();
 
-  template <typename TKey>
-  bool containsKey(const TKey &key) const;
+  template <typename TAdaptedString>
+  bool containsKey(const TAdaptedString &key) const;
 
   bool copyFrom(const CollectionData &src, MemoryPool *pool);
 
@@ -39,8 +39,8 @@ class CollectionData {
 
   VariantData *get(size_t index) const;
 
-  template <typename TKey>
-  VariantData *get(TKey key) const;
+  template <typename TAdaptedString>
+  VariantData *get(TAdaptedString key) const;
 
   VariantSlot *head() const {
     return _head;
@@ -48,8 +48,8 @@ class CollectionData {
 
   void remove(size_t index);
 
-  template <typename TKey>
-  void remove(TKey key) {
+  template <typename TAdaptedString>
+  void remove(TAdaptedString key) {
     remove(getSlot(key));
   }
 
@@ -62,8 +62,8 @@ class CollectionData {
  private:
   VariantSlot *getSlot(size_t index) const;
 
-  template <typename TKey>
-  VariantSlot *getSlot(TKey key) const;
+  template <typename TAdaptedString>
+  VariantSlot *getSlot(TAdaptedString key) const;
 
   VariantSlot *getPreviousSlot(VariantSlot *) const;
 };

+ 11 - 11
src/ArduinoJson/Collection/CollectionImpl.hpp

@@ -29,8 +29,8 @@ inline VariantData* CollectionData::add(MemoryPool* pool) {
   return addSlot(pool)->data();
 }
 
-template <typename TKey>
-inline VariantData* CollectionData::add(TKey key, MemoryPool* pool) {
+template <typename TAdaptedString>
+inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) {
   VariantSlot* slot = addSlot(pool);
   if (!slotSetKey(slot, key, pool)) return 0;
   return slot->data();
@@ -41,8 +41,8 @@ inline void CollectionData::clear() {
   _tail = 0;
 }
 
-template <typename TKey>
-inline bool CollectionData::containsKey(const TKey& key) const {
+template <typename TAdaptedString>
+inline bool CollectionData::containsKey(const TAdaptedString& key) const {
   return getSlot(key) != 0;
 }
 
@@ -53,9 +53,9 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
     VariantData* var;
     if (s->key() != 0) {
       if (s->ownsKey())
-        var = add(RamStringWrapper(s->key()), pool);
+        var = add(RamStringAdapter(s->key()), pool);
       else
-        var = add(ConstRamStringWrapper(s->key()), pool);
+        var = add(ConstRamStringAdapter(s->key()), pool);
     } else {
       var = add(pool);
     }
@@ -69,7 +69,7 @@ inline bool CollectionData::equalsObject(const CollectionData& other) const {
   size_t count = 0;
   for (VariantSlot* slot = _head; slot; slot = slot->next()) {
     VariantData* v1 = slot->data();
-    VariantData* v2 = other.get(wrapString(slot->key()));
+    VariantData* v2 = other.get(adaptString(slot->key()));
     if (!variantEquals(v1, v2)) return false;
     count++;
   }
@@ -88,8 +88,8 @@ inline bool CollectionData::equalsArray(const CollectionData& other) const {
   }
 }
 
-template <typename TKey>
-inline VariantSlot* CollectionData::getSlot(TKey key) const {
+template <typename TAdaptedString>
+inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
   VariantSlot* slot = _head;
   while (slot) {
     if (key.equals(slot->key())) break;
@@ -112,8 +112,8 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
   return 0;
 }
 
-template <typename TKey>
-inline VariantData* CollectionData::get(TKey key) const {
+template <typename TAdaptedString>
+inline VariantData* CollectionData::get(TAdaptedString key) const {
   VariantSlot* slot = getSlot(key);
   return slot ? slot->data() : 0;
 }

+ 10 - 9
src/ArduinoJson/Deserialization/deserialize.hpp

@@ -23,8 +23,8 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
   return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit);
 }
 
-// DeserializationError deserialize(JsonDocument& doc, TString input);
-// TString = const std::string&, const String&
+// deserialize(JsonDocument&, const std::string&);
+// deserialize(JsonDocument&, const String&);
 template <template <typename, typename> class TDeserializer, typename TString>
 typename enable_if<!is_array<TString>::value, DeserializationError>::type
 deserialize(JsonDocument &doc, const TString &input,
@@ -36,8 +36,9 @@ deserialize(JsonDocument &doc, const TString &input,
       .parse(doc.data());
 }
 //
-// DeserializationError deserialize(JsonDocument& doc, TChar* input);
-// TChar* = char*, const char*, const __FlashStringHelper*
+// deserialize(JsonDocument&, char*);
+// deserialize(JsonDocument&, const char*);
+// deserialize(JsonDocument&, const __FlashStringHelper*);
 template <template <typename, typename> class TDeserializer, typename TChar>
 DeserializationError deserialize(JsonDocument &doc, TChar *input,
                                  NestingLimit nestingLimit) {
@@ -48,9 +49,9 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
       .parse(doc.data());
 }
 //
-// DeserializationError deserialize(JsonDocument& doc, TChar* input, size_t
-// inputSize);
-// TChar* = char*, const char*, const __FlashStringHelper*
+// deserialize(JsonDocument&, char*, size_t);
+// deserialize(JsonDocument&, const char*, size_t);
+// deserialize(JsonDocument&, const __FlashStringHelper*, size_t);
 template <template <typename, typename> class TDeserializer, typename TChar>
 DeserializationError deserialize(JsonDocument &doc, TChar *input,
                                  size_t inputSize, NestingLimit nestingLimit) {
@@ -61,8 +62,8 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
       .parse(doc.data());
 }
 //
-// DeserializationError deserialize(JsonDocument& doc, TStream input);
-// TStream = std::istream&, Stream&
+// deserialize(JsonDocument&, std::istream&);
+// deserialize(JsonDocument&, Stream&);
 template <template <typename, typename> class TDeserializer, typename TStream>
 DeserializationError deserialize(JsonDocument &doc, TStream &input,
                                  NestingLimit nestingLimit) {

+ 82 - 60
src/ArduinoJson/Document/JsonDocument.hpp

@@ -86,13 +86,18 @@ class JsonDocument : public Visitable {
     return add().to<ArrayRef>();
   }
 
-  template <typename TKey>
-  ArrayRef createNestedArray(TKey* key) {
+  // createNestedArray(char*)
+  // createNestedArray(const char*)
+  // createNestedArray(const __FlashStringHelper*)
+  template <typename TChar>
+  ArrayRef createNestedArray(TChar* key) {
     return getOrCreate(key).template to<ArrayRef>();
   }
 
-  template <typename TKey>
-  ArrayRef createNestedArray(const TKey& key) {
+  // createNestedArray(const std::string&)
+  // createNestedArray(const String&)
+  template <typename TString>
+  ArrayRef createNestedArray(const TString& key) {
     return getOrCreate(key).template to<ArrayRef>();
   }
 
@@ -100,48 +105,57 @@ class JsonDocument : public Visitable {
     return add().to<ObjectRef>();
   }
 
-  template <typename TKey>
-  ObjectRef createNestedObject(TKey* key) {
+  // createNestedObject(char*)
+  // createNestedObject(const char*)
+  // createNestedObject(const __FlashStringHelper*)
+  template <typename TChar>
+  ObjectRef createNestedObject(TChar* key) {
     return getOrCreate(key).template to<ObjectRef>();
   }
 
-  template <typename TKey>
-  ObjectRef createNestedObject(const TKey& key) {
+  // createNestedObject(const std::string&)
+  // createNestedObject(const String&)
+  template <typename TString>
+  ObjectRef createNestedObject(const TString& key) {
     return getOrCreate(key).template to<ObjectRef>();
   }
 
-  // MemberProxy operator[](TKey)
-  // TKey = const std::string&, const String&
-  template <typename TKey>
+  // operator[](const std::string&)
+  // operator[](const String&)
+  template <typename TString>
   FORCE_INLINE
-      typename enable_if<IsString<TKey>::value,
-                         MemberProxy<JsonDocument&, const TKey&> >::type
-      operator[](const TKey& key) {
-    return MemberProxy<JsonDocument&, const TKey&>(*this, key);
-  }
-
-  // MemberProxy operator[](TKey);
-  // TKey = const char*, const char[N], const __FlashStringHelper*
-  template <typename TKey>
-  FORCE_INLINE typename enable_if<IsString<TKey*>::value,
-                                  MemberProxy<JsonDocument&, TKey*> >::type
-  operator[](TKey* key) {
-    return MemberProxy<JsonDocument&, TKey*>(*this, key);
-  }
-
-  // VariantConstRef operator[](TKey) const
-  // TKey = const std::string&, const String&
-  template <typename TKey>
-  FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantConstRef>::type
-  operator[](const TKey& key) const {
+      typename enable_if<IsString<TString>::value,
+                         MemberProxy<JsonDocument&, const TString&> >::type
+      operator[](const TString& key) {
+    return MemberProxy<JsonDocument&, const TString&>(*this, key);
+  }
+
+  // operator[](char*)
+  // operator[](const char*)
+  // operator[](const __FlashStringHelper*)
+  template <typename TChar>
+  FORCE_INLINE typename enable_if<IsString<TChar*>::value,
+                                  MemberProxy<JsonDocument&, TChar*> >::type
+  operator[](TChar* key) {
+    return MemberProxy<JsonDocument&, TChar*>(*this, key);
+  }
+
+  // operator[](const std::string&) const
+  // operator[](const String&) const
+  template <typename TString>
+  FORCE_INLINE
+      typename enable_if<IsString<TString>::value, VariantConstRef>::type
+      operator[](const TString& key) const {
     return getVariant()[key];
   }
 
-  // VariantConstRef operator[](TKey) const;
-  // TKey = const char*, const char[N], const __FlashStringHelper*
-  template <typename TKey>
-  FORCE_INLINE typename enable_if<IsString<TKey*>::value, VariantConstRef>::type
-  operator[](TKey* key) const {
+  // 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 getVariant()[key];
   }
 
@@ -157,43 +171,51 @@ class JsonDocument : public Visitable {
     return VariantRef(&_pool, _data.get(index));
   }
 
-  template <typename TKey>
-  FORCE_INLINE VariantRef get(TKey* key) {
-    return VariantRef(&_pool, _data.get(wrapString(key)));
+  // get(char*) const
+  // get(const char*) const
+  // get(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef get(TChar* key) {
+    return VariantRef(&_pool, _data.get(adaptString(key)));
   }
 
-  template <typename TKey>
-  FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get(
-      const TKey& key) {
-    return VariantRef(&_pool, _data.get(wrapString(key)));
+  // get(const std::string&) const
+  // get(const String&) const
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
+  get(const TString& key) {
+    return VariantRef(&_pool, _data.get(adaptString(key)));
   }
 
-  template <typename TKey>
-  FORCE_INLINE VariantRef getOrCreate(TKey* key) {
-    return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool));
+  // getOrCreate(char*)
+  // getOrCreate(const char*)
+  // getOrCreate(const __FlashStringHelper*)
+  template <typename TChar>
+  FORCE_INLINE VariantRef getOrCreate(TChar* key) {
+    return VariantRef(&_pool, _data.getOrCreate(adaptString(key), &_pool));
   }
 
-  template <typename TKey>
-  FORCE_INLINE VariantRef getOrCreate(const TKey& key) {
-    return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool));
+  // getOrCreate(const std::string&)
+  // getOrCreate(const String&)
+  template <typename TString>
+  FORCE_INLINE VariantRef getOrCreate(const TString& key) {
+    return VariantRef(&_pool, _data.getOrCreate(adaptString(key), &_pool));
   }
 
   FORCE_INLINE VariantRef add() {
     return VariantRef(&_pool, _data.add(&_pool));
   }
-  //
-  // bool add(TValue);
-  // TValue = bool, long, int, short, float, double, serialized, VariantRef,
-  //          std::string, String, ObjectRef
-  template <typename T>
-  FORCE_INLINE bool add(const T& value) {
+
+  template <typename TValue>
+  FORCE_INLINE bool add(const TValue& value) {
     return add().set(value);
   }
-  //
-  // bool add(TValue);
-  // TValue = char*, const char*, const __FlashStringHelper*
-  template <typename T>
-  FORCE_INLINE bool add(T* value) {
+
+  // add(char*) const
+  // add(const char*) const
+  // add(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE bool add(TChar* value) {
     return add().set(value);
   }
 

+ 2 - 2
src/ArduinoJson/Misc/SerializedValue.hpp

@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include "../Strings/StringWrappers.hpp"
+#include "../Strings/StringAdapters.hpp"
 
 namespace ARDUINOJSON_NAMESPACE {
 
@@ -58,7 +58,7 @@ inline SerializedValue<T> serialized(T str) {
 
 template <typename TChar>
 inline SerializedValue<TChar*> serialized(TChar* p) {
-  return SerializedValue<TChar*>(p, wrapString(p).size());
+  return SerializedValue<TChar*>(p, adaptString(p).size());
 }
 
 template <typename TChar>

+ 35 - 34
src/ArduinoJson/Object/MemberProxy.hpp

@@ -15,13 +15,13 @@
 
 namespace ARDUINOJSON_NAMESPACE {
 
-template <typename TObject, typename TString>
-class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
+template <typename TObject, typename TStringRef>
+class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
                     public Visitable {
-  typedef MemberProxy<TObject, TString> this_type;
+  typedef MemberProxy<TObject, TStringRef> this_type;
 
  public:
-  FORCE_INLINE MemberProxy(TObject variant, TString key)
+  FORCE_INLINE MemberProxy(TObject variant, TStringRef key)
       : _object(variant), _key(key) {}
 
   FORCE_INLINE operator VariantConstRef() const {
@@ -33,22 +33,18 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
     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>
   FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
   operator=(const TValue &src) {
     getOrCreateMember().set(src);
     return *this;
   }
-  //
-  // operator=(TValue);
-  // TValue = char*, const char*, const __FlashStringHelper*
-  template <typename TValue>
-  FORCE_INLINE this_type &operator=(TValue *src) {
+
+  // operator=(char*) const
+  // operator=(const char*) const
+  // operator=(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE this_type &operator=(TChar *src) {
     getOrCreateMember().set(src);
     return *this;
   }
@@ -72,22 +68,17 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
     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>
   FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
       const TValue &value) {
     return getOrCreateMember().set(value);
   }
-  //
-  // bool set(TValue);
-  // TValue = char*, const char, const __FlashStringHelper*
-  template <typename TValue>
-  FORCE_INLINE bool set(const TValue *value) {
+
+  // set(char*) const
+  // set(const char*) const
+  // set(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE bool set(const TChar *value) {
     return getOrCreateMember().set(value);
   }
 
@@ -101,23 +92,33 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
     return getOrCreateMember().add();
   }
 
-  template <typename TNestedKey>
-  FORCE_INLINE VariantRef get(TNestedKey *key) const {
+  // get(char*) const
+  // get(const char*) const
+  // get(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef get(TChar *key) const {
     return getMember().get(key);
   }
 
-  template <typename TNestedKey>
-  FORCE_INLINE VariantRef get(const TNestedKey &key) const {
+  // get(const std::string&) const
+  // get(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef get(const TString &key) const {
     return getMember().get(key);
   }
 
-  template <typename TNestedKey>
-  FORCE_INLINE VariantRef getOrCreate(TNestedKey *key) const {
+  // getOrCreate(char*) const
+  // getOrCreate(const char*) const
+  // getOrCreate(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef getOrCreate(TChar *key) const {
     return getOrCreateMember().getOrCreate(key);
   }
 
-  template <typename TNestedKey>
-  FORCE_INLINE VariantRef getOrCreate(const TNestedKey &key) const {
+  // getOrCreate(const std::string&) const
+  // getOrCreate(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef getOrCreate(const TString &key) const {
     return getOrCreateMember().getOrCreate(key);
   }
 
@@ -131,7 +132,7 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
   }
 
   TObject _object;
-  TString _key;
+  TStringRef _key;
 };
 
 template <typename TObject>

+ 8 - 8
src/ArduinoJson/Object/ObjectFunctions.hpp

@@ -16,8 +16,8 @@ void objectAccept(const CollectionData *obj, Visitor &visitor) {
     visitor.visitNull();
 }
 
-template <typename TKey>
-inline bool objectContainsKey(const CollectionData *obj, TKey key) {
+template <typename TAdaptedString>
+inline bool objectContainsKey(const CollectionData *obj, TAdaptedString key) {
   return obj && obj->containsKey(key);
 }
 
@@ -27,20 +27,20 @@ inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
   return lhs->equalsObject(*rhs);
 }
 
-template <typename TKey>
-inline VariantData *objectGet(const CollectionData *obj, TKey key) {
+template <typename TAdaptedString>
+inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) {
   if (!obj) return 0;
   return obj->get(key);
 }
 
-template <typename TKey>
-void objectRemove(CollectionData *obj, TKey key) {
+template <typename TAdaptedString>
+void objectRemove(CollectionData *obj, TAdaptedString key) {
   if (!obj) return;
   obj->remove(key);
 }
 
-template <typename TKey>
-inline VariantData *objectGetOrCreate(CollectionData *obj, TKey key,
+template <typename TAdaptedString>
+inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key,
                                       MemoryPool *pool) {
   if (!obj) return 0;
 

+ 9 - 10
src/ArduinoJson/Object/ObjectImpl.hpp

@@ -17,23 +17,22 @@ inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
 }
 
 template <typename TObject>
-template <typename TString>
-inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
-    TString* key) const {
+template <typename TChar>
+inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(TChar* key) const {
   return impl()->getOrCreate(key).template to<ArrayRef>();
 }
 
 template <typename TObject>
-template <typename TKey>
-ObjectRef ObjectShortcuts<TObject>::createNestedObject(const TKey& key) const {
+template <typename TString>
+inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
+    const TString& key) const {
   return impl()->getOrCreate(key).template to<ObjectRef>();
 }
-//
-// ObjectRef createNestedObject(TKey);
-// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
+
 template <typename TObject>
-template <typename TKey>
-ObjectRef ObjectShortcuts<TObject>::createNestedObject(TKey* key) const {
+template <typename TChar>
+inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
+    TChar* key) const {
   return impl()->getOrCreate(key).template to<ObjectRef>();
 }
 }  // namespace ARDUINOJSON_NAMESPACE

+ 86 - 87
src/ArduinoJson/Object/ObjectRef.hpp

@@ -26,20 +26,19 @@ class ObjectRefBase {
     objectAccept(_data, visitor);
   }
 
-  // Tells weither the specified key is present and associated with a value.
-  //
-  // bool containsKey(TKey);
-  // TKey = const std::string&, const String&
-  template <typename TKey>
-  FORCE_INLINE bool containsKey(const TKey& key) const {
-    return objectContainsKey(_data, wrapString(key));
-  }
-  //
-  // bool containsKey(TKey);
-  // TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
-  template <typename TKey>
-  FORCE_INLINE bool containsKey(TKey* key) const {
-    return objectContainsKey(_data, wrapString(key));
+  // containsKey(const std::string&) const
+  // containsKey(const String&) const
+  template <typename TString>
+  FORCE_INLINE bool containsKey(const TString& key) const {
+    return objectContainsKey(_data, adaptString(key));
+  }
+
+  // containsKey(char*) const
+  // containsKey(const char*) const
+  // containsKey(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE bool containsKey(TChar* key) const {
+    return objectContainsKey(_data, adaptString(key));
   }
 
   FORCE_INLINE bool isNull() const {
@@ -83,41 +82,38 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>,
     return iterator();
   }
 
-  // Gets the value associated with the specified key.
-  //
-  // TValue get<TValue>(TKey) const;
-  // TKey = const std::string&, const String&
-  // TValue = bool, char, long, int, short, float, double,
-  //          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));
-  }
-
-  //
-  // VariantConstRef operator[](TKey) const;
-  // TKey = const std::string&, const String&
-  template <typename TKey>
-  FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantConstRef>::type
-  operator[](const TKey& key) const {
-    return get_impl(wrapString(key));
-  }
-  //
-  // VariantConstRef operator[](TKey) const;
-  // TKey = const char*, const char[N], const __FlashStringHelper*
-  template <typename TKey>
-  FORCE_INLINE typename enable_if<IsString<TKey*>::value, VariantConstRef>::type
-  operator[](TKey* key) const {
-    return get_impl(wrapString(key));
+  // get(const std::string&) const
+  // get(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantConstRef get(const TString& key) const {
+    return get_impl(adaptString(key));
+  }
+
+  // get(char*) const
+  // get(const char*) const
+  // get(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantConstRef get(TChar* key) const {
+    return get_impl(adaptString(key));
+  }
+
+  // operator[](const std::string&) const
+  // operator[](const String&) const
+  template <typename TString>
+  FORCE_INLINE
+      typename enable_if<IsString<TString>::value, VariantConstRef>::type
+      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 {
@@ -125,8 +121,8 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>,
   }
 
  private:
-  template <typename TKey>
-  FORCE_INLINE VariantConstRef get_impl(TKey key) const {
+  template <typename TAdaptedString>
+  FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const {
     return VariantConstRef(objectGet(_data, key));
   }
 };
@@ -170,30 +166,34 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
     return _data->copyFrom(*src._data, _pool);
   }
 
-  // Gets the value associated with the specified key.
-  //
-  // VariantRef get<TValue>(TKey) const;
-  // TKey = const std::string&, const String&
-  template <typename TKey>
-  FORCE_INLINE VariantRef get(const TKey& key) const {
-    return get_impl(wrapString(key));
+  // get(const std::string&) const
+  // get(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef get(const TString& key) const {
+    return get_impl(adaptString(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));
+
+  // get(char*) const
+  // get(const char*) const
+  // get(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef get(TChar* key) const {
+    return get_impl(adaptString(key));
   }
 
-  template <typename TKey>
-  FORCE_INLINE VariantRef getOrCreate(TKey* key) const {
-    return getOrCreate_impl(wrapString(key));
+  // getOrCreate(const std::string&) const
+  // getOrCreate(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef getOrCreate(const TString& key) const {
+    return getOrCreate_impl(adaptString(key));
   }
 
-  template <typename TKey>
-  FORCE_INLINE VariantRef getOrCreate(const TKey& key) const {
-    return getOrCreate_impl(wrapString(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 {
@@ -205,30 +205,29 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
     _data->remove(it.internal());
   }
 
-  // Removes the specified key and the associated value.
-  //
-  // void remove(TKey);
-  // TKey = const std::string&, const String&
-  template <typename TKey>
-  FORCE_INLINE void remove(const TKey& key) const {
-    objectRemove(_data, wrapString(key));
+  // remove(const std::string&) const
+  // remove(const String&) const
+  template <typename TString>
+  FORCE_INLINE void remove(const TString& key) const {
+    objectRemove(_data, adaptString(key));
   }
-  //
-  // void remove(TKey);
-  // TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
-  template <typename TKey>
-  FORCE_INLINE void remove(TKey* key) const {
-    objectRemove(_data, wrapString(key));
+
+  // remove(char*) const
+  // remove(const char*) const
+  // remove(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE void remove(TChar* key) const {
+    objectRemove(_data, adaptString(key));
   }
 
  private:
-  template <typename TKey>
-  FORCE_INLINE VariantRef get_impl(TKey key) const {
+  template <typename TAdaptedString>
+  FORCE_INLINE VariantRef get_impl(TAdaptedString key) const {
     return VariantRef(_pool, objectGet(_data, key));
   }
 
-  template <typename TKey>
-  FORCE_INLINE VariantRef getOrCreate_impl(TKey key) const {
+  template <typename TAdaptedString>
+  FORCE_INLINE VariantRef getOrCreate_impl(TAdaptedString key) const {
     return VariantRef(_pool, objectGetOrCreate(_data, key, _pool));
   }
 

+ 38 - 38
src/ArduinoJson/Object/ObjectShortcuts.hpp

@@ -6,52 +6,52 @@
 
 #include "../Polyfills/attributes.hpp"
 #include "../Polyfills/type_traits.hpp"
-#include "../Strings/StringWrappers.hpp"
+#include "../Strings/StringAdapters.hpp"
 
 namespace ARDUINOJSON_NAMESPACE {
-template <typename TParent, typename TKey>
+template <typename TParent, typename TStringRef>
 class MemberProxy;
 
 template <typename TObject>
 class ObjectShortcuts {
  public:
-  // MemberProxy operator[](TKey) const;
-  // TKey = const std::string&, const String&
-  template <typename TKey>
+  // operator[](const std::string&) const
+  // operator[](const String&) const
+  template <typename TString>
   FORCE_INLINE
-      typename enable_if<IsString<TKey>::value,
-                         MemberProxy<const TObject &, const TKey &> >::type
-      operator[](const TKey &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.
-  //
-  // ArrayRef createNestedArray(TKey);
-  // TKey = const std::string&, const String&
-  template <typename TKey>
-  FORCE_INLINE ArrayRef createNestedArray(const TKey &key) const;
-  // ArrayRef createNestedArray(TKey);
-  // TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
-  template <typename TKey>
-  FORCE_INLINE ArrayRef createNestedArray(TKey *key) const;
-
-  // Creates and adds a ObjectRef.
-  //
-  // ObjectRef createNestedObject(TKey);
-  // TKey = const std::string&, const String&
-  template <typename TKey>
-  ObjectRef createNestedObject(const TKey &key) const;
-  //
-  // ObjectRef createNestedObject(TKey);
-  // TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
-  template <typename TKey>
-  ObjectRef createNestedObject(TKey *key) const;
+      typename enable_if<IsString<TString>::value,
+                         MemberProxy<const TObject &, const TString &> >::type
+      operator[](const TString &key) const;
+
+  // operator[](char*) const
+  // operator[](const char*) const
+  // operator[](const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE typename enable_if<IsString<TChar *>::value,
+                                  MemberProxy<const TObject &, TChar *> >::type
+  operator[](TChar *key) const;
+
+  // createNestedArray(const std::string&) const
+  // createNestedArray(const String&) const
+  template <typename TString>
+  FORCE_INLINE ArrayRef createNestedArray(const TString &key) const;
+
+  // createNestedArray(char*) const
+  // createNestedArray(const char*) const
+  // createNestedArray(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE ArrayRef createNestedArray(TChar *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:
   const TObject *impl() const {

+ 2 - 2
src/ArduinoJson/Object/Pair.hpp

@@ -13,7 +13,7 @@ class Pair {
  public:
   Pair(MemoryPool* pool, VariantSlot* slot) {
     if (slot) {
-      _key = slot->key();
+      _key = String(slot->key(), !slot->ownsKey());
       _value = VariantRef(pool, slot->data());
     }
   }
@@ -35,7 +35,7 @@ class PairConst {
  public:
   PairConst(const VariantSlot* slot) {
     if (slot) {
-      _key = slot->key();
+      _key = String(slot->key(), !slot->ownsKey());
       _value = VariantConstRef(slot->data());
     }
   }

+ 8 - 8
src/ArduinoJson/Operators/VariantComparisons.hpp

@@ -21,28 +21,28 @@ class VariantComparisons {
   template <typename T>
   friend typename enable_if<IsString<T *>::value, bool>::type operator==(
       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
   template <typename T>
   friend typename enable_if<IsString<T>::value, bool>::type operator==(
       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*
   template <typename T>
   friend typename enable_if<IsString<T *>::value, bool>::type operator==(
       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
   template <typename T>
   friend typename enable_if<IsString<T>::value, bool>::type operator==(
       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
@@ -63,28 +63,28 @@ class VariantComparisons {
   template <typename T>
   friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
       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
   template <typename T>
   friend typename enable_if<IsString<T>::value, bool>::type operator!=(
       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*
   template <typename T>
   friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
       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
   template <typename T>
   friend typename enable_if<IsString<T>::value, bool>::type operator!=(
       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

+ 8 - 4
src/ArduinoJson/Strings/ArduinoStringWrapper.hpp → src/ArduinoJson/Strings/ArduinoStringAdapter.hpp

@@ -8,9 +8,9 @@
 
 namespace ARDUINOJSON_NAMESPACE {
 
-class ArduinoStringWrapper {
+class ArduinoStringAdapter {
  public:
-  ArduinoStringWrapper(const ::String& str) : _str(&str) {}
+  ArduinoStringAdapter(const ::String& str) : _str(&str) {}
 
   char* save(MemoryPool* pool) const {
     if (isNull()) return NULL;
@@ -40,6 +40,10 @@ class ArduinoStringWrapper {
     return _str->length();
   }
 
+  bool isStatic() const {
+    return false;
+  }
+
  private:
   const ::String* _str;
 };
@@ -50,8 +54,8 @@ struct IsString< ::String> : true_type {};
 template <>
 struct IsString< ::StringSumHelper> : true_type {};
 
-inline ArduinoStringWrapper wrapString(const ::String& str) {
-  return ArduinoStringWrapper(str);
+inline ArduinoStringAdapter adaptString(const ::String& str) {
+  return ArduinoStringAdapter(str);
 }
 
 }  // namespace ARDUINOJSON_NAMESPACE

+ 13 - 9
src/ArduinoJson/Strings/ConstRamStringWrapper.hpp → src/ArduinoJson/Strings/ConstRamStringAdapter.hpp

@@ -9,9 +9,9 @@
 
 namespace ARDUINOJSON_NAMESPACE {
 
-class ConstRamStringWrapper {
+class ConstRamStringAdapter {
  public:
-  ConstRamStringWrapper(const char* str = 0) : _str(str) {}
+  ConstRamStringAdapter(const char* str = 0) : _str(str) {}
 
   bool equals(const char* expected) const {
     const char* actual = _str;
@@ -23,25 +23,29 @@ class ConstRamStringWrapper {
     return !_str;
   }
 
-  // template <typename TMemoryPool>
-  // const char* save(TMemoryPool*) const {
-  //   return _str;
-  // }
+  template <typename TMemoryPool>
+  char* save(TMemoryPool*) const {
+    return 0;
+  }
 
   size_t size() const {
     return strlen(_str);
   }
 
-  const char* c_str() const {
+  const char* data() const {
     return _str;
   }
 
+  bool isStatic() const {
+    return true;
+  }
+
  protected:
   const char* _str;
 };
 
-inline ConstRamStringWrapper wrapString(const char* str) {
-  return ConstRamStringWrapper(str);
+inline ConstRamStringAdapter adaptString(const char* str) {
+  return ConstRamStringAdapter(str);
 }
 
 }  // namespace ARDUINOJSON_NAMESPACE

+ 12 - 4
src/ArduinoJson/Strings/FlashStringWrapper.hpp → src/ArduinoJson/Strings/FlashStringAdapter.hpp

@@ -6,9 +6,9 @@
 
 namespace ARDUINOJSON_NAMESPACE {
 
-class FlashStringWrapper {
+class FlashStringAdapter {
  public:
-  FlashStringWrapper(const __FlashStringHelper* str) : _str(str) {}
+  FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {}
 
   bool equals(const char* expected) const {
     const char* actual = reinterpret_cast<const char*>(_str);
@@ -28,16 +28,24 @@ class FlashStringWrapper {
     return dup;
   }
 
+  const char* data() const {
+    return 0;
+  }
+
   size_t size() const {
     return strlen_P(reinterpret_cast<const char*>(_str));
   }
 
+  bool isStatic() const {
+    return false;
+  }
+
  private:
   const __FlashStringHelper* _str;
 };
 
-inline FlashStringWrapper wrapString(const __FlashStringHelper* str) {
-  return FlashStringWrapper(str);
+inline FlashStringAdapter adaptString(const __FlashStringHelper* str) {
+  return FlashStringAdapter(str);
 }
 
 template <>

+ 11 - 7
src/ArduinoJson/Strings/RamStringWrapper.hpp → src/ArduinoJson/Strings/RamStringAdapter.hpp

@@ -4,13 +4,13 @@
 
 #pragma once
 
-#include "ConstRamStringWrapper.hpp"
+#include "ConstRamStringAdapter.hpp"
 
 namespace ARDUINOJSON_NAMESPACE {
 
-class RamStringWrapper : public ConstRamStringWrapper {
+class RamStringAdapter : public ConstRamStringAdapter {
  public:
-  RamStringWrapper(const char* str) : ConstRamStringWrapper(str) {}
+  RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
 
   char* save(MemoryPool* pool) const {
     if (!_str) return NULL;
@@ -19,15 +19,19 @@ class RamStringWrapper : public ConstRamStringWrapper {
     if (dup) memcpy(dup, _str, n);
     return dup;
   }
+
+  bool isStatic() const {
+    return false;
+  }
 };
 
 template <typename TChar>
-inline RamStringWrapper wrapString(const TChar* str) {
-  return RamStringWrapper(reinterpret_cast<const char*>(str));
+inline RamStringAdapter adaptString(const TChar* str) {
+  return RamStringAdapter(reinterpret_cast<const char*>(str));
 }
 
-inline RamStringWrapper wrapString(char* str) {
-  return RamStringWrapper(str);
+inline RamStringAdapter adaptString(char* str) {
+  return RamStringAdapter(str);
 }
 
 template <typename TChar>

+ 9 - 5
src/ArduinoJson/Strings/SizedFlashStringWrapper.hpp → src/ArduinoJson/Strings/SizedFlashStringAdapter.hpp

@@ -6,9 +6,9 @@
 
 namespace ARDUINOJSON_NAMESPACE {
 
-class SizedFlashStringWrapper {
+class SizedFlashStringAdapter {
  public:
-  SizedFlashStringWrapper(const __FlashStringHelper* str, size_t sz)
+  SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz)
       : _str(str), _size(sz) {}
 
   bool equals(const char* expected) const {
@@ -32,13 +32,17 @@ class SizedFlashStringWrapper {
     return strlen_P(reinterpret_cast<const char*>(_str));
   }
 
+  bool isStatic() const {
+    return false;
+  }
+
  private:
   const __FlashStringHelper* _str;
   size_t _size;
 };
 
-inline SizedFlashStringWrapper wrapString(const __FlashStringHelper* str,
-                                          size_t sz) {
-  return SizedFlashStringWrapper(str, sz);
+inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str,
+                                           size_t sz) {
+  return SizedFlashStringAdapter(str, sz);
 }
 }  // namespace ARDUINOJSON_NAMESPACE

+ 8 - 4
src/ArduinoJson/Strings/SizedRamStringWrapper.hpp → src/ArduinoJson/Strings/SizedRamStringAdapter.hpp

@@ -8,9 +8,9 @@
 
 namespace ARDUINOJSON_NAMESPACE {
 
-class SizedRamStringWrapper {
+class SizedRamStringAdapter {
  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 {
     const char* actual = reinterpret_cast<const char*>(_str);
@@ -33,14 +33,18 @@ class SizedRamStringWrapper {
     return strlen(reinterpret_cast<const char*>(_str));
   }
 
+  bool isStatic() const {
+    return false;
+  }
+
  private:
   const char* _str;
   size_t _size;
 };
 
 template <typename TChar>
-inline SizedRamStringWrapper wrapString(const TChar* str, size_t size) {
-  return SizedRamStringWrapper(reinterpret_cast<const char*>(str), size);
+inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) {
+  return SizedRamStringAdapter(reinterpret_cast<const char*>(str), size);
 }
 
 }  // namespace ARDUINOJSON_NAMESPACE

+ 8 - 4
src/ArduinoJson/Strings/StlStringWrapper.hpp → src/ArduinoJson/Strings/StlStringAdapter.hpp

@@ -8,9 +8,9 @@
 
 namespace ARDUINOJSON_NAMESPACE {
 
-class StlStringWrapper {
+class StlStringAdapter {
  public:
-  StlStringWrapper(const std::string& str) : _str(&str) {}
+  StlStringAdapter(const std::string& str) : _str(&str) {}
 
   char* save(MemoryPool* pool) const {
     size_t n = _str->length() + 1;
@@ -36,6 +36,10 @@ class StlStringWrapper {
     return _str->size();
   }
 
+  bool isStatic() const {
+    return false;
+  }
+
  private:
   const std::string* _str;
 };
@@ -43,8 +47,8 @@ class StlStringWrapper {
 template <>
 struct IsString<std::string> : true_type {};
 
-inline StlStringWrapper wrapString(const std::string& str) {
-  return StlStringWrapper(str);
+inline StlStringAdapter adaptString(const std::string& str) {
+  return StlStringAdapter(str);
 }
 
 }  // namespace ARDUINOJSON_NAMESPACE

+ 35 - 2
src/ArduinoJson/Strings/String.hpp

@@ -4,12 +4,15 @@
 
 #pragma once
 
+#include "ConstRamStringAdapter.hpp"
+
 namespace ARDUINOJSON_NAMESPACE {
 
 class String {
  public:
-  String() : _data(0) {}
-  String(const char* slot) : _data(slot) {}
+  String() : _data(0), _isStatic(true) {}
+  String(const char* data, bool isStaticData = true)
+      : _data(data), _isStatic(isStaticData) {}
 
   const char* c_str() const {
     return _data;
@@ -19,6 +22,10 @@ class String {
     return !_data;
   }
 
+  bool isStatic() const {
+    return _isStatic;
+  }
+
   friend bool operator==(String lhs, String rhs) {
     if (lhs._data == rhs._data) return true;
     if (!lhs._data) return false;
@@ -28,5 +35,31 @@ class String {
 
  private:
   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

+ 7 - 7
src/ArduinoJson/Strings/StringWrappers.hpp → src/ArduinoJson/Strings/StringAdapters.hpp

@@ -18,19 +18,19 @@ template <typename T>
 struct IsString<T&> : IsString<T> {};
 }  // namespace ARDUINOJSON_NAMESPACE
 
-#include "ConstRamStringWrapper.hpp"
-#include "RamStringWrapper.hpp"
-#include "SizedRamStringWrapper.hpp"
+#include "ConstRamStringAdapter.hpp"
+#include "RamStringAdapter.hpp"
+#include "SizedRamStringAdapter.hpp"
 
 #if ARDUINOJSON_ENABLE_STD_STRING
-#include "StlStringWrapper.hpp"
+#include "StlStringAdapter.hpp"
 #endif
 
 #if ARDUINOJSON_ENABLE_ARDUINO_STRING
-#include "ArduinoStringWrapper.hpp"
+#include "ArduinoStringAdapter.hpp"
 #endif
 
 #if ARDUINOJSON_ENABLE_PROGMEM
-#include "FlashStringWrapper.hpp"
-#include "SizedFlashStringWrapper.hpp"
+#include "FlashStringAdapter.hpp"
+#include "SizedFlashStringAdapter.hpp"
 #endif

+ 10 - 13
src/ArduinoJson/Variant/SlotFunctions.hpp

@@ -6,24 +6,21 @@
 
 #include "../Memory/MemoryPool.hpp"
 #include "../Polyfills/assert.hpp"
-#include "../Strings/StringWrappers.hpp"
+#include "../Strings/StringAdapters.hpp"
 #include "VariantData.hpp"
 
 namespace ARDUINOJSON_NAMESPACE {
 
-template <typename TKey>
-inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) {
+template <typename TAdaptedString>
+inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
   if (!var) return false;
-  char* dup = key.save(pool);
-  if (!dup) return false;
-  var->setOwnedKey(dup);
-  return true;
-}
-
-inline bool slotSetKey(VariantSlot* var, ConstRamStringWrapper key,
-                       MemoryPool*) {
-  if (!var) return false;
-  var->setLinkedKey(key.c_str());
+  if (key.isStatic()) {
+    var->setLinkedKey(key.data());
+  } else {
+    char* dup = key.save(pool);
+    if (!dup) return false;
+    var->setOwnedKey(dup);
+  }
   return true;
 }
 

+ 6 - 6
src/ArduinoJson/Variant/VariantData.hpp

@@ -89,7 +89,7 @@ class VariantData {
       case VALUE_IS_OBJECT:
         return toObject().copyFrom(src._content.asCollection, pool);
       case VALUE_IS_OWNED_STRING:
-        return setOwnedString(RamStringWrapper(src._content.asString), pool);
+        return setOwnedString(RamStringAdapter(src._content.asString), pool);
       case VALUE_IS_OWNED_RAW:
         return setOwnedRaw(
             serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
@@ -186,7 +186,7 @@ class VariantData {
 
   template <typename T>
   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) {
       setType(VALUE_IS_OWNED_RAW);
       _content.asRaw.data = dup;
@@ -289,13 +289,13 @@ class VariantData {
     return isArray() ? _content.asCollection.get(index) : 0;
   }
 
-  template <typename TKey>
-  VariantData *get(TKey key) const {
+  template <typename TAdaptedString>
+  VariantData *get(TAdaptedString key) const {
     return isObject() ? _content.asCollection.get(key) : 0;
   }
 
-  template <typename TKey>
-  VariantData *getOrCreate(TKey key, MemoryPool *pool) {
+  template <typename TAdaptedString>
+  VariantData *getOrCreate(TAdaptedString key, MemoryPool *pool) {
     if (isNull()) toObject();
     if (!isObject()) return 0;
     VariantData *var = _content.asCollection.get(key);

+ 6 - 6
src/ArduinoJson/Variant/VariantFunctions.hpp

@@ -150,16 +150,16 @@ inline NO_INLINE VariantData *variantAdd(VariantData *var, MemoryPool *pool) {
   return var != 0 ? var->add(pool) : 0;
 }
 
-template <typename TKey>
-NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TKey *key,
+template <typename TChar>
+NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TChar *key,
                                           MemoryPool *pool) {
-  return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0;
+  return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0;
 }
 
-template <typename TKey>
-NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TKey &key,
+template <typename TString>
+NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TString &key,
                                           MemoryPool *pool) {
-  return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0;
+  return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0;
 }
 
 }  // namespace ARDUINOJSON_NAMESPACE

+ 11 - 11
src/ArduinoJson/Variant/VariantImpl.hpp

@@ -110,24 +110,24 @@ inline VariantRef VariantRef::get(size_t index) const {
   return VariantRef(_pool, _data != 0 ? _data->get(index) : 0);
 }
 
-template <typename TKey>
-inline VariantRef VariantRef::get(TKey *key) const {
-  return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0);
+template <typename TChar>
+inline VariantRef VariantRef::get(TChar *key) const {
+  return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0);
 }
 
-template <typename TKey>
-inline typename enable_if<IsString<TKey>::value, VariantRef>::type
-VariantRef::get(const TKey &key) const {
-  return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0);
+template <typename TString>
+inline typename enable_if<IsString<TString>::value, VariantRef>::type
+VariantRef::get(const TString &key) const {
+  return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0);
 }
 
-template <typename TKey>
-inline VariantRef VariantRef::getOrCreate(TKey *key) const {
+template <typename TChar>
+inline VariantRef VariantRef::getOrCreate(TChar *key) const {
   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
 }
 
-template <typename TKey>
-inline VariantRef VariantRef::getOrCreate(const TKey &key) const {
+template <typename TString>
+inline VariantRef VariantRef::getOrCreate(const TString &key) const {
   return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
 }
 }  // namespace ARDUINOJSON_NAMESPACE

+ 31 - 24
src/ArduinoJson/Variant/VariantRef.hpp

@@ -194,7 +194,7 @@ class VariantRef : public VariantRefBase<VariantData>,
   FORCE_INLINE bool set(
       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(char*)
@@ -202,7 +202,7 @@ class VariantRef : public VariantRefBase<VariantData>,
   template <typename T>
   FORCE_INLINE bool set(
       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*);
@@ -285,20 +285,27 @@ class VariantRef : public VariantRefBase<VariantData>,
 
   FORCE_INLINE VariantRef get(size_t) const;
 
-  template <typename TKey>
-  FORCE_INLINE VariantRef get(TKey *) const;
+  // get(const char*) const
+  // get(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef get(TChar *) const;
 
-  // get(const char*)
-  // get(const __FlashStringHelper*)
-  template <typename TKey>
-  FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get(
-      const TKey &) const;
+  // get(const std::string&) const
+  // get(const String&) const
+  template <typename TString>
+  FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
+  get(const TString &) const;
 
-  template <typename TKey>
-  FORCE_INLINE VariantRef getOrCreate(TKey *) const;
+  // getOrCreate(char*) const
+  // getOrCreate(const char*) const
+  // getOrCreate(const __FlashStringHelper*) const
+  template <typename TChar>
+  FORCE_INLINE VariantRef getOrCreate(TChar *) const;
 
-  template <typename TKey>
-  FORCE_INLINE VariantRef getOrCreate(const TKey &) const;
+  // getOrCreate(const std::string&) const
+  // getOrCreate(const String&) const
+  template <typename TString>
+  FORCE_INLINE VariantRef getOrCreate(const TString &) const;
 
  private:
   MemoryPool *_pool;
@@ -329,24 +336,24 @@ class VariantConstRef : public VariantRefBase<const VariantData>,
 
   FORCE_INLINE VariantConstRef operator[](size_t index) const;
 
-  //
-  // const VariantConstRef operator[](TKey) const;
-  // TKey = const std::string&, const String&
+  // operator[](const std::string&) const
+  // operator[](const String&) const
   template <typename TString>
   FORCE_INLINE
       typename enable_if<IsString<TString>::value, VariantConstRef>::type
       operator[](const TString &key) const {
-    return VariantConstRef(objectGet(variantAsObject(_data), wrapString(key)));
+    return VariantConstRef(objectGet(variantAsObject(_data), adaptString(key)));
   }
-  //
-  // VariantConstRef operator[](TKey);
-  // TKey = const char*, const char[N], const __FlashStringHelper*
-  template <typename TString>
+
+  // operator[](char*) const
+  // operator[](const char*) const
+  // operator[](const __FlashStringHelper*) const
+  template <typename TChar>
   FORCE_INLINE
-      typename enable_if<IsString<TString *>::value, VariantConstRef>::type
-      operator[](TString *key) const {
+      typename enable_if<IsString<TChar *>::value, VariantConstRef>::type
+      operator[](TChar *key) const {
     const CollectionData *obj = variantAsObject(_data);
-    return VariantConstRef(obj ? obj->get(wrapString(key)) : 0);
+    return VariantConstRef(obj ? obj->get(adaptString(key)) : 0);
   }
 };
 }  // namespace ARDUINOJSON_NAMESPACE

+ 12 - 0
test/JsonObject/subscript.cpp

@@ -141,6 +141,18 @@ TEST_CASE("JsonObject::operator[]") {
     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") {
     // object must have a value to make a call to strcmp()
     obj["dummy"] = 42;

+ 20 - 0
test/JsonVariant/set.cpp

@@ -71,6 +71,26 @@ TEST_CASE("JsonVariant and strings") {
 
     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") {