config: Cstring serialization. 58/48758/3
authorJan Olszak <j.olszak@samsung.com>
Mon, 28 Sep 2015 16:19:07 +0000 (18:19 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Wed, 30 Sep 2015 10:42:52 +0000 (03:42 -0700)
[Feature]       Serialization of null-terminated strings
[Cause]         N/A
[Solution]      Memory for serialized data is allocated with new,
                user should delete[] the field in the destructor
                or when it's not used.
[Verification]  Build, install, run tests.

Change-Id: Iff49e14ab95410bd7a80ee23abf04e9d92e65a55

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.cpp
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 3863f7f..a948b3b 100644 (file)
@@ -61,6 +61,16 @@ private:
         mStore.read(&value.front(), size);
     }
 
+    void readInternal(char* &value)
+    {
+        size_t size;
+        readInternal(size);
+
+        value = new char[size + 1];
+        mStore.read(value, size);
+        value[size] = '\0';
+    }
+
     void readInternal(config::FileDescriptor& fd)
     {
         fd = mStore.receiveFD();
index e648625..a4134b6 100644 (file)
@@ -127,6 +127,18 @@ private:
         value = g_variant_get_string(object, NULL);
     }
 
+    static void fromGVariant(GVariant* object, char* &value)
+    {
+        checkType(object, G_VARIANT_TYPE_STRING);
+
+        const char* source = g_variant_get_string(object, NULL);
+        size_t len = std::strlen(source);
+
+        value = new char[len + 1];
+        std::strncpy(value, source, len);
+        value[len] = '\0';
+    }
+
     static void fromGVariant(GVariant* object, config::FileDescriptor& value)
     {
         checkType(object, G_VARIANT_TYPE_INT32);
index 74d309b..bc7864a 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <json.h>
 #include <string>
+#include <cstring>
 #include <vector>
 
 namespace config {
@@ -137,6 +138,16 @@ private:
         value = json_object_get_string(object);
     }
 
+    static void fromJsonObject(json_object* object, char* &value)
+    {
+        checkType(object, json_type_string);
+
+        int len = json_object_get_string_len(object);
+        value = new char[len + 1];
+        std::strncpy(value, json_object_get_string(object), len);
+        value[len] = '\0';
+    }
+
     template<typename T>
     static void fromJsonObject(json_object* object, std::vector<T>& value)
     {
index eea975c..cc6e14a 100644 (file)
@@ -273,6 +273,16 @@ private:
         checkType(object, json_type_string);
         value = json_object_get_string(object);
     }
+
+    static void fromJsonObject(json_object* object, char* &value)
+    {
+        checkType(object, json_type_string);
+
+        int len = json_object_get_string_len(object);
+        value = new char[len + 1];
+        std::strncpy(value, json_object_get_string(object), len);
+        value[len] = '\0';
+    }
 };
 
 } // namespace config
index b6d922e..25febf6 100644 (file)
@@ -32,6 +32,7 @@
 #include <memory>
 #include <set>
 #include <cassert>
+#include <cstring>
 
 namespace config {
 
@@ -231,13 +232,13 @@ void KVStore::remove(const std::string& key)
     transaction.commit();
 }
 
-void KVStore::setInternal(const std::string& key, const std::string& value)
+void KVStore::setInternal(const std::string& key, const char* value)
 {
     Transaction transaction(*this);
     ScopedReset scopedReset(mSetValueStmt);
 
     ::sqlite3_bind_text(mSetValueStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, SQLITE_STATIC);
-    ::sqlite3_bind_text(mSetValueStmt->get(), 2, value.c_str(), AUTO_DETERM_SIZE, SQLITE_STATIC);
+    ::sqlite3_bind_text(mSetValueStmt->get(), 2, value, AUTO_DETERM_SIZE, SQLITE_STATIC);
 
 
     if (::sqlite3_step(mSetValueStmt->get()) != SQLITE_DONE) {
@@ -246,6 +247,11 @@ void KVStore::setInternal(const std::string& key, const std::string& value)
     transaction.commit();
 }
 
+void KVStore::setInternal(const std::string& key, const std::string& value)
+{
+    setInternal(key, value.c_str());
+}
+
 void KVStore::setInternal(const std::string& key, const std::initializer_list<std::string>& values)
 {
     setInternal(key, std::vector<std::string>(values));
@@ -294,6 +300,33 @@ std::string KVStore::getInternal(const std::string& key, std::string*)
     return value;
 }
 
+char* KVStore::getInternal(const std::string& key, char**)
+{
+    Transaction transaction(*this);
+    ScopedReset scopedReset(mGetValueStmt);
+
+    ::sqlite3_bind_text(mGetValueStmt->get(), 1, key.c_str(), AUTO_DETERM_SIZE, SQLITE_TRANSIENT);
+
+    int ret = ::sqlite3_step(mGetValueStmt->get());
+    if (ret == SQLITE_DONE) {
+        throw ConfigException("No value corresponding to the key: " + key + "@" + mPath);
+    }
+    if (ret != SQLITE_ROW) {
+        throw ConfigException("Error during stepping: " + mConn.getErrorMessage());
+    }
+
+    const char* source = reinterpret_cast<const char*>(sqlite3_column_text(mGetValueStmt->get(), FIRST_COLUMN));
+
+    size_t length = std::strlen(source);
+    char* value = new char[length + 1];
+
+    std::strncpy(value, source, length);
+    value[length] = '\0';
+
+    transaction.commit();
+    return value;
+}
+
 std::vector<std::string> KVStore::getInternal(const std::string& key, std::vector<std::string>*)
 {
     Transaction transaction(*this);
index eaf568b..583d534 100644 (file)
@@ -134,6 +134,7 @@ private:
     bool mIsTransactionCommited;
 
     void setInternal(const std::string& key, const std::string& value);
+    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>
@@ -142,6 +143,7 @@ private:
     void setInternal(const std::string& key, const std::vector<T>& values);
 
     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>
     T getInternal(const std::string& key, T*);
index 1eedddb..7da3d76 100644 (file)
@@ -30,6 +30,7 @@
 #include "config/types.hpp"
 
 #include <string>
+#include <cstring>
 
 namespace config {
 
@@ -60,6 +61,13 @@ private:
         mStore.write(value.c_str(), value.size());
     }
 
+    void writeInternal(const char* &value)
+    {
+        size_t size = std::strlen(value);
+        writeInternal(size);
+        mStore.write(value, size);
+    }
+
     void writeInternal(const config::FileDescriptor& fd)
     {
         mStore.sendFD(fd.value);
index 047aa17..40c002d 100644 (file)
@@ -83,6 +83,7 @@ private:
     void writeInternal(bool value) { add("b", value); };
     void writeInternal(double value) { add("d", value); };
     void writeInternal(const std::string& value) { add("s", value.c_str()); };
+    void writeInternal(const char* value) { add("s", value); };
     void writeInternal(const config::FileDescriptor& value) { add("h", value.value); };
 
     template<typename T>
index 4ab4a4b..717b952 100644 (file)
@@ -120,6 +120,11 @@ private:
         return json_object_new_string(value.c_str());
     }
 
+    static json_object* toJsonObject(char* value)
+    {
+        return json_object_new_string(value);
+    }
+
     template<typename T>
     static json_object* toJsonObject(const std::vector<T>& value)
     {
index 549985b..949239d 100644 (file)
@@ -88,6 +88,7 @@ struct TestConfig {
     std::uint32_t uint32Val;
     std::uint64_t uint64Val;
     std::string stringVal;
+    char* cstringVal;
     double doubleVal;
     bool boolVal;
 
@@ -110,6 +111,7 @@ struct TestConfig {
         uint32Val,
         uint64Val,
         stringVal,
+        cstringVal,
         doubleVal,
         boolVal,
 
@@ -150,6 +152,7 @@ const std::string jsonTestString =
     "\"uint32Val\": 123456, "
     "\"uint64Val\": 1234567890123456789, "
     "\"stringVal\": \"blah\", "
+    "\"cstringVal\": \"blah\", "
     "\"doubleVal\": -1.234000, "
     "\"boolVal\": true, "
     "\"emptyIntVector\": [ ], "
@@ -173,6 +176,7 @@ const std::string jsonEmptyTestString =
     "\"uint32Val\": 0, "
     "\"uint64Val\": 0, "
     "\"stringVal\": \"\", "
+    "\"cstringVal\": \"\", "
     "\"boolVal\": false, "
     "\"emptyIntVector\": [ ], "
     "\"intVector\": [ ], "
index 88b6a4e..68311eb 100644 (file)
@@ -64,6 +64,7 @@ BOOST_AUTO_TEST_CASE(FromJsonString)
     BOOST_CHECK_EQUAL(123456, testConfig.uint32Val);
     BOOST_CHECK_EQUAL(1234567890123456789ll, testConfig.uint64Val);
     BOOST_CHECK_EQUAL("blah", testConfig.stringVal);
+    BOOST_CHECK_EQUAL("blah", testConfig.cstringVal);
     BOOST_CHECK_CLOSE(-1.234, testConfig.doubleVal, TOLERANCE);
     BOOST_CHECK_EQUAL(true, testConfig.boolVal);