Bläddra i källkod

Changed JsonVariantConst::is<JsonArray/JsonObject>() to return false (closes #1412)

Benoit Blanchon 4 år sedan
förälder
incheckning
3aab36fec2

+ 5 - 1
CHANGELOG.md

@@ -10,6 +10,7 @@ HEAD
 * Removed `DeserializationError::NotSupported`
 * Added `JsonVariant::is<JsonArrayConst/JsonObjectConst>()` (issue #1412)
 * Added `JsonVariant::is<JsonVariant/JsonVariantConst>()` (issue #1412)
+* Changed `JsonVariantConst::is<JsonArray/JsonObject>()` to return `false` (issue #1412)
 
 > ### BREAKING CHANGES
 >
@@ -38,7 +39,10 @@ HEAD
 >
 > * `deserializeJson()` leaves `\uXXXX` unchanged (only when `ARDUINOJSON_DECODE_UNICODE` is `0`)
 > * `deserializeMsgPack()` replaces unsupported values with `null`s
-
+>
+> Lastly, a very minor change conserns `JsonVariantConst::is<T>()`.
+> It used to return `true` for `JsonArray` and `JsonOject`, but now it returns `false`.
+> Instead, you must use `JsonArrayConst` and `JsonObjectConst`.
 
 v6.17.3 (2021-02-15)
 -------

+ 21 - 11
extras/tests/JsonVariant/is.cpp

@@ -163,9 +163,12 @@ TEST_CASE("JsonVariantConst::is<T>()") {
   SECTION("undefined") {
     cvariant = JsonVariantConst();
 
-    CHECK(cvariant.is<JsonObject>() == false);
     CHECK(cvariant.is<JsonArray>() == false);
+    CHECK(cvariant.is<JsonArrayConst>() == false);
+    CHECK(cvariant.is<JsonObject>() == false);
+    CHECK(cvariant.is<JsonObjectConst>() == false);
     CHECK(cvariant.is<JsonVariant>() == false);
+    CHECK(cvariant.is<JsonVariantConst>() == false);
     CHECK(cvariant.is<bool>() == false);
     CHECK(cvariant.is<char *>() == false);
     CHECK(cvariant.is<int>() == false);
@@ -175,9 +178,10 @@ TEST_CASE("JsonVariantConst::is<T>()") {
   }
 
   SECTION("null") {
+    CHECK(cvariant.is<JsonVariantConst>() == true);
     CHECK(cvariant.is<JsonObject>() == false);
     CHECK(cvariant.is<JsonArray>() == false);
-    CHECK(cvariant.is<JsonVariant>() == true);
+    CHECK(cvariant.is<JsonVariant>() == false);
     CHECK(cvariant.is<bool>() == false);
     CHECK(cvariant.is<char *>() == false);
     CHECK(cvariant.is<int>() == false);
@@ -190,7 +194,8 @@ TEST_CASE("JsonVariantConst::is<T>()") {
     variant.set(true);
 
     CHECK(cvariant.is<bool>() == true);
-    CHECK(cvariant.is<JsonVariant>() == true);
+    CHECK(cvariant.is<JsonVariantConst>() == true);
+    CHECK(cvariant.is<JsonVariant>() == false);
     CHECK(cvariant.is<JsonObject>() == false);
     CHECK(cvariant.is<JsonArray>() == false);
     CHECK(cvariant.is<char *>() == false);
@@ -204,7 +209,8 @@ TEST_CASE("JsonVariantConst::is<T>()") {
     variant.set(false);
 
     CHECK(cvariant.is<bool>() == true);
-    CHECK(cvariant.is<JsonVariant>() == true);
+    CHECK(cvariant.is<JsonVariantConst>() == true);
+    CHECK(cvariant.is<JsonVariant>() == false);
     CHECK(cvariant.is<JsonObject>() == false);
     CHECK(cvariant.is<JsonArray>() == false);
     CHECK(cvariant.is<char *>() == false);
@@ -223,10 +229,11 @@ TEST_CASE("JsonVariantConst::is<T>()") {
     CHECK(cvariant.is<double>() == true);
     CHECK(cvariant.is<float>() == true);
     CHECK(cvariant.is<MYENUM2>() == true);
-    CHECK(cvariant.is<JsonVariant>() == true);
+    CHECK(cvariant.is<JsonVariantConst>() == true);
     CHECK(cvariant.is<bool>() == false);
     CHECK(cvariant.is<JsonObject>() == false);
     CHECK(cvariant.is<JsonArray>() == false);
+    CHECK(cvariant.is<JsonVariant>() == false);
     CHECK(cvariant.is<char *>() == false);
     CHECK(cvariant.is<std::string>() == false);
   }
@@ -236,10 +243,11 @@ TEST_CASE("JsonVariantConst::is<T>()") {
 
     CHECK(cvariant.is<double>() == true);
     CHECK(cvariant.is<float>() == true);
-    CHECK(cvariant.is<JsonVariant>() == true);
+    CHECK(cvariant.is<JsonVariantConst>() == true);
     CHECK(cvariant.is<bool>() == false);
     CHECK(cvariant.is<JsonObject>() == false);
     CHECK(cvariant.is<JsonArray>() == false);
+    CHECK(cvariant.is<JsonVariant>() == false);
     CHECK(cvariant.is<char *>() == false);
     CHECK(cvariant.is<int>() == false);
     CHECK(cvariant.is<std::string>() == false);
@@ -252,12 +260,12 @@ TEST_CASE("JsonVariantConst::is<T>()") {
     CHECK(cvariant.is<char *>() == true);
     CHECK(cvariant.is<const char *>() == true);
     CHECK(cvariant.is<std::string>() == true);
-    CHECK(cvariant.is<JsonVariant>() == true);
     CHECK(cvariant.is<double>() == false);
     CHECK(cvariant.is<float>() == false);
     CHECK(cvariant.is<bool>() == false);
     CHECK(cvariant.is<JsonObject>() == false);
     CHECK(cvariant.is<JsonArray>() == false);
+    CHECK(cvariant.is<JsonVariant>() == false);
     CHECK(cvariant.is<int>() == false);
     CHECK(cvariant.is<MYENUM2>() == false);
   }
@@ -265,9 +273,10 @@ TEST_CASE("JsonVariantConst::is<T>()") {
   SECTION("JsonArray") {
     variant.to<JsonArray>();
 
-    CHECK(cvariant.is<JsonArray>() == true);
     CHECK(cvariant.is<JsonArrayConst>() == true);
-    CHECK(cvariant.is<JsonVariant>() == true);
+    CHECK(cvariant.is<JsonVariantConst>() == true);
+    CHECK(cvariant.is<JsonArray>() == false);
+    CHECK(cvariant.is<JsonVariant>() == false);
     CHECK(cvariant.is<JsonObject>() == false);
     CHECK(cvariant.is<JsonObjectConst>() == false);
     CHECK(cvariant.is<int>() == false);
@@ -280,9 +289,10 @@ TEST_CASE("JsonVariantConst::is<T>()") {
   SECTION("JsonObject") {
     variant.to<JsonObject>();
 
-    CHECK(cvariant.is<JsonObject>() == true);
     CHECK(cvariant.is<JsonObjectConst>() == true);
-    CHECK(cvariant.is<JsonVariant>() == true);
+    CHECK(cvariant.is<JsonVariantConst>() == true);
+    CHECK(cvariant.is<JsonObject>() == false);
+    CHECK(cvariant.is<JsonVariant>() == false);
     CHECK(cvariant.is<JsonArray>() == false);
     CHECK(cvariant.is<JsonArrayConst>() == false);
     CHECK(cvariant.is<int>() == false);

+ 2 - 2
src/ArduinoJson/Deserialization/Filter.hpp

@@ -17,11 +17,11 @@ class Filter {
   }
 
   bool allowArray() const {
-    return _variant == true || _variant.is<ArrayRef>();
+    return _variant == true || _variant.is<ArrayConstRef>();
   }
 
   bool allowObject() const {
-    return _variant == true || _variant.is<ObjectRef>();
+    return _variant == true || _variant.is<ObjectConstRef>();
   }
 
   bool allowValue() const {

+ 5 - 0
src/ArduinoJson/Document/JsonDocument.hpp

@@ -35,6 +35,11 @@ class JsonDocument : public Visitable {
     _data.setNull();
   }
 
+  template <typename T>
+  bool is() {
+    return getVariant().template is<T>();
+  }
+
   template <typename T>
   bool is() const {
     return getVariant().template is<T>();

+ 0 - 29
src/ArduinoJson/Variant/VariantFunctions.hpp

@@ -43,35 +43,6 @@ inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
 
 inline int variantCompare(const VariantData *a, const VariantData *b);
 
-inline bool variantIsArray(const VariantData *var) {
-  return var && var->isArray();
-}
-
-inline bool variantIsBoolean(const VariantData *var) {
-  return var && var->isBoolean();
-}
-
-template <typename T>
-inline bool variantIsInteger(const VariantData *var) {
-  return var && var->isInteger<T>();
-}
-
-inline bool variantIsFloat(const VariantData *var) {
-  return var && var->isFloat();
-}
-
-inline bool variantIsString(const VariantData *var) {
-  return var && var->isString();
-}
-
-inline bool variantIsObject(const VariantData *var) {
-  return var && var->isObject();
-}
-
-inline bool variantIsNull(const VariantData *var) {
-  return var == 0 || var->isNull();
-}
-
 inline bool variantSetBoolean(VariantData *var, bool value) {
   if (!var)
     return false;

+ 146 - 0
src/ArduinoJson/Variant/VariantIs.hpp

@@ -0,0 +1,146 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantFunctions.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+inline bool variantIsNull(const VariantData *var) {
+  return var == 0 || var->isNull();
+}
+
+// bool is<char>() const;
+// bool is<signed char>() const;
+// bool is<signed short>() const;
+// bool is<signed int>() const;
+// bool is<signed long>() const;
+// bool is<unsigned char>() const;
+// bool is<unsigned short>() const;
+// bool is<unsigned int>() const;
+// bool is<unsigned long>() const;
+template <typename T>
+NO_INLINE typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
+                             bool>::type
+variantIs(const VariantData *var) {
+  return var && var->isInteger<T>();
+}
+
+// bool is<double>() const;
+// bool is<float>() const;
+template <typename T>
+NO_INLINE typename enable_if<is_floating_point<T>::value, bool>::type variantIs(
+    const VariantData *var) {
+  return var && var->isFloat();
+}
+
+// bool is<bool>() const
+template <typename T>
+NO_INLINE typename enable_if<is_same<T, bool>::value, bool>::type variantIs(
+    const VariantData *var) {
+  return var && var->isBoolean();
+}
+
+// bool is<const char*>() const;
+// bool is<char*>() const;
+// bool is<std::string>() const;
+// bool is<String>() const;
+template <typename T>
+NO_INLINE typename enable_if<is_same<T, const char *>::value ||
+                                 is_same<T, char *>::value ||
+                                 IsWriteableString<T>::value,
+                             bool>::type
+variantIs(const VariantData *var) {
+  return var && var->isString();
+}
+
+// bool is<ArrayConstRef> const;
+// bool is<const ArrayConstRef> const;
+template <typename T>
+NO_INLINE typename enable_if<
+    is_same<typename remove_const<T>::type, ArrayConstRef>::value, bool>::type
+variantIs(const VariantData *var) {
+  return var && var->isArray();
+}
+
+// bool is<ObjectConstRef> const;
+// bool is<const ObjectConstRef> const;
+template <typename T>
+NO_INLINE typename enable_if<
+    is_same<typename remove_const<T>::type, ObjectConstRef>::value, bool>::type
+variantIs(const VariantData *var) {
+  return var && var->isObject();
+}
+
+// bool is<VariantConstRef> const;
+// bool is<const VariantConstRef> const;
+template <typename T>
+NO_INLINE typename enable_if<
+    is_same<typename remove_const<T>::type, VariantConstRef>::value, bool>::type
+variantIs(const VariantData *var) {
+  return !!var;
+}
+#if ARDUINOJSON_HAS_NULLPTR
+
+// bool is<nullptr_t> const;
+template <typename T>
+NO_INLINE typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type
+variantIs(const VariantData *var) {
+  return variantIsNull(var);
+}
+#endif
+// bool is<enum>() const;
+template <typename T>
+typename enable_if<is_enum<T>::value, bool>::type variantIs(
+    const VariantData *var) {
+  return variantIs<int>(var);
+}
+
+// bool is<ArrayRef> const;
+// bool is<const ArrayRef> const;
+template <typename T>
+NO_INLINE
+    typename enable_if<is_same<typename remove_const<T>::type, ArrayRef>::value,
+                       bool>::type
+    variantIs(VariantData *var) {
+  return var && var->isArray();
+}
+
+// bool is<ObjectRef> const;
+// bool is<const ObjectRef> const;
+template <typename T>
+NO_INLINE typename enable_if<
+    is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type
+variantIs(VariantData *var) {
+  return var && var->isObject();
+}
+
+// bool is<VariantRef> const;
+// bool is<const VariantRef> const;
+template <typename T>
+NO_INLINE typename enable_if<
+    is_same<typename remove_const<T>::type, VariantRef>::value, bool>::type
+variantIs(VariantData *var) {
+  return !!var;
+}
+
+// bool is<ArrayRef> const;
+// bool is<const ArrayRef> const;
+// bool is<ObjectRef> const;
+// bool is<const ObjectRef> const;
+// bool is<VariantRef> const;
+// bool is<const VariantRef> const;
+template <typename T>
+typename enable_if<
+    is_same<typename remove_const<T>::type, ArrayRef>::value ||
+        is_same<typename remove_const<T>::type, ObjectRef>::value ||
+        is_same<typename remove_const<T>::type, VariantRef>::value,
+    bool>::type
+variantIs(const VariantData *) {
+  return false;
+}
+
+}  // namespace ARDUINOJSON_NAMESPACE

+ 3 - 116
src/ArduinoJson/Variant/VariantRef.hpp

@@ -13,6 +13,7 @@
 #include <ArduinoJson/Strings/StringAdapters.hpp>
 #include <ArduinoJson/Variant/VariantAs.hpp>
 #include <ArduinoJson/Variant/VariantFunctions.hpp>
+#include <ArduinoJson/Variant/VariantIs.hpp>
 #include <ArduinoJson/Variant/VariantOperators.hpp>
 #include <ArduinoJson/Variant/VariantRef.hpp>
 #include <ArduinoJson/Variant/VariantShortcuts.hpp>
@@ -28,123 +29,9 @@ class ObjectRef;
 template <typename TData>
 class VariantRefBase : public VariantTag {
  public:
-  // Tells wether the variant has the specified type.
-  // Returns true if the variant has type type T, false otherwise.
-  //
-  // bool is<char>() const;
-  // bool is<signed char>() const;
-  // bool is<signed short>() const;
-  // bool is<signed int>() const;
-  // bool is<signed long>() const;
-  // bool is<unsigned char>() const;
-  // bool is<unsigned short>() const;
-  // bool is<unsigned int>() const;
-  // bool is<unsigned long>() const;
-  template <typename T>
-  FORCE_INLINE
-      typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
-                         bool>::type
-      is() const {
-    return variantIsInteger<T>(_data);
-  }
-  //
-  // bool is<double>() const;
-  // bool is<float>() const;
-  template <typename T>
-  FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
-      const {
-    return variantIsFloat(_data);
-  }
-  //
-  // bool is<bool>() const
-  template <typename T>
-  FORCE_INLINE typename enable_if<is_same<T, bool>::value, bool>::type is()
-      const {
-    return variantIsBoolean(_data);
-  }
-  //
-  // bool is<const char*>() const;
-  // bool is<char*>() const;
-  // bool is<std::string>() const;
-  // bool is<String>() const;
-  template <typename T>
-  FORCE_INLINE typename enable_if<is_same<T, const char *>::value ||
-                                      is_same<T, char *>::value ||
-                                      IsWriteableString<T>::value,
-                                  bool>::type
-  is() const {
-    return variantIsString(_data);
-  }
-  //
-  // bool is<ArrayRef> const;
-  // bool is<const ArrayRef> const;
-  template <typename T>
-  FORCE_INLINE typename enable_if<
-      is_same<typename remove_const<T>::type, ArrayRef>::value, bool>::type
-  is() const {
-    return variantIsArray(_data);
-  }
-  //
-  // bool is<ArrayConstRef> const;
-  // bool is<const ArrayConstRef> const;
-  template <typename T>
-  FORCE_INLINE typename enable_if<
-      is_same<typename remove_const<T>::type, ArrayConstRef>::value, bool>::type
-  is() const {
-    return variantIsArray(_data);
-  }
-  //
-  // bool is<ObjectRef> const;
-  // bool is<const ObjectRef> const;
-  template <typename T>
-  FORCE_INLINE typename enable_if<
-      is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type
-  is() const {
-    return variantIsObject(_data);
-  }
-  //
-  // bool is<ObjectConstRef> const;
-  // bool is<const ObjectConstRef> const;
-  template <typename T>
-  FORCE_INLINE typename enable_if<
-      is_same<typename remove_const<T>::type, ObjectConstRef>::value,
-      bool>::type
-  is() const {
-    return variantIsObject(_data);
-  }
-  //
-  // bool is<VariantRef> const;
-  // bool is<const VariantRef> const;
-  template <typename T>
-  FORCE_INLINE typename enable_if<
-      is_same<typename remove_const<T>::type, VariantRef>::value, bool>::type
-  is() const {
-    return !!_data;
-  }
-  //
-  // bool is<VariantConstRef> const;
-  // bool is<const VariantConstRef> const;
-  template <typename T>
-  FORCE_INLINE typename enable_if<
-      is_same<typename remove_const<T>::type, VariantConstRef>::value,
-      bool>::type
-  is() const {
-    return !!_data;
-  }
-#if ARDUINOJSON_HAS_NULLPTR
-  //
-  // bool is<nullptr_t> const;
-  template <typename T>
-  FORCE_INLINE
-      typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type
-      is() const {
-    return variantIsNull(_data);
-  }
-#endif
-  // bool is<enum>() const;
   template <typename T>
-  FORCE_INLINE typename enable_if<is_enum<T>::value, bool>::type is() const {
-    return variantIsInteger<int>(_data);
+  FORCE_INLINE bool is() const {
+    return variantIs<T>(_data);
   }
 
   FORCE_INLINE bool isNull() const {