24 #include <seastar/core/sstring.hh>
25 #include <seastar/core/print.hh>
26 #include <seastar/util/modules.hh>
28 #ifndef SEASTAR_MODULE
29 #include <fmt/format.h>
31 #include <boost/any.hpp>
32 #include <boost/intrusive/list.hpp>
35 #include <unordered_map>
56 namespace program_options {
71 class string_map final :
private std::unordered_map<sstring, sstring> {
73 using base = std::unordered_map<sstring, sstring>;
75 using base::value_type;
77 using base::mapped_type;
85 using base::operator[];
94 return static_cast<const string_map::base&
>(lhs) ==
static_cast<const string_map::base&
>(rhs);
97 inline bool operator!=(
const string_map& lhs,
const string_map& rhs) {
104 sstring get_or_default(
const string_map&,
const sstring& key,
const sstring& def = sstring());
106 std::istream& operator>>(std::istream& is, string_map&);
107 std::ostream& operator<<(std::ostream& os,
const string_map&);
114 void validate(boost::any& out,
const std::vector<std::string>& in, string_map*,
int);
116 using list_base_hook = boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
120 SEASTAR_MODULE_EXPORT_BEGIN
128 namespace program_options {
179 virtual void visit_value(
const std::set<unsigned>* default_val) = 0;
189 virtual void visit_value(
const std::unordered_map<sstring, log_level>* default_val) = 0;
192 virtual void visit_selection_value(
const std::vector<std::string>& candidate_names,
const std::size_t* default_candidate) = 0;
247 virtual bool visit_value(std::unordered_map<sstring, log_level>& val) = 0;
250 virtual bool visit_selection_value(
const std::vector<std::string>& candidate_names, std::size_t& selected_candidate) = 0;
294 using value_list_type = boost::intrusive::list<
296 boost::intrusive::base_hook<list_base_hook>,
297 boost::intrusive::constant_time_size<false>>;
299 using option_group_list_type = boost::intrusive::list<
301 boost::intrusive::base_hook<list_base_hook>,
302 boost::intrusive::constant_time_size<false>>;
308 value_list_type _values;
309 option_group_list_type _subgroups;
332 operator bool ()
const {
return !_values.empty(); }
333 bool used()
const {
return _used; }
334 const std::string& name()
const {
return _name; }
335 const value_list_type& values()
const {
return _values; }
336 value_list_type& values() {
return _values; }
387 std::string _description;
402 bool used()
const {
return _used; }
403 const std::string& name()
const {
return _name; }
404 const std::string& description()
const {
return _description; }
413 template <
typename T = std::monostate>
415 std::optional<T> _value;
416 bool _defaulted =
true;
420 auto* val = _value ? &*_value :
nullptr;
426 _value = std::move(val);
431 _value = std::move(
value);
442 value(
option_group& group, std::string name, std::optional<T> default_value, std::string description)
443 :
basic_value(group, true, std::move(name), std::move(description))
444 , _value(std::move(default_value))
452 operator bool ()
const {
return bool(_value); }
457 T&
get_value() {
return _value.value(); }
458 void set_default_value(T
value) { do_set_value(std::move(
value),
true); }
459 void set_value(T
value) { do_set_value(std::move(
value),
false); }
467 std::optional<bool> _set;
475 if (_set.has_value()) {
492 :
basic_value(group, true, std::move(name), std::move(description))
499 operator bool ()
const {
return _set ? _set.value() :
false; }
500 void set_value() { _set =
true; }
501 void unset_value() { _set =
false; }
514 template <
typename T = std::monostate>
517 using deleter = std::function<void(T*)>;
518 using value_handle = std::unique_ptr<T, deleter>;
522 std::unique_ptr<option_group> opts;
524 using candidates = std::vector<candidate>;
527 static constexpr
size_t no_selected_candidate = -1;
530 candidates _candidates;
531 size_t _selected_candidate = no_selected_candidate;
532 bool _defaulted =
true;
535 std::vector<std::string> get_candidate_names()
const {
536 std::vector<std::string> candidate_names;
537 candidate_names.reserve(_candidates.size());
538 for (
const auto& c : _candidates) {
539 candidate_names.push_back(c.name);
541 return candidate_names;
543 virtual void do_describe(options_descriptor& descriptor)
const override {
544 descriptor.visit_selection_value(get_candidate_names(), _selected_candidate == no_selected_candidate ?
nullptr : &_selected_candidate);
545 for (
auto& c : _candidates) {
547 c.opts->describe(descriptor);
551 virtual void do_mutate(options_mutator& mutator)
override {
552 if (mutator.visit_selection_value(get_candidate_names(), _selected_candidate)) {
555 if (_selected_candidate != no_selected_candidate) {
556 auto& c = _candidates.at(_selected_candidate);
558 c.opts->mutate(mutator);
562 size_t find_candidate(
const std::string& candidate_name) {
563 auto it = find_if(_candidates.begin(), _candidates.end(), [&] (
const auto& candidate) {
564 return candidate.name == candidate_name;
566 if (it == _candidates.end()) {
567 throw std::invalid_argument(fmt::format(
"find_candidate(): failed to find candidate {}", candidate_name));
569 return it - _candidates.begin();
572 option_group* do_select_candidate(std::string candidate_name,
bool defaulted) {
573 _selected_candidate = find_candidate(candidate_name);
575 return _candidates.at(_selected_candidate).opts.get();
587 :
basic_value(group, true, std::move(name), std::move(description))
588 , _candidates(std::move(candidates))
589 , _selected_candidate(find_candidate(default_candidate))
592 :
basic_value(group, true, std::move(name), std::move(description))
593 , _candidates(std::move(candidates))
600 operator bool ()
const {
return _selected_candidate != no_selected_candidate; }
609 T& get_selected_candidate()
const {
return *_candidates.at(_selected_candidate).value; }
623 SEASTAR_MODULE_EXPORT_END
Definition: program-options.hh:380
Definition: program-options.hh:290
void mutate(options_mutator &mutator)
option_group(option_group *parent, std::string name, unused)
void describe(options_descriptor &descriptor) const
option_group(option_group *parent, std::string name)
Definition: program-options.hh:140
virtual void visit_value(const std::set< unsigned > *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_value(const logger_ostream_type *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_value(const double *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_value(const std::unordered_map< sstring, log_level > *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_selection_value(const std::vector< std::string > &candidate_names, const std::size_t *default_candidate)=0
Visit a selection value (selection_value), default_candidate is null when there is no default candida...
virtual bool visit_value_metadata(const std::string &name, const std::string &description, bool used)=0
virtual void visit_value(const log_level *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_value(const float *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_group_end()=0
virtual void visit_value(const memory::alloc_failure_kind *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_value(const std::string *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_value(const unsigned *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_value(const int *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual bool visit_group_start(const std::string &name, bool used)=0
virtual void visit_value()=0
Visit a switch (value<std::monostate>).
virtual void visit_value(const logger_timestamp_style *default_val)=0
Visit a value (value), default_val is null when value has no default.
virtual void visit_value(const bool *default_val)=0
Visit a value (value), default_val is null when value has no default.
Definition: program-options.hh:198
virtual bool visit_value(std::set< unsigned > &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual bool visit_value(std::unordered_map< sstring, log_level > &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual bool visit_value_metadata(const std::string &name, bool used)=0
virtual bool visit_value(logger_ostream_type &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual void visit_group_end()=0
virtual bool visit_value()=0
Visit a switch (value<std::monostate>), switch is set to returned value.
virtual bool visit_value(double &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual bool visit_value(float &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual bool visit_group_start(const std::string &name, bool used)=0
virtual bool visit_value(unsigned &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual bool visit_selection_value(const std::vector< std::string > &candidate_names, std::size_t &selected_candidate)=0
Visit and optionally mutate a selection value (selection_value), should return true if value was muta...
virtual bool visit_value(memory::alloc_failure_kind &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual bool visit_value(logger_timestamp_style &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual bool visit_value(int &val)=0
Visit a value (value), default_val is null when value has no default.
virtual bool visit_value(std::string &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual bool visit_value(log_level &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
virtual bool visit_value(bool &val)=0
Visit and optionally mutate a value (value), should return true if value was mutated.
Definition: program-options.hh:515
const option_group * get_selected_candidate_opts() const
Get the options of the currently selected candidate (assumes there is one selected,...
Definition: program-options.hh:606
selection_value(option_group &group, std::string name, unused)
Construct an unused value.
Definition: program-options.hh:596
option_group * select_candidate(std::string candidate_name)
Definition: program-options.hh:613
option_group * select_default_candidate(std::string candidate_name)
Definition: program-options.hh:617
bool defaulted() const
Is the currently selected candidate the default one?
Definition: program-options.hh:602
selection_value(option_group &group, std::string name, candidates candidates, std::string default_candidate, std::string description)
Definition: program-options.hh:586
option_group * get_selected_candidate_opts()
Get the options of the currently selected candidate (assumes there is one selected,...
Definition: program-options.hh:608
const std::string & get_selected_candidate_name() const
Get the name of the currently selected candidate (assumes there is one selected, see \operator bool()...
Definition: program-options.hh:604
Definition: program-options.hh:519
Wrapper for command-line options with arbitrary string associations.
Definition: program-options.hh:71
value(option_group &group, std::string name, unused)
Construct an unused value.
Definition: program-options.hh:495
value(option_group &group, std::string name, std::string description)
Definition: program-options.hh:491
Definition: program-options.hh:414
value(option_group &group, std::string name, std::optional< T > default_value, std::string description)
Definition: program-options.hh:442
bool defaulted() const
Does this value still contain a default-value?
Definition: program-options.hh:454
const T & get_value() const
Return the contained value, assumes there is one, see operator bool().
Definition: program-options.hh:456
value(option_group &group, std::string name, unused)
Construct an unused value.
Definition: program-options.hh:447
A tag type used to construct unused option_group and basic_value objects.
Definition: program-options.hh:254
alloc_failure_kind
The kind of allocation failures to dump diagnostics report for.
Definition: memory_diagnostics.hh:41
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
logger_timestamp_style
Timestamp style.
Definition: log.hh:498
logger_ostream_type
Output stream to use for logging.
Definition: log.hh:505
log_level
log level used with
Definition: log.hh:52