#include "pom.hpp" #include #include #include #include #include namespace pom { Configuration::~Configuration() { pom_conf_free(static_cast(C)); } Configuration::Configuration(): C(nullptr) {} Error::~Error() { if (m_is_original) free(C); } Error::Error(void *C_error): C(C_error), m_is_original(true) { const pom_error *next = pom_error_next(static_cast(C)); if (next) m_next = std::unique_ptr(new Error(static_cast(next))); } // const_cast here to avoid creating a separate ConstError type Error::Error(const void *C_error): C(const_cast(C_error)), m_is_original(false) { const pom_error *next = pom_error_next(static_cast(C)); if (next) m_next = std::unique_ptr(new Error(static_cast(next))); } std::string_view Error::file() const noexcept { return pom_error_file(static_cast(C)); } uint64_t Error::line() const noexcept { return pom_error_line(static_cast(C)); } std::string_view Error::message() const noexcept { return pom_error_message(static_cast(C)); } const Error *Error::next() const noexcept { return m_next.get(); } const char *Error::what() const noexcept { return m_is_original ? pom_error_to_string(static_cast(C)) : pom_error_message(static_cast(C)); } std::string_view Error::to_string() noexcept { return what(); } Configuration Configuration::section(std::string_view name) const { std::string name_str(name); const pom_conf *C_section = pom_conf_section( static_cast(C), name_str.c_str()); pom_conf *C_section_copy = pom_conf_copy(C_section); return Configuration(static_cast(C_section_copy)); } static void *allocator_calloc(void *udata, size_t n, size_t sz) { return static_cast(udata)->calloc(n, sz); } static void *allocator_realloc(void *udata, void *ptr, size_t sz) { return static_cast(udata)->realloc(ptr, sz); } static void allocator_free(void *udata, void *ptr) { return static_cast(udata)->free(ptr); } void Settings::to_C(void *C) const { pom_settings &C_settings = *static_cast(C); strcpy(C_settings.error_lang, m_error_lang); if (m_allocator) { C_settings.allocator_udata = m_allocator.get(); C_settings.calloc = allocator_calloc; C_settings.realloc = allocator_realloc; C_settings.free = allocator_free; } } static size_t readable_read(void *udata, char *buf, size_t count) { return static_cast(udata)->read(buf, count); } Configuration::Configuration(std::string_view filename, Reader &source, const Settings *settings) { pom_settings C_settings = {}; if (settings) { settings->to_C(static_cast(&C_settings)); } pom_error *error; std::string filename_str(filename); C = pom_load(&C_settings, filename_str.c_str(), readable_read, &source, &error); if (error) { throw Error(static_cast(error)); } } Configuration::Configuration(std::string_view path, const Settings *settings) { pom_settings C_settings = {}; if (settings) { settings->to_C(static_cast(&C_settings)); } pom_error *error; std::string path_str(path); C = pom_load_path(&C_settings, path_str.c_str(), &error); if (error) { throw Error(static_cast(error)); } } class StringViewReader: public Reader { public: explicit StringViewReader(std::string_view v): string(v) {} virtual size_t read(char *buf, size_t count) { count = std::min(count, string.size()); memcpy(buf, string.data(), count); return count; } private: std::string_view string; }; Configuration::Configuration(std::string_view filename, std::string_view string, const Settings *settings) { StringViewReader reader(string); Configuration(filename, reader, settings); } class IStreamReader: public Reader { public: explicit IStreamReader(std::istream &stream): ifstream(stream) {} virtual size_t read(char *buf, size_t count) { ifstream.read(buf, count); return ifstream.gcount(); } private: std::istream &ifstream; }; Configuration::Configuration(std::string_view filename, std::istream &stream, const Settings *settings) { IStreamReader reader(stream); Configuration(filename, reader, settings); } void Configuration::merge(const Configuration &other) { if (!other.C) return; if (!C) { C = pom_conf_copy(static_cast(other.C)); return; } pom_conf_merge(static_cast(C), static_cast(other.C)); } std::optional Configuration::get(std::string_view key) const { if (!C) return {}; std::string key_str(key); const char *value = pom_conf_get(static_cast(C), key_str.c_str()); if (!value) return {}; else return value; } std::string_view Configuration::get_or_default(std::string_view key, std::string_view dflt) const { return get(key).value_or(dflt); } } // namespace pom