summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt27
-rw-r--r--configpp.cpp84
-rw-r--r--configpp.hpp94
-rw-r--r--tests/CMakeLists.txt8
-rw-r--r--tests/test1.cpp19
6 files changed, 234 insertions, 0 deletions
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 <boost/filesystem/path.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/property_tree/json_parser.hpp>
+
+#include <fstream>
+
+namespace configpp {
+
+std::unique_ptr<Config> 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 <boost/property_tree/ptree.hpp>
+#include <boost/hana.hpp>
+
+#include <memory>
+#include <type_traits>
+
+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> 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 <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
+ void set(std::string const & key, T const& value) {
+ std::ostringstream oss;
+ oss << value;
+
+ set(key, oss.str());
+ }
+
+ template <typename T, typename std::enable_if<boost::hana::Struct<T>::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<const char*>(key), oss.str(), *top_element);
+ }));
+ }
+
+ template <typename T>
+ 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"});
+}