mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-29 18:27:37 +02:00
Replace ConverterNeedsWriteableRef
with function_traits
This commit is contained in:
@ -140,15 +140,3 @@ TEST_CASE("Custom converter with specialization") {
|
||||
REQUIRE(doc["value"]["imag"] == 3);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ConverterNeedsWriteableRef") {
|
||||
using namespace ArduinoJson::detail;
|
||||
CHECK(ConverterNeedsWriteableRef<int>::value == false);
|
||||
CHECK(ConverterNeedsWriteableRef<float>::value == false);
|
||||
CHECK(ConverterNeedsWriteableRef<JsonVariant>::value == true);
|
||||
CHECK(ConverterNeedsWriteableRef<JsonVariantConst>::value == false);
|
||||
CHECK(ConverterNeedsWriteableRef<JsonObject>::value == true);
|
||||
CHECK(ConverterNeedsWriteableRef<JsonObjectConst>::value == false);
|
||||
CHECK(ConverterNeedsWriteableRef<JsonArray>::value == true);
|
||||
CHECK(ConverterNeedsWriteableRef<JsonArrayConst>::value == false);
|
||||
}
|
||||
|
@ -17,3 +17,24 @@ TEST_CASE("JsonVariantConst::as<T>()") {
|
||||
REQUIRE(var.as<const char*>() == std::string("hello"));
|
||||
REQUIRE(var.as<std::string>() == std::string("hello"));
|
||||
}
|
||||
|
||||
TEST_CASE("Invalid conversions") {
|
||||
using namespace ArduinoJson::detail;
|
||||
|
||||
JsonVariantConst variant;
|
||||
|
||||
CHECK(is_same<decltype(variant.as<int>()), int>::value);
|
||||
CHECK(is_same<decltype(variant.as<float>()), float>::value);
|
||||
CHECK(is_same<decltype(variant.as<JsonVariantConst>()),
|
||||
JsonVariantConst>::value);
|
||||
CHECK(
|
||||
is_same<decltype(variant.as<JsonObjectConst>()), JsonObjectConst>::value);
|
||||
CHECK(is_same<decltype(variant.as<JsonArrayConst>()), JsonArrayConst>::value);
|
||||
|
||||
CHECK(is_same<decltype(variant.as<JsonVariant>()),
|
||||
InvalidConversion<JsonVariantConst, JsonVariant>>::value);
|
||||
CHECK(is_same<decltype(variant.as<JsonObject>()),
|
||||
InvalidConversion<JsonVariantConst, JsonObject>>::value);
|
||||
CHECK(is_same<decltype(variant.as<JsonArray>()),
|
||||
InvalidConversion<JsonVariantConst, JsonArray>>::value);
|
||||
}
|
||||
|
@ -58,5 +58,10 @@
|
||||
// issue #1914
|
||||
#define V7 7
|
||||
|
||||
// STM32, Mbed, Particle
|
||||
#define A0 16
|
||||
#define A1 17
|
||||
#define A2 18
|
||||
|
||||
// catch.hpp mutes several warnings, this file also allows to detect them
|
||||
#include "ArduinoJson.h"
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "type_traits/conditional.hpp"
|
||||
#include "type_traits/enable_if.hpp"
|
||||
#include "type_traits/function_traits.hpp"
|
||||
#include "type_traits/integral_constant.hpp"
|
||||
#include "type_traits/is_array.hpp"
|
||||
#include "type_traits/is_base_of.hpp"
|
||||
|
27
src/ArduinoJson/Polyfills/type_traits/function_traits.hpp
Normal file
27
src/ArduinoJson/Polyfills/type_traits/function_traits.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2024, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Namespace.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
template <typename Sig>
|
||||
struct function_traits;
|
||||
|
||||
template <typename ReturnType, typename Arg1>
|
||||
struct function_traits<ReturnType (*)(Arg1)> {
|
||||
using return_type = ReturnType;
|
||||
using arg1_type = Arg1;
|
||||
};
|
||||
|
||||
template <typename ReturnType, typename Arg1, typename Arg2>
|
||||
struct function_traits<ReturnType (*)(Arg1, Arg2)> {
|
||||
using return_type = ReturnType;
|
||||
using arg1_type = Arg1;
|
||||
using arg2_type = Arg2;
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
@ -20,7 +20,4 @@ template <typename T1, typename T2>
|
||||
class InvalidConversion; // Error here? See https://arduinojson.org/v7/invalid-conversion/
|
||||
// clang-format on
|
||||
|
||||
template <typename T>
|
||||
struct ConverterNeedsWriteableRef;
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
@ -305,19 +305,6 @@ inline bool canConvertFromJson(JsonVariantConst src, const std::string_view&) {
|
||||
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct ConverterNeedsWriteableRef {
|
||||
protected: // <- to avoid GCC's "all member functions in class are private"
|
||||
static int probe(T (*f)(ArduinoJson::JsonVariant));
|
||||
static char probe(T (*f)(ArduinoJson::JsonVariantConst));
|
||||
|
||||
public:
|
||||
static const bool value =
|
||||
sizeof(probe(Converter<T>::fromJson)) == sizeof(int);
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <>
|
||||
struct Converter<JsonArrayConst> : private detail::VariantAttorney {
|
||||
static void toJson(JsonArrayConst src, JsonVariant dst) {
|
||||
@ -354,13 +341,6 @@ struct Converter<JsonArray> : private detail::VariantAttorney {
|
||||
return JsonArray(data != 0 ? data->asArray() : 0, resources);
|
||||
}
|
||||
|
||||
static detail::InvalidConversion<JsonVariantConst, JsonArray> fromJson(
|
||||
JsonVariantConst);
|
||||
|
||||
static bool checkJson(JsonVariantConst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariant src) {
|
||||
auto data = getData(src);
|
||||
return data && data->isArray();
|
||||
@ -403,13 +383,6 @@ struct Converter<JsonObject> : private detail::VariantAttorney {
|
||||
return JsonObject(data != 0 ? data->asObject() : 0, resources);
|
||||
}
|
||||
|
||||
static detail::InvalidConversion<JsonVariantConst, JsonObject> fromJson(
|
||||
JsonVariantConst);
|
||||
|
||||
static bool checkJson(JsonVariantConst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariant src) {
|
||||
auto data = getData(src);
|
||||
return data && data->isObject();
|
||||
|
@ -53,17 +53,10 @@ struct Converter<JsonVariant> : private detail::VariantAttorney {
|
||||
return src;
|
||||
}
|
||||
|
||||
static detail::InvalidConversion<JsonVariantConst, JsonVariant> fromJson(
|
||||
JsonVariantConst);
|
||||
|
||||
static bool checkJson(JsonVariant src) {
|
||||
auto data = getData(src);
|
||||
return !!data;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
|
@ -27,6 +27,12 @@ class JsonVariantConst : public detail::VariantTag,
|
||||
public detail::VariantOperators<JsonVariantConst> {
|
||||
friend class detail::VariantAttorney;
|
||||
|
||||
template <typename T>
|
||||
using ConversionSupported =
|
||||
detail::is_same<typename detail::function_traits<
|
||||
decltype(&Converter<T>::fromJson)>::arg1_type,
|
||||
JsonVariantConst>;
|
||||
|
||||
public:
|
||||
// Creates an unbound reference.
|
||||
JsonVariantConst() : data_(nullptr), resources_(nullptr) {}
|
||||
@ -62,23 +68,35 @@ class JsonVariantConst : public detail::VariantTag,
|
||||
// Casts the value to the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/as/
|
||||
template <typename T>
|
||||
typename detail::enable_if<!detail::is_same<T, char*>::value &&
|
||||
!detail::is_same<T, char>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
typename detail::enable_if<ConversionSupported<T>::value, T>::type as()
|
||||
const {
|
||||
return Converter<T>::fromJson(*this);
|
||||
}
|
||||
|
||||
// Casts the value to the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/as/
|
||||
template <typename T>
|
||||
typename detail::enable_if<
|
||||
!ConversionSupported<T>::value,
|
||||
detail::InvalidConversion<JsonVariantConst, T>>::type
|
||||
as() const;
|
||||
|
||||
// Returns true if the value is of the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/is/
|
||||
template <typename T>
|
||||
typename detail::enable_if<!detail::is_same<T, char*>::value &&
|
||||
!detail::is_same<T, char>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
typename detail::enable_if<ConversionSupported<T>::value, bool>::type is()
|
||||
const {
|
||||
return Converter<T>::checkJson(*this);
|
||||
}
|
||||
|
||||
// Always returns false for the unsupported types.
|
||||
// https://arduinojson.org/v7/api/jsonvariantconst/is/
|
||||
template <typename T>
|
||||
typename detail::enable_if<!ConversionSupported<T>::value, bool>::type is()
|
||||
const {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
operator T() const {
|
||||
return as<T>();
|
||||
|
@ -46,16 +46,7 @@ class VariantRefBase : public VariantTag {
|
||||
// Casts the value to the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/as/
|
||||
template <typename T>
|
||||
|
||||
typename enable_if<!ConverterNeedsWriteableRef<T>::value, T>::type as()
|
||||
const {
|
||||
return Converter<T>::fromJson(getVariantConst());
|
||||
}
|
||||
|
||||
// Casts the value to the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/as/
|
||||
template <typename T>
|
||||
typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type as() const;
|
||||
T as() const;
|
||||
|
||||
template <typename T,
|
||||
typename = typename enable_if<!is_same<T, TDerived>::value>::type>
|
||||
@ -83,18 +74,7 @@ class VariantRefBase : public VariantTag {
|
||||
// Returns true if the value is of the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/is/
|
||||
template <typename T>
|
||||
FORCE_INLINE
|
||||
typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
|
||||
is() const;
|
||||
|
||||
// Returns true if the value is of the specified type.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/is/
|
||||
template <typename T>
|
||||
FORCE_INLINE
|
||||
typename enable_if<!ConverterNeedsWriteableRef<T>::value, bool>::type
|
||||
is() const {
|
||||
return Converter<T>::checkJson(getVariantConst());
|
||||
}
|
||||
FORCE_INLINE bool is() const;
|
||||
|
||||
// Copies the specified value.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/set/
|
||||
@ -298,6 +278,18 @@ class VariantRefBase : public VariantTag {
|
||||
return ArduinoJson::JsonVariantConst(getData(), getResourceManager());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename enable_if<is_same<T, JsonVariantConst>::value, T>::type
|
||||
getVariant() const {
|
||||
return getVariantConst();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename enable_if<is_same<T, JsonVariant>::value, T>::type
|
||||
getVariant() const {
|
||||
return getVariant();
|
||||
}
|
||||
|
||||
ArduinoJson::JsonVariant getOrCreateVariant() const;
|
||||
};
|
||||
|
||||
|
@ -17,9 +17,10 @@ inline JsonVariant VariantRefBase<TDerived>::add() const {
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T>
|
||||
inline typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
|
||||
VariantRefBase<TDerived>::as() const {
|
||||
return Converter<T>::fromJson(getVariant());
|
||||
inline T VariantRefBase<TDerived>::as() const {
|
||||
using variant_type = // JsonVariantConst or JsonVariant?
|
||||
typename function_traits<decltype(&Converter<T>::fromJson)>::arg1_type;
|
||||
return Converter<T>::fromJson(getVariant<variant_type>());
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
@ -109,9 +110,10 @@ inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant() const {
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T>
|
||||
inline typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
|
||||
VariantRefBase<TDerived>::is() const {
|
||||
return Converter<T>::checkJson(getVariant());
|
||||
inline bool VariantRefBase<TDerived>::is() const {
|
||||
using variant_type = // JsonVariantConst or JsonVariant?
|
||||
typename function_traits<decltype(&Converter<T>::checkJson)>::arg1_type;
|
||||
return Converter<T>::checkJson(getVariant<variant_type>());
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
|
Reference in New Issue
Block a user