config: std::array serialization. 91/48791/4
authorJan Olszak <j.olszak@samsung.com>
Tue, 29 Sep 2015 15:41:18 +0000 (17:41 +0200)
committerJan Olszak <j.olszak@samsung.com>
Thu, 1 Oct 2015 09:27:58 +0000 (02:27 -0700)
[Feature]       Serialization of std::array
[Cause]         N/A
[Solution]      N/A
[Verification]  Build, install, run tests.

Change-Id: I3e2f890d07ef6c0818135566eadb11a025438fd7

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 a948b3b..1013a61 100644 (file)
@@ -29,7 +29,9 @@
 #include "config/fdstore.hpp"
 #include "config/types.hpp"
 
+#include <array>
 #include <string>
+#include <vector>
 
 namespace config {
 
@@ -100,6 +102,14 @@ private:
             readInternal(value);
         }
     }
+
+    template<typename T, std::size_t N>
+    void readInternal(std::array<T, N>& values)
+    {
+        for (T& value : values) {
+            readInternal(value);
+        }
+    }
 };
 
 } // namespace config
index a4134b6..213f917 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <string>
 #include <vector>
+#include <array>
 #include <memory>
 #include <cassert>
 #include <glib.h>
@@ -160,6 +161,20 @@ private:
         }
     }
 
+    template<typename T, std::size_t N>
+    static void fromGVariant(GVariant* object, std::array<T, N>& values)
+    {
+        checkType(object, G_VARIANT_TYPE_ARRAY);
+
+        GVariantIter iter;
+        g_variant_iter_init(&iter, object);
+
+        for (T& value: values) {
+            auto child = makeUnique(g_variant_iter_next_value(&iter));
+            fromGVariant(child.get(), value);
+        }
+    }
+
     template<typename T>
     static typename std::enable_if<isUnion<T>::value>::type
     fromGVariant(GVariant* object, T& value)
index bc7864a..041027e 100644 (file)
@@ -32,6 +32,7 @@
 #include <string>
 #include <cstring>
 #include <vector>
+#include <array>
 
 namespace config {
 
@@ -149,13 +150,23 @@ private:
     }
 
     template<typename T>
-    static void fromJsonObject(json_object* object, std::vector<T>& value)
+    static void fromJsonObject(json_object* object, std::vector<T>& values)
     {
         checkType(object, json_type_array);
         int length = json_object_array_length(object);
-        value.resize(static_cast<size_t>(length));
+        values.resize(static_cast<size_t>(length));
         for (int i = 0; i < length; ++i) {
-            fromJsonObject(json_object_array_get_idx(object, i), value[static_cast<size_t>(i)]);
+            fromJsonObject(json_object_array_get_idx(object, i), values[static_cast<size_t>(i)]);
+        }
+    }
+
+    template<typename T, std::size_t N>
+    static void fromJsonObject(json_object* object, std::array<T, N>& values)
+    {
+        checkType(object, json_type_array);
+
+        for (std::size_t i = 0; i < N; ++i) {
+            fromJsonObject(json_object_array_get_idx(object, i), values[i]);
         }
     }
 
index cc6e14a..96f3888 100644 (file)
@@ -167,6 +167,25 @@ private:
         }
     }
 
+    template<typename T, std::size_t N>
+    void getValue(const std::string& name, std::array<T, N>& values)
+    {
+        json_object* object = nullptr;
+        if (mObject && json_object_object_get_ex(mObject, name.c_str(), &object)) {
+            checkType(object, json_type_array);
+        }
+
+        std::string k = key(mKeyPrefix, name);
+        FromKVJsonVisitor visitor(*this, name, false);
+        if (mStore.exists(k)) {
+            json_object_put(visitor.mObject);
+            visitor.mObject = nullptr;
+        }
+        for (std::size_t i = 0; i < N; ++i) {
+            visitor.getValue(i, values[i]);
+        }
+    }
+
     template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
     void getValue(int i, T& t)
     {
@@ -213,6 +232,21 @@ private:
         }
     }
 
+    template<typename T, std::size_t N>
+    void getValue(int i, std::array<T, N>& values)
+    {
+        std::string k = key(mKeyPrefix, std::to_string(i));
+
+        FromKVJsonVisitor visitor(*this, i, false);
+        if (mStore.exists(k)) {
+            json_object_put(visitor.mObject);
+            visitor.mObject = nullptr;
+        }
+        for (std::size_t idx = 0; idx < N; ++idx) {
+            visitor.getValue(idx, values[idx]);
+        }
+    }
+
     static void checkType(json_object* object, json_type type)
     {
         if (type != json_object_get_type(object)) {
index 583d534..fe30e21 100644 (file)
@@ -141,6 +141,8 @@ private:
     void setInternal(const std::string& key, const T& value);
     template<typename T>
     void setInternal(const std::string& key, const std::vector<T>& values);
+    template<typename T, std::size_t N>
+    void setInternal(const std::string& key, const std::array<T, N>& values);
 
     std::string getInternal(const std::string& key, std::string*);
     char* getInternal(const std::string& key, char**);
@@ -149,6 +151,8 @@ private:
     T getInternal(const std::string& key, T*);
     template<typename T>
     std::vector<T> getInternal(const std::string& key, std::vector<T>*);
+    template<typename T, std::size_t N>
+    std::array<T, N> getInternal(const std::string& key, std::array<T, N>*);
 
     std::string mPath;
     sqlite3::Connection mConn;
@@ -204,12 +208,39 @@ void KVStore::setInternal(const std::string& key, const std::vector<T>& values)
     setInternal(key, strValues);
 }
 
+template<typename T, std::size_t N>
+void KVStore::setInternal(const std::string& key, const std::array<T, N>& values)
+{
+    std::vector<std::string> strValues(N);
+
+    std::transform(values.begin(),
+                   values.end(),
+                   strValues.begin(),
+                   toString<T>);
+
+    setInternal(key, strValues);
+}
+
 template<typename T>
 T KVStore::getInternal(const std::string& key, T*)
 {
     return fromString<T>(getInternal(key, static_cast<std::string*>(nullptr)));
 }
 
+template<typename T, std::size_t N>
+std::array<T, N> KVStore::getInternal(const std::string& key, std::array<T, N>*)
+{
+    std::vector<std::string> strValues = getInternal(key, static_cast<std::vector<std::string>*>(nullptr));
+    std::array<T, N> values;
+
+    std::transform(strValues.begin(),
+                   strValues.end(),
+                   values.begin(),
+                   fromString<T>);
+
+    return values;
+}
+
 template<typename T>
 std::vector<T> KVStore::getInternal(const std::string& key, std::vector<T>*)
 {
index 7da3d76..7ce8058 100644 (file)
 #include "config/fdstore.hpp"
 #include "config/types.hpp"
 
-#include <string>
+#include <array>
 #include <cstring>
+#include <string>
+#include <vector>
 
 namespace config {
 
@@ -90,7 +92,15 @@ private:
     void writeInternal(const std::vector<T>& values)
     {
         writeInternal(values.size());
-        for (const T& value : values) {
+        for (const T& value: values) {
+            writeInternal(value);
+        }
+    }
+
+    template<typename T, std::size_t N>
+    void writeInternal(const std::array<T, N>& values)
+    {
+        for (const T& value: values) {
             writeInternal(value);
         }
     }
index 40c002d..1bd1375 100644 (file)
@@ -29,6 +29,7 @@
 #include "config/is-union.hpp"
 #include "config/types.hpp"
 
+#include <array>
 #include <string>
 #include <vector>
 #include <glib.h>
@@ -100,6 +101,20 @@ private:
         }
     }
 
+    template<typename T, std::size_t N>
+    void writeInternal(const std::array<T, N>& values)
+    {
+        if (!values.empty()) {
+            g_variant_builder_open(mBuilder, G_VARIANT_TYPE_ARRAY);
+            for (const T& v : values) {
+                writeInternal(v);
+            }
+            g_variant_builder_close(mBuilder);
+        } else {
+            g_variant_builder_add(mBuilder, "as", NULL);
+        }
+    }
+
     template<typename T>
     typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value>::type
     writeInternal(const T& value)
index 717b952..3c746d2 100644 (file)
@@ -135,6 +135,16 @@ private:
         return array;
     }
 
+    template<typename T, std::size_t N>
+    static json_object* toJsonObject(const std::array<T, N>& values)
+    {
+        json_object* array = json_object_new_array();
+        for (const T& v : values) {
+            json_object_array_add(array, toJsonObject(v));
+        }
+        return array;
+    }
+
     template<typename T, class = typename std::enable_if<isVisitable<T>::value>::type>
     static json_object* toJsonObject(const T& value)
     {
index 949239d..c6f8476 100644 (file)
@@ -97,6 +97,8 @@ struct TestConfig {
     std::vector<std::string> stringVector;
     std::vector<double> doubleVector;
 
+    std::array<int, 2> intArray;
+
     SubConfig subObj;
     std::vector<SubConfig> subVector;
 
@@ -120,6 +122,8 @@ struct TestConfig {
         stringVector,
         doubleVector,
 
+        intArray,
+
         subObj,
         subVector,
 
@@ -159,6 +163,7 @@ const std::string jsonTestString =
     "\"intVector\": [ 1, 2, 3 ], "
     "\"stringVector\": [ \"a\", \"b\" ], "
     "\"doubleVector\": [ 0.000000, 1.000000, 2.000000 ], "
+    "\"intArray\": [ 0, 1 ], "
     "\"subObj\": { \"intVal\": 54321, \"intVector\": [ 1, 2 ], \"subSubObj\": { \"intVal\": 234 } }, "
     "\"subVector\": [ { \"intVal\": 123, \"intVector\": [ 3, 4 ], \"subSubObj\": { \"intVal\": 345 } }, "
         "{ \"intVal\": 456, \"intVector\": [ 5, 6 ], \"subSubObj\": { \"intVal\": 567 } } ], "
@@ -182,6 +187,7 @@ const std::string jsonEmptyTestString =
     "\"intVector\": [ ], "
     "\"stringVector\": [ ], "
     "\"doubleVector\": [ ], "
+    "\"intArray\": [ ], "
     "\"subObj\": { \"intVal\": 0, \"intVector\": [ ], \"subSubObj\": { \"intVal\": 0 } }, "
     "\"subVector\": [ ], "
     "\"union1\": { \"type\": \"int\", \"value\": 0 }, "
index 68311eb..a134b7b 100644 (file)
@@ -71,9 +71,9 @@ BOOST_AUTO_TEST_CASE(FromJsonString)
     BOOST_REQUIRE_EQUAL(0, testConfig.emptyIntVector.size());
 
     BOOST_REQUIRE_EQUAL(3, testConfig.intVector.size());
-    BOOST_CHECK_EQUAL(1, testConfig.intVector[0]);
-    BOOST_CHECK_EQUAL(2, testConfig.intVector[1]);
-    BOOST_CHECK_EQUAL(3, testConfig.intVector[2]);
+    BOOST_CHECK_EQUAL(1,   testConfig.intVector[0]);
+    BOOST_CHECK_EQUAL(2,   testConfig.intVector[1]);
+    BOOST_CHECK_EQUAL(3,   testConfig.intVector[2]);
 
     BOOST_REQUIRE_EQUAL(2, testConfig.stringVector.size());
     BOOST_CHECK_EQUAL("a", testConfig.stringVector[0]);
@@ -84,6 +84,10 @@ BOOST_AUTO_TEST_CASE(FromJsonString)
     BOOST_CHECK_CLOSE(1.0, testConfig.doubleVector[1], TOLERANCE);
     BOOST_CHECK_CLOSE(2.0, testConfig.doubleVector[2], TOLERANCE);
 
+    BOOST_REQUIRE_EQUAL(2, testConfig.intArray.size());
+    BOOST_CHECK_EQUAL(0,   testConfig.intArray[0]);
+    BOOST_CHECK_EQUAL(1,   testConfig.intArray[1]);
+
     BOOST_CHECK_EQUAL(54321, testConfig.subObj.intVal);
     BOOST_CHECK_EQUAL(2,     testConfig.subObj.intVector.size());
     BOOST_CHECK_EQUAL(1,     testConfig.subObj.intVector[0]);