From d86042141ef0a0e77935f4b48d1a627fc1ec776b Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Sun, 28 Aug 2016 15:19:31 +0200 Subject: Initial commit, allows for storing simpel values and boost::hana adapted structs at "key" --- .gitignore | 2 ++ CMakeLists.txt | 27 +++++++++++++++ configpp.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++ configpp.hpp | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 8 +++++ tests/test1.cpp | 19 +++++++++++ 6 files changed, 234 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 configpp.cpp create mode 100644 configpp.hpp create mode 100644 tests/CMakeLists.txt create mode 100644 tests/test1.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..394decf --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +CMakeLists.txt.user +build* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..0d9ab6a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ + +cmake_minimum_required(VERSION 3.6.1) +#this is the my current development version, it could probably be lower. + +Project(configpp) + +find_package(Boost COMPONENTS filesystem REQUIRED) + +add_library(configpp SHARED + configpp.hpp configpp.cpp +) + +target_include_directories(configpp + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(configpp + PRIVATE Boost::boost + PRIVATE Boost::filesystem +) + +target_compile_options(configpp + PUBLIC -std=c++14 +) + +enable_testing() +add_subdirectory(tests) \ No newline at end of file diff --git a/configpp.cpp b/configpp.cpp new file mode 100644 index 0000000..c434979 --- /dev/null +++ b/configpp.cpp @@ -0,0 +1,84 @@ + +#include "configpp.hpp" + +#include +#include +#include + +#include + +namespace configpp { + +std::unique_ptr Config::config_ptr = nullptr; + +#if defined( _WIN32 ) || defined( _WIN64 ) +boost::filesystem::path get_config_base_dir() { + if(!std::getenv("APPDATA")) { + throw std::runtime_error("Environment variable \"APPDATA\" is not set, could not find suitable config home."); + } + boost::filesystem::path appdata(std::getenv("APPDATA")); + return appdata +} +#endif + +#if defined( __unix__ ) && !defined( __APPLE__) && !defined( __MACH__ ) +boost::filesystem::path get_config_base_dir() { + boost::filesystem::path config_home; + boost::filesystem::path path; + if(!std::getenv("XDG_CONFIG_HOME")) { + if(!std::getenv("HOME")) { + throw std::runtime_error("Neither \"XDG_CONFIG_HOME\" nor \"HOME\" environment variable are set, could not find suitable config home."); + } else { + config_home = getenv("HOME"); + path = config_home / boost::filesystem::path(".config"); + } + } else { + path = getenv("XDG_CONFIG_HOME"); + } + return path; +} + +#endif + +#if defined( __APPLE__ ) && defined( __MACH__ ) +boost::filesystem::path get_config_base_dir(std::string subdir) { + boost::filesystem::path path; + if(!std::getenv("HOME")) { + throw std::runtime_error("\"HOME\" environment variable is not set, could not find a suitable config home."); + } else { + path = boost::filesystem::path(std::getenv("HOME")); + } + return path; +} +#endif + +using namespace boost::filesystem; + +Config::Config(std::string subdir, std::string filename) +: config() +, subdir(subdir) +, filename(filename) +{ + auto dir = get_config_base_dir() / path(subdir); + auto file_path = dir / filename; + + if(exists(file_path)) { + std::ifstream file_stream(file_path.string()); + boost::property_tree::read_json(file_stream, config); + } +} + +Config::~Config() +{ + auto dir = get_config_base_dir() / path(subdir); + auto file_path = dir / filename; + + if(!exists(dir)) { + boost::filesystem::create_directories(dir); + } + + std::ofstream file_stream(file_path.string()); + boost::property_tree::write_json(file_stream, config); +} + +} //namespace configpp \ No newline at end of file diff --git a/configpp.hpp b/configpp.hpp new file mode 100644 index 0000000..90038af --- /dev/null +++ b/configpp.hpp @@ -0,0 +1,94 @@ +#pragma once + +#include +#include + +#include +#include + +struct X { + int a; + int b; +}; + +BOOST_HANA_ADAPT_STRUCT(X, a, b); + +struct X2 { + int a; + int b; +}; + +namespace configpp { + + struct ConfigStructure{}; + + class Config { + Config(std::string subdir, std::string filename = "config.json"); + + boost::property_tree::ptree config; + std::string subdir; + std::string filename; + + static std::unique_ptr config_ptr; + + void set(std::string const& key, std::string const& value, boost::property_tree::ptree& base) const { + base.put(key, value); + } + + public: + + Config() = delete; + Config(Config const&) = delete; + Config(Config&&) = delete; + Config& operator=(Config const&) = delete; + Config& operator=(Config&&) = delete; + + ~Config(); + + static Config& get(std::string subdir, std::string filename = "config.json") { + if(!config_ptr) { + config_ptr.reset(new Config(subdir, filename)); + } + return *config_ptr; + } + + void set(std::string const& key, std::string const& value) { + set(key, value, config); + } + + template ::value>::type* = nullptr> + void set(std::string const & key, T const& value) { + std::ostringstream oss; + oss << value; + + set(key, oss.str()); + } + + template ::value>::type* = nullptr> + void set(std::string const& key, T const& value) { + auto top_element = config.get_child_optional(key); + + if(!top_element) { + boost::property_tree::ptree array; + config.add_child(key, array); + top_element = config.get_child(key); + } + + boost::hana::for_each(value, boost::hana::fuse([&top_element, this](auto&& key, auto&& value) { + std::ostringstream oss; + oss << value; + + set(boost::hana::to(key), oss.str(), *top_element); + })); + } + + template + void get(std::string key, T const& value) { + + } + + }; + +} //namespace configpp + +//configpp::Config& config = configpp::Config::get({}); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..1260e05 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,8 @@ +set(CTEST_ENVIRONMENT + "XDG_CONFIG_HOME=${CMAKE_CURRENT_BINARY_DIR}" + "HOME=${CMAKE_CURRENT_BINARY_DIR}" +) + +add_executable(test1 test1.cpp) +target_link_libraries(test1 PRIVATE configpp) +add_test(NAME test1 COMMAND test1) \ No newline at end of file diff --git a/tests/test1.cpp b/tests/test1.cpp new file mode 100644 index 0000000..fedcb48 --- /dev/null +++ b/tests/test1.cpp @@ -0,0 +1,19 @@ + +#include "configpp.hpp" + +struct Data { + int i; + float f; + std::string str; +}; + +BOOST_HANA_ADAPT_STRUCT(Data, i, f, str); + +int main() { + configpp::Config& config = configpp::Config::get("configpp_test1"); + + config.set("int", 1); + config.set("float", 1.0f); + config.set("string", "yolo"); + config.set("struct", Data{1, 1.0f, "yolo"}); +} -- cgit v1.2.3-70-g09d2