Skip to content

Commit

Permalink
Allow set enum as json value (#4363)
Browse files Browse the repository at this point in the history
* fix issue #4341
add testEnum
if you set enum as json value then it will be cast to int

* add behavour for enum into VarHolderImpl
add tests for enum classes with differnent underline integral types

* replace static_cast with convertTo* methods, they can chaeck types and
limits

* fix missing types for convert methods

* fix code style
add testEnumType to the VarTest.cpp, extract() works
  • Loading branch information
bas524 authored and matejk committed Mar 26, 2024
1 parent 482c066 commit 7a2c2fc
Show file tree
Hide file tree
Showing 5 changed files with 591 additions and 1 deletion.
317 changes: 317 additions & 0 deletions Foundation/include/Poco/Dynamic/VarHolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,42 @@ class Foundation_API VarHolder
checkUpperLimit<F,T>(from);
to = static_cast<T>(from);
}

template <typename F, typename T, std::enable_if_t<std::is_signed<F>::value && std::is_signed<T>::value && (sizeof(F) <= sizeof(T))>* = nullptr>
void convertToSigned(const F& from, T& to) const
{
to = static_cast<T>(from);
}

template <typename F, typename T, std::enable_if_t<std::is_signed<F>::value && std::is_signed<T>::value && (sizeof(F) > sizeof(T))>* = nullptr>
void convertToSigned(const F& from, T& to) const
{
convertToSmaller(from, to);
}

template <typename F, typename T, std::enable_if_t<!std::is_signed<F>::value && std::is_signed<T>::value>* = nullptr>
void convertToSigned(const F& from, T& to) const
{
convertUnsignedToSigned(from, to);
}

template <typename F, typename T, std::enable_if_t<!std::is_signed<F>::value && !std::is_signed<T>::value && (sizeof(F) <= sizeof(T))>* = nullptr>
void convertToUnsigned(const F& from, T& to) const
{
to = static_cast<T>(from);
}

template <typename F, typename T, std::enable_if_t<!std::is_signed<F>::value && !std::is_signed<T>::value && (sizeof(F) > sizeof(T))>* = nullptr>
void convertToUnsigned(const F& from, T& to) const
{
convertToSmallerUnsigned(from, to);
}

template <typename F, typename T, std::enable_if_t<std::is_signed<F>::value && !std::is_signed<T>::value>* = nullptr>
void convertToUnsigned(const F& from, T& to) const
{
convertSignedToUnsigned(from, to);
}

template <typename F, typename T,
std::enable_if_t<std::is_integral<F>::value, bool> = true,
Expand Down Expand Up @@ -787,6 +823,287 @@ class VarHolderImpl: public VarHolder
return typeid(T);
}

void convert(Int8& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToSigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

void convert(Int16& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToSigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

void convert(Int32& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToSigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

void convert(Int64& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToSigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

void convert(UInt8& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToUnsigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

void convert(UInt16& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToUnsigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

void convert(UInt32& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToUnsigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

void convert(UInt64& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToUnsigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

#ifdef POCO_INT64_IS_LONG

void convert(long long& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToSigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

void convert(unsigned long long& val) const
{
if constexpr (std::is_enum<T>::value)
{
convertToUnsigned(std::underlying_type_t<T>(_val), val);
}
else
{
VarHolder::convert(val);
}
}

#endif

void convert(bool& val) const
{
if constexpr (std::is_enum<T>::value)
{
val = (std::underlying_type_t<T>(_val) != 0);
}
else
{
VarHolder::convert(val);
}
}

void convert(float& val) const
{
if constexpr (std::is_enum<T>::value)
{
val = static_cast<float>(_val);
}
else
{
VarHolder::convert(val);
}
}

void convert(double& val) const
{
if constexpr (std::is_enum<T>::value)
{
val = static_cast<double>(_val);
}
else
{
VarHolder::convert(val);
}
}

void convert(char& val) const
{
if constexpr (std::is_enum<T>::value)
{
val = static_cast<char>(_val);
}
else
{
VarHolder::convert(val);
}
}

void convert(std::string& val) const
{
if constexpr (std::is_enum<T>::value)
{
val = NumberFormatter::format(std::underlying_type_t<T>(_val));
}
else
{
VarHolder::convert(val);
}
}

void convert(Poco::UTF16String& val) const
{
if constexpr (std::is_enum<T>::value)
{
std::string str = NumberFormatter::format(std::underlying_type_t<T>(_val));
Poco::UnicodeConverter::convert(str, val);
}
else
{
VarHolder::convert(val);
}
}

bool isArray() const
{
if constexpr (std::is_enum<T>::value)
{
return false;
}
else
{
return VarHolder::isArray();
}
}

bool isStruct() const
{
if constexpr (std::is_enum<T>::value)
{
return false;
}
else
{
return VarHolder::isStruct();
}
}

bool isInteger() const
{
if constexpr (std::is_enum<T>::value)
{
return std::numeric_limits<std::underlying_type_t<T>>::is_integer;
}
else
{
return VarHolder::isInteger();
}
}

bool isSigned() const
{
if constexpr (std::is_enum<T>::value)
{
return std::numeric_limits<std::underlying_type_t<T>>::is_signed;
}
else
{
return VarHolder::isSigned();
}
}

bool isNumeric() const
{
if constexpr (std::is_enum<T>::value)
{
return std::numeric_limits<std::underlying_type_t<T>>::is_specialized;
}
else
{
return VarHolder::isNumeric();
}
}

bool isBoolean() const
{
if constexpr (std::is_enum<T>::value)
{
return false;
}
else
{
return VarHolder::isBoolean();
}
}

bool isString() const
{
if constexpr (std::is_enum<T>::value)
{
return false;
}
else
{
return VarHolder::isString();
}
}

VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
{
return cloneHolder(pVarHolder, _val);
Expand Down
Loading

0 comments on commit 7a2c2fc

Please sign in to comment.