#include "config/is-visitable.hpp"
#include "config/fdstore.hpp"
#include "config/types.hpp"
+#include "config/visit-fields.hpp"
#include <array>
#include <string>
+#include <utility>
#include <vector>
namespace config {
readInternal(value);
}
}
+
+ template<typename ... T>
+ void readInternal(std::pair<T...>& values)
+ {
+ visitFields(values, this, std::string());
+ }
};
} // namespace config
#include "config/exception.hpp"
#include "config/is-union.hpp"
#include "config/types.hpp"
+#include "config/visit-fields.hpp"
#include <string>
#include <vector>
#include <array>
+#include <utility>
#include <memory>
#include <cassert>
+
#include <glib.h>
namespace config {
}
}
+ struct HelperVisitor
+ {
+ template<typename T>
+ static void visit(GVariantIter* iter, T&& value)
+ {
+ auto child = makeUnique(g_variant_iter_next_value(iter));
+ fromGVariant(child.get(), value);
+ }
+ };
+
+ template<typename ... T>
+ static void fromGVariant(GVariant* object, std::pair<T...>& values)
+ {
+ checkType(object, G_VARIANT_TYPE_ARRAY);
+
+ GVariantIter iter;
+ g_variant_iter_init(&iter, object);
+
+ HelperVisitor visitor;
+ visitFields(values, &visitor, &iter);
+ }
+
template<typename T>
static typename std::enable_if<isUnion<T>::value>::type
fromGVariant(GVariant* object, T& value)
#include "config/is-visitable.hpp"
#include "config/exception.hpp"
+#include "config/visit-fields.hpp"
#include <json.h>
#include <string>
#include <cstring>
#include <vector>
#include <array>
+#include <utility>
namespace config {
}
}
+ struct HelperVisitor
+ {
+ template<typename T>
+ static void visit(json_object* object, std::size_t& idx, T&& value)
+ {
+ fromJsonObject(json_object_array_get_idx(object, idx), value);
+ idx += 1;
+ }
+ };
+
+ template<typename ... T>
+ static void fromJsonObject(json_object* object, std::pair<T...>& values)
+ {
+ checkType(object, json_type_array);
+
+ std::size_t idx = 0;
+ HelperVisitor visitor;
+ visitFields(values, &visitor, object, idx);
+ }
+
template<typename T, class = typename std::enable_if<isVisitable<T>::value>::type>
static void fromJsonObject(json_object* object, T& value)
{
#include "config/from-kvstore-visitor.hpp"
#include "config/is-union.hpp"
+#include "config/visit-fields.hpp"
+#include <utility>
#include <json.h>
namespace config {
getValue(name, value);
}
+ template<typename T>
+ void visit(std::size_t& idx, T& value) {
+ getValue(idx, value);
+ idx += 1;
+ }
+
private:
KVStore& mStore;
std::string mKeyPrefix;
std::string k = key(mKeyPrefix, name);
if (mStore.exists(k)) {
t = mStore.get<T>(k);
- }
- else {
+ } else {
json_object* object = nullptr;
if (mObject) {
json_object_object_get_ex(mObject, name.c_str(), &object);
}
if (!object) {
- throw ConfigException("Missing json field " + key(mKeyPrefix, name));
+ throw ConfigException("Missing json field " + k);
}
fromJsonObject(object, t);
}
}
}
+ template<typename ... T>
+ void getValue(const std::string& name, std::pair<T...>& 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;
+ }
+
+ std::size_t idx = 0;
+ visitFields(values, &visitor, idx);
+ }
+
template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
void getValue(int i, T& t)
{
#include "config/sqlite3/connection.hpp"
#include "config/sqlite3/statement.hpp"
+#include "config/visit-fields.hpp"
#include <algorithm>
#include <initializer_list>
#include <string>
#include <vector>
#include <atomic>
+#include <utility>
namespace config {
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);
+ template<typename ... T>
+ void setInternal(const std::string& key, const std::pair<T...>& values);
std::string getInternal(const std::string& key, std::string*);
char* getInternal(const std::string& key, char**);
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>*);
+ template<typename ... T>
+ std::pair<T...> getInternal(const std::string& key, std::pair<T...>*);
std::string mPath;
sqlite3::Connection mConn;
setInternal(key, strValues);
}
+struct SetTupleVisitor
+{
+ template<typename T>
+ static void visit(std::vector<std::string>::iterator& it, const T& value)
+ {
+ *it = toString<T>(value);
+ ++it;
+ }
+};
+
+template<typename ... T>
+void KVStore::setInternal(const std::string& key, const std::pair<T...>& values)
+{
+ std::vector<std::string> strValues(std::tuple_size<std::pair<T...>>::value);
+
+ SetTupleVisitor visitor;
+ visitFields(values, &visitor, strValues.begin());
+ setInternal(key, strValues);
+}
+
template<typename T>
T KVStore::getInternal(const std::string& key, T*)
{
return values;
}
+struct GetTupleVisitor
+{
+ template<typename T>
+ static void visit(std::vector<std::string>::iterator& it, T& value)
+ {
+ value = fromString<T>(*it);
+ ++it;
+ }
+};
+
+template<typename ... T>
+std::pair<T...> KVStore::getInternal(const std::string& key, std::pair<T...>*)
+{
+ std::vector<std::string> strValues = getInternal(key, static_cast<std::vector<std::string>*>(nullptr));
+ std::pair<T...> values;
+
+ GetTupleVisitor visitor;
+ visitFields(values, &visitor, strValues.begin());
+
+ return values;
+}
+
/**
* Concatenates all parameters into one std::string.
* Uses '.' to connect the terms.
#include "config/is-visitable.hpp"
#include "config/fdstore.hpp"
#include "config/types.hpp"
+#include "config/visit-fields.hpp"
#include <array>
#include <cstring>
#include <string>
#include <vector>
+#include <utility>
+
namespace config {
}
}
+ template<typename ... T>
+ void writeInternal(const std::pair<T...>& values)
+ {
+ visitFields(values, this, std::string());
+ }
+
};
} // namespace config
#include "config/is-visitable.hpp"
#include "config/is-union.hpp"
#include "config/types.hpp"
+#include "config/visit-fields.hpp"
#include <array>
#include <string>
#include <vector>
#include <glib.h>
+#include <utility>
namespace config {
private:
GVariantBuilder* mBuilder;
- void writeInternal(std::int32_t value) { add("i", value); };
- void writeInternal(std::int64_t value) { add("x", value); };
- void writeInternal(std::uint32_t value) { add("u", value); };
- void writeInternal(std::uint64_t value) { add("t", value); };
- 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); };
+ void writeInternal(std::int32_t value) {
+ add("i", value);
+ };
+ void writeInternal(std::int64_t value) {
+ add("x", value);
+ };
+ void writeInternal(std::uint32_t value) {
+ add("u", value);
+ };
+ void writeInternal(std::uint64_t value) {
+ add("t", value);
+ };
+ 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>
void writeInternal(const std::vector<T>& value)
}
}
+ template<typename ... T>
+ void writeInternal(const std::pair<T...>& values)
+ {
+ g_variant_builder_open(mBuilder, G_VARIANT_TYPE_ARRAY);
+ visitFields(values, this, std::string());
+ g_variant_builder_close(mBuilder);
+ }
+
template<typename T>
typename std::enable_if<isVisitable<T>::value && !isUnion<T>::value>::type
writeInternal(const T& value)
#include "config/is-visitable.hpp"
#include "config/exception.hpp"
+#include "config/visit-fields.hpp"
-#include <json.h>
+#include <array>
#include <string>
#include <vector>
+#include <utility>
+
+#include <json.h>
namespace config {
return array;
}
+ struct HelperVisitor
+ {
+ template<typename T>
+ static void visit(json_object* array, const T& value)
+ {
+ json_object_array_add(array, toJsonObject(value));
+ }
+ };
+
+ template<typename ... T>
+ static json_object* toJsonObject(const std::pair<T...>& values)
+ {
+ json_object* array = json_object_new_array();
+
+ HelperVisitor visitor;
+ visitFields(values, &visitor, array);
+ return array;
+ }
+
template<typename T, class = typename std::enable_if<isVisitable<T>::value>::type>
static json_object* toJsonObject(const T& value)
{
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Jan Olszak (j.olszak@samsung.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+/**
+ * @file
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Helper function for iterating tuples, pairs and arrays
+ */
+
+
+#ifndef CONFIG_VISIT_FIELDS_HPP
+#define CONFIG_VISIT_FIELDS_HPP
+
+#include <string>
+#include <tuple>
+
+namespace {
+
+template<int I, class T, class F, typename ... A>
+struct visitImpl
+{
+ static void visit(T& t, F f, A&& ... args)
+ {
+ visitImpl<I - 1, T, F, A...>::visit(t, f, std::forward<A>(args)...);
+ f->visit(args..., std::get<I>(t));
+ }
+};
+
+template<class T, class F, typename ... A>
+struct visitImpl<0, T, F, A...>
+{
+ static void visit(T& t, F f, A&& ... args)
+ {
+ f->visit(args..., std::get<0>(t));
+ }
+};
+
+} // namespace
+
+namespace config {
+
+template<class T, class F, typename ... A>
+void visitFields(T& t, F f, A ... args)
+{
+ visitImpl<std::tuple_size<T>::value - 1, T, F, A...>::visit(t, f, std::forward<A>(args)...);
+}
+
+} // namespace config
+
+#endif // CONFIG_VISIT_FIELDS_HPP
std::array<int, 2> intArray;
+ std::pair<int, int> intIntPair;
+
SubConfig subObj;
std::vector<SubConfig> subVector;
intArray,
+ intIntPair,
+
subObj,
subVector,
"\"stringVector\": [ \"a\", \"b\" ], "
"\"doubleVector\": [ 0.000000, 1.000000, 2.000000 ], "
"\"intArray\": [ 0, 1 ], "
+ "\"intIntPair\": [ 8, 9 ], "
"\"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 } } ], "
+ "{ \"intVal\": 456, \"intVector\": [ 5, 6 ], \"subSubObj\": { \"intVal\": 567 } } ], "
"\"union1\": { \"type\": \"int\", \"value\": 2 }, "
"\"union2\": { \"type\": \"SubConfig\", \"value\": { \"intVal\": 54321, \"intVector\": [ 1 ], "
- "\"subSubObj\": { \"intVal\": 234 } } }, "
+ "\"subSubObj\": { \"intVal\": 234 } } }, "
"\"unions\": [ "
- "{ \"type\": \"int\", \"value\": 2 }, "
- "{ \"type\": \"SubConfig\", \"value\": { \"intVal\": 54321, \"intVector\": [ 1 ], "
- "\"subSubObj\": { \"intVal\": 234 } } } ] }";
+ "{ \"type\": \"int\", \"value\": 2 }, "
+ "{ \"type\": \"SubConfig\", \"value\": { \"intVal\": 54321, \"intVector\": [ 1 ], "
+ "\"subSubObj\": { \"intVal\": 234 } } } ] }";
const std::string jsonEmptyTestString =
"{ \"intVal\": 0, "
"\"stringVector\": [ ], "
"\"doubleVector\": [ ], "
"\"intArray\": [ ], "
+ "\"intIntPair\": [ ], "
"\"subObj\": { \"intVal\": 0, \"intVector\": [ ], \"subSubObj\": { \"intVal\": 0 } }, "
"\"subVector\": [ ], "
"\"union1\": { \"type\": \"int\", \"value\": 0 }, "
BOOST_CHECK_EQUAL(0, testConfig.intArray[0]);
BOOST_CHECK_EQUAL(1, testConfig.intArray[1]);
+ BOOST_CHECK_EQUAL(8, testConfig.intIntPair.first);
+ BOOST_CHECK_EQUAL(9, testConfig.intIntPair.second);
+
BOOST_CHECK_EQUAL(54321, testConfig.subObj.intVal);
BOOST_CHECK_EQUAL(2, testConfig.subObj.intVector.size());
BOOST_CHECK_EQUAL(1, testConfig.subObj.intVector[0]);