--- /dev/null
+#ifndef CONFIG_FROM_KVJSON_VISITOR_HPP
+#define CONFIG_FROM_KVJSON_VISITOR_HPP
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Krzysztof Dynowski (k.dynowski@samsumg.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 Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief KVStore visitor with defaults values from json
+ */
+
+#include "config/manager.hpp"
+
+
+namespace config {
+
+class FromKVJsonVisitor {
+public:
+ FromKVJsonVisitor(const std::string& db, const std::string& json) :
+ mStorePtr(new KVStore(db))
+ {
+ mObject = json_tokener_parse(json.c_str());
+ if (mObject == nullptr) {
+ throw ConfigException("Json parsing error");
+ }
+ }
+
+ ~FromKVJsonVisitor() {
+ json_object_put(mObject);
+ }
+
+ FromKVJsonVisitor(const FromKVJsonVisitor& v) :
+ mObject(json_object_get(v.mObject)),
+ mStorePtr(v.mStorePtr),
+ mKeyPrefix(v.mKeyPrefix)
+ {
+ }
+ FromKVJsonVisitor& operator=(const FromKVJsonVisitor&) = delete;
+
+ template<typename T>
+ void visit(const std::string& name, T& value) {
+ getValue(name, value);
+ }
+
+private:
+ std::shared_ptr<KVStore> mStorePtr;
+ std::string mKeyPrefix;
+ json_object* mObject;
+
+ // create visitor for field object (visitable object)
+ FromKVJsonVisitor(const FromKVJsonVisitor& v, const std::string& name) :
+ mStorePtr(v.mStorePtr)
+ {
+ json_object* object;
+ if (!json_object_object_get_ex(v.mObject, name.c_str(), &object)) {
+ throw ConfigException("Missing json field " + key(mKeyPrefix, name));
+ }
+ mObject = json_object_get(object);
+ mKeyPrefix = key(v.mKeyPrefix, name);
+ }
+
+ // create visitor for vector i-th element (visitable object)
+ FromKVJsonVisitor(const FromKVJsonVisitor& v, int i) :
+ mStorePtr(v.mStorePtr)
+ {
+ json_object* object = json_object_array_get_idx(v.mObject, i);
+ checkType(object, json_type_object);
+ mObject = json_object_get(object);
+ mKeyPrefix = key(v.mKeyPrefix, std::to_string(i));
+ }
+
+ template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
+ void getValue(const std::string& name, T& t)
+ {
+ json_object* object;
+ if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
+ throw ConfigException("Missing json field " + key(mKeyPrefix, name));
+ }
+ std::string k = key(mKeyPrefix, name);
+ if (mStorePtr->exists(k)) {
+ t = mStorePtr->get<T>(k);
+ }
+ else {
+ fromJsonObject(object, t);
+ }
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
+ void getValue(const std::string& name, T& t)
+ {
+ FromKVJsonVisitor visitor(*this, name);
+ t.accept(visitor);
+ }
+
+ int getArraySize(std::string& name, json_object* object)
+ {
+ int length = -1, jlength = json_object_array_length(object);
+ if (mStorePtr->exists(name)) {
+ length = mStorePtr->get<int>(name);
+ }
+ return length != jlength ? jlength : length;
+ }
+
+ template<typename T>
+ void getValue(const std::string& name, std::vector<T>& value)
+ {
+ json_object* object;
+ if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
+ throw ConfigException("Missing json field " + key(mKeyPrefix, name));
+ }
+ checkType(object, json_type_array);
+
+ std::string k = key(mKeyPrefix, name);
+ int length = getArraySize(k, object);
+ value.resize(static_cast<size_t>(length));
+ FromKVJsonVisitor visitor(*this, name);
+ for (int i = 0; i < length; ++i) {
+ visitor.getValue(i, value[i]);
+ }
+ }
+
+ template<typename T, typename std::enable_if<!isVisitable<T>::value, int>::type = 0>
+ void getValue(int i, T& t)
+ {
+ json_object* object = json_object_array_get_idx(mObject, i);
+ std::string k = key(mKeyPrefix, std::to_string(i));
+ if (mStorePtr->exists(k)) {
+ t = mStorePtr->get<T>(k);
+ }
+ else {
+ fromJsonObject(object, t);
+ }
+ }
+
+ template<typename T, typename std::enable_if<isVisitable<T>::value, int>::type = 0>
+ void getValue(int i, T& t)
+ {
+ FromKVJsonVisitor visitor(*this, i);
+ t.accept(visitor);
+ }
+
+ template<typename T>
+ void getValue(int i, std::vector<T>& value)
+ {
+ std::string k = key(mKeyPrefix, std::to_string(i));
+ int length = getArraySize(k, mObject);
+ value.resize(static_cast<size_t>(length));
+ FromKVJsonVisitor visitor(*this, i);
+ for (int i = 0; i < length; ++i) {
+ visitor.getValue(i, value[i]);
+ }
+ }
+
+ static void checkType(json_object* object, json_type type)
+ {
+ if (type != json_object_get_type(object)) {
+ throw ConfigException("Invalid field type " + std::to_string(type));
+ }
+ }
+
+ static void fromJsonObject(json_object* object, int& value)
+ {
+ checkType(object, json_type_int);
+ std::int64_t value64 = json_object_get_int64(object);
+ if (value64 > INT32_MAX || value64 < INT32_MIN) {
+ throw ConfigException("Value out of range");
+ }
+ value = static_cast<int>(value64);
+ }
+
+ static void fromJsonObject(json_object* object, std::int64_t& value)
+ {
+ checkType(object, json_type_int);
+ value = json_object_get_int64(object);
+ }
+
+ static void fromJsonObject(json_object* object, bool& value)
+ {
+ checkType(object, json_type_boolean);
+ value = json_object_get_boolean(object);
+ }
+
+ static void fromJsonObject(json_object* object, double& value)
+ {
+ checkType(object, json_type_double);
+ value = json_object_get_double(object);
+ }
+
+ static void fromJsonObject(json_object* object, std::string& value)
+ {
+ checkType(object, json_type_string);
+ value = json_object_get_string(object);
+ }
+};
+
+} // namespace config
+
+#endif // CONFIG_FROM_KVJSON_VISITOR_HPP
#include "config/from-json-visitor.hpp"
#include "config/from-kvstore-visitor.hpp"
#include "config/from-fdstore-visitor.hpp"
+#include "config/from-kvjson-visitor.hpp"
#include "config/is-visitable.hpp"
#include "config/fs-utils.hpp"
}
/**
+ * Load the config from KVStore with defaults given in json
+ *
+ * @param kvfile path to the KVStore db
+ * @param jsonfile path to json file with defaults
+ * @param config visitable structure to save
+ */
+template <class Config>
+void loadFromKVStoreWithJson(const std::string& kvfile, const std::string& json, Config& config)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+ FromKVJsonVisitor visitor(kvfile, json);
+ config.accept(visitor);
+}
+/**
+ * Load the config from KVStore with defaults given in json file
+ *
+ * @param kvfile path to the KVStore db
+ * @param jsonfile path to json file with defaults
+ * @param config visitable structure to save
+ */
+template <class Config>
+void loadFromKVStoreWithJsonFile(const std::string& kvfile, const std::string& jsonfile, Config& config)
+{
+ static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+ std::string content;
+ if (!fsutils::readFileContent(jsonfile, content)) {
+ throw ConfigException("Could not load " + jsonfile);
+ }
+ try {
+ loadFromKVStoreWithJson(kvfile, content, config);
+ } catch (ConfigException& e) {
+ throw ConfigException("Error in " + jsonfile + ": " + e.what());
+ }
+}
+
+/**
* Load binary data from a file/socket/pipe represented by the fd
*
* @param fd file descriptor