From 6d63eb3b5fa8ce01447fbb2ddc2ba2a50113ae0e Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Tue, 13 Jan 2015 13:45:30 +0100 Subject: [PATCH] implement generic method checker and is-union [Bug/Feature] N/A [Cause] N/A [Solution] N/A [Verification] Build, install Change-Id: Iaf8eb549729e095ed1d446bc6fd2cd71399e1019 --- src/config/from-kvjson-visitor.hpp | 102 ++++++++++++++++++++++++------------- src/config/is-union.hpp | 70 +++++++++++++++++++++++++ src/config/manager.hpp | 1 - 3 files changed, 138 insertions(+), 35 deletions(-) create mode 100644 src/config/is-union.hpp diff --git a/src/config/from-kvjson-visitor.hpp b/src/config/from-kvjson-visitor.hpp index d2c1060..e01774e 100644 --- a/src/config/from-kvjson-visitor.hpp +++ b/src/config/from-kvjson-visitor.hpp @@ -1,6 +1,3 @@ -#ifndef CONFIG_FROM_KVJSON_VISITOR_HPP -#define CONFIG_FROM_KVJSON_VISITOR_HPP - /* * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved * @@ -26,8 +23,12 @@ * @brief KVStore visitor with defaults values from json */ -#include "config/manager.hpp" +#ifndef CONFIG_FROM_KVJSON_VISITOR_HPP +#define CONFIG_FROM_KVJSON_VISITOR_HPP +#include "config/from-kvstore-visitor.hpp" +#include "config/is-union.hpp" +#include namespace config { @@ -36,6 +37,7 @@ public: FromKVJsonVisitor(const std::string& db, const std::string& json, const std::string& prefix) : mStorePtr(new KVStore(db)) , mKeyPrefix(prefix) + , mIsUnion(false) { mObject = json_tokener_parse(json.c_str()); if (mObject == nullptr) { @@ -43,14 +45,16 @@ public: } } + ~FromKVJsonVisitor() { json_object_put(mObject); } FromKVJsonVisitor(const FromKVJsonVisitor& v) : - mObject(json_object_get(v.mObject)), + mObject(v.mObject ? json_object_get(v.mObject) : nullptr), mStorePtr(v.mStorePtr), - mKeyPrefix(v.mKeyPrefix) + mKeyPrefix(v.mKeyPrefix), + mIsUnion(v.mIsUnion) { } FromKVJsonVisitor& operator=(const FromKVJsonVisitor&) = delete; @@ -64,49 +68,64 @@ private: std::shared_ptr mStorePtr; std::string mKeyPrefix; json_object* mObject; + bool mIsUnion; // create visitor for field object (visitable object) - FromKVJsonVisitor(const FromKVJsonVisitor& v, const std::string& name) : - mStorePtr(v.mStorePtr) + FromKVJsonVisitor(const FromKVJsonVisitor& v, const std::string& name, const bool isUnion) : + mStorePtr(v.mStorePtr), mIsUnion(isUnion || v.mIsUnion) { - 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); + json_object* object = nullptr; + if (v.mObject && !json_object_object_get_ex(v.mObject, name.c_str(), &object)) { + if (!mIsUnion) + throw ConfigException("Missing json field " + mKeyPrefix); + } + mObject = object ? json_object_get(object) : nullptr; } // create visitor for vector i-th element (visitable object) - FromKVJsonVisitor(const FromKVJsonVisitor& v, int i) : - mStorePtr(v.mStorePtr) + FromKVJsonVisitor(const FromKVJsonVisitor& v, int i, const bool isUnion) : + mStorePtr(v.mStorePtr), mIsUnion(isUnion || v.mIsUnion) { - 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)); + json_object* object = nullptr; + if (v.mObject) { + object = json_object_array_get_idx(v.mObject, i); + checkType(object, json_type_object); + } + mObject = object ? json_object_get(object) : nullptr; } template::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(k); } 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)); + } fromJsonObject(object, t); } } - template::value, int>::type = 0> + template::value, int>::type = 0> + void getValue(const std::string& name, T& t) + { + FromKVJsonVisitor visitor(*this, name, true); + t.accept(visitor); + } + + template::value && !isUnion::value, int>::type = 0> void getValue(const std::string& name, T& t) { - FromKVJsonVisitor visitor(*this, name); + FromKVJsonVisitor visitor(*this, name, false); t.accept(visitor); } @@ -115,22 +134,27 @@ private: if (mStorePtr->exists(name)) { return mStorePtr->get(name); } - return json_object_array_length(object); + if (object) { + return json_object_array_length(object); + } + return -1; } template void getValue(const std::string& name, std::vector& value) { - json_object* object; - if (!json_object_object_get_ex(mObject, name.c_str(), &object)) { - throw ConfigException("Missing json field " + key(mKeyPrefix, name)); + json_object* object = nullptr; + if (mObject && json_object_object_get_ex(mObject, name.c_str(), &object)) { + checkType(object, json_type_array); } - checkType(object, json_type_array); std::string k = key(mKeyPrefix, name); int length = getArraySize(k, object); + if (length < 0) { + throw ConfigException("Missing json field " + key(mKeyPrefix, name)); + } value.resize(static_cast(length)); - FromKVJsonVisitor visitor(*this, name); + FromKVJsonVisitor visitor(*this, name, false); for (int i = 0; i < length; ++i) { visitor.getValue(i, value[i]); } @@ -139,20 +163,30 @@ private: template::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(k); } else { + json_object* object = mObject ? json_object_array_get_idx(mObject, i) : nullptr; + if (!object) { + throw ConfigException("Missing json array elem " + k); + } fromJsonObject(object, t); } } - template::value, int>::type = 0> + template::value, int>::type = 0> + void getValue(int i, T& t) + { + FromKVJsonVisitor visitor(*this, i, true); + t.accept(visitor); + } + + template::value && !isUnion::value, int>::type = 0> void getValue(int i, T& t) { - FromKVJsonVisitor visitor(*this, i); + FromKVJsonVisitor visitor(*this, i, false); t.accept(visitor); } @@ -162,7 +196,7 @@ private: std::string k = key(mKeyPrefix, std::to_string(i)); int length = getArraySize(k, mObject); value.resize(static_cast(length)); - FromKVJsonVisitor visitor(*this, i); + FromKVJsonVisitor visitor(*this, i, false); for (int i = 0; i < length; ++i) { visitor.getValue(i, value[i]); } diff --git a/src/config/is-union.hpp b/src/config/is-union.hpp new file mode 100644 index 0000000..f696b72 --- /dev/null +++ b/src/config/is-union.hpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.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 Krzysztof Dynowski (k.dynowski@samsumg.com) + * @brief Internal configuration helper + */ + +#ifndef CONFIG_IS_UNION_HPP +#define CONFIG_IS_UNION_HPP + +#include "config/is-visitable.hpp" + +namespace config { + +// generic member checker, start +template +struct has_member_impl { + template + static std::true_type check(typename F::template checker__* =0); + + template + static std::false_type check(...); + + static const bool value = std::is_same(0)), std::true_type>::value; +}; + +template +struct has_member : public std::integral_constant::value> {}; +// generic member checker, end + + +template +struct check_union : isVisitable { + template + struct checker__ {}; +}; +template +struct isUnion : has_member> {}; + +//Note: +// unfortunately, above generic has_member can't be used for isVisitable +// because Vistable need 'accept' OR 'accept const', while has_member make exect match +// e.g accept AND accept const + +} // namespace config + +#endif // CONFIG_FROM_KVJSON_VISITOR_HPP + diff --git a/src/config/manager.hpp b/src/config/manager.hpp index 0785094..7c50087 100644 --- a/src/config/manager.hpp +++ b/src/config/manager.hpp @@ -32,7 +32,6 @@ #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" -- 2.7.4