Writing the size of a vector in the KVStore
[archive/platform/core/system/libConfig.git] / src / config / kvstore.hpp
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Jan Olszak <j.olszak@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18
19 /**
20  * @file
21  * @author Jan Olszak (j.olszak@samsung.com)
22  * @brief  Declaration of a class for key-value storage in a sqlite3 database
23  */
24
25 #ifndef COMMON_CONFIG_KVSTORE_HPP
26 #define COMMON_CONFIG_KVSTORE_HPP
27
28 #include "config/sqlite3/connection.hpp"
29 #include "config/sqlite3/statement.hpp"
30
31 #include <algorithm>
32 #include <initializer_list>
33 #include <memory>
34 #include <mutex>
35 #include <sstream>
36 #include <string>
37 #include <vector>
38
39 namespace config {
40
41 class KVStore {
42
43 public:
44
45     /**
46      * @param path configuration database file path
47      */
48     KVStore(const std::string& path);
49     KVStore(const KVStore& store);
50     ~KVStore();
51
52     /**
53      * Clears all the stored data
54      */
55     void clear();
56
57     /**
58      * @return Is there any data stored
59      */
60     bool isEmpty();
61
62     /**
63      * @param key string regexp of the stored values
64      *
65      * @return Does this key exist in the database
66      */
67     bool exists(const std::string& key);
68
69     /**
70      * Removes values corresponding to the passed key.
71      * Many values may correspond to one key, so many values may
72      * need to be deleted
73      *
74      * @param key string regexp of the stored values
75      */
76     void remove(const std::string& key);
77
78     /**
79      * Stores a single value corresponding to the passed key
80      *
81      * @param key string key of the value
82      * @param value value corresponding to the key
83      */
84     template<typename T>
85     void set(const std::string& key, const T& value)
86     {
87         return setInternal(key, value);
88     }
89
90     /**
91      * Gets the value corresponding to the key.
92      * Uses stringstreams to parse.
93      *
94      * @param key string key of the value
95      * @tparam T = std::string desired type of the return value
96      * @return value corresponding to the key
97      */
98     template<typename T = std::string>
99     T get(const std::string& key)
100     {
101         return getInternal(key, static_cast<T*>(nullptr));
102     }
103
104
105 private:
106     struct Transaction;
107     typedef std::lock_guard<std::recursive_mutex> Lock;
108     unsigned int mTransactionCounter;
109
110     void setInternal(const std::string& key, const std::string& value);
111     void setInternal(const std::string& key, const std::initializer_list<std::string>& values);
112     void setInternal(const std::string& key, const std::vector<std::string>& values);
113     template<typename T>
114     void setInternal(const std::string& key, const T& value);
115     template<typename T>
116     void setInternal(const std::string& key, const std::vector<T>& values);
117
118     std::string getInternal(const std::string& key, std::string*);
119     std::vector<std::string> getInternal(const std::string& key, std::vector<std::string>*);
120     template<typename T>
121     T getInternal(const std::string& key, T*);
122     template<typename T>
123     std::vector<T> getInternal(const std::string& key, std::vector<T>*);
124
125     std::recursive_mutex mConnMtx;
126
127     std::string mPath;
128     sqlite3::Connection mConn;
129     std::unique_ptr<sqlite3::Statement> mGetValueStmt;
130     std::unique_ptr<sqlite3::Statement> mGetKeyExistsStmt;
131     std::unique_ptr<sqlite3::Statement> mGetIsEmptyStmt;
132     std::unique_ptr<sqlite3::Statement> mGetValueListStmt;
133     std::unique_ptr<sqlite3::Statement> mSetValueStmt;
134     std::unique_ptr<sqlite3::Statement> mRemoveValuesStmt;
135
136     void setupDb();
137     void prepareStatements();
138     void createFunctions();
139
140     void removeInternal(const std::string& key);
141
142 };
143
144 namespace {
145 template<typename T>
146 std::string toString(const T& value)
147 {
148     std::ostringstream oss;
149     oss << value;
150     return oss.str();
151 }
152
153 template<typename T>
154 T fromString(const std::string& strValue)
155 {
156     std::istringstream iss(strValue);
157     T value;
158     iss >> value;
159     return value;
160 }
161
162 } // namespace
163
164 template<typename T>
165 void KVStore::setInternal(const std::string& key, const T& value)
166 {
167     setInternal(key, toString(value));
168 }
169
170 template<typename T>
171 void KVStore::setInternal(const std::string& key, const std::vector<T>& values)
172 {
173     std::vector<std::string> strValues(values.size());
174
175     std::transform(values.begin(),
176                    values.end(),
177                    strValues.begin(),
178                    toString<T>);
179
180     setInternal(key, strValues);
181 }
182
183 template<typename T>
184 T KVStore::getInternal(const std::string& key, T*)
185 {
186     return fromString<T>(getInternal(key, static_cast<std::string*>(nullptr)));
187 }
188
189 template<typename T>
190 std::vector<T> KVStore::getInternal(const std::string& key, std::vector<T>*)
191 {
192     std::vector<std::string> strValues = getInternal(key, static_cast<std::vector<std::string>*>(nullptr));
193     std::vector<T> values(strValues.size());
194
195     std::transform(strValues.begin(),
196                    strValues.end(),
197                    values.begin(),
198                    fromString<T>);
199
200     return values;
201 }
202
203 /**
204  * Concatenates all parameters into one std::string.
205  * Uses '.' to connect the terms.
206  * @param args components of the string
207  * @tparam delim optional delimiter
208  * @tparam typename ... Args any type implementing str
209  * @return string created from he args
210  */
211 template<char delim = '.', typename Arg1, typename ... Args>
212 std::string key(const Arg1& a1, const Args& ... args)
213 {
214     std::string ret = toString(a1);
215     std::initializer_list<std::string> strings {toString(args)...};
216     for (const std::string& s : strings) {
217         ret += delim + s;
218     }
219
220     return ret;
221 }
222
223 /**
224  * Function added for key function completeness.
225  *
226  * @tparam delim = '.' parameter not used, added for consistency
227  * @return empty string
228  */
229 template<char delim = '.'>
230 std::string key()
231 {
232     return std::string();
233 }
234
235 } // namespace config
236
237 #endif // COMMON_CONFIG_KVSTORE_HPP
238
239