From 02556bdba37caca8b022a7d8d1f2bde6a676b75e Mon Sep 17 00:00:00 2001 From: coderhyme Date: Wed, 8 Jul 2015 13:00:50 +0900 Subject: [PATCH] Add type class for ResourceAttriutes The class helps distinguish types between Values Change-Id: I7a02c290bb6b1f3fb7d26ef7cb1087268afa36ac Signed-off-by: coderhyme Reviewed-on: https://gerrit.iotivity.org/gerrit/1569 Tested-by: jenkins-iotivity Reviewed-by: Uze Choi Tested-by: Uze Choi --- .../primitiveResource/include/ResourceAttributes.h | 84 +++++++++---- .../include/internal/ResourceAttributesUtils.h | 3 +- .../primitiveResource/src/ResourceAttributes.cpp | 137 ++++++++++++++++++++- .../unittests/ResourceAttributesTest.cpp | 16 +++ 4 files changed, 211 insertions(+), 29 deletions(-) diff --git a/service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h b/service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h index 35219fb..3dda5eb 100755 --- a/service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h +++ b/service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h @@ -60,7 +60,7 @@ namespace OIC class ResourceAttributes { private: - template< typename T > struct is_supported_type_helper; + template< typename T > struct IsSupportedTypeHelper; using ValueVariant = boost::variant< std::nullptr_t, @@ -76,11 +76,11 @@ namespace OIC template< typename T, typename V = void > using enable_if_supported = typename std::enable_if< - is_supported_type_helper< T >::type::value, V >::type; + IsSupportedTypeHelper< T >::type::value, V >::type; template< typename T, typename V = void > using enable_if_unsupported = typename std::enable_if< - !is_supported_type_helper< T >::type::value, V >::type; + !IsSupportedTypeHelper< T >::type::value, V >::type; template< typename VISITOR > class KeyValueVisitorHelper: public boost::static_visitor< > @@ -101,9 +101,52 @@ namespace OIC VISITOR& m_visitor; }; + template struct IndexOfType; + public: template< typename T > - using is_supported_type = typename is_supported_type_helper< T >::type; + using is_supported_type = typename IsSupportedTypeHelper< T >::type; + + enum class TypeId + { + NULL_T, + INT, + DOUBLE, + BOOL, + STRING, + ATTRIBUTES, + VECTOR + }; + + class Type + { + public: + Type(const Type&) = default; + Type(Type&&) = default; + + Type& operator=(const Type&) = default; + Type& operator=(Type&&) = default; + + TypeId getId() const; + + template < typename T > + static Type typeOf(const T& value) + { + return Type(value); + } + + friend bool operator==(const Type&, const Type&); + + private: + template < typename T > + explicit Type(const T&) : + m_which{ IndexOfType< T >::value } + { + } + + private: + int m_which; + }; class Value { @@ -145,25 +188,7 @@ namespace OIC return checkedGet< T >(); } - bool isTypeEqualWith(const Value& rhs) const - { - return m_data->which() == rhs.m_data->which(); - } - - template< typename T > - enable_if_supported< T, bool > isTypeOf() const - { - using iter = typename boost::mpl::find< ValueVariant::types, T >::type; - - return m_data->which() - == boost::mpl::distance< mpl_begin< ValueVariant::types >, iter >::value; - } - - template< typename T > - enable_if_unsupported< T, bool > isTypeOf() const - { - return false; - } + Type getType() const; std::string toString() const; @@ -264,12 +289,23 @@ namespace OIC friend class ResourceAttributesConverter; }; - template< typename T > struct ResourceAttributes::is_supported_type_helper + template< typename T > + struct ResourceAttributes::IsSupportedTypeHelper { using type = boost::mpl::contains::type>; }; + template + struct ResourceAttributes::IndexOfType + { + using iter = typename boost::mpl::find< ValueVariant::types, T >::type; + + static constexpr int value = boost::mpl::distance< mpl_begin< ValueVariant::types >, + iter >::value; + }; + bool operator==(const ResourceAttributes::Type&, const ResourceAttributes::Type&); + bool operator!=(const ResourceAttributes::Type&, const ResourceAttributes::Type&); bool operator!=(const ResourceAttributes::Value&, const ResourceAttributes::Value&); diff --git a/service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h b/service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h index 8672373..50f3b2d 100644 --- a/service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h +++ b/service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h @@ -36,7 +36,8 @@ namespace OIC bool acceptableAttributeValue(const ResourceAttributes::Value& dest, const ResourceAttributes::Value& value); - AttrKeyValuePairs replaceAttributes(ResourceAttributes& dest, const ResourceAttributes& attrs); + AttrKeyValuePairs replaceAttributes(ResourceAttributes& dest, + const ResourceAttributes& attrs); } } diff --git a/service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp b/service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp index 95d1746..aa74adb 100755 --- a/service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp +++ b/service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp @@ -24,10 +24,15 @@ #include #include +#include +#include +#include namespace { + using namespace OIC::Service; + class ToStringVisitor: public boost::static_visitor< std::string > { public: @@ -65,6 +70,112 @@ namespace } }; + class TypeVisitor: public boost::static_visitor< ResourceAttributes::Type > + { + public: + TypeVisitor() = default; + TypeVisitor(const TypeVisitor&) = delete; + TypeVisitor(TypeVisitor&&) = delete; + + TypeVisitor& operator=(const TypeVisitor&) = delete; + TypeVisitor& operator=(TypeVisitor&&) = delete; + + template< typename T > + ResourceAttributes::Type operator()(const T& value) const + { + return ResourceAttributes::Type::typeOf(value); + } + + }; + + template< int > + struct Int2Type {}; + + template< typename T > + struct TypeInfoConverter; + + template< > + struct TypeInfoConverter< int > + { + static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::INT; + }; + + template< > + struct TypeInfoConverter< std::nullptr_t > + { + static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::NULL_T; + }; + + template< > + struct TypeInfoConverter< double > + { + static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::DOUBLE; + }; + + template< > + struct TypeInfoConverter< bool > + { + static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::BOOL; + }; + + template< > + struct TypeInfoConverter< std::string > + { + static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::STRING; + }; + + template< > + struct TypeInfoConverter< ResourceAttributes > + { + static constexpr ResourceAttributes::TypeId typeId = ResourceAttributes::TypeId::ATTRIBUTES; + }; + + struct TypeInfo + { + ResourceAttributes::TypeId typeId; + + template< typename TRAIT > + constexpr TypeInfo(TRAIT) : + typeId{ TRAIT::typeId } + { + } + + template< typename VARIANT, int POS > + static constexpr TypeInfo get() + { + return TypeInfo( + TypeInfoConverter< + typename boost::mpl::deref< + typename boost::mpl::advance< + typename boost::mpl::begin< typename VARIANT::types >::type, + boost::mpl::int_< POS > >::type >::type >{ }); + } + }; + + template< typename VARIANT, int POS > + constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >) + { + auto&& vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ }); + vec.push_back(TypeInfo::get< VARIANT, POS >()); + return vec; + } + + template< typename VARIANT > + constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >) + { + return { TypeInfo::get< VARIANT, 0 >() }; + } + + template< typename VARIANT > + inline TypeInfo getTypeInfo(int which) + { + static constexpr int variantEnd = boost::mpl::size< typename VARIANT::types >::value - 1; + static const std::vector< TypeInfo > typeInfos = getTypeInfo< VARIANT >( + Int2Type< variantEnd >{ }); + + return typeInfos[which]; + } + } // unnamed namespace @@ -73,6 +184,16 @@ namespace OIC namespace Service { + bool operator==(const ResourceAttributes::Type& lhs, const ResourceAttributes::Type& rhs) + { + return lhs.m_which == rhs.m_which; + } + + bool operator!=(const ResourceAttributes::Type& lhs, const ResourceAttributes::Type& rhs) + { + return !(lhs == rhs); + } + bool operator!=(const ResourceAttributes::Value& lhs, const ResourceAttributes::Value& rhs) { return !(lhs == rhs); @@ -83,7 +204,6 @@ namespace OIC return !(rhs == lhs); } - bool operator==(const char* lhs, const ResourceAttributes::Value& rhs) { return rhs == lhs; @@ -104,6 +224,11 @@ namespace OIC return !(lhs == rhs); } + auto ResourceAttributes::Type::getId() const -> TypeId + { + return ::getTypeInfo< ValueVariant >(m_which).typeId; + } + ResourceAttributes::Value::Value() : m_data{ new ValueVariant{} } { @@ -155,6 +280,11 @@ namespace OIC return equals< std::string >(rhs); } + auto ResourceAttributes::Value::getType() const -> Type + { + return boost::apply_visitor(TypeVisitor(), *m_data); + } + std::string ResourceAttributes::Value::toString() const { return boost::apply_visitor(ToStringVisitor(), *m_data); @@ -211,7 +341,6 @@ namespace OIC return boost::apply_visitor(m_valueVisitor, m_iterRef); } - ResourceAttributes::KeyValuePair::KeyValuePair(boost::variant&& ref) : m_iterRef{ ref } @@ -406,7 +535,7 @@ namespace OIC bool acceptableAttributeValue(const ResourceAttributes::Value& dest, const ResourceAttributes::Value& value) { - if (!dest.isTypeEqualWith(value)) + if (dest.getType() != value.getType()) { return false; } @@ -414,7 +543,7 @@ namespace OIC static_assert(ResourceAttributes::is_supported_type< ResourceAttributes >::value, "ResourceAttributes doesn't have ResourceAttributes recursively."); - if (dest.isTypeOf< ResourceAttributes >() + if (dest.getType().getId() == ResourceAttributes::TypeId::ATTRIBUTES && !acceptableAttributes(dest.get< ResourceAttributes >(), value.get< ResourceAttributes >())) { diff --git a/service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp b/service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp index 3066a5f..b8f593c 100644 --- a/service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp +++ b/service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp @@ -272,6 +272,22 @@ TEST(ResourceAttributesValueTest, ValuesCanBeSwapped) ASSERT_EQ(i, strValue); } +TEST(ResourceAttributesTypeTest, TypeIdMatchesTypeOfValue) +{ + ResourceAttributes::Value intValue { 1 }; + + ASSERT_EQ(intValue.getType().getId(), ResourceAttributes::TypeId::INT); +} + +TEST(ResourceAttributesTypeTest, TypeCanBeConstructedFromValue) +{ + ResourceAttributes::Value intValue { 1 }; + + ResourceAttributes::Type t = ResourceAttributes::Type::typeOf(0); + + ASSERT_EQ(intValue.getType(), t); +} + TEST(ResourceAttributesConverterTest, OCRepresentationCanBeConvertedIntoResourceAttributes) { constexpr double value = 9876; -- 2.7.4