config: enum class serialization 71/49171/5
authorJan Olszak <j.olszak@samsung.com>
Wed, 7 Oct 2015 16:13:52 +0000 (18:13 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Mon, 12 Oct 2015 07:51:09 +0000 (00:51 -0700)
[Feature]       Serialization of strongly typed enums
[Cause]         N/A
[Solution]      N/A
[Verification]  Build, install, run tests.

Change-Id: Ie4d112995cff8d58c0cc6fad6c0646ec03d5aa83

libs/config/from-fdstore-visitor.hpp
libs/config/from-gvariant-visitor.hpp
libs/config/from-json-visitor.hpp
libs/config/from-kvjson-visitor.hpp
libs/config/kvstore.hpp
libs/config/to-fdstore-visitor.hpp
libs/config/to-gvariant-visitor.hpp
libs/config/to-json-visitor.hpp
tests/unit_tests/config/testconfig-example.hpp
tests/unit_tests/config/ut-configuration.cpp

index f0c8dbe..8b7d082 100644 (file)
@@ -93,6 +93,12 @@ private:
         value.accept(visitor);
     }
 
+    template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
+    void readInternal(T& value)
+    {
+        readInternal(*reinterpret_cast<typename std::underlying_type<T>::type*>(&value));
+    }
+
     template<typename T>
     void readInternal(std::vector<T>& values)
     {
index afc1beb..78e001d 100644 (file)
@@ -200,6 +200,13 @@ private:
         visitFields(values, &visitor, &iter);
     }
 
+    template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
+    static void fromGVariant(GVariant* object, T& value)
+    {
+        fromGVariant(object,
+                     *reinterpret_cast<typename std::underlying_type<T>::type*>(&value));
+    }
+
     template<typename T>
     static typename std::enable_if<isUnion<T>::value>::type
     fromGVariant(GVariant* object, T& value)
index 9bdf19b..b599084 100644 (file)
@@ -192,7 +192,14 @@ private:
         visitFields(values, &visitor, object, idx);
     }
 
-    template<typename T, class = typename std::enable_if<isVisitable<T>::value>::type>
+    template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
+    static void fromJsonObject(json_object* object, T& value)
+    {
+        fromJsonObject(object,
+                       *reinterpret_cast<typename std::underlying_type<T>::type*>(&value));
+    }
+
+    template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
     static void fromJsonObject(json_object* object, T& value)
     {
         checkType(object, json_type_object);
index d9dbce7..e66b90d 100644 (file)
@@ -107,7 +107,16 @@ private:
         mObject = object ? json_object_get(object) : nullptr;
     }
 
-    template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
+    template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
+    void getValue(const std::string& name, T& t)
+    {
+        getValue(name,
+                 *reinterpret_cast<typename std::underlying_type<T>::type*>(&t));
+    }
+
+    template<typename T,
+             typename std::enable_if<!isVisitable<T>::value &&
+                                     !std::is_enum<T>::value, int>::type = 0>
     void getValue(const std::string& name, T& t)
     {
         std::string k = key(mKeyPrefix, name);
index 1206d08..40aa199 100644 (file)
@@ -139,7 +139,9 @@ private:
     void setInternal(const std::string& key, const char* value);
     void setInternal(const std::string& key, const std::initializer_list<std::string>& values);
     void setInternal(const std::string& key, const std::vector<std::string>& values);
-    template<typename T>
+    template<typename T, typename std::enable_if<!std::is_enum<T>::value, int>::type = 0>
+    void setInternal(const std::string& key, const T& value);
+    template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
     void setInternal(const std::string& key, const T& value);
     template<typename T>
     void setInternal(const std::string& key, const std::vector<T>& values);
@@ -151,7 +153,9 @@ private:
     std::string getInternal(const std::string& key, std::string*);
     char* getInternal(const std::string& key, char**);
     std::vector<std::string> getInternal(const std::string& key, std::vector<std::string>*);
-    template<typename T>
+    template<typename T, typename std::enable_if<!std::is_enum<T>::value, int>::type = 0>
+    T getInternal(const std::string& key, T*);
+    template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
     T getInternal(const std::string& key, T*);
     template<typename T>
     std::vector<T> getInternal(const std::string& key, std::vector<T>*);
@@ -195,12 +199,19 @@ T fromString(const std::string& strValue)
 
 } // namespace
 
-template<typename T>
+template<typename T, typename std::enable_if<!std::is_enum<T>::value, int>::type>
 void KVStore::setInternal(const std::string& key, const T& value)
 {
     setInternal(key, toString(value));
 }
 
+template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type>
+void KVStore::setInternal(const std::string& key, const T& value)
+{
+    setInternal(key,
+                static_cast<const typename std::underlying_type<T>::type>(value));
+}
+
 template<typename T>
 void KVStore::setInternal(const std::string& key, const std::vector<T>& values)
 {
@@ -247,12 +258,19 @@ void KVStore::setInternal(const std::string& key, const std::pair<T...>& values)
     setInternal(key, strValues);
 }
 
-template<typename T>
+template<typename T, typename std::enable_if<!std::is_enum<T>::value, int>::type>
 T KVStore::getInternal(const std::string& key, T*)
 {
     return fromString<T>(getInternal(key, static_cast<std::string*>(nullptr)));
 }
 
+template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type>
+T KVStore::getInternal(const std::string& key, T*)
+{
+    return static_cast<T>(getInternal(key,
+                                      static_cast<typename std::underlying_type<T>::type*>(nullptr)));
+}
+
 template<typename T, std::size_t N>
 std::array<T, N> KVStore::getInternal(const std::string& key, std::array<T, N>*)
 {
index ba9bb8e..b3e6b84 100644 (file)
@@ -78,6 +78,12 @@ private:
         mStore.sendFD(fd.value);
     }
 
+    template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
+    void writeInternal(const T& value)
+    {
+        writeInternal(static_cast<const typename std::underlying_type<T>::type>(value));
+    }
+
     template<typename T, typename std::enable_if<std::is_arithmetic<T>::value, int>::type = 0>
     void writeInternal(const T& value)
     {
index 09c04e6..c0df2da 100644 (file)
@@ -143,6 +143,12 @@ private:
         g_variant_builder_close(mBuilder);
     }
 
+    template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
+    void writeInternal(const T& value)
+    {
+        writeInternal(static_cast<const typename std::underlying_type<T>::type>(value));
+    }
+
     template<typename T>
     typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value>::type
     writeInternal(const T& value)
index 3b8facf..ba0d6ed 100644 (file)
@@ -168,13 +168,20 @@ private:
         return array;
     }
 
-    template<typename T, class = typename std::enable_if<isVisitable<T>::value>::type>
+    template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
     static json_object* toJsonObject(const T& value)
     {
         ToJsonVisitor visitor;
         value.accept(visitor);
         return visitor.detach();
     }
+
+    template<typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
+    static json_object* toJsonObject(const T& value)
+    {
+        return toJsonObject(static_cast<const typename std::underlying_type<T>::type>(value));
+    }
+
 };
 
 } // namespace config
index 3cdd876..0ddd975 100644 (file)
 #include "config/fields.hpp"
 #include "config/fields-union.hpp"
 
+enum class TestEnum: int {
+    FIRST = 0,
+    SECOND = 12
+};
+
 struct TestConfig {
     // subtree class
     struct SubConfig {
@@ -91,6 +96,7 @@ struct TestConfig {
     char* cstringVal;
     double doubleVal;
     bool boolVal;
+    TestEnum enumVal;
 
     std::vector<int> emptyIntVector;
     std::vector<int> intVector;
@@ -118,6 +124,7 @@ struct TestConfig {
         cstringVal,
         doubleVal,
         boolVal,
+        enumVal,
 
         emptyIntVector,
         intVector,
@@ -163,6 +170,7 @@ const std::string jsonTestString =
     "\"cstringVal\": \"blah\", "
     "\"doubleVal\": -1.234000, "
     "\"boolVal\": true, "
+    "\"enumVal\": 12, "
     "\"emptyIntVector\": [ ], "
     "\"intVector\": [ 1, 2, 3 ], "
     "\"stringVector\": [ \"a\", \"b\" ], "
@@ -188,6 +196,7 @@ const std::string jsonEmptyTestString =
     "\"stringVal\": \"\", "
     "\"cstringVal\": \"\", "
     "\"boolVal\": false, "
+    "\"enumVal\": 0, "
     "\"emptyIntVector\": [ ], "
     "\"intVector\": [ ], "
     "\"stringVector\": [ ], "
index e50ed92..ab1a200 100644 (file)
@@ -67,6 +67,7 @@ BOOST_AUTO_TEST_CASE(FromJsonString)
     BOOST_CHECK_EQUAL("blah", testConfig.cstringVal);
     BOOST_CHECK_CLOSE(-1.234, testConfig.doubleVal, TOLERANCE);
     BOOST_CHECK_EQUAL(true, testConfig.boolVal);
+    BOOST_CHECK(TestEnum::SECOND == testConfig.enumVal);
 
     BOOST_REQUIRE_EQUAL(0, testConfig.emptyIntVector.size());