Add helper methods to invoke OC methods safely
authorcoderhyme <jhyo.kim@samsung.com>
Mon, 22 Jun 2015 07:29:01 +0000 (16:29 +0900)
committerUze Choi <uzchoi@samsung.com>
Tue, 23 Jun 2015 04:06:53 +0000 (04:06 +0000)
Change-Id: I94b4310f39530587003c5c153cf6feb870f924d2
Signed-off-by: coderhyme <jhyo.kim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/1376
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
service/basis/common/primitiveResource/include/internal/AssertUtils.h

index 40d286e..d8f5244 100644 (file)
 #define __PRIMITIVERESOURCE_ASSERTUTILS_H
 
 #include <cstdint>
+
+#include <memory>
+
 #include <octypes.h>
+#include <OCException.h>
 
 #include <PrimitiveException.h>
 
@@ -30,6 +34,63 @@ namespace OIC
 {
     namespace Service
     {
+        namespace Detail
+        {
+            struct NotOCStackResult;
+
+            template< typename RET, typename FUNC, typename ENABLER = void, typename ...PARAMS >
+            struct EnableIfReturnTypeIs;
+
+            template< typename FUNC, typename ...PARAMS >
+            struct EnableIfReturnTypeIs< OCStackResult, FUNC,
+                    typename std::enable_if<
+                            std::is_same< typename std::result_of< FUNC(PARAMS...) >::type,
+                                    OCStackResult >::value >::type, PARAMS... >
+            {
+                using type = void;
+            };
+
+            template< typename FUNC, typename ...PARAMS >
+            struct EnableIfReturnTypeIs< NotOCStackResult, FUNC,
+                    typename std::enable_if<
+                            !std::is_same< typename std::result_of< FUNC(PARAMS...) >::type,
+                                    OCStackResult >::value >::type, PARAMS... >
+            {
+                using type = typename std::result_of< FUNC(PARAMS...) >::type;
+            };
+
+
+            template< typename A, typename B, typename ENABLER = void >
+            struct EnableIfTypeIs;
+
+            template< typename A >
+            struct EnableIfTypeIs< A, OCStackResult,
+                    typename std::enable_if< std::is_same< A, OCStackResult >::value >::type >
+            {
+                using type = void;
+            };
+
+            template< typename A >
+            struct EnableIfTypeIs< A, NotOCStackResult,
+                    typename std::enable_if< !std::is_same< A, OCStackResult >::value >::type >
+            {
+                using type = A;
+            };
+
+
+            template< typename T, typename = typename std::enable_if<
+                    std::is_class<T>::value && std::is_pointer<T>::value>::type >
+            struct EnableIfClassPointer
+            {
+                using type = void;
+            };
+
+            template< typename T, typename = typename std::enable_if<std::is_class<T>::value > >
+             struct EnableIfClass
+             {
+                 using type = void;
+             };
+        }
 
         inline void expectOCStackResult(OCStackResult actual, OCStackResult expected)
         {
@@ -44,6 +105,108 @@ namespace OIC
             expectOCStackResult(actual, OC_STACK_OK);
         }
 
+        template< typename FUNC,
+            typename = typename std::enable_if<std::is_function<FUNC>::value>::type,
+            typename ...PARAMS >
+        typename Detail::EnableIfReturnTypeIs< OCStackResult, FUNC, PARAMS... >::type
+        invokeOC(FUNC&& fn, PARAMS&& ...params)
+        {
+            try
+            {
+                expectOCStackResultOK(fn(std::forward< PARAMS >(params)...));
+            }
+            catch (OC::OCException& e)
+            {
+                throw PlatformException(e.code());
+            }
+        }
+
+        template< typename FUNC,
+            typename = typename std::enable_if<std::is_function<FUNC>::value>::type,
+            typename ...PARAMS >
+        typename Detail::EnableIfReturnTypeIs< Detail::NotOCStackResult, FUNC, PARAMS... >::type
+        invokeOC(FUNC&& fn, PARAMS&& ...params)
+        {
+            try
+            {
+                return fn(std::forward< PARAMS >(params)...);
+            }
+            catch (OC::OCException& e)
+            {
+                throw PlatformException(e.code());
+            }
+        }
+
+        template< typename OBJ, typename = typename Detail::EnableIfClassPointer<OBJ>::type,
+                typename FUNC, typename ...PARAMS >
+        inline auto invokeOC(OBJ&& obj, FUNC&& fn, PARAMS&& ...params) ->
+            typename Detail::EnableIfTypeIs<
+                decltype((obj->*fn)(std::forward< PARAMS >(params)...)), OCStackResult>::
+                type
+        {
+            try
+            {
+                expectOCStackResultOK(obj->*fn(std::forward< PARAMS >(params)...));
+            }
+            catch (OC::OCException& e)
+            {
+                throw PlatformException(e.code());
+            }
+        }
+
+        template< typename OBJ, typename = typename Detail::EnableIfClassPointer<OBJ>::type,
+                typename FUNC, typename ...PARAMS >
+        inline auto invokeOC(OBJ&& obj, FUNC&& fn, PARAMS&& ...params) ->
+                typename Detail::EnableIfTypeIs<
+                    decltype((obj->*fn)(std::forward< PARAMS >(params)...)),
+                    Detail::NotOCStackResult>::
+                    type
+        {
+            try
+            {
+                obj->*fn(std::forward< PARAMS >(params)...);
+            }
+            catch (OC::OCException& e)
+            {
+                throw PlatformException(e.code());
+            }
+        }
+
+        template< typename OBJ, typename = typename Detail::EnableIfClass<OBJ>::type,
+                typename FUNC, typename ...PARAMS >
+        inline auto invokeOC(const std::shared_ptr< OBJ >& obj, FUNC&& fn, PARAMS&& ...params) ->
+                typename Detail::EnableIfTypeIs<
+                    decltype((obj.get()->*fn)(std::forward< PARAMS >(params)...)), OCStackResult>::
+                    type
+        {
+            try
+            {
+                expectOCStackResultOK((obj.get()->*fn)(std::forward< PARAMS >(params)...));
+            }
+            catch (OC::OCException& e)
+            {
+                throw PlatformException(e.code());
+            }
+        }
+
+        template< typename OBJ, typename = typename Detail::EnableIfClass< OBJ >::type,
+                typename FUNC, typename ...PARAMS >
+        inline auto invokeOC(const std::shared_ptr<OBJ>& obj, FUNC&& fn, PARAMS&& ...params) ->
+            typename Detail::EnableIfTypeIs<
+                   decltype((obj.get()->*fn)(std::forward< PARAMS >(params)...)),
+                   Detail::NotOCStackResult>::
+                   type
+        {
+            try
+            {
+                return (obj.get()->*fn)(std::forward< PARAMS >(params)...);
+            }
+            catch (OC::OCException& e)
+            {
+                throw PlatformException(e.code());
+            }
+        }
+
     }
 }