9 #ifndef LARDATAALG_UTILITIES_MULTIPLECHOICESELECTION_H
10 #define LARDATAALG_UTILITIES_MULTIPLECHOICESELECTION_H
19 #include <type_traits>
27 namespace util::details {
30 template <
typename... Strings>
32 = std::conjunction_v<std::is_convertible<Strings, std::string>...>;
38 static bool equal(std::string
const&
a, std::string
const& b);
41 static bool less(std::string
const& a, std::string
const& b);
44 static bool cmp_lower(
unsigned char a,
unsigned char b);
45 static bool eq_lower(
unsigned char a,
unsigned char b);
51 template <
typename Comparer>
53 bool operator() (std::string
const&
a, std::string
const& b)
const;
72 template <
typename Choices>
83 template <
typename... Aliases>
88 template <
typename... Aliases>
90 addAlias(std::string alias, Aliases... moreAliases);
93 bool match(std::string
const& label)
const;
106 operator std::string()
const {
return name(); }
121 std::string
dump()
const;
145 static bool equal(std::string
const&
a, std::string
const& b)
158 namespace util {
class MultipleChoiceSelectionBase; }
174 virtual const char*
what()
const noexcept
override {
return s.c_str(); }
184 std::string
const&
label()
const {
return s; }
192 std::string
const&
label()
const {
return s; }
214 template <
typename Choices>
240 template <
typename... Options>
251 std::size_t
size()
const;
273 template <
typename... Aliases>
287 template <
typename... Aliases>
303 template <
typename... Aliases>
313 bool hasOption(std::string
const& label)
const;
343 Option_t const&
get(std::string
const& label)
const;
369 (std::string
const& indent, std::string
const& firstIndent)
const;
386 std::string, std::size_t,
413 void recordLabel(std::string&& label, std::size_t index);
418 template <
typename... Aliases>
420 recordLabels(std::size_t index, std::string alias, Aliases... moreAliases);
442 static constexpr
auto npos = std::numeric_limits<std::size_t>::max();
448 namespace util::details {
456 template <
typename Choices>
458 MultipleChoiceSelectionOption_t<Choices>
const&
option,
461 template <
typename Choices>
464 MultipleChoiceSelectionOption_t<Choices>
const&
option
470 template <
typename Choices>
472 MultipleChoiceSelectionOption_t<Choices>
const&
option,
475 template <
typename Choices>
478 MultipleChoiceSelectionOption_t<Choices>
const&
option
484 template <
typename Choices>
486 MultipleChoiceSelectionOption_t<Choices>
const&
option,
487 std::string
const& label
489 template <
typename Choices>
491 std::string
const& label,
492 MultipleChoiceSelectionOption_t<Choices>
const&
option
498 template <
typename Choices>
500 MultipleChoiceSelectionOption_t<Choices>
const&
option,
501 std::string
const& label
503 template <
typename Choices>
505 std::string
const& label,
506 MultipleChoiceSelectionOption_t<Choices>
const&
option
515 template <
typename Choices>
516 std::ostream&
operator<<
517 (std::ostream& out, MultipleChoiceSelectionOption_t<Choices>
const&
option);
530 template <
typename B1,
typename E1,
typename B2,
typename E2,
typename Comp>
534 if (b2 == e2)
return false;
536 if (less(*b1, *b2))
return true;
537 if (less(*b2, *b1))
return false;
546 (std::string
const&
a, std::string
const& b)
547 {
return std::equal(a.begin(), a.end(), b.begin(), b.end(), eq_lower); }
552 (std::string
const& a, std::string
const& b)
554 return std::lexicographical_compare
555 (a.begin(), a.end(), b.begin(), b.end(), cmp_lower);
561 (
unsigned char a,
unsigned char b)
562 {
return std::tolower(a) < std::tolower(b); }
567 (
unsigned char a,
unsigned char b)
568 {
return std::tolower(a) == std::tolower(b); }
572 template <
typename Comparer>
574 (std::string
const&
a, std::string
const& b)
const
575 {
return Comparer::less(a, b); }
579 namespace util::details {
581 template <
typename Value,
typename >
585 template <
typename T>
586 static std::optional<std::string>
convert(T
const&) {
return {}; }
590 template <
typename Value>
594 template <
typename T>
598 {
std::to_string(
static_cast<std::underlying_type_t<T>
>(value)) };
603 template <
typename Value>
606 std::is_convertible_v<Value, std::string>
607 || std::is_constructible_v<std::string, Value>
611 template <
typename T>
613 {
return { std::string{ value } }; }
617 template <
typename Value>
619 <Value,
std::
void_t<decltype(std::to_string(std::declval<Value>()))>>
622 template <
typename T>
633 template <
typename Choices>
634 template <
typename... Aliases>
639 fLabels.reserve(1U +
sizeof...(aliases));
640 addAlias(std::move(name), std::move(aliases)...);
645 template <
typename Choices>
646 template <
typename... Aliases>
648 (std::string alias, Aliases... moreAliases)
651 fLabels.push_back(std::move(alias));
652 if constexpr(
sizeof...(moreAliases) > 0)
653 return addAlias(std::move(moreAliases)...);
659 template <
typename Choices>
661 (std::string
const& label)
const
664 fLabels.begin(), fLabels.end(),
665 [&label](std::string
const& alias){
return equal(label, alias); }
671 template <
typename Choices>
674 (std::string
const& defValue)
const
675 {
return value_as_string(
value(), defValue); }
679 template <
typename Choices>
682 {
return value_as_string(
name()); }
686 template <
typename Choices>
687 std::optional<std::string>
696 template <
typename Choices>
701 return value_as_string(value).value_or(defValue);
706 template <
typename Choices>
710 auto iLabel = fLabels.begin();
711 auto const lend = fLabels.end();
712 std::string
s {
'"' };
715 auto const valueStr = value_as_string();
716 if (valueStr != *iLabel) {
721 if (++iLabel != lend) {
722 s +=
" (aliases: \"";
725 while (++iLabel != lend) {
738 template <
typename Choices>
739 bool util::details::operator==
743 template <
typename Choices>
744 bool util::details::operator==
746 {
return option ==
value; }
750 template <
typename Choices>
751 bool util::details::operator!=
755 template <
typename Choices>
756 bool util::details::operator!=
758 {
return option !=
value; }
762 template <
typename Choices>
765 std::string
const& label
767 {
return option.
match(label); }
769 template <
typename Choices>
771 std::string
const& label,
774 {
return option == label; }
778 template <
typename Choices>
781 std::string
const& label
783 {
return !option.
match(label); }
785 template <
typename Choices>
787 std::string
const& label,
790 {
return option != label; }
794 template <
typename Choices>
795 std::ostream& util::details::operator<<
797 { out << option.
name();
return out; }
803 template <
typename Choices>
804 template <
typename... Options>
808 for (
Option_t option: options) addOption(std::move(option));
813 template <
typename Choices>
815 {
return fOptions.size(); }
819 template <
typename Choices>
821 {
return fOptions.empty(); }
825 template <
typename Choices>
826 template <
typename... Aliases>
830 return addOption({
value, std::move(label), std::move(aliases)... });
835 template <
typename Choices>
836 template <
typename... Aliases>
842 std::size_t
const index = findOptionIndex(value);
843 if (index >= fOptions.size())
845 recordLabels(index, aliases...);
846 return fOptions[index].addAlias(std::move(aliases)...);
851 template <
typename Choices>
852 template <
typename... Aliases>
858 return addAlias(option.
value(), std::move(aliases)...);
863 template <
typename Choices>
865 {
return findOption(value) != fOptions.end(); }
869 template <
typename Choices>
871 (std::string
const& label)
const
873 return fLabelToOptionIndex.find(label) != fLabelToOptionIndex.end();
878 template <
typename Choices>
881 {
return hasOption(option.
value()); }
885 template <
typename Choices>
889 auto const iOption = findOption(value);
890 if (iOption == fOptions.end())
897 template <
typename Choices>
901 auto const iLabelIndexPair = fLabelToOptionIndex.find(label);
902 if (iLabelIndexPair == fLabelToOptionIndex.end()) {
905 assert(iLabelIndexPair->second < fOptions.size());
906 return fOptions[iLabelIndexPair->second];
911 template <
typename Choices>
913 (std::string
const& label)
const ->
Option_t const&
920 template <
typename Choices>
922 (std::string
const& sep )
const
924 using namespace std::string_literals;
926 auto iOption = fOptions.begin();
927 auto const oend = fOptions.end();
929 if (iOption == oend)
return "<no options>"s;
931 std::string
s { *iOption };
932 while (++iOption != oend) {
941 template <
typename Choices>
943 (std::string
const& indent, std::string
const& firstIndent)
const
945 using namespace std::string_literals;
947 auto iOption = fOptions.begin();
948 auto const oend = fOptions.end();
950 if (iOption == oend)
return firstIndent +
"<no options>\n"s;
952 std::string
s { firstIndent };
953 s += iOption->dump();
955 while (++iOption != oend) {
957 s += iOption->dump();
965 template <
typename Choices>
969 std::size_t
const newOptionIndex =
size();
971 fOptions.push_back(std::move(option));
972 Option_t const& newOption = fOptions.back();
974 for (
auto iLabel =
labels.begin(); iLabel !=
labels.end(); ++iLabel) {
976 recordLabel(std::string{ *iLabel }, newOptionIndex);
984 for (
auto iNewLabel =
labels.begin(); iNewLabel != iLabel; ++iNewLabel)
985 unregisterLabel(*iNewLabel);
1000 template <
typename Choices>
1002 (std::string&& label, std::size_t index)
1005 auto const iOption = fLabelToOptionIndex.lower_bound(label);
1012 if ((iOption != fLabelToOptionIndex.end())
1013 && !OptionLabelMap_t::key_compare()(label, iOption->first))
1019 fLabelToOptionIndex.emplace_hint(iOption, std::move(label), index);
1025 template <
typename Choices>
1026 template <
typename... Aliases>
1028 (std::size_t index, std::string alias, Aliases... moreAliases)
1032 recordLabel(std::move(alias), index);
1033 if constexpr(
sizeof...(moreAliases) > 0U)
1034 recordLabels(index, std::move(moreAliases)...);
1037 unregisterLabel(alias);
1044 template <
typename Choices>
1046 (std::string
const& label)
1047 { fLabelToOptionIndex.erase(label); }
1051 template <
typename Choices>
1053 ->
typename OptionList_t::const_iterator
1055 auto const matchValue
1057 return std::find_if(fOptions.begin(), fOptions.end(), matchValue);
1062 template <
typename Choices>
1064 ->
typename OptionList_t::iterator
1066 auto const matchValue
1068 return std::find_if(fOptions.begin(), fOptions.end(), matchValue);
1073 template <
typename Choices>
1077 auto const d =
static_cast<std::size_t
>
1079 return (d >=
size())? npos: d;
1084 template <
typename Choices>
1086 (std::string
const& label)
const
1088 auto const iOption = fLabelToOptionIndex.find(label);
1089 return (iOption == fLabelToOptionIndex.end())? npos: iOption->second;
1094 template <
typename Choices>
1096 auto const iOption = findOption(value);
1097 if (iOption == fOptions.end()) {
1109 #endif // LARDATAALG_UTILITIES_MULTIPLECHOICESELECTION_H
Choices Choices_t
Type of the underlying choice.
Request for unknown option.
std::string const & label() const
bool my_lexicographical_compare(B1 b1, E1 e1, B2 b2, E2 e2, Comp less)
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
bool hasOption(Choices_t value) const
Returns whether the selector has an option with the specified value.
std::vector< std::string > const & labels() const
Returns an iterable object with all the labels of the option.
std::enable_if_t< AllConvertibleToStrings_v< Aliases...>, Option_t & > addAlias(std::string alias, Aliases...moreAliases)
Adds aliases.
OptionLabelMap_t fLabelToOptionIndex
Map from labels to option index in fOptions.
static std::optional< std::string > convert(T const &value)
static std::optional< std::string > convert(T const &)
Option_t const & parse(std::string const &label) const
Returns the option matching the specified label.
bool operator==(Option_t const &option) const
Returns whether the two options are the same (same value and name).
static bool cmp_lower(unsigned char a, unsigned char b)
static std::optional< std::string > convert(T const &value)
std::string optionListString(std::string const &sep=", ") const
Returns a string with the (main) name of all options.
void recordLabel(std::string &&label, std::size_t index)
std::size_t size(FixedBins< T, C > const &) noexcept
Base class of util::MultipleChoiceSelection with basics independent of the option type...
static constexpr auto npos
Special value.
Option_t const & addOption(Choices_t value, std::string label, Aliases...aliases)
Adds a new option to the selector.
std::enable_if_t< details::AllConvertibleToStrings_v< Aliases...> > recordLabels(std::size_t index, std::string alias, Aliases...moreAliases)
bool operator!=(Option_t const &option) const
Returns whether the two options are not the same.
Class representing one of the available options to be selected.
Choices_t fValue
The value associated to the option.
std::vector< std::string > fLabels
All the labels.
std::vector< Option_t > OptionList_t
Type of collection of options.
static bool eq_lower(unsigned char a, unsigned char b)
OptionAlreadyExistsError()
std::string optionListDump(std::string const &indent="") const
Returns a string with all the options, one per line.
MultipleChoiceSelectionOption_t(Choices_t value, std::string name, Aliases...aliases)
Constructor: assigns value, name and aliases.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
Option_t const & get(Choices_t value) const
Returns the specified option.
typename std::enable_if< B, T >::type enable_if_t
std::map< std::string, std::size_t, details::SorterFrom< details::CaseInsensitiveComparer > > OptionLabelMap_t
Type of label index (associative container: label to option index).
std::string value_as_string() const
void unregisterLabel(std::string const &label)
Removes the specified label from the register.
static std::optional< std::string > convert(T const &value)
std::string name() const
Returns the name of the option (i.e. the main label).
static bool equal(std::string const &a, std::string const &b)
bool operator()(std::string const &a, std::string const &b) const
bool equal(double a, double b)
Comparison tolerance, in centimeters.
UnknownOptionError(std::string const &label)
constexpr auto AllConvertibleToStrings_v
OptionList_t::const_iterator findOption(Choices_t value) const
Returns an iterator to the option with label, or npos if none.
std::string dump() const
Returns in a string the name and all the aliases.
bool empty() const
Returns whether there is no available option.
static constexpr bool can_convert
std::string optionListDump(std::string const &indent, std::string const &firstIndent) const
Returns a string with all the options, one per line.
std::string to_string(WindowPattern const &pattern)
then echo File list $list not found else cat $list while read file do echo $file sed s
typename make_void< Ts...>::type void_t
static bool less(std::string const &a, std::string const &b)
Returns whether a is lexicographically smaller than b.
bool match(std::string const &label) const
Returns whether this option matches the specified label (name or alias).
OptionAlreadyExistsError(std::string const &label)
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker options
std::string const & label() const
bool operator!=(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Never admit a infinite_endcount_iterator to be equal to anything else.
std::size_t findOptionIndex(Choices_t value) const
Returns the index of the option with label, or npos if none.
Adding an option that already exists.
Helper to select one among multiple choices via strings.
std::size_t size() const
Returns the number of available options.
static bool equal(std::string const &a, std::string const &b)
Returns whether strings a and b are equal.
std::enable_if_t< details::AllConvertibleToStrings_v< Aliases...>, Option_t const & > addAlias(Choices_t value, Aliases...aliases)
Adds aliases to an existing option.
Exception(std::string const &s)
bool operator==(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
TimeTrackTreeStorage::TriggerInputSpec_t convert(TimeTrackTreeStorage::Config::TriggerSpecConfig const &config)
Choices_t value() const
Returns a copy of the value of the option.
virtual const char * what() const noexceptoverride
OptionList_t fOptions
The list of registered objects.
MultipleChoiceSelection()=default