Clingo
Loading...
Searching...
No Matches
config.hh
1#pragma once
2
3#include <clingo/util/enum.hh>
4#include <clingo/util/print.hh>
5
6#include <clasp/cli/clasp_options.h>
7
8#include <map>
9#include <sstream>
10
11namespace CppClingo::Control {
12
25 public:
29 using KeyType = Clasp::Cli::ClaspCliConfig::KeyType;
33 enum class ValueFlags : uint8_t {
34 none = 0,
35 get = 1, //<! The entry can be read.
36 set = 2,
37 };
40
50 class Entry {
51 public:
56
58 Entry() = default;
60 Entry(Entry &&other) = delete;
62 auto operator=(Entry &&other) -> Entry & = delete;
64 virtual ~Entry() = default;
65
67 [[nodiscard]] auto value_info() -> ValueFlags { return do_value_type(); }
69 auto get_value(std::optional<IndexType> index, std::string &value) -> bool {
70 return do_get_value(index, value);
71 }
73 void set_value(std::optional<KeyType> index, std::string_view value) { do_set_value(index, value); }
77 auto size_array() -> std::optional<int> { return do_array_size(); }
78
79 private:
80 virtual auto do_value_type() -> ValueFlags { return ValueFlags::none; }
81 virtual auto do_get_value([[maybe_unused]] std::optional<KeyType> index, [[maybe_unused]] std::string &value)
82 -> bool {
83 error_("cannot get value");
84 return false;
85 }
86 virtual void do_set_value([[maybe_unused]] std::optional<KeyType> index,
87 [[maybe_unused]] std::string_view value) {
88 error_("cannot set value");
89 }
90 virtual auto do_array_size() -> std::optional<int> { return std::nullopt; }
91 };
92
96 ClingoConfig(Clasp::Cli::ClaspCliConfig &config) : config_{&config} {}
97
99 static auto key_root() -> KeyType { return Clasp::Cli::ClaspCliConfig::key_root; }
100
109 void key_info(KeyType key, int *n_children, int *array_info, ValueFlags *value_info) const;
110
115 auto description(KeyType key) const -> std::string_view;
116
126 [[nodiscard]] auto array_at(KeyType key, KeyType index) const -> KeyType;
127
137 [[nodiscard]] auto map_at(KeyType key, std::string_view path) const -> std::optional<KeyType>;
138
148 [[nodiscard]] auto map_nth(KeyType key, KeyType index) const -> std::string_view;
149
158 [[nodiscard]] auto get_value(KeyType key) const -> std::optional<std::string_view>;
159
167 void set_value(KeyType key, std::string_view value);
168
183 void add_entry(KeyType key, std::string_view name, std::string_view description,
184 std::unique_ptr<Entry> entry = nullptr);
185
190 void str(Util::OutputBuffer &out, KeyType key) const;
191
193 [[nodiscard]] auto clasp() const -> Clasp::Cli::ClaspCliConfig & { return *config_; }
194
195 private:
196 static constexpr KeyType Bits = sizeof(KeyType) * 8;
197 static constexpr KeyType BitsIndex = 8;
198 static constexpr KeyType BitsKeyId = Bits - BitsIndex - 1;
199
200 static constexpr KeyType MaskClingo = KeyType{1} << (Bits - 1);
201 static constexpr KeyType MaskKeyId = ((KeyType{1} << BitsKeyId) - 1) << BitsIndex;
202 static constexpr KeyType MaskIndex = (KeyType{1} << BitsIndex) - 1;
203
208 static auto index_invalid() -> KeyType { return KeyType(-1); }
212 static auto key_invalid() -> KeyType { return Clasp::Cli::ClaspCliConfig::key_invalid; }
213
214 struct FromRep {};
215 [[maybe_unused]] static constexpr FromRep from_rep{};
216
218 static auto check_(KeyType key) -> KeyType {
219 if (key == key_invalid()) {
220 error_("invalid key");
221 }
222 return key;
223 }
224
226 template <class... T> static void error_(T const &...args) {
227 std::ostringstream oss;
228 oss << "configuration error: ";
229 (oss << ... << args); // NOLINT
230 throw std::runtime_error{oss.str()};
231 }
232
234 template <class P> static void init_(P *val, P def) {
235 if (val != nullptr) {
236 *val = def;
237 }
238 }
239
252 class Key {
253 public:
257 explicit Key(KeyType key_id, std::optional<KeyType> index = std::nullopt)
258 : rep_{MaskClingo | encode_key_id(key_id) | encode_array(index)} {}
259
263 explicit Key([[maybe_unused]] FromRep tag, KeyType value) : rep_{value} {
264 if ((rep_ & MaskIndex) == MaskIndex || (rep_ & MaskClingo) == 0) {
265 error_("invalid key");
266 }
267 }
268
270 [[nodiscard]] auto key_id() const -> KeyType;
272 [[nodiscard]] auto index() const -> std::optional<KeyType>;
274 [[nodiscard]] auto subkey(Key child) const -> Key;
276 [[nodiscard]] auto rep() const -> KeyType;
277
279 [[nodiscard, maybe_unused]] friend auto operator==(Key const &a, Key const &b) -> bool = default;
281 [[nodiscard, maybe_unused]] friend auto operator<=>(Key const &a, Key const &b)
282 -> std::strong_ordering = default;
283
284 private:
285 static auto encode_array(std::optional<KeyType> index) -> KeyType;
286 static auto encode_key_id(KeyType key_id) -> KeyType;
287
288 KeyType rep_;
289 };
290
292 class Node {
293 public:
295 explicit Node(std::string_view description, std::unique_ptr<Entry> entry)
296 : entry_{std::move(entry)}, description_{description} {}
297
299 [[nodiscard]] auto description() const -> std::string_view;
301 [[nodiscard]] auto entries() const -> int;
302
304 [[nodiscard]] auto map_at(Key key, std::string_view name) const -> std::optional<Key>;
306 [[nodiscard]] auto map_nth(KeyType index) const -> std::optional<std::string_view>;
308 [[nodiscard]] auto array_at(Key key, KeyType index) const -> Key;
310 auto get_value(std::optional<KeyType> index, std::string &value) const -> bool;
312 void set_value(std::optional<KeyType> index, std::string_view value);
314 void info(Key key, int *n_children, int *array_info, ValueFlags *value_info) const;
316 void add_subkey(std::string_view name, Key parent, Key child);
317
318 private:
319 std::unique_ptr<Entry> entry_;
320 std::map<std::string, Key, std::less<>> subkeys_;
321 std::string description_;
322 };
323
334 static auto parse_name_(std::string_view &name) -> std::optional<IndexType>;
335
350 auto parse_path_(Key key, std::string_view path) const -> std::optional<Key>;
351 // Checks if this key is a clasp key.
352 //
353 // Returns true if the upper bit is not set.
354 [[nodiscard]] static auto is_clasp(KeyType key) -> bool;
355
356 // Checks if this key is a clingo key.
357 //
358 // Returns the key if the upper bit is set and thows an exception for the
359 // invalid key.
360 [[nodiscard]] static auto is_clingo(KeyType key) -> std::optional<Key>;
361
362 // Get the string representation of the configuration tree under the given key.
363 void str_(Util::OutputBuffer &out, KeyType key, size_t first_indent, size_t indent) const;
364
365 Clasp::Cli::ClaspCliConfig *config_;
366 std::string mutable buf_;
367 std::vector<Node> nodes_;
368};
369
370} // namespace CppClingo::Control
A configuration entry interface to interact with configuration entries.
Definition config.hh:50
Entry()=default
Constructor for Entry.
Entry(Entry &&other)=delete
Prevent copying and moving of Entries.
virtual ~Entry()=default
Destructor for Entry.
auto value_info() -> ValueFlags
Get information about the value of the entry.
Definition config.hh:67
ClingoConfig::KeyType KeyType
Type used for indexing array entries.
Definition config.hh:55
auto size_array() -> std::optional< int >
Returns the number of elements of an array entry.
Definition config.hh:77
void set_value(std::optional< KeyType > index, std::string_view value)
Set a new value for the entry.
Definition config.hh:73
auto get_value(std::optional< IndexType > index, std::string &value) -> bool
Get the value of the entry.
Definition config.hh:69
auto operator=(Entry &&other) -> Entry &=delete
Prevent copying and moving of Entries.
This class provides a hierarchical configuration interface for clingo.
Definition config.hh:24
Clasp::Cli::ClaspCliConfig::KeyType KeyType
The type of configuration keys to refer to entries.
Definition config.hh:29
ValueFlags
The available value types of configuration entries.
Definition config.hh:33
@ none
The entry cannot have a value.
void set_value(KeyType key, std::string_view value)
Set the value of a configuration entry.
void str(Util::OutputBuffer &out, KeyType key) const
Get the string representation of a configuration tree.
KeyType IndexType
Type used for array indexing of configuration entries.
Definition config.hh:31
CLINGO_ENABLE_BITSET_ENUM(ValueFlags, friend)
Enabes bitset operations for ValueFlags.
auto clasp() const -> Clasp::Cli::ClaspCliConfig &
Get the underlying clasp configuration object.
Definition config.hh:193
auto description(KeyType key) const -> std::string_view
Get the description of a configuration entry.
void key_info(KeyType key, int *n_children, int *array_info, ValueFlags *value_info) const
Retrieves information about the specified key.
auto array_at(KeyType key, KeyType index) const -> KeyType
Get the key for an element at a specific index in an array entry.
ClingoConfig(Clasp::Cli::ClaspCliConfig &config)
Constructor for ClingoConfig.
Definition config.hh:96
auto get_value(KeyType key) const -> std::optional< std::string_view >
Get the value of a configuration entry.
auto map_at(KeyType key, std::string_view path) const -> std::optional< KeyType >
Get the key for a named subkey in a map entry.
void add_entry(KeyType key, std::string_view name, std::string_view description, std::unique_ptr< Entry > entry=nullptr)
Adds a new clingo configuration entry to the configuration tree.
auto map_nth(KeyType key, KeyType index) const -> std::string_view
Get the name of the nth subkey in a map entry.
static auto key_root() -> KeyType
The root key of the configuration.
Definition config.hh:99
Create an output buffer that bears some similarities with C++'s iostreams.
Definition print.hh:24
@ info
Debug messages.
@ less
The less than symbol (<).