Common System 0.2.0
Common interfaces and patterns for system integration
Loading...
Searching...
No Matches
config.cppm
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
17module;
18
19#include <functional>
20#include <map>
21#include <memory>
22#include <optional>
23#include <string>
24#include <variant>
25#include <vector>
26
27export module kcenon.common:config;
28
29export namespace kcenon::common::config {
30
31// ============================================================================
32// Feature Flags
33// ============================================================================
34
39 static constexpr bool has_source_location =
40#if __has_include(<source_location>)
41 true;
42#else
43 false;
44#endif
45
46 static constexpr bool has_concepts = true; // Required for C++20 modules
47 static constexpr bool has_ranges =
48#if __has_include(<ranges>)
49 true;
50#else
51 false;
52#endif
53};
54
55// ============================================================================
56// Configuration Types
57// ============================================================================
58
62using config_value = std::variant<
63 std::string,
64 int64_t,
65 double,
66 bool,
67 std::vector<std::string>,
68 std::map<std::string, std::string>
69>;
70
76 std::string key;
78 std::optional<std::string> description;
79 bool required = false;
80
81 config_entry() = default;
82 config_entry(std::string k, config_value v, std::string desc = "", bool req = false)
83 : key(std::move(k)), value(std::move(v)), description(desc), required(req) {}
84};
85
91public:
92 virtual ~IConfigLoader() = default;
93
98 virtual bool load() = 0;
99
105 virtual std::optional<config_value> get(const std::string& key) const = 0;
106
110 virtual bool has(const std::string& key) const = 0;
111};
112
113// ============================================================================
114// CLI Config Parser
115// ============================================================================
116
122 std::string name;
123 std::string short_name;
124 std::string description;
125 bool required = false;
126 bool takes_value = true;
127 std::optional<std::string> default_value;
128};
129
135 std::map<std::string, std::string> options;
136 std::vector<std::string> positional_args;
137 std::vector<std::string> errors;
138
139 bool has_errors() const { return !errors.empty(); }
140 bool has_option(const std::string& name) const {
141 return options.find(name) != options.end();
142 }
143 std::optional<std::string> get_option(const std::string& name) const {
144 auto it = options.find(name);
145 if (it != options.end()) return it->second;
146 return std::nullopt;
147 }
148};
149
155public:
156 CliConfigParser() = default;
157
161 void add_option(const cli_option& opt) {
162 options_.push_back(opt);
163 }
164
168 cli_parse_result parse(int argc, const char* const* argv) const {
169 cli_parse_result result;
170
171 for (int i = 1; i < argc; ++i) {
172 std::string arg = argv[i];
173
174 if (arg.starts_with("--")) {
175 std::string name = arg.substr(2);
176 auto eq_pos = name.find('=');
177 if (eq_pos != std::string::npos) {
178 result.options[name.substr(0, eq_pos)] = name.substr(eq_pos + 1);
179 } else if (i + 1 < argc && argv[i + 1][0] != '-') {
180 result.options[name] = argv[++i];
181 } else {
182 result.options[name] = "true";
183 }
184 } else if (arg.starts_with("-") && arg.size() == 2) {
185 std::string short_name = arg.substr(1);
186 for (const auto& opt : options_) {
187 if (opt.short_name == short_name) {
188 if (opt.takes_value && i + 1 < argc) {
189 result.options[opt.name] = argv[++i];
190 } else {
191 result.options[opt.name] = "true";
192 }
193 break;
194 }
195 }
196 } else {
197 result.positional_args.push_back(arg);
198 }
199 }
200
201 // Check required options
202 for (const auto& opt : options_) {
203 if (opt.required && !result.has_option(opt.name)) {
204 result.errors.push_back("Missing required option: " + opt.name);
205 }
206 }
207
208 return result;
209 }
210
211private:
212 std::vector<cli_option> options_;
213};
214
215} // namespace kcenon::common::config
Simple command-line argument parser.
Definition config.cppm:154
void add_option(const cli_option &opt)
Add an option definition.
Definition config.cppm:161
std::vector< cli_option > options_
Definition config.cppm:212
cli_parse_result parse(int argc, const char *const *argv) const
Parse command-line arguments.
Definition config.cppm:168
Interface for configuration loaders.
Definition config.cppm:90
virtual bool has(const std::string &key) const =0
Check if a key exists.
virtual bool load()=0
Load configuration from source.
virtual std::optional< config_value > get(const std::string &key) const =0
Get a configuration value.
std::variant< std::string, int64_t, double, bool, std::vector< std::string >, std::map< std::string, std::string > > config_value
Configuration value type.
Definition config.cppm:62
Definition for a CLI option.
Definition config.cppm:121
std::optional< std::string > default_value
Definition config.cppm:127
bool has_option(const std::string &name) const
Definition config.cppm:140
std::map< std::string, std::string > options
Definition config.cppm:135
std::optional< std::string > get_option(const std::string &name) const
Definition config.cppm:143
std::vector< std::string > positional_args
Definition config.cppm:136
std::vector< std::string > errors
Definition config.cppm:137
A single configuration entry.
Definition config.cppm:75
bool required
Definition config.cppm:79
std::optional< std::string > description
Definition config.cppm:78
config_value value
Definition config.cppm:77
std::string key
Definition config.cppm:76
config_entry(std::string k, config_value v, std::string desc="", bool req=false)
Definition config.cppm:82
config_entry()=default
Compile-time feature detection flags.
Definition config.cppm:38
static constexpr bool has_source_location
Definition config.cppm:39
static constexpr bool has_ranges
Definition config.cppm:47
static constexpr bool has_concepts
Definition config.cppm:46