[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>
--- /dev/null
+# 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})
+%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}
--- /dev/null
+# 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")
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+# Package Information for pkg-config
+
+includedir=@INCLUDE_INSTALL_DIR@
+
+Name: libConfig
+Description: Config library
+Version: @VERSION@
+Cflags: -I${includedir}/sc_tools