diff options
author | Fabien Proriol <fabien.proriol@kazoe.org> | 2025-05-22 15:42:13 +0200 |
---|---|---|
committer | Fabien Proriol <fabien.proriol@kazoe.org> | 2025-05-22 15:48:00 +0200 |
commit | c842548fef050ac5f8b56a5fcb4f579820247434 (patch) | |
tree | 68bce34d0932db0157761635a010695c5e9616e3 /src/settings.h |
Initial Commit
Diffstat (limited to 'src/settings.h')
-rw-r--r-- | src/settings.h | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/src/settings.h b/src/settings.h new file mode 100644 index 0000000..5dfe90b --- /dev/null +++ b/src/settings.h @@ -0,0 +1,180 @@ +#ifndef KAZOESETTINGS_H +#define KAZOESETTINGS_H + +#include <functional> +#include <memory> +#include <variant> +#include <string> +#include <algorithm> + +/** @brief Key type for settings, composed of category and name */ +using SettingKey = std::pair<std::string, std::string>; + +/** @brief Value type that can hold string, int, double or boolean */ +using SettingValue = std::variant<std::string, int, double, bool>; + + +namespace KaZoe { + +class SettingsPrivate; + +/** + * @brief Main class for managing KaZoe settings + * + * This class provides a thread-safe interface for storing and retrieving + * configuration settings with support for different value types. + */ +class Settings +{ +public: + /** @brief Constructs a new Settings instance */ + explicit Settings(); + + /** @brief Virtual destructor */ + virtual ~Settings(); + + /** + * @brief Retrieves a setting value + * @param key The setting key + * @param category The setting category (optional) + * @param def Default value if setting not found (optional) + * @return The setting value or default if not found + */ + SettingValue get(const std::string &key, const std::string &category = "", SettingValue def = SettingValue()) const; + + /** + * @brief Sets a setting value + * @param key The setting key + * @param value The value to set + * @param category The setting category (optional) + * @return true if successful, false otherwise + */ + bool set(const std::string &key, SettingValue value, const std::string &category = ""); + + /** + * @brief Gets the current instance identifier + * @return The instance ID string, by default, this is the excecutable filename + */ + std::string id() const; + + /** + * @brief Sets the instance identifier + * @param newid The new ID to set + */ + void setId(const std::string &newid); + + /** + * @brief Sets a callback for setting changes notification + * @param callback Function to call when settings change + */ + void setNotifier(const std::function<void(const std::string&, const std::string&, SettingValue)>& callback); + + /** + * @brief Gets the number of settings + * @return The total count of settings + */ + std::size_t size() const; + + /** + * @brief Iterates over all settings in a thread-safe manner + * @param callback Function called for each key-value pair + */ + void forEach(const std::function<void(const SettingKey&, const SettingValue&)>& callback) const; + +private: + std::unique_ptr<SettingsPrivate> m_ptr; ///< Private implementation pointer +}; + + +/** + * @brief Functor to convert SettingValue variants to string + * + * Provides string conversion for all supported setting value types + */ +struct settingValueFunctor { + std::string operator()(const std::string &x) const { return x; } + std::string operator()(int x) const { return std::to_string(x); } + std::string operator()(double x) const { return std::to_string(x); } + std::string operator()(bool x) const { return x ? "true" : "false"; } +}; + +/** + * @brief Convert a SettingValue into a string for display + * @param value Input SettingValue to convert + * @return std::string containing the converted value + */ +static inline std::string valueToStr(const SettingValue &value) +{ + return std::visit(settingValueFunctor(), value); +} + +/** + * @brief Check if a string represents a valid numeric value + * @param str String to check + * @return true if string is numeric, false otherwise + */ +static inline bool is_numeric(const std::string& str) { + return !str.empty() && + str.find_first_not_of("0123456789.-") == std::string::npos && + (std::count(str.begin(), str.end(), '.') <= 1) && + (std::count(str.begin(), str.end(), '-') <= 1) && + (str[0] == '-' || std::isdigit(str[0])); +} + +/** + * @brief Convert a string to appropriate SettingValue type + * @param value Input string to convert + * @return SettingValue containing the converted value + * + * Conversion rules: + * - Quoted strings -> string without quotes + * - Numeric values -> int or double + * - "true"/"on" -> boolean true + * - "false"/"off" -> boolean false + * - Other -> string + */ +static inline SettingValue makeValue(const std::string &value) +{ + if(value.starts_with('"') || value.starts_with('\'')) + { + return value.substr(1, value.length() - 2); + } + + if(is_numeric(value)) + { + // double + if(value.find('.') != value.npos) + { + return std::stod(value); + } + else + { + return std::stoi(value); + } + } + + // To Lower case + std::string lvalue = value; + std::transform(lvalue.begin(), lvalue.end(), lvalue.begin(), + [](unsigned char c){ return std::tolower(c); }); + + + // bool true + if(lvalue == "true" || lvalue == "on") + { + return true; + } + + // bool false + if(lvalue == "false" || lvalue == "off") + { + return false; + } + + // else, string without quote + return value; +} + +}; + +#endif // KAZOESETTINGS_H |