From: Mateusz Malicki Date: Tue, 17 Feb 2015 14:30:54 +0000 (+0100) Subject: Added GVariant visitor X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=69c97a86e2e86f02561ddd66a2aadf22777bb8ac;p=archive%2Fplatform%2Fcore%2Fsystem%2FlibConfig.git Added GVariant visitor [Bug/Feature] GVariant visitor [Cause] N/A [Solution] N/A [Verification] N/A Change-Id: I66f8c94a62180b95d3684608a2c528509bf49980 --- diff --git a/packaging/libConfig.spec b/packaging/libConfig.spec index 5219bac..f4ae855 100644 --- a/packaging/libConfig.spec +++ b/packaging/libConfig.spec @@ -10,6 +10,7 @@ Summary: Config library BuildRequires: cmake BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(glib-2.0) %description The package provides libConfig library. @@ -63,4 +64,4 @@ rm -rf %{buildroot} %post -p /sbin/ldconfig -%postun -p /sbin/ldconfig \ No newline at end of file +%postun -p /sbin/ldconfig diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 911e71a..9f1d903 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,7 +29,7 @@ SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY SOVERSION ${_LIB_SOVERSION_}) SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY VERSION ${_LIB_VERSION_}) ## Link libraries ############################################################# -PKG_CHECK_MODULES(CONFIG_DEPS REQUIRED sqlite3) +PKG_CHECK_MODULES(CONFIG_DEPS REQUIRED sqlite3 glib-2.0) INCLUDE_DIRECTORIES(${SRC_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${CONFIG_DEPS_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${CONFIG_DEPS_LIBRARIES}) diff --git a/src/config/from-gvariant-visitor.hpp b/src/config/from-gvariant-visitor.hpp new file mode 100644 index 0000000..ba7dc7e --- /dev/null +++ b/src/config/from-gvariant-visitor.hpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Mateusz Malicki (m.malicki2@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 Mateusz Malicki (m.malicki2@samsung.com) + * @brief GVariant visitor + */ + +#ifndef CONFIG_FROM_GVARIANT_VISITOR_HPP +#define CONFIG_FROM_GVARIANT_VISITOR_HPP + +#include "config/is-visitable.hpp" +#include "config/exception.hpp" +#include "config/is-union.hpp" + +#include +#include +#include +#include + +namespace config { + +class FromGVariantVisitor { +public: + explicit FromGVariantVisitor(GVariant* variant) + { + //Assume that the visited object is not a union + checkType(variant, G_VARIANT_TYPE_TUPLE); + mIter = g_variant_iter_new(variant); + } + + FromGVariantVisitor(const FromGVariantVisitor& visitor) + : mIter(g_variant_iter_copy(visitor.mIter)) + { + } + + ~FromGVariantVisitor() + { + g_variant_iter_free(mIter); + } + + FromGVariantVisitor& operator=(const FromGVariantVisitor&) = delete; + + template + void visit(const std::string& name, T& value) + { + GVariant* child = g_variant_iter_next_value(mIter); + if (child == NULL) { + throw config::ConfigException( + "GVariant doesn't match with config. Can't set '" + name + "'"); + } + fromGVariant(child, value); + g_variant_unref(child); + } + +private: + GVariantIter* mIter; + + explicit FromGVariantVisitor(GVariant* variant, bool isUnion) + { + if (isUnion) { + checkType(variant, G_VARIANT_TYPE_VARIANT); + variant = g_variant_get_variant(variant); + } + checkType(variant, G_VARIANT_TYPE_TUPLE); + mIter = g_variant_iter_new(variant); + } + + static void checkType(GVariant* object, const GVariantType* type) + { + if (!g_variant_is_of_type(object, type)) { + throw ConfigException("Invalid field type"); + } + } + + static void fromGVariant(GVariant* object, int& value) + { + checkType(object, G_VARIANT_TYPE_INT32); + value = g_variant_get_int32(object); + } + + static void fromGVariant(GVariant* object, std::int64_t& value) + { + checkType(object, G_VARIANT_TYPE_INT64); + value = g_variant_get_int64(object); + } + + static void fromGVariant(GVariant* object, bool& value) + { + checkType(object, G_VARIANT_TYPE_BOOLEAN); + value = g_variant_get_boolean(object); + } + + static void fromGVariant(GVariant* object, double& value) + { + checkType(object, G_VARIANT_TYPE_DOUBLE); + value = g_variant_get_double(object); + } + + static void fromGVariant(GVariant* object, std::string& value) + { + checkType(object, G_VARIANT_TYPE_STRING); + value = g_variant_get_string(object, NULL); + } + + template + static void fromGVariant(GVariant* object, std::vector& value) + { + checkType(object, G_VARIANT_TYPE_ARRAY); + GVariantIter iter; + g_variant_iter_init(&iter, object); + int length = g_variant_iter_n_children(&iter); + value.resize(static_cast(length)); + for (int i = 0; i < length; ++i) { + GVariant* child = g_variant_iter_next_value(&iter); + assert(child != NULL); + fromGVariant(child, value[static_cast(i)]); + g_variant_unref(child); + } + } + + template + static typename std::enable_if::value>::type + fromGVariant(GVariant* object, T& value) + { + FromGVariantVisitor visitor(object, isUnion::value); + value.accept(visitor); + } + +}; + +} // namespace config + +#endif // CONFIG_FROM_GVARIANT_VISITOR_HPP diff --git a/src/config/manager.hpp b/src/config/manager.hpp index 7afde48..7b000f2 100644 --- a/src/config/manager.hpp +++ b/src/config/manager.hpp @@ -25,19 +25,53 @@ #ifndef CONFIG_MANAGER_HPP #define CONFIG_MANAGER_HPP +#include "config/to-gvariant-visitor.hpp" #include "config/to-json-visitor.hpp" #include "config/to-kvstore-visitor.hpp" #include "config/to-fdstore-visitor.hpp" +#include "config/from-gvariant-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/fs-utils.hpp" - +#include "config/is-union.hpp" namespace config { /** + * Fills the configuration with data stored in the GVariant + * + * @param gvariant configuration in GVariant type + * @param config visitable structure to fill + */ +template +void loadFromGVariant(GVariant* gvariant, Config& config) +{ + static_assert(isVisitable::value, "Use CONFIG_REGISTER macro"); + static_assert(!isUnion::value, "Don't use CONFIG_DECLARE_UNION in top level config"); + + FromGVariantVisitor visitor(gvariant); + config.accept(visitor); +} + +/** + * Saves the config in a GVariant + * + * @param config visitable structure to convert + */ +template +GVariant* saveToGVariant(const Config& config) +{ + static_assert(isVisitable::value, "Use CONFIG_REGISTER macro"); + static_assert(!isUnion::value, "Don't use CONFIG_DECLARE_UNION in top level config"); + + ToGVariantVisitor visitor; + config.accept(visitor); + return visitor.toVariant(); +} + +/** * Fills the configuration with data stored in the json string * * @param jsonString configuration in a json format diff --git a/src/config/to-gvariant-visitor.hpp b/src/config/to-gvariant-visitor.hpp new file mode 100644 index 0000000..e8476fc --- /dev/null +++ b/src/config/to-gvariant-visitor.hpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Mateusz Malicki (m.malicki2@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 Mateusz Malicki (m.malicki2@samsung.com) + * @brief GVariant visitor + */ + +#ifndef CONFIG_TO_GVARIANT_VISITOR_HPP +#define CONFIG_TO_GVARIANT_VISITOR_HPP + +#include "config/is-visitable.hpp" +#include "config/is-union.hpp" + +#include +#include +#include + +namespace config { + +class ToGVariantVisitor { + +public: + ToGVariantVisitor() + : mBuilder(g_variant_builder_new(G_VARIANT_TYPE_TUPLE)) + { + } + + ToGVariantVisitor(const ToGVariantVisitor& visitor) + : mBuilder(visitor.mBuilder ? g_variant_builder_ref(visitor.mBuilder) : nullptr) + { + } + + ~ToGVariantVisitor() + { + if (mBuilder) { + g_variant_builder_unref(mBuilder); + } + } + + ToGVariantVisitor& operator=(const ToGVariantVisitor&) = delete; + + GVariant* toVariant() + { + if (mBuilder) { + GVariant* ret = g_variant_builder_end(mBuilder); + g_variant_builder_unref(mBuilder); + mBuilder = nullptr; + return ret; + } + return nullptr; + } + + template + void visit(const std::string& /* name */, const T& value) + { + writeInternal(value); + } +private: + GVariantBuilder* mBuilder; + + void writeInternal(std::int32_t value) { add("i", value); }; + void writeInternal(std::int64_t value) { add("x", 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()); }; + + template + void writeInternal(const std::vector& value) + { + if (!value.empty()) { + g_variant_builder_open(mBuilder, G_VARIANT_TYPE_ARRAY); + for (const T& v : value) { + writeInternal(v); + } + g_variant_builder_close(mBuilder); + } else { + g_variant_builder_add(mBuilder, "as", NULL); + } + } + + template + typename std::enable_if::value && !isUnion::value>::type + writeInternal(const T& value) + { + ToGVariantVisitor visitor; + value.accept(visitor); + g_variant_builder_add_value(mBuilder, visitor.toVariant()); + } + + template + typename std::enable_if::value && isUnion::value>::type + writeInternal(const T& value) + { + ToGVariantVisitor visitor; + value.accept(visitor); + add("v", visitor.toVariant()); + } + + template + void add(const char* type, Value value) { + g_variant_builder_add(mBuilder, type, value); + } +}; + +} // namespace config + +#endif // CONFIG_TO_GVARIANT_VISITOR_HPP