Clingo
Loading...
Searching...
No Matches
config.hh
1#pragma once
2
3#include <clingo/core.hh>
4
5#include <clingo/config.h>
6
7namespace Clingo {
8
17
29
31class ConfigArray;
32class ConstConfigMap;
33class ConfigMap;
34
37 public:
42 explicit ConstConfig(clingo_config_t const *stats, ProgramId key) : cfg_{stats}, key_{key} {}
43
48 friend auto c_cast(ConstConfig const &stats) -> clingo_config_t const * { return stats.cfg_; }
49
53 [[nodiscard]] auto type() const -> ConfigType {
54 return static_cast<ConfigType>(Detail::call<clingo_config_type>(cfg_, key_));
55 }
56
60 [[nodiscard]] auto array() const -> ConstConfigArray;
61
66 [[nodiscard]] auto at(size_t index) const -> ConstConfig;
67
69 [[nodiscard]] auto operator[](size_t index) const -> ConstConfig { return at(index); }
70
74 [[nodiscard]] auto map() const -> ConstConfigMap;
75
80 [[nodiscard]] auto get(std::string_view name) const -> ConstConfig;
81
83 [[nodiscard]] auto operator[](std::string_view name) const -> ConstConfig { return get(name); }
84
91 [[nodiscard]] auto value() const -> std::optional<std::string_view> {
92 if (intersects(type(), ConfigType::value)) {
94 bool assigned = false;
95 Detail::handle_error(clingo_config_value_get(cfg_, key_, &value, &assigned));
96 if (assigned) {
97 return std::string_view{value.data, value.size};
98 }
99 return std::nullopt;
100 }
101 throw std::logic_error{"not a value"};
102 }
103
105 [[nodiscard]] auto operator*() const -> std::optional<std::string_view> { return value(); }
106
113 [[nodiscard]] auto description() const -> std::string_view {
114 auto [data, size] = Detail::call<clingo_config_description>(cfg_, key_);
115 return {data, size};
116 }
117
124 [[nodiscard]] auto to_string() const -> std::string {
125 auto bld = StringBuilder{};
126 Detail::handle_error(clingo_config_to_string(cfg_, key_, c_cast(bld)));
127 return std::string{bld.str()};
128 }
129
130 private:
131 friend class Config;
132
133 clingo_config_t const *cfg_;
134 clingo_id_t key_;
135};
136
138class Config : public ConstConfig {
139 public:
144 explicit Config(clingo_config_t *stats, ProgramId key) : ConstConfig{stats, key} {}
145
150 friend auto c_cast(Config const &stats) -> clingo_config_t * { return stats.cfg_(); }
151
153 [[nodiscard]] auto array() const -> ConfigArray;
155 [[nodiscard]] auto at(size_t index) const -> Config;
157 [[nodiscard]] auto operator[](size_t index) const -> Config { return at(index); }
159 [[nodiscard]] auto map() const -> ConfigMap;
161 [[nodiscard]] auto get(std::string_view name) const -> Config;
163 [[nodiscard]] auto operator[](std::string_view name) const -> Config { return get(name); }
164 using ConstConfig::value;
168 void value(std::string_view value) const {
169 if (intersects(type(), ConfigType::value)) {
170 Detail::handle_error(clingo_config_value_set(cfg_(), key_, value.data(), value.size()));
171 } else {
172 throw std::logic_error{"not a value"};
173 }
174 }
177 auto operator=(std::string_view value) const -> Config { // NOLINT
178 this->value(value);
179 return *this;
180 }
181
207 template <class Handler> void add(std::string_view name, std::string_view description, Handler &&handler) const {
208 using HandlerType = std::remove_cvref_t<Handler>;
209
210 static constexpr auto has_get = requires { handler.get(); };
211 static constexpr auto has_array_get = requires { handler.get(std::optional<size_t>{}); };
212 static constexpr auto has_set = requires { std::declval<HandlerType>().set(std::string_view{}); };
213 static constexpr auto has_array_set =
214 requires { std::declval<HandlerType>().set(std::optional<size_t>{}, std::string_view{}); };
215 static constexpr auto is_array = requires { handler.size(); };
216
217 static_assert(!has_get || !has_array_get, "entry cannot have both get with and without index");
218 static_assert(!has_set || !has_array_set, "entry cannot have both set with and without index");
219
220 static constexpr auto c_entry = clingo_config_entry_t{
221 has_get || has_array_get ? +[](size_t const *index, void *data, clingo_string_t *value, bool *has_value) -> bool {
222 CLINGO_TRY {
223 auto *self = static_cast<HandlerType *>(data);
224 thread_local std::optional<std::string> str;
225 if constexpr (has_array_get) {
226 str = self->get(index != nullptr ? std::optional{*index} : std::nullopt);
227 }
228 if constexpr (has_get) {
229 if (index != nullptr) {
230 throw std::logic_error{"cannot get array value"};
231 }
232 str = self->get();
233 }
234 if (str.has_value() && value != nullptr) {
235 value->data = str->data();
236 value->size = str->size();
237 }
238 if (has_value != nullptr) {
239 *has_value = str.has_value();
240 }
241 }
242 CLINGO_CATCH;
243 } : nullptr,
244 has_set || has_array_set ? +[](size_t const *index, char const *value, size_t size, void *data) -> bool {
245 CLINGO_TRY {
246 auto *self = static_cast<HandlerType *>(data);
247 if constexpr (has_array_set) {
248 self->set(index != nullptr ? std::optional{*index} : std::nullopt,
249 std::string_view{value, size});
250 }
251 if constexpr (has_set) {
252 if (index != nullptr) {
253 throw std::logic_error{"cannot set array value"};
254 }
255 self->set(std::string_view{value, size});
256 }
257 }
258 CLINGO_CATCH;
259 } : nullptr,
260 is_array ? +[](void *data, size_t *size, bool *has_size) -> bool {
261 CLINGO_TRY {
262 auto *self = static_cast<HandlerType *>(data);
263 if constexpr (is_array) {
264 if (size != nullptr) {
265 *size = self->size();
266 }
267 }
268 if (has_size != nullptr) {
269 *has_size = is_array;
270 }
271 }
272 CLINGO_CATCH;
273 } : nullptr,
274 [](void *data) { std::unique_ptr<HandlerType>{static_cast<HandlerType *>(data)}; },
275 };
276
277 auto copy = std::make_unique<HandlerType>(std::forward<Handler>(handler));
278 Detail::handle_error(clingo_config_add(cfg_(), key_, name.data(), name.size(), description.data(),
279 description.size(), &c_entry, copy.release()));
280 }
281
289 void add(std::string_view name, std::string_view description) const {
290 Detail::handle_error(clingo_config_add(cfg_(), key_, name.data(), name.size(), description.data(),
291 description.size(), nullptr, nullptr));
292 }
293
294 private:
295 [[nodiscard]] auto cfg_() const -> clingo_config_t * {
296 // NOLINTNEXTLINE
297 return const_cast<clingo_config_t *>(ConstConfig::cfg_);
298 }
299};
300
303 public:
307 using size_type = std::size_t;
309 using difference_type = std::ptrdiff_t;
313 using pointer = Detail::ArrowProxy<value_type>;
315 using iterator = Detail::RandomAccessIterator<ConstConfigArray>;
316
321 explicit ConstConfigArray(clingo_config_t const *stats, ProgramId key) : cfg_{stats}, key_{key} {}
322
324 [[nodiscard]] auto at(size_t index) const -> ConstConfig { return ConstConfig{cfg_, at_(index)}; }
326 [[nodiscard]] auto operator[](size_t index) const -> ConstConfig { return at(index); }
330 [[nodiscard]] auto size() const -> size_t { return Detail::call<clingo_config_array_size>(cfg_, key_); }
334 [[nodiscard]] auto begin() const -> iterator { return iterator{*this, 0}; }
338 [[nodiscard]] auto end() const -> iterator { return iterator{*this, size()}; }
339
340 private:
341 friend class ConfigArray;
342 [[nodiscard]] auto at_(size_t index) const -> clingo_id_t {
343 return Detail::call<clingo_config_array_at>(cfg_, key_, index);
344 }
345
346 clingo_config_t const *cfg_;
347 clingo_id_t key_;
348};
349
350inline auto ConstConfig::array() const -> ConstConfigArray {
351 if (intersects(type(), ConfigType::array)) {
352 return ConstConfigArray{cfg_, key_};
353 }
354 throw std::logic_error{"not an array"};
355}
356
357inline auto ConstConfig::at(size_t index) const -> ConstConfig {
358 return array().at(index);
359}
360
363 public:
367 using size_type = std::size_t;
369 using difference_type = std::ptrdiff_t;
373 using pointer = Detail::ArrowProxy<value_type>;
375 using iterator = Detail::RandomAccessIterator<ConfigArray>;
376
378 explicit ConfigArray(clingo_config_t *stats, ProgramId key) : ConstConfigArray{stats, key} {}
379
381 [[nodiscard]] auto at(size_t index) const -> Config { return Config{cfg_(), at_(index)}; }
383 [[nodiscard]] auto operator[](size_t index) const -> Config { return at(index); }
385 [[nodiscard]] auto begin() const -> iterator { return iterator{*this, 0}; }
387 [[nodiscard]] auto end() const -> iterator { return iterator{*this, size()}; }
388
389 private:
390 [[nodiscard]] auto cfg_() const -> clingo_config_t * {
391 // NOLINTNEXTLINE
392 return const_cast<clingo_config_t *>(ConstConfigArray::cfg_);
393 }
394};
395
396[[nodiscard]] inline auto Config::array() const -> ConfigArray {
397 if (intersects(type(), ConfigType::array)) {
398 return ConfigArray{cfg_(), key_};
399 }
400 throw std::logic_error{"not an array"};
401}
402
403inline auto Config::at(size_t index) const -> Config {
404 return array().at(index);
405}
406
409 public:
411 using key_type = std::string_view;
415 using value_type = std::pair<key_type, mapped_type>;
417 using size_type = std::size_t;
419 using difference_type = std::ptrdiff_t;
423 using pointer = Detail::ArrowProxy<value_type>;
425 using iterator = Detail::RandomAccessIterator<ConstConfigMap>;
426
431 explicit ConstConfigMap(clingo_config_t const *stats, ProgramId key) : cfg_{stats}, key_{key} {}
432
436 [[nodiscard]] auto size() const -> size_t { return Detail::call<clingo_config_map_size>(cfg_, key_); }
437
442 [[nodiscard]] auto at(size_t index) const -> value_type {
443 auto [name, subkey] = at_(index);
444 return {name, ConstConfig{cfg_, subkey}};
445 }
446
451 [[nodiscard]] auto get(std::string_view name) const -> ConstConfig { return ConstConfig{cfg_, at_(name)}; }
452
454 [[nodiscard]] auto operator[](std::string_view name) const -> ConstConfig { return get(name); }
455
460 [[nodiscard]] auto contains(std::string_view name) const -> bool {
461 return Detail::call<clingo_config_map_at>(cfg_, key_, name.data(), name.size(), nullptr);
462 }
463
467 [[nodiscard]] auto begin() const -> iterator { return iterator{*this, 0}; }
468
472 [[nodiscard]] auto end() const -> iterator { return iterator{*this, size()}; }
473
474 private:
475 friend class ConfigMap;
476
477 [[nodiscard]] auto at_(std::string_view name) const -> clingo_id_t {
478 bool has_subkey = false;
479 clingo_id_t subkey = 0;
480 Detail::handle_error(clingo_config_map_at(cfg_, key_, name.data(), name.size(), &subkey, &has_subkey));
481 if (!has_subkey) {
482 throw std::out_of_range{"subkey not found"};
483 }
484 return subkey;
485 }
486
487 [[nodiscard]] auto at_(size_t index) const -> std::pair<std::string_view, clingo_id_t> {
488 auto [data, size] = Detail::call<clingo_config_map_subkey_name>(cfg_, key_, index);
489 auto str = std::string_view{data, size};
490 return {str, at_(str)};
491 }
492
493 clingo_config_t const *cfg_;
494 clingo_id_t key_;
495};
496
497inline auto ConstConfig::map() const -> ConstConfigMap {
498 if (intersects(type(), ConfigType::map)) {
499 return ConstConfigMap{cfg_, key_};
500 }
501 throw std::logic_error{"not a map"};
502}
503
504inline auto ConstConfig::get(std::string_view name) const -> ConstConfig {
505 return map().get(name);
506}
507
509class ConfigMap : public ConstConfigMap {
510 public:
512 using key_type = std::string_view;
516 using value_type = std::pair<key_type, mapped_type>;
518 using size_type = std::size_t;
520 using difference_type = std::ptrdiff_t;
524 using pointer = Detail::ArrowProxy<value_type>;
526 using iterator = Detail::RandomAccessIterator<ConfigMap>;
527
529 explicit ConfigMap(clingo_config_t *stats, ProgramId key) : ConstConfigMap{stats, key} {}
530
532 [[nodiscard]] auto at(size_t index) const -> value_type {
533 auto [name, subkey] = at_(index);
534 return {name, Config{cfg_(), subkey}};
535 }
537 [[nodiscard]] auto get(std::string_view name) const -> Config { return Config{cfg_(), at_(name)}; }
539 [[nodiscard]] auto operator[](std::string_view name) const -> Config { return get(name); }
541 [[nodiscard]] auto begin() const -> iterator { return iterator{*this, 0}; }
543 [[nodiscard]] auto end() const -> iterator { return iterator{*this, size()}; }
544
545 private:
546 [[nodiscard]] auto cfg_() const -> clingo_config_t * {
547 // NOLINTNEXTLINE
548 return const_cast<clingo_config_t *>(ConstConfigMap::cfg_);
549 }
550};
551
552inline auto Config::map() const -> ConfigMap {
553 if (intersects(type(), ConfigType::map)) {
554 return ConfigMap{cfg_(), key_};
555 }
556 throw std::logic_error{"not a map"};
557}
558
559inline auto Config::get(std::string_view name) const -> Config {
560 return map().get(name);
561}
562
564
565} // namespace Clingo
Class modeling a mutable array of configuration entries.
Definition config.hh:362
auto begin() const -> iterator
Get an iterator to the beginning of the array.
Definition config.hh:385
ConfigArray(clingo_config_t *stats, ProgramId key)
Construct from the underlying C API type and a key.
Definition config.hh:378
auto operator[](size_t index) const -> Config
Get the configuration entry at the given index in the array.
Definition config.hh:383
auto end() const -> iterator
Get an iterator to the beginning of the array.
Definition config.hh:387
Detail::ArrowProxy< value_type > pointer
The pointer type.
Definition config.hh:373
auto at(size_t index) const -> Config
Get the configuration entry at the given index in the array.
Definition config.hh:381
Detail::RandomAccessIterator< ConfigArray > iterator
The iterator type.
Definition config.hh:375
std::size_t size_type
The size type.
Definition config.hh:367
std::ptrdiff_t difference_type
The difference type.
Definition config.hh:369
Config value_type
The value type.
Definition config.hh:365
Class modeling a mutable map of configuration entries.
Definition config.hh:509
auto at(size_t index) const -> value_type
Get the name configuration entry pair at the given index in the map.
Definition config.hh:532
Detail::RandomAccessIterator< ConfigMap > iterator
The iterator type.
Definition config.hh:526
std::pair< key_type, mapped_type > value_type
The value type.
Definition config.hh:516
auto begin() const -> iterator
Get an iterator to the beginning of the map.
Definition config.hh:541
std::string_view key_type
The key type.
Definition config.hh:512
value_type reference
The reference type.
Definition config.hh:522
std::ptrdiff_t difference_type
The difference type.
Definition config.hh:520
auto get(std::string_view name) const -> Config
Get the configuration entry with the given name in the map.
Definition config.hh:537
auto end() const -> iterator
Get an iterator to the end of the map.
Definition config.hh:543
auto operator[](std::string_view name) const -> Config
Get the configuration entry with the given name in the map.
Definition config.hh:539
Detail::ArrowProxy< value_type > pointer
The pointer type.
Definition config.hh:524
std::size_t size_type
The size type.
Definition config.hh:518
ConfigMap(clingo_config_t *stats, ProgramId key)
Construct from the underlying C API type and a key.
Definition config.hh:529
Class modeling a mutable configuration entry.
Definition config.hh:138
void add(std::string_view name, std::string_view description) const
Add a new configuration entry.
Definition config.hh:289
auto value() const -> std::optional< std::string_view >
Get the value of the configuration entry.
Definition config.hh:91
friend auto c_cast(Config const &stats) -> clingo_config_t *
Cast the configuration to the underlying C API type.
Definition config.hh:150
void value(std::string_view value) const
Set the value of the configuration entry.
Definition config.hh:168
auto operator=(std::string_view value) const -> Config
Set the value of the configuration entry.
Definition config.hh:177
Config(clingo_config_t *stats, ProgramId key)
Construct from the underlying C API type and a key.
Definition config.hh:144
void add(std::string_view name, std::string_view description, Handler &&handler) const
Add a new configuration entry with a custom handler.
Definition config.hh:207
Class modeling an immutable array of configuration entries.
Definition config.hh:302
std::size_t size_type
The size type.
Definition config.hh:307
ConstConfigArray(clingo_config_t const *stats, ProgramId key)
Construct from the underlying C API type and a key.
Definition config.hh:321
auto operator[](size_t index) const -> ConstConfig
Get the configuration entry at the given index in the array.
Definition config.hh:326
Detail::ArrowProxy< value_type > pointer
The pointer type.
Definition config.hh:313
auto end() const -> iterator
Get an iterator to the end of the array.
Definition config.hh:338
auto size() const -> size_t
Get the size of the array.
Definition config.hh:330
ConstConfig value_type
The value type.
Definition config.hh:305
auto at(size_t index) const -> ConstConfig
Get the configuration entry at the given index in the array.
Definition config.hh:324
auto begin() const -> iterator
Get an iterator to the beginning of the array.
Definition config.hh:334
Detail::RandomAccessIterator< ConstConfigArray > iterator
The iterator type.
Definition config.hh:315
std::ptrdiff_t difference_type
The difference type.
Definition config.hh:309
Class modeling an immutable map of configuration entries.
Definition config.hh:408
std::pair< key_type, mapped_type > value_type
The value type.
Definition config.hh:415
ConstConfigMap(clingo_config_t const *stats, ProgramId key)
Construct from the underlying C API type and a key.
Definition config.hh:431
std::size_t size_type
The size type.
Definition config.hh:417
auto end() const -> iterator
Get an iterator to the end of the map.
Definition config.hh:472
auto begin() const -> iterator
Get an iterator to the beginning of the map.
Definition config.hh:467
value_type reference
The reference type.
Definition config.hh:421
auto contains(std::string_view name) const -> bool
Check if the map contains a configuration entry with the given name.
Definition config.hh:460
std::string_view key_type
The key type.
Definition config.hh:411
auto operator[](std::string_view name) const -> ConstConfig
Get the configuration entry with the given name in the map.
Definition config.hh:454
Detail::ArrowProxy< value_type > pointer
The pointer type.
Definition config.hh:423
auto at(size_t index) const -> value_type
Get the name configuration entry pair at the given index in the map.
Definition config.hh:442
auto size() const -> size_t
Get the size of the map.
Definition config.hh:436
std::ptrdiff_t difference_type
The difference type.
Definition config.hh:419
Detail::RandomAccessIterator< ConstConfigMap > iterator
The iterator type.
Definition config.hh:425
auto get(std::string_view name) const -> ConstConfig
Get the configuration entry with the given name in the map.
Definition config.hh:451
Class modeling an immutable configuration entry.
Definition config.hh:36
friend auto c_cast(ConstConfig const &stats) -> clingo_config_t const *
Cast the configuration to the underlying C API type.
Definition config.hh:48
auto description() const -> std::string_view
Get the description of the configuration entry.
Definition config.hh:113
auto value() const -> std::optional< std::string_view >
Get the value of the configuration entry.
Definition config.hh:91
auto type() const -> ConfigType
Get the type of the configuration entry.
Definition config.hh:53
auto to_string() const -> std::string
Get a string representation of the configuration entry.
Definition config.hh:124
auto operator*() const -> std::optional< std::string_view >
Get the value of the configuration entry.
Definition config.hh:105
ConstConfig(clingo_config_t const *stats, ProgramId key)
Construct from the underlying C API type and a key.
Definition config.hh:42
A string builder for constructing strings.
Definition core.hh:524
struct clingo_config clingo_config_t
Handle for to the solver configuration.
Definition config.h:46
CLINGO_VISIBILITY_DEFAULT bool clingo_config_value_get(clingo_config_t const *config, clingo_id_t key, clingo_string_t *value, bool *has_value)
Get the string value of the given entry.
unsigned clingo_config_type_bitset_t
Bitset for values of type clingo_config_type_e.
Definition config.h:43
CLINGO_VISIBILITY_DEFAULT bool clingo_config_add(clingo_config_t *config, clingo_id_t parent, char const *name, size_t name_size, char const *description, size_t description_size, clingo_config_entry_t const *entry, void *data)
Add a custom configuration entry under a parent key.
CLINGO_VISIBILITY_DEFAULT bool clingo_config_value_set(clingo_config_t *config, clingo_id_t key, char const *value, size_t size)
Set the value of an entry.
CLINGO_VISIBILITY_DEFAULT bool clingo_config_map_at(clingo_config_t const *config, clingo_id_t key, char const *name, size_t size, clingo_id_t *subkey, bool *has_subkey)
Lookup a subkey under the given name.
CLINGO_VISIBILITY_DEFAULT bool clingo_config_to_string(clingo_config_t const *config, clingo_id_t key, clingo_string_builder_t *builder)
Get the string representation of the given theory element.
@ clingo_config_type_array
the entry is an array
Definition config.h:39
@ clingo_config_type_map
the entry is a map
Definition config.h:40
@ clingo_config_type_value
the entry is a (string) value
Definition config.h:38
uint32_t clingo_id_t
Unsigned integer type used in various places.
Definition core.h:77
ConfigType
Enumeration of configuration types.
Definition config.hh:19
auto array() const -> ConstConfigArray
Access the configuration entry as an array.
Definition config.hh:350
auto get(std::string_view name) const -> Config
Get the configuration entry with the given name in the map.
Definition config.hh:559
auto array() const -> ConfigArray
Access the configuration entry as an array.
Definition config.hh:396
auto map() const -> ConstConfigMap
Access the configuration entry as a map.
Definition config.hh:497
auto at(size_t index) const -> Config
Get the configuration entry at the given index in the array.
Definition config.hh:403
auto get(std::string_view name) const -> ConstConfig
Get the configuration entry with the given name in the map.
Definition config.hh:504
auto at(size_t index) const -> ConstConfig
Get the configuration entry at the given index in the array.
Definition config.hh:357
auto map() const -> ConfigMap
Access the configuration entry as a map.
Definition config.hh:552
@ map
The configuration entry is a map of configurations.
@ value
The configuration entry is a double value.
@ array
The configuration entry is a array of configurations.
clingo_id_t ProgramId
A program id used for various kinds of indices.
Definition core.hh:382
#define CLINGO_ENABLE_BITSET_ENUM(E,...)
Opt-in macro for enabling bit operations for a given enum type.
Definition enum.hh:18
Callback interface for custom configuration entries.
Definition config.h:62
Struct to capture strings that are not null-terminated.
Definition core.h:86