9 #ifndef LARDATAALG_UTILITIES_MULTIPLECHOICESELECTION_H 10 #define LARDATAALG_UTILITIES_MULTIPLECHOICESELECTION_H 19 #include <type_traits> 32 = std::conjunction_v<std::is_convertible<Strings, std::string>...>;
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>
72 template <
typename Choices>
83 template <
typename... Aliases>
88 template <
typename... Aliases>
90 addAlias(
std::string alias, Aliases... moreAliases);
102 std::vector<std::string>
const&
labels()
const {
return fLabels; }
133 static std::optional<std::string> value_as_string(
Choices_t value);
146 {
return Comparer_t::equal(a, b); }
174 virtual const char*
what()
const noexcept
override {
return s.c_str(); }
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>
306 addAlias(
Option_t const& option, Aliases... aliases);
316 bool hasOption(
Option_t const& option)
const;
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);
423 void unregisterLabel(std::string
const&
label);
439 std::size_t findOptionIndex(std::string
const&
label)
const;
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,
489 template <
typename Choices>
492 MultipleChoiceSelectionOption_t<Choices>
const& option
498 template <
typename Choices>
500 MultipleChoiceSelectionOption_t<Choices>
const& option,
503 template <
typename Choices>
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;
547 {
return std::equal(a.begin(), a.end(), b.begin(), b.end(),
eq_lower); }
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>
575 {
return Comparer::less(a, b); }
581 template <
typename Value,
typename >
583 static constexpr
bool can_convert =
false;
585 template <
typename T>
586 static std::optional<std::string>
convert(
T const&) {
return {}; }
590 template <
typename Value>
592 static constexpr
bool can_convert =
true;
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>
610 static constexpr
bool can_convert =
true;
611 template <
typename T>
617 template <
typename Value>
619 <Value,
std::void_t<decltype(std::to_string(std::declval<Value>()))>>
621 static constexpr
bool can_convert =
true;
622 template <
typename T>
633 template <
typename Choices>
634 template <
typename... Aliases>
639 fLabels.reserve(1U +
sizeof...(aliases));
645 template <
typename Choices>
646 template <
typename... Aliases>
652 if constexpr(
sizeof...(moreAliases) > 0)
653 return addAlias(
std::move(moreAliases)...);
659 template <
typename Choices>
664 fLabels.begin(), fLabels.end(),
671 template <
typename Choices>
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();
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>
767 {
return option.
match(label); }
769 template <
typename Choices>
774 {
return option ==
label; }
778 template <
typename Choices>
783 {
return !option.
match(label); }
785 template <
typename Choices>
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>
813 template <
typename Choices>
815 {
return fOptions.size(); }
819 template <
typename Choices>
821 {
return fOptions.empty(); }
825 template <
typename Choices>
826 template <
typename... 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...);
851 template <
typename Choices>
852 template <
typename... Aliases>
863 template <
typename Choices>
865 {
return findOption(value) != fOptions.end(); }
869 template <
typename Choices>
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>
920 template <
typename Choices>
926 auto iOption = fOptions.begin();
927 auto const oend = fOptions.end();
929 if (iOption == oend)
return "<no options>"s;
932 while (++iOption != oend) {
941 template <
typename Choices>
947 auto iOption = fOptions.begin();
948 auto const oend = fOptions.end();
950 if (iOption == oend)
return firstIndent +
"<no options>\n"s;
953 s += iOption->dump();
955 while (++iOption != oend) {
957 s += iOption->dump();
965 template <
typename Choices>
969 std::size_t
const newOptionIndex =
size();
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>
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>
1033 if constexpr(
sizeof...(moreAliases) > 0U)
1034 recordLabels(index,
std::move(moreAliases)...);
1037 unregisterLabel(alias);
1044 template <
typename Choices>
1047 { fLabelToOptionIndex.erase(label); }
1051 template <
typename Choices>
1055 auto const matchValue
1057 return std::find_if(fOptions.begin(), fOptions.end(), matchValue);
1062 template <
typename Choices>
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>
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
Request for unknown option.
std::string const & label() const
std::enable_if_t< details::AllConvertibleToStrings_v< Aliases... >, Option_t const & > addAlias(Choices_t value, Aliases...aliases)
Adds aliases to an existing option.
bool my_lexicographical_compare(B1 b1, E1 e1, B2 b2, E2 e2, Comp less)
Namespace for general, non-LArSoft-specific utilities.
static std::optional< std::string > convert(T const &value)
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.
static std::optional< std::string > convert(T const &)
Option_t const & parse(std::string const &label) const
Returns the option matching the specified label.
static bool cmp_lower(unsigned char a, unsigned char b)
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)
Base class of util::MultipleChoiceSelection with basics independent of the option type...
Choices Choices_t
Type of the underlying choice.
std::vector< Option_t > OptionList_t
Type of collection of options.
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.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
static bool eq_lower(unsigned char a, unsigned char b)
OptionAlreadyExistsError()
MultipleChoiceSelectionOption_t(Choices_t value, std::string name, Aliases...aliases)
Constructor: assigns value, name and aliases.
Option_t const & get(Choices_t value) const
Returns the specified option.
std::string optionListDump(std::string const &indent="") const
Returns a string with all the options, one per line.
def convert(inputfile, outputfile="wire-cell-garfield-fine-response.json.bz2", average=False, shaped=False)
OptionLabelMap_t fLabelToOptionIndex
Map from labels to option index in fOptions.
def dump(input_file, output_file)
MultipleChoiceSelection()=default
std::string value_as_string() const
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
static int max(int a, int b)
void unregisterLabel(std::string const &label)
Removes the specified label from the register.
Option_t const & addOption(Choices_t value, std::string label, Aliases...aliases)
Adds a new option to the selector.
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)
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.
static std::optional< std::string > convert(T const &value)
std::string dump() const
Returns in a string the name and all the aliases.
OptionList_t fOptions
The list of registered objects.
bool empty() const
Returns whether there is no available option.
std::string optionListDump(std::string const &indent, std::string const &firstIndent) const
Returns a string with all the options, one per line.
std::map< std::string, std::size_t, details::SorterFrom< details::CaseInsensitiveComparer > > OptionLabelMap_t
Type of label index (associative container: label to option index).
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)
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::vector< std::string > Strings
std::enable_if_t< details::AllConvertibleToStrings_v< Aliases... > > recordLabels(std::size_t index, std::string alias, Aliases...moreAliases)
virtual const char * what() const noexcept override
Exception(std::string const &s)
bool operator==(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
std::string to_string(ModuleType const mt)
cet::coded_exception< error, detail::translate > exception
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Choices_t value() const
Returns a copy of the value of the option.