Преглед изворни кода

Added `as<JsonArray>()` as a synonym for `as<JsonArray&>()`... (issue #291)

Benoit Blanchon пре 9 година
родитељ
комит
c87a0e97ab

+ 1 - 0
CHANGELOG.md

@@ -5,6 +5,7 @@ HEAD
 ----
 
 * Improved speed of float serialization (about twice faster)
+* Added `as<JsonArray>()` as a synonym for `as<JsonArray&>()`... (issue #291)
 
 v5.6.2
 ------

+ 45 - 0
include/ArduinoJson/Internals/JsonVariantAs.hpp

@@ -0,0 +1,45 @@
+// Copyright Benoit Blanchon 2014-2016
+// MIT License
+//
+// Arduino JSON library
+// https://github.com/bblanchon/ArduinoJson
+// If you like this project, please add a star!
+
+#pragma once
+
+namespace ArduinoJson {
+namespace Internals {
+
+// A metafunction that returns the type of the value returned by
+// JsonVariant::as<T>()
+template <typename T>
+struct JsonVariantAs {
+  typedef T type;
+};
+
+template <>
+struct JsonVariantAs<char*> {
+  typedef const char* type;
+};
+
+template <>
+struct JsonVariantAs<JsonArray> {
+  typedef JsonArray& type;
+};
+
+template <>
+struct JsonVariantAs<const JsonArray> {
+  typedef const JsonArray& type;
+};
+
+template <>
+struct JsonVariantAs<JsonObject> {
+  typedef JsonObject& type;
+};
+
+template <>
+struct JsonVariantAs<const JsonObject> {
+  typedef const JsonObject& type;
+};
+}
+}

+ 1 - 1
include/ArduinoJson/JsonArray.hpp

@@ -137,7 +137,7 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
 
   // Gets the value at the specified index.
   template <typename T>
-  T get(size_t index) const {
+  typename Internals::JsonVariantAs<T>::type get(size_t index) const {
     node_type *node = getNodeAt(index);
     return node ? node->content.as<T>() : JsonVariant::defaultValue<T>();
   }

+ 11 - 1
include/ArduinoJson/JsonArray.ipp

@@ -21,13 +21,23 @@ inline bool JsonArray::setNodeValue(node_type *node, String &value) {
   return true;
 }
 
+template <>
+inline JsonArray &JsonVariant::defaultValue<JsonArray>() {
+  return JsonArray::invalid();
+}
+
 template <>
 inline JsonArray &JsonVariant::defaultValue<JsonArray &>() {
   return JsonArray::invalid();
 }
 
 template <>
-inline JsonArray const &JsonVariant::defaultValue<JsonArray const &>() {
+inline const JsonArray &JsonVariant::defaultValue<const JsonArray>() {
+  return JsonArray::invalid();
+}
+
+template <>
+inline const JsonArray &JsonVariant::defaultValue<const JsonArray &>() {
   return JsonArray::invalid();
 }
 

+ 7 - 3
include/ArduinoJson/JsonArraySubscript.hpp

@@ -42,12 +42,16 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
     return *this;
   }
 
-  FORCE_INLINE bool success() const { return _index < _array.size(); }
+  FORCE_INLINE bool success() const {
+    return _index < _array.size();
+  }
 
-  FORCE_INLINE operator JsonVariant() const { return _array.get(_index); }
+  FORCE_INLINE operator JsonVariant() const {
+    return _array.get(_index);
+  }
 
   template <typename T>
-  FORCE_INLINE T as() const {
+  FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const {
     return _array.get<T>(_index);
   }
 

+ 1 - 1
include/ArduinoJson/JsonObject.hpp

@@ -106,7 +106,7 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
 
   // Gets the value associated with the specified key.
   template <typename T>
-  T get(JsonObjectKey key) const {
+  typename Internals::JsonVariantAs<T>::type get(JsonObjectKey key) const {
     node_type* node = getNodeAt(key.c_str());
     return node ? node->content.value.as<T>() : JsonVariant::defaultValue<T>();
   }

+ 11 - 1
include/ArduinoJson/JsonObject.ipp

@@ -26,7 +26,12 @@ inline bool JsonObject::setNodeValue(node_type *node, const String &value) {
 }
 
 template <>
-inline JsonObject const &JsonVariant::defaultValue<JsonObject const &>() {
+inline const JsonObject &JsonVariant::defaultValue<const JsonObject &>() {
+  return JsonObject::invalid();
+}
+
+template <>
+inline const JsonObject &JsonVariant::defaultValue<const JsonObject>() {
   return JsonObject::invalid();
 }
 
@@ -35,6 +40,11 @@ inline JsonObject &JsonVariant::defaultValue<JsonObject &>() {
   return JsonObject::invalid();
 }
 
+template <>
+inline JsonObject &JsonVariant::defaultValue<JsonObject>() {
+  return JsonObject::invalid();
+}
+
 inline JsonObject &JsonVariant::asObject() const {
   if (_type == Internals::JSON_OBJECT) return *_content.asObject;
   return JsonObject::invalid();

+ 1 - 1
include/ArduinoJson/JsonObjectSubscript.hpp

@@ -54,7 +54,7 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
   }
 
   template <typename TValue>
-  FORCE_INLINE TValue as() const {
+  FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const {
     return _object.get<TValue>(_key);
   }
 

+ 26 - 11
include/ArduinoJson/JsonVariant.hpp

@@ -177,31 +177,46 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
   //
   // JsonArray& as<JsonArray> const;
   // JsonArray& as<JsonArray&> const;
-  // JsonArray& as<const JsonArray&> const;
   template <typename T>
   typename TypeTraits::EnableIf<
-      TypeTraits::IsSame<
-          typename TypeTraits::RemoveConst<
-              typename TypeTraits::RemoveReference<T>::type>::type,
-          JsonArray>::value,
+      TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
+                         JsonArray>::value,
       JsonArray &>::type
   as() const {
     return asArray();
   }
   //
+  // const JsonArray& as<const JsonArray&> const;
+  template <typename T>
+  typename TypeTraits::EnableIf<
+      TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
+                         const JsonArray>::value,
+      const JsonArray &>::type
+  as() const {
+    return asArray();
+  }
+  //
   // JsonObject& as<JsonObject> const;
   // JsonObject& as<JsonObject&> const;
-  // JsonObject& as<const JsonObject&> const;
   template <typename T>
   typename TypeTraits::EnableIf<
-      TypeTraits::IsSame<
-          typename TypeTraits::RemoveConst<
-              typename TypeTraits::RemoveReference<T>::type>::type,
-          JsonObject>::value,
+      TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
+                         JsonObject>::value,
       JsonObject &>::type
   as() const {
     return asObject();
   }
+  //
+  // JsonObject& as<const JsonObject> const;
+  // JsonObject& as<const JsonObject&> const;
+  template <typename T>
+  typename TypeTraits::EnableIf<
+      TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
+                         const JsonObject>::value,
+      const JsonObject &>::type
+  as() const {
+    return asObject();
+  }
 
   // Tells weither the variant has the specified type.
   // Returns true if the variant has type type T, false otherwise.
@@ -281,7 +296,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
 
   // Value returned if the variant has an incompatible type
   template <typename T>
-  static T defaultValue() {
+  static typename Internals::JsonVariantAs<T>::type defaultValue() {
     return T();
   }
 

+ 29 - 9
include/ArduinoJson/JsonVariantBase.hpp

@@ -7,8 +7,9 @@
 
 #pragma once
 
-#include "Polyfills/attributes.hpp"
+#include "Internals/JsonVariantAs.hpp"
 #include "JsonObjectKey.hpp"
+#include "Polyfills/attributes.hpp"
 
 namespace ArduinoJson {
 
@@ -20,20 +21,35 @@ class JsonObjectSubscript;
 template <typename TImpl>
 class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
  public:
-  FORCE_INLINE const char *asString() const { return as<const char *>(); }
+  // DEPRECATED: use as<char*>() instead
+  FORCE_INLINE const char *asString() const {
+    return as<const char *>();
+  }
 
   // Gets the variant as an array.
   // Returns a reference to the JsonArray or JsonArray::invalid() if the
   // variant
   // is not an array.
-  FORCE_INLINE operator JsonArray &() const { return as<JsonArray &>(); }
-  FORCE_INLINE JsonArray &asArray() const { return as<JsonArray &>(); }
+  FORCE_INLINE operator JsonArray &() const {
+    return as<JsonArray &>();
+  }
+
+  // DEPRECATED: use as<JsonArray>() instead
+  FORCE_INLINE JsonArray &asArray() const {
+    return as<JsonArray &>();
+  }
 
   // Gets the variant as an object.
   // Returns a reference to the JsonObject or JsonObject::invalid() if the
   // variant is not an object.
-  FORCE_INLINE operator JsonObject &() const { return as<JsonObject &>(); }
-  FORCE_INLINE JsonObject &asObject() const { return as<JsonObject &>(); }
+  FORCE_INLINE operator JsonObject &() const {
+    return as<JsonObject &>();
+  }
+
+  // DEPRECATED: use as<JsonObject>() instead
+  FORCE_INLINE JsonObject &asObject() const {
+    return as<JsonObject &>();
+  }
 
   template <typename T>
   FORCE_INLINE operator T() const {
@@ -41,14 +57,16 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
   }
 
   template <typename T>
-  FORCE_INLINE const T as() const {
+  FORCE_INLINE const typename Internals::JsonVariantAs<T>::type as() const {
     return impl()->template as<T>();
   }
 
   // Mimics an array or an object.
   // Returns the size of the array or object if the variant has that type.
   // Returns 0 if the variant is neither an array nor an object
-  size_t size() const { return asArray().size() + asObject().size(); }
+  size_t size() const {
+    return asArray().size() + asObject().size();
+  }
 
   // Mimics an array.
   // Returns the element at specified index if the variant is an array.
@@ -68,7 +86,9 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
   void writeTo(Internals::JsonWriter &writer) const;
 
  private:
-  const TImpl *impl() const { return static_cast<const TImpl *>(this); }
+  const TImpl *impl() const {
+    return static_cast<const TImpl *>(this);
+  }
 };
 
 template <typename TImpl, typename TComparand>

+ 7 - 0
test/JsonArray_Subscript_Tests.cpp

@@ -59,6 +59,7 @@ TEST_(StoreBoolean) {
 TEST_(StoreString) {
   _array[0] = "hello";
   EXPECT_STREQ("hello", _array[0].as<const char*>());
+  EXPECT_STREQ("hello", _array[0].as<char*>());  // <- short hand
   EXPECT_TRUE(_array[0].is<const char*>());
   EXPECT_FALSE(_array[0].is<int>());
 }
@@ -69,6 +70,9 @@ TEST_(StoreNestedArray) {
   _array[0] = arr;
 
   EXPECT_EQ(&arr, &_array[0].as<JsonArray&>());
+  EXPECT_EQ(&arr, &_array[0].as<JsonArray>());  // <- short hand
+  EXPECT_EQ(&arr, &_array[0].as<const JsonArray&>());
+  EXPECT_EQ(&arr, &_array[0].as<const JsonArray>());  // <- short hand
   EXPECT_TRUE(_array[0].is<JsonArray&>());
   EXPECT_FALSE(_array[0].is<int>());
 }
@@ -79,6 +83,9 @@ TEST_(StoreNestedObject) {
   _array[0] = obj;
 
   EXPECT_EQ(&obj, &_array[0].as<JsonObject&>());
+  EXPECT_EQ(&obj, &_array[0].as<JsonObject>());  // <- short hand
+  EXPECT_EQ(&obj, &_array[0].as<const JsonObject&>());
+  EXPECT_EQ(&obj, &_array[0].as<const JsonObject>());  // <- short hand
   EXPECT_TRUE(_array[0].is<JsonObject&>());
   EXPECT_FALSE(_array[0].is<int>());
 }

+ 17 - 2
test/JsonObject_Subscript_Tests.cpp

@@ -68,6 +68,7 @@ TEST_(StoreString) {
   EXPECT_TRUE(_object["hello"].is<const char*>());
   EXPECT_FALSE(_object["hello"].is<long>());
   EXPECT_STREQ("h3110", _object["hello"].as<const char*>());
+  EXPECT_STREQ("h3110", _object["hello"].as<char*>());  // <- short hand
 }
 
 TEST_(StoreArray) {
@@ -75,8 +76,15 @@ TEST_(StoreArray) {
 
   _object["hello"] = arr;
 
-  EXPECT_EQ(&arr, &_object["hello"].asArray());
+  EXPECT_EQ(&arr, &_object["hello"].asArray());  // <- DEPRECATED
+  EXPECT_EQ(&arr, &_object["hello"].as<JsonArray&>());
+  EXPECT_EQ(&arr, &_object["hello"].as<JsonArray>());  // <- short hand
+  EXPECT_EQ(&arr, &_object["hello"].as<const JsonArray&>());
+  EXPECT_EQ(&arr, &_object["hello"].as<const JsonArray>());  // <- short hand
   EXPECT_TRUE(_object["hello"].is<JsonArray&>());
+  EXPECT_TRUE(_object["hello"].is<JsonArray>());
+  EXPECT_TRUE(_object["hello"].is<const JsonArray&>());
+  EXPECT_TRUE(_object["hello"].is<const JsonArray>());
   EXPECT_FALSE(_object["hello"].is<JsonObject&>());
 }
 
@@ -85,8 +93,15 @@ TEST_(StoreObject) {
 
   _object["hello"] = obj;
 
-  EXPECT_EQ(&obj, &_object["hello"].asObject());
+  EXPECT_EQ(&obj, &_object["hello"].asObject());  // DEPRECATED
+  EXPECT_EQ(&obj, &_object["hello"].as<JsonObject&>());
+  EXPECT_EQ(&obj, &_object["hello"].as<JsonObject>());  // <- short hand
+  EXPECT_EQ(&obj, &_object["hello"].as<const JsonObject&>());
+  EXPECT_EQ(&obj, &_object["hello"].as<const JsonObject>());  // <- short hand
   EXPECT_TRUE(_object["hello"].is<JsonObject&>());
+  EXPECT_TRUE(_object["hello"].is<JsonObject>());
+  EXPECT_TRUE(_object["hello"].is<const JsonObject&>());
+  EXPECT_TRUE(_object["hello"].is<const JsonObject>());
   EXPECT_FALSE(_object["hello"].is<JsonArray&>());
 }
 

+ 18 - 0
test/JsonVariant_As_Tests.cpp

@@ -214,3 +214,21 @@ TEST(JsonVariant_As_Tests, ArrayAsString) {
   JsonVariant variant = arr;
   ASSERT_EQ(String("[4,2]"), variant.as<String>());
 }
+
+TEST(JsonVariant_As_Tests, ArrayAsJsonArray) {
+  DynamicJsonBuffer buffer;
+  JsonArray& arr = buffer.createArray();
+
+  JsonVariant variant = arr;
+  ASSERT_EQ(&arr, &variant.as<JsonArray&>());
+  ASSERT_EQ(&arr, &variant.as<JsonArray>());  // <- shorthand
+}
+
+TEST(JsonVariant_As_Tests, ObjectAsJsonObject) {
+  DynamicJsonBuffer buffer;
+  JsonObject& arr = buffer.createObject();
+
+  JsonVariant variant = arr;
+  ASSERT_EQ(&arr, &variant.as<JsonObject&>());
+  ASSERT_EQ(&arr, &variant.as<JsonObject>());  // <- shorthand
+}