Initial library content. 25/23725/8
authorJacek Pielaszkiewicz <j.pielaszkie@samsung.com>
Tue, 17 Jun 2014 08:28:19 +0000 (10:28 +0200)
committerJacek Pielaszkiewicz <j.pielaszkie@samsung.com>
Thu, 24 Jul 2014 09:38:11 +0000 (11:38 +0200)
[Bug/Feature]  Initial library content.
[Cause]        N/A
[Solution]     N/A
[Verification] Build, install, run tests

Change-Id: I0de77757b11c87099b5b0d915e30aeeff1becf61
Signed-off-by: Jacek Pielaszkiewicz <j.pielaszkie@samsung.com>
CMakeLists.txt [new file with mode: 0644]
packaging/libConfig.spec
src/CMakeLists.txt [new file with mode: 0644]
src/config/config.hpp [new file with mode: 0644]
src/config/exception.hpp [new file with mode: 0644]
src/config/fields.hpp [new file with mode: 0644]
src/config/from-json-visitor.hpp [new file with mode: 0644]
src/config/is-visitable.hpp [new file with mode: 0644]
src/config/manager.hpp [new file with mode: 0644]
src/config/to-json-visitor.hpp [new file with mode: 0644]
src/libConfig.pc.in [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2118f07
--- /dev/null
@@ -0,0 +1,66 @@
+#    Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    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   CMakeLists.txt
+# @author Jacek Pielaszkiewicz (j.pielaszkie@samsung.com)
+#
+CMAKE_MINIMUM_REQUIRED (VERSION 2.6.2)
+PROJECT(Config)
+
+## pkgconfig ###################################################################
+INCLUDE(FindPkgConfig)
+
+## default CMAKE_INSTALL_* variables ###########################################
+INCLUDE(GNUInstallDirs)
+
+## Compiler flags, depending on the build type #################################
+IF(NOT CMAKE_BUILD_TYPE)
+    SET(CMAKE_BUILD_TYPE "DEBUG")
+ENDIF(NOT CMAKE_BUILD_TYPE)
+MESSAGE(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
+
+# special case for a GCC < 4.7, assume rest is fine
+IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7)
+    SET(CXX_11_STD "c++0x")
+else()
+    SET(CXX_11_STD "c++11")
+endif()
+
+SET(CMAKE_C_FLAGS_PROFILING    "-g -O0 -pg")
+SET(CMAKE_CXX_FLAGS_PROFILING  "-g -std=${CXX_11_STD} -O0 -pg")
+SET(CMAKE_C_FLAGS_DEBUG        "-g -O0 -ggdb")
+SET(CMAKE_CXX_FLAGS_DEBUG      "-g -std=${CXX_11_STD} -O0 -ggdb")
+SET(CMAKE_C_FLAGS_RELEASE      "-g -O2 -DNDEBUG")
+SET(CMAKE_CXX_FLAGS_RELEASE    "-g -std=${CXX_11_STD} -O2 -DNDEBUG")
+SET(CMAKE_C_FLAGS_CCOV         "-g -O2 --coverage")
+SET(CMAKE_CXX_FLAGS_CCOV       "-g -std=${CXX_11_STD} -O2 --coverage")
+
+ADD_DEFINITIONS("-fPIC")   # Position Independent Code
+ADD_DEFINITIONS("-Werror") # Make all warnings into errors
+ADD_DEFINITIONS("-Wall")   # Generate all warnings
+ADD_DEFINITIONS("-Wextra") # Generate even more extra warnings
+ADD_DEFINITIONS("-pedantic") # Be pedantic
+ADD_DEFINITIONS("-pedantic-errors") # Make pedantic warnings into errors
+ADD_DEFINITIONS(-DPROGRAM_VERSION="${VERSION}")
+ADD_DEFINITIONS(-DPROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}")
+
+## Subdirectories ##############################################################
+SET(SRC_FOLDER ${PROJECT_SOURCE_DIR}/src)
+
+IF(NOT DEFINED INCLUDE_INSTALL_DIR)
+    SET(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_FULL_INCLUDEDIR})
+ENDIF(NOT DEFINED INCLUDE_INSTALL_DIR)
+
+ADD_SUBDIRECTORY(${SRC_FOLDER})
index 45a604f..f65c1fb 100644 (file)
@@ -1,50 +1,53 @@
+%define lib_version   0.0.1
+
 Name:          libConfig
-Version:       0.0.1
+Version:       %{lib_version}
 Release:       0
 Source0:       %{name}-%{version}.tar.gz
 License:       Apache-2.0
 Group:         Security/Other
-Summary:       libConfig library.
+Summary:       Config library
+
+BuildRequires: cmake
 
 %description
 The package provides libConfig library.
 
-%files
-%manifest packaging/libConfig.manifest
-%defattr(644,root,root,755)
-
 %package       devel
-Summary:       libConfig development
+Summary:       Development package for config library
 Group:         Development/Libraries
+Requires:      boost-devel
+Requires:      pkgconfig(libLogger)
+Requires:      libjson-devel
 
 %description   devel
 The package provides libConfig development tools and libs.
 
 %files         devel
 %defattr(644,root,root,755)
-
-%package       tests
-Summary:       libConfig tests
-Group:         Development/Libraries
-
-%description  tests
-The package provides libConfig test tools.
-
-%files        tests
-%defattr(644,root,root,755)
+%{_includedir}/sc-tools
+%{_libdir}/pkgconfig/*.pc
 
 %prep
 %setup -q
 
 %build
+%{!?build_type:%define build_type "RELEASE"}
 
-%install
+%if %{build_type} == "DEBUG" || %{build_type} == "PROFILING"
+    CFLAGS="$CFLAGS -Wp,-U_FORTIFY_SOURCE"
+    CXXFLAGS="$CXXFLAGS -Wp,-U_FORTIFY_SOURCE"
+%endif
 
-%clean
-rm -rf %{buildroot}
+%cmake . \
+         -D_LIB_VERSION_=%{lib_version} \
+         -DVERSION=%{version} \
+         -DCMAKE_BUILD_TYPE=%{build_type}
 
-%post
+make -k %{?jobs:-j%jobs}
 
-%preun
+%install
+%make_install
 
-%postun
+%clean
+rm -rf %{buildroot}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..437e6ca
--- /dev/null
@@ -0,0 +1,35 @@
+# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    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   CMakeLists.txt
+# @author Jacek Pielaszkiewicz (j.pielaszkie@samsung.com)
+#
+SET(PC_FILE "${SRC_FOLDER}/lib${PROJECT_NAME}.pc")
+
+MESSAGE(STATUS "Generating makefile for the libConfig sources...")
+FILE(GLOB         HEADERS       "${SRC_FOLDER}/config/*.hpp")
+FILE(GLOB_RECURSE SRCS          "${SRC_FOLDER}" *.hpp *.cpp)
+
+## Setup target ################################################################
+
+## Link libraries #############################################################
+INCLUDE_DIRECTORIES(${SRC_FOLDER})
+INCLUDE_DIRECTORIES(SYSTEM ${CONFIG_DEPS_INCLUDE_DIRS})
+
+## Install #####################################################################
+CONFIGURE_FILE(${PC_FILE}.in "${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE}" @ONLY)
+
+INSTALL(FILES ${HEADERS}                               DESTINATION "${INCLUDE_INSTALL_DIR}/sc-tools/config")
+INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE}" DESTINATION "/usr/lib/pkgconfig")
diff --git a/src/config/config.hpp b/src/config/config.hpp
new file mode 100644 (file)
index 0000000..a65c2ad
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Lukasz Pawelczyk (l.pawelczyk@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  Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com)
+ * @brief   Configuration file for the code
+ */
+
+#ifndef CONFIG_HPP
+#define CONFIG_HPP
+
+#ifdef __clang__
+#define CLANG_VERSION (__clang__major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
+#endif // __clang__
+
+#if defined __GNUC__ && !defined __clang__  // clang also defines GCC versions
+#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif // __GNUC__
+
+#ifdef GCC_VERSION
+
+#if GCC_VERSION < 40800
+// GCC 4.8 is the first where those defines are not required for
+// std::this_thread::sleep_for() and ::yield(). They might exist though
+// in previous versions depending on the build configuration of the GCC.
+#ifndef _GLIBCXX_USE_NANOSLEEP
+#define _GLIBCXX_USE_NANOSLEEP
+#endif // _GLIBCXX_USE_NANOSLEEP
+#ifndef _GLIBCXX_USE_SCHED_YIELD
+#define _GLIBCXX_USE_SCHED_YIELD
+#endif // _GLIBCXX_USE_SCHED_YIELD
+#endif // GCC_VERSION < 40800
+
+#if GCC_VERSION < 40700
+// Those appeared in 4.7 with full c++11 support
+#define final
+#define override
+#define thread_local __thread  // use GCC extension instead of C++11
+#endif // GCC_VERSION < 40700
+
+#endif // GCC_VERSION
+
+#endif // CONFIG_HPP
diff --git a/src/config/exception.hpp b/src/config/exception.hpp
new file mode 100644 (file)
index 0000000..6489c73
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Lukasz Pawelczyk <l.pawelczyk@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  Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com)
+ * @brief   Exceptions for the configuration
+ */
+
+#ifndef CONFIG_EXCEPTION_HPP
+#define CONFIG_EXCEPTION_HPP
+
+#include <stdexcept>
+
+namespace config {
+
+/**
+ * Base class for exceptions in configuration.
+ * Error occured during a config file parsing,
+ * e.g. syntax error
+ */
+struct ConfigException: public std::runtime_error {
+
+    ConfigException(const std::string& error = "") : std::runtime_error(error) {}
+};
+
+} // namespace config
+
+#endif // CONFIG_EXCEPTION_HPP
diff --git a/src/config/fields.hpp b/src/config/fields.hpp
new file mode 100644 (file)
index 0000000..3269856
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  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  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief   Macros for registering configuration fields
+ */
+
+#ifndef CONFIG_FIELDS_HPP
+#define CONFIG_FIELDS_HPP
+
+#include <boost/preprocessor/variadic/to_list.hpp>
+#include <boost/preprocessor/list/for_each.hpp>
+
+#if BOOST_PP_VARIADICS != 1
+#error variadic macros not supported
+#endif
+
+/**
+ * Use this macro to register config fields.
+ *
+ * Example:
+ *   struct Foo
+ *   {
+ *       std::string bar;
+ *       std::vector<int> tab;
+ *
+ *       // SubConfigA must also register config fields
+ *       SubConfigA sub_a;
+ *
+ *       // SubConfigB must also register config fields
+ *       std::vector<SubConfigB> tab_sub;
+ *
+ *       CONFIG_REGISTER
+ *       (
+ *           bar,
+ *           tab,
+ *           sub_a
+ *       )
+ *   };
+ */
+#define CONFIG_REGISTER(...)                                       \
+    template<typename Visitor>                                     \
+    void accept(Visitor v) {                                       \
+        GENERATE_ELEMENTS__(__VA_ARGS__)                           \
+    }                                                              \
+    template<typename Visitor>                                     \
+    void accept(Visitor v) const {                                 \
+        GENERATE_ELEMENTS__(__VA_ARGS__)                           \
+    }                                                              \
+
+#define GENERATE_ELEMENTS__(...)                                   \
+    BOOST_PP_LIST_FOR_EACH(GENERATE_ELEMENT__,                     \
+                           _,                                      \
+                           BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \
+
+#define GENERATE_ELEMENT__(r, _, element)                          \
+    v.visit(#element, element);                                    \
+
+#endif // CONFIG_FIELDS_HPP
diff --git a/src/config/from-json-visitor.hpp b/src/config/from-json-visitor.hpp
new file mode 100644 (file)
index 0000000..a3b502d
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ *  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  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief   JSON visitor
+ */
+
+#ifndef CONFIG_FROM_JSON_VISITOR_HPP
+#define CONFIG_FROM_JSON_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+#include "config/exception.hpp"
+
+#include <json/json.h>
+#include <string>
+#include <vector>
+
+namespace config {
+
+class FromJsonVisitor {
+public:
+    explicit FromJsonVisitor(const std::string& jsonString)
+        : mObject(nullptr)
+    {
+        mObject = json_tokener_parse(jsonString.c_str());
+        if (mObject == nullptr) {
+            throw ConfigException("Json parsing error");
+        }
+    }
+
+    FromJsonVisitor(const FromJsonVisitor& visitor)
+        : mObject(json_object_get(visitor.mObject))
+    {
+    }
+
+    ~FromJsonVisitor()
+    {
+        json_object_put(mObject);
+    }
+
+    template<class T>
+    void visit(const std::string& name, T& value)
+    {
+        json_object* object = nullptr;
+        if (!json_object_object_get_ex(mObject, name.c_str(), &object)) {
+            throw ConfigException("Missing field '" + name + "' in json");
+        }
+        fromJsonObject(object, value);
+    }
+
+private:
+    json_object* mObject;
+
+    FromJsonVisitor& operator=(const FromJsonVisitor&) = delete;
+
+    explicit FromJsonVisitor(json_object* object)
+        : mObject(json_object_get(object))
+    {
+    }
+
+    static void checkType(json_object* object, json_type type)
+    {
+        if (type != json_object_get_type(object)) {
+            throw ConfigException("Invalid field 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);
+    }
+
+    template<class T>
+    static void fromJsonObject(json_object* object, std::vector<T>& value)
+    {
+        checkType(object, json_type_array);
+        int length = json_object_array_length(object);
+        value.resize(static_cast<size_t>(length));
+        for (int i = 0; i < length; ++i) {
+            fromJsonObject(json_object_array_get_idx(object, i), value[static_cast<size_t>(i)]);
+        }
+    }
+
+    template<class T, class = typename std::enable_if<isVisitable<T>::value>::type>
+    static void fromJsonObject(json_object* object, T& value)
+    {
+        checkType(object, json_type_object);
+        FromJsonVisitor visitor(object);
+        value.accept(visitor);
+    }
+};
+
+} // namespace config
+
+#endif // CONFIG_FROM_JSON_VISITOR_HPP
diff --git a/src/config/is-visitable.hpp b/src/config/is-visitable.hpp
new file mode 100644 (file)
index 0000000..74f6036
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  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  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief   Internal configuration helper
+ */
+
+#ifndef CONFIG_IS_VISITABLE_HPP
+#define CONFIG_IS_VISITABLE_HPP
+
+#include <type_traits>
+
+namespace config {
+
+template <typename T>
+struct isVisitableHelper__ {
+    struct Visitor {};
+
+    template <typename C> static std::true_type
+    test(decltype(std::declval<C>().template accept(Visitor()))*);
+
+    template <typename C> static std::false_type
+    test(...);
+
+    static constexpr bool value = std::is_same<decltype(test<T>(0)), std::true_type>::value;
+};
+
+/**
+ * Helper for compile-time checking against existance of template method 'accept'.
+ */
+template <typename T>
+struct isVisitable : public std::integral_constant<bool, isVisitableHelper__<T>::value> {};
+
+} // namespace config
+
+#endif // CONFIG_IS_VISITABLE_HPP
diff --git a/src/config/manager.hpp b/src/config/manager.hpp
new file mode 100644 (file)
index 0000000..902633f
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *  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  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief   Configuration management functions
+ */
+
+#ifndef CONFIG_MANAGER_HPP
+#define CONFIG_MANAGER_HPP
+
+#include "config/to-json-visitor.hpp"
+#include "config/from-json-visitor.hpp"
+#include "config/is-visitable.hpp"
+#include "logger/logger.hpp"
+
+#include <fstream>
+#include <streambuf>
+
+
+namespace config {
+
+template <class Config>
+void loadFromString(const std::string& jsonString, Config& config)
+{
+    static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+    FromJsonVisitor visitor(jsonString);
+    config.accept(visitor);
+}
+
+template <class Config>
+std::string saveToString(const Config& config)
+{
+    static_assert(isVisitable<Config>::value, "Use CONFIG_REGISTER macro");
+
+    ToJsonVisitor visitor;
+    config.accept(visitor);
+    return visitor.toString();
+}
+
+static bool readFileContent(const std::string& path, std::string& result)
+{
+    std::ifstream file(path);
+
+    if (!file) {
+        LOGD(path << ": could not open for reading");
+        return false;
+    }
+
+    file.seekg(0, std::ios::end);
+    std::streampos length = file.tellg();
+    if (length < 0) {
+        LOGD(path << ": tellg failed");
+        return false;
+    }
+    result.resize(static_cast<size_t>(length));
+    file.seekg(0, std::ios::beg);
+
+    file.read(&result[0], length);
+    if (!file) {
+        LOGD(path << ": read error");
+        result.clear();
+        return false;
+    }
+
+    return true;
+}
+
+static bool saveFileContent(const std::string& path, const std::string& content)
+{
+    std::ofstream file(path);
+    if (!file) {
+        LOGD(path << ": could not open for writing");
+        return false;
+    }
+    file.write(content.data(), content.size());
+    if (!file) {
+        LOGD(path << ": could not write to");
+        return false;
+    }
+    return true;
+}
+
+template <class Config>
+void loadFromFile(const std::string& filename, Config& config)
+{
+    try {
+        std::string content;
+        if (!readFileContent(filename, content)) {
+            throw ConfigException("Could not load " + filename);
+        }
+        loadFromString(content, config);
+    }
+    catch(...) {
+        throw ConfigException("Could not load configuration.");
+    }
+}
+
+template <class Config>
+void saveToFile(const std::string& filename, const Config& config)
+{
+    const std::string content = saveToString(config);
+    if (!saveFileContent(filename, content)) {
+        throw ConfigException("Could not save " + filename);
+    }
+}
+
+} // namespace config
+
+#endif // CONFIG_MANAGER_HPP
diff --git a/src/config/to-json-visitor.hpp b/src/config/to-json-visitor.hpp
new file mode 100644 (file)
index 0000000..5b70eb9
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  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  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief   JSON visitor
+ */
+
+#ifndef CONFIG_TO_JSON_VISITOR_HPP
+#define CONFIG_TO_JSON_VISITOR_HPP
+
+#include "config/is-visitable.hpp"
+
+#include <json/json.h>
+#include <string>
+#include <vector>
+
+namespace config {
+
+class ToJsonVisitor {
+
+public:
+    ToJsonVisitor()
+        : mObject(json_object_new_object())
+    {
+    }
+
+    ToJsonVisitor(const ToJsonVisitor& visitor)
+        : mObject(json_object_get(visitor.mObject))
+    {
+    }
+
+    ~ToJsonVisitor()
+    {
+        json_object_put(mObject);
+    }
+
+    std::string toString() const
+    {
+        return json_object_to_json_string(mObject);
+    }
+
+    template<class T>
+    void visit(const std::string& name, const T& value)
+    {
+        json_object_object_add(mObject, name.c_str(), toJsonObject(value));
+    }
+private:
+    json_object* mObject;
+
+    ToJsonVisitor& operator=(const ToJsonVisitor&) = delete;
+
+    json_object* detach()
+    {
+        json_object* ret = mObject;
+        mObject = nullptr;
+        return ret;
+    }
+
+    static json_object* toJsonObject(int value)
+    {
+        return json_object_new_int(value);
+    }
+
+    static json_object* toJsonObject(std::int64_t value)
+    {
+        return json_object_new_int64(value);
+    }
+
+    static json_object* toJsonObject(bool value)
+    {
+        return json_object_new_boolean(value);
+    }
+
+    static json_object* toJsonObject(double value)
+    {
+        return json_object_new_double(value);
+    }
+
+    static json_object* toJsonObject(const std::string& value)
+    {
+        return json_object_new_string(value.c_str());
+    }
+
+    template<class T>
+    static json_object* toJsonObject(const std::vector<T>& value)
+    {
+        json_object* array = json_object_new_array();
+        for (const T& v : value) {
+            json_object_array_add(array, toJsonObject(v));
+        }
+        return array;
+    }
+
+    template<class T, class = typename std::enable_if<isVisitable<T>::value>::type>
+    static json_object* toJsonObject(const T& value)
+    {
+        ToJsonVisitor visitor;
+        value.accept(visitor);
+        return visitor.detach();
+    }
+};
+
+} // namespace config
+
+#endif // CONFIG_TO_JSON_VISITOR_HPP
diff --git a/src/libConfig.pc.in b/src/libConfig.pc.in
new file mode 100644 (file)
index 0000000..67f53d6
--- /dev/null
@@ -0,0 +1,8 @@
+# Package Information for pkg-config
+
+includedir=@INCLUDE_INSTALL_DIR@
+
+Name: libConfig
+Description: Config library
+Version: @VERSION@
+Cflags: -I${includedir}/sc_tools