LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
MultipleChoiceSelection.h
Go to the documentation of this file.
1 
9 #ifndef LARDATAALG_UTILITIES_MULTIPLECHOICESELECTION_H
10 #define LARDATAALG_UTILITIES_MULTIPLECHOICESELECTION_H
11 
12 // C/C++ standard library
13 #include <algorithm> // std::equal(), std::lexicographical_compare()
14 #include <cassert>
15 #include <cctype> // std::tolower()
16 #include <cstddef> // std::size_t
17 #include <exception> // std::exception
18 #include <limits>
19 #include <map>
20 #include <optional>
21 #include <ostream>
22 #include <string>
23 #include <type_traits> // std::conjunction_v, std::is_convertible...
24 #include <vector>
25 
26 // -----------------------------------------------------------------------------
27 namespace util::details {
28 
29  // ---------------------------------------------------------------------------
30  template <typename... Strings>
31  constexpr auto AllConvertibleToStrings_v =
32  std::conjunction_v<std::is_convertible<Strings, std::string>...>;
33 
34  // ---------------------------------------------------------------------------
36 
38  static bool equal(std::string const& a, std::string const& b);
39 
41  static bool less(std::string const& a, std::string const& b);
42 
43  private:
44  static bool cmp_lower(unsigned char a, unsigned char b);
45  static bool eq_lower(unsigned char a, unsigned char b);
46 
47  }; // struct CaseInsensitiveComparer
48 
49  // ---------------------------------------------------------------------------
50  template <typename Comparer>
51  struct SorterFrom {
52  bool operator()(std::string const& a, std::string const& b) const;
53  }; // struct SorterFrom<>
54 
55  // ---------------------------------------------------------------------------
56  template <typename Value, typename = void>
57  struct ValueToString;
58 
59  // ---------------------------------------------------------------------------
71  template <typename Choices>
73 
75 
76  public:
77  using Choices_t = Choices;
79 
81  template <typename... Aliases>
82  MultipleChoiceSelectionOption_t(Choices_t value, std::string name, Aliases... aliases);
83 
85  template <typename... Aliases>
86  std::enable_if_t<AllConvertibleToStrings_v<Aliases...>, Option_t&> addAlias(
87  std::string alias,
88  Aliases... moreAliases);
89 
91  bool match(std::string const& label) const;
92 
94  Choices_t value() const { return fValue; }
95 
97  std::string name() const { return labels().front(); }
98 
100  std::vector<std::string> const& labels() const { return fLabels; }
101 
103  operator std::string() const { return name(); }
104 
106  operator Choices_t() const { return value(); }
107 
112  std::string value_as_string() const;
113 
115  std::string value_as_string(std::string const& defValue) const;
116 
118  std::string dump() const;
119 
121  bool operator==(Option_t const& option) const
122  {
123  return (value() == option.value()) && equal(name(), option.name());
124  }
125 
127  bool operator!=(Option_t const& option) const
128  {
129  return (value() != option.value()) || !equal(name(), option.name());
130  }
131 
133  static std::optional<std::string> value_as_string(Choices_t value);
134 
136  static std::string value_as_string(Choices_t value, std::string const& defValue);
137 
138  private:
140  std::vector<std::string> fLabels;
141 
142  static bool equal(std::string const& a, std::string const& b)
143  {
144  return Comparer_t::equal(a, b);
145  }
146 
147  }; // MultipleChoiceSelectionOption_t
148 
149  // ---------------------------------------------------------------------------
150 
151 } // namespace util::details
152 
153 // -----------------------------------------------------------------------------
154 namespace util {
156 }
157 
163 
164 public:
165  // --- BEGIN -- Exceptions ---------------------------------------------------
168 
170  Exception(std::string const& s) : s(s) {}
171  virtual const char* what() const noexcept override { return s.c_str(); }
172 
173  std::string s;
174  }; // Exception
175 
179  UnknownOptionError(std::string const& label) : Exception(label) {}
180 
181  std::string const& label() const { return s; }
182  }; // UnknownOptionError
183 
187  OptionAlreadyExistsError(std::string const& label) : Exception(label) {}
188 
189  std::string const& label() const { return s; }
190  }; // OptionAlreadyExistsError
191 
193  // --- END -- Exceptions -----------------------------------------------------
194 
195 }; // class MultipleChoiceSelectionBase
196 
197 // -----------------------------------------------------------------------------
198 namespace util {
199  template <typename>
201 }
211 template <typename Choices>
213 
215 
216 public:
217  using Choices_t = Choices;
218 
220 
221  // --- BEGIN -- Constructors -------------------------------------------------
222 
225  MultipleChoiceSelection() = default;
226 
234  template <typename... Options>
235  MultipleChoiceSelection(std::initializer_list<Option_t> options);
236 
237  // --- END -- Constructors ---------------------------------------------------
238 
239  // --- BEGIN -- Option management --------------------------------------------
242 
244  std::size_t size() const;
245 
247  bool empty() const;
248 
265  template <typename... Aliases>
266  Option_t const& addOption(Choices_t value, std::string label, Aliases... aliases);
267 
277  template <typename... Aliases>
278  std::enable_if_t<details::AllConvertibleToStrings_v<Aliases...>, Option_t const&> addAlias(
280  Aliases... aliases);
281 
293  template <typename... Aliases>
294  std::enable_if_t<details::AllConvertibleToStrings_v<Aliases...>, Option_t const&> addAlias(
295  Option_t const& option,
296  Aliases... aliases);
297 
299  bool hasOption(Choices_t value) const;
300 
302  bool hasOption(std::string const& label) const;
303 
305  bool hasOption(Option_t const& option) const;
306 
308  // --- END -- Option management ----------------------------------------------
309 
310  // --- BEGIN -- Option access ------------------------------------------------
313 
321  Option_t const& get(Choices_t value) const;
322 
330  Option_t const& get(std::string const& label) const;
331 
339  Option_t const& parse(std::string const& label) const;
340 
342  // --- END -- Option access --------------------------------------------------
343 
347 
349  std::string optionListString(std::string const& sep = ", ") const;
350 
352  std::string optionListDump(std::string const& indent, std::string const& firstIndent) const;
353 
355  std::string optionListDump(std::string const& indent = "") const
356  {
357  return optionListDump(indent, indent);
358  }
359 
362 
363 private:
365  using OptionList_t = std::vector<Option_t>;
366 
368  using OptionLabelMap_t =
369  std::map<std::string, std::size_t, details::SorterFrom<details::CaseInsensitiveComparer>>;
370 
372 
375 
387  Option_t const& addOption(Option_t&& option);
388 
391  void recordLabel(std::string&& label, std::size_t index);
392 
396  template <typename... Aliases>
397  std::enable_if_t<details::AllConvertibleToStrings_v<Aliases...>>
398  recordLabels(std::size_t index, std::string alias, Aliases... moreAliases);
399 
401  void unregisterLabel(std::string const& label);
402 
404  typename OptionList_t::const_iterator findOption(Choices_t value) const;
405 
407  typename OptionList_t::iterator findOption(Choices_t value);
408 
410  std::size_t findOptionIndex(Choices_t value) const;
411 
413  std::size_t findOptionIndex(std::string const& label) const;
414 
416  static constexpr auto npos = std::numeric_limits<std::size_t>::max();
417 
418 }; // class util::MultipleChoiceSelection
419 
420 // -----------------------------------------------------------------------------
421 namespace util::details {
422 
426 
428  template <typename Choices>
430  bool operator==(MultipleChoiceSelectionOption_t<Choices> const& option, Choices const value);
431  template <typename Choices>
432  bool operator==(Choices const value, MultipleChoiceSelectionOption_t<Choices> const& option);
434 
436  template <typename Choices>
438  bool operator!=(MultipleChoiceSelectionOption_t<Choices> const& option, Choices const value);
439  template <typename Choices>
440  bool operator!=(Choices const value, MultipleChoiceSelectionOption_t<Choices> const& option);
442 
444  template <typename Choices>
446  bool operator==(MultipleChoiceSelectionOption_t<Choices> const& option, std::string const& label);
447  template <typename Choices>
448  bool operator==(std::string const& label, MultipleChoiceSelectionOption_t<Choices> const& option);
450 
452  template <typename Choices>
454  bool operator!=(MultipleChoiceSelectionOption_t<Choices> const& option, std::string const& label);
455  template <typename Choices>
456  bool operator!=(std::string const& label, MultipleChoiceSelectionOption_t<Choices> const& option);
458 
461 
463  template <typename Choices>
464  std::ostream& operator<<(std::ostream& out,
465  MultipleChoiceSelectionOption_t<Choices> const& option);
466 
467 } // namespace util
468 
469 // =============================================================================
470 // --- template implementation
471 // =============================================================================
472 // -----------------------------------------------------------------------------
473 // --- (details)
474 // -----------------------------------------------------------------------------
475 template <typename B1, typename E1, typename B2, typename E2, typename Comp>
476 bool my_lexicographical_compare(B1 b1, E1 e1, B2 b2, E2 e2, Comp less)
477 {
478 
479  while (b1 != e1) {
480  if (b2 == e2) return false; // shorter is less
481 
482  if (less(*b1, *b2)) return true;
483  if (less(*b2, *b1)) return false;
484  // equal so far...
485  ++b1;
486  ++b2;
487  } // while
488  return true; // 1 is shorter
489 } // my_lexicographical_compare()
490 
491 inline bool util::details::CaseInsensitiveComparer::equal(std::string const& a,
492  std::string const& b)
493 {
494  return std::equal(a.begin(), a.end(), b.begin(), b.end(), eq_lower);
495 }
496 
497 // -----------------------------------------------------------------------------
498 inline bool util::details::CaseInsensitiveComparer::less(std::string const& a, std::string const& b)
499 {
500  return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(), cmp_lower);
501 } // util::details::CaseInsensitiveComparer::less()
502 
503 // -----------------------------------------------------------------------------
504 inline bool util::details::CaseInsensitiveComparer::cmp_lower(unsigned char a, unsigned char b)
505 {
506  return std::tolower(a) < std::tolower(b);
507 }
508 
509 // -----------------------------------------------------------------------------
510 inline bool util::details::CaseInsensitiveComparer::eq_lower(unsigned char a, unsigned char b)
511 {
512  return std::tolower(a) == std::tolower(b);
513 }
514 
515 // -----------------------------------------------------------------------------
516 template <typename Comparer>
518  std::string const& b) const
519 {
520  return Comparer::less(a, b);
521 }
522 
523 // -----------------------------------------------------------------------------
524 namespace util::details {
525 
526  template <typename Value, typename /* = void */>
527  struct ValueToString {
528  static constexpr bool can_convert = false;
529 
530  template <typename T>
531  static std::optional<std::string> convert(T const&)
532  {
533  return {};
534  }
535  }; // struct ValueToString
536 
537  // enumerators
538  template <typename Value>
539  struct ValueToString<Value, std::enable_if_t<std::is_enum_v<Value>>> {
540  static constexpr bool can_convert = true;
541 
542  template <typename T>
543  static std::optional<std::string> convert(T const& value)
544  {
545  return {std::to_string(static_cast<std::underlying_type_t<T>>(value))};
546  }
547  }; // ValueToString(enum)
548 
549  // whatever converts to `std::to_string`
550  template <typename Value>
551  struct ValueToString<Value,
552  std::enable_if_t<std::is_convertible_v<Value, std::string> ||
553  std::is_constructible_v<std::string, Value>>> {
554  static constexpr bool can_convert = true;
555  template <typename T>
556  static std::optional<std::string> convert(T const& value)
557  {
558  return {std::string{value}};
559  }
560  }; // ValueToString(string)
561 
562  // whatever supports `std::to_string`
563  template <typename Value>
564  struct ValueToString<Value, std::void_t<decltype(std::to_string(std::declval<Value>()))>> {
565  static constexpr bool can_convert = true;
566  template <typename T>
567  static std::optional<std::string> convert(T const& value)
568  {
569  return {std::to_string(value)};
570  }
571  }; // ValueToString(to_string)
572 
573 } // namespace util::details
574 
575 // -----------------------------------------------------------------------------
576 // --- util::details::MultipleChoiceSelectionOption_t
577 // -----------------------------------------------------------------------------
578 template <typename Choices>
579 template <typename... Aliases>
582  std::string name,
583  Aliases... aliases)
584  : fValue(value)
585 {
586  fLabels.reserve(1U + sizeof...(aliases));
587  addAlias(std::move(name), std::move(aliases)...);
588 } // util::details::MultipleChoiceSelectionOption_t<>::MultipleChoiceSelectionOption_t
589 
590 // -----------------------------------------------------------------------------
591 template <typename Choices>
592 template <typename... Aliases>
594  Aliases... moreAliases)
595  -> std::enable_if_t<AllConvertibleToStrings_v<Aliases...>, Option_t&>
596 {
597  fLabels.push_back(std::move(alias));
598  if constexpr (sizeof...(moreAliases) > 0)
599  return addAlias(std::move(moreAliases)...);
600  else
601  return *this;
602 } // util::details::MultipleChoiceSelectionOption_t<>::addAlias()
603 
604 // -----------------------------------------------------------------------------
605 template <typename Choices>
607 {
608  return std::find_if(fLabels.begin(), fLabels.end(), [&label](std::string const& alias) {
609  return equal(label, alias);
610  }) != fLabels.end();
611 } // util::details::MultipleChoiceSelectionOption_t<>::match()
612 
613 // -----------------------------------------------------------------------------
614 template <typename Choices>
616  std::string const& defValue) const
617 {
618  return value_as_string(value(), defValue);
619 }
620 
621 // -----------------------------------------------------------------------------
622 template <typename Choices>
624 {
625  return value_as_string(name());
626 }
627 
628 // -----------------------------------------------------------------------------
629 template <typename Choices>
632 {
633  return details::ValueToString<std::decay_t<Choices_t>>::convert(value);
634 } // util::details::MultipleChoiceSelectionOption_t<>::value_as_string()
635 
636 // -----------------------------------------------------------------------------
637 template <typename Choices>
640  std::string const& defValue)
641 {
642  return value_as_string(value).value_or(defValue);
643 } // util::details::MultipleChoiceSelectionOption_t<>::value_as_string()
644 
645 // -----------------------------------------------------------------------------
646 template <typename Choices>
648 {
649  auto iLabel = fLabels.begin();
650  auto const lend = fLabels.end();
651  std::string s{'"'};
652  s += *iLabel;
653  s += '"';
654  auto const valueStr = value_as_string();
655  if (valueStr != *iLabel) {
656  s += " [=";
657  s += valueStr;
658  s += "]";
659  }
660  if (++iLabel != lend) {
661  s += " (aliases: \"";
662  s += *iLabel;
663  s += '"';
664  while (++iLabel != lend) {
665  s += " \"";
666  s += *iLabel;
667  s += '"';
668  } // while
669  s += ')';
670  } // if aliases
671 
672  return s;
673 } // util::details::MultipleChoiceSelectionOption_t<>::dump()
674 
675 // -----------------------------------------------------------------------------
676 template <typename Choices>
678  Choices const value)
679 {
680  return option.value() == value;
681 }
682 
683 template <typename Choices>
684 bool util::details::operator==(Choices const value,
686 {
687  return option == value;
688 }
689 
690 // -----------------------------------------------------------------------------
691 template <typename Choices>
693  Choices const value)
694 {
695  return option.value() != value;
696 }
697 
698 template <typename Choices>
699 bool util::details::operator!=(Choices const value,
701 {
702  return option != value;
703 }
704 
705 // -----------------------------------------------------------------------------
706 template <typename Choices>
708  std::string const& label)
709 {
710  return option.match(label);
711 }
712 
713 template <typename Choices>
714 bool util::details::operator==(std::string const& label,
716 {
717  return option == label;
718 }
719 
720 // -----------------------------------------------------------------------------
721 template <typename Choices>
723  std::string const& label)
724 {
725  return !option.match(label);
726 }
727 
728 template <typename Choices>
729 bool util::details::operator!=(std::string const& label,
731 {
732  return option != label;
733 }
734 
735 // -----------------------------------------------------------------------------
736 template <typename Choices>
737 std::ostream& util::details::operator<<(std::ostream& out,
739 {
740  out << option.name();
741  return out;
742 }
743 
744 // -----------------------------------------------------------------------------
745 // --- util::MultipleChoiceSelection
746 // -----------------------------------------------------------------------------
747 template <typename Choices>
748 template <typename... Options>
750  std::initializer_list<Option_t> options)
751 {
752  for (Option_t option : options)
753  addOption(std::move(option));
754 } // util::MultipleChoiceSelection<>::MultipleChoiceSelection()
755 
756 // -----------------------------------------------------------------------------
757 template <typename Choices>
759 {
760  return fOptions.size();
761 }
762 
763 // -----------------------------------------------------------------------------
764 template <typename Choices>
766 {
767  return fOptions.empty();
768 }
769 
770 // -----------------------------------------------------------------------------
771 template <typename Choices>
772 template <typename... Aliases>
774  std::string label,
775  Aliases... aliases) -> Option_t const&
776 {
777  return addOption({value, std::move(label), std::move(aliases)...});
778 } // util::MultipleChoiceSelection<>::addOption()
779 
780 // -----------------------------------------------------------------------------
781 template <typename Choices>
782 template <typename... Aliases>
784  -> std::enable_if_t<details::AllConvertibleToStrings_v<Aliases...>, Option_t const&>
785 {
786  std::size_t const index = findOptionIndex(value);
787  if (index >= fOptions.size()) throw UnknownOptionError(Option_t::value_as_string(value, ""));
788  recordLabels(index, aliases...);
789  return fOptions[index].addAlias(std::move(aliases)...);
790 } // util::MultipleChoiceSelection<>::addAlias()
791 
792 // -----------------------------------------------------------------------------
793 template <typename Choices>
794 template <typename... Aliases>
795 auto util::MultipleChoiceSelection<Choices>::addAlias(Option_t const& option, Aliases... aliases)
796  -> std::enable_if_t<details::AllConvertibleToStrings_v<Aliases...>, Option_t const&>
797 {
798  return addAlias(option.value(), std::move(aliases)...);
799 } // util::MultipleChoiceSelection<>::addAlias()
800 
801 // -----------------------------------------------------------------------------
802 template <typename Choices>
804 {
805  return findOption(value) != fOptions.end();
806 }
807 
808 // -----------------------------------------------------------------------------
809 template <typename Choices>
810 bool util::MultipleChoiceSelection<Choices>::hasOption(std::string const& label) const
811 {
812  return fLabelToOptionIndex.find(label) != fLabelToOptionIndex.end();
813 } // util::MultipleChoiceSelection<>::hasOption(string)
814 
815 // -----------------------------------------------------------------------------
816 template <typename Choices>
818 {
819  return hasOption(option.value());
820 }
821 
822 // -----------------------------------------------------------------------------
823 template <typename Choices>
825 {
826  auto const iOption = findOption(value);
827  if (iOption == fOptions.end())
829  return *iOption;
830 } // util::MultipleChoiceSelection<>::get(value)
831 
832 // -----------------------------------------------------------------------------
833 template <typename Choices>
834 auto util::MultipleChoiceSelection<Choices>::get(std::string const& label) const -> Option_t const&
835 {
836  auto const iLabelIndexPair = fLabelToOptionIndex.find(label);
837  if (iLabelIndexPair == fLabelToOptionIndex.end()) { throw UnknownOptionError(label); }
838  assert(iLabelIndexPair->second < fOptions.size());
839  return fOptions[iLabelIndexPair->second];
840 } // util::MultipleChoiceSelection<>::get(string)
841 
842 // -----------------------------------------------------------------------------
843 template <typename Choices>
844 auto util::MultipleChoiceSelection<Choices>::parse(std::string const& label) const
845  -> Option_t const&
846 {
847  return get(label);
848 } // util::MultipleChoiceSelection<>::parse()
849 
850 // -----------------------------------------------------------------------------
851 template <typename Choices>
853  std::string const& sep /* = ", " */) const
854 {
855  using namespace std::string_literals;
856 
857  auto iOption = fOptions.begin();
858  auto const oend = fOptions.end();
859 
860  if (iOption == oend) return "<no options>"s;
861 
862  std::string s{*iOption};
863  while (++iOption != oend) {
864  s += sep;
865  s += *iOption;
866  } // while
867  return s;
868 } // util::MultipleChoiceSelection<>::optionListString()
869 
870 // -----------------------------------------------------------------------------
871 template <typename Choices>
873  std::string const& indent,
874  std::string const& firstIndent) const
875 {
876  using namespace std::string_literals;
877 
878  auto iOption = fOptions.begin();
879  auto const oend = fOptions.end();
880 
881  if (iOption == oend) return firstIndent + "<no options>\n"s;
882 
883  std::string s{firstIndent};
884  s += iOption->dump();
885  s += '\n';
886  while (++iOption != oend) {
887  s += indent;
888  s += iOption->dump();
889  s += '\n';
890  } // while
891  return s;
892 } // util::MultipleChoiceSelection<>::optionListDump()
893 
894 // -----------------------------------------------------------------------------
895 template <typename Choices>
897 {
898  std::size_t const newOptionIndex = size();
899 
900  fOptions.push_back(std::move(option));
901  Option_t const& newOption = fOptions.back();
902  auto const& labels = newOption.labels();
903  for (auto iLabel = labels.begin(); iLabel != labels.end(); ++iLabel) {
904  try {
905  recordLabel(std::string{*iLabel}, newOptionIndex);
906  }
907  catch (OptionAlreadyExistsError const&) {
908  // we attempt to offer a strong guarantee here,
909  // that the object is restored in the state it was before the call
910 
911  // remove the new entries from the index
912  // (*iLabel was not inserted, and all labels before it were new)
913  for (auto iNewLabel = labels.begin(); iNewLabel != iLabel; ++iNewLabel)
914  unregisterLabel(*iNewLabel);
915 
916  // remove the new option from the list
917  fOptions.pop_back();
918 
919  // let the caller handle the rest
920  throw;
921  } // try ... catch
922  } // for labels
923 
924  return newOption;
925 } // util::MultipleChoiceSelection<>::addOption()
926 
927 // -----------------------------------------------------------------------------
928 template <typename Choices>
929 void util::MultipleChoiceSelection<Choices>::recordLabel(std::string&& label, std::size_t index)
930 {
931 
932  auto const iOption = fLabelToOptionIndex.lower_bound(label);
933 
934  // check for duplicate entries: if iOption is not `end()`, it points to an
935  // element whose key is either greater or equal (equivalent) to `label`;
936  // if the key is greater than `label`, we are good:
937  // we check it by requiring that `label` is smaller than the key;
938  // `key_compare(a, b)` comparison is equivalent to `a < b`,
939  if ((iOption != fLabelToOptionIndex.end()) &&
940  !OptionLabelMap_t::key_compare()(label, iOption->first)) {
941  throw OptionAlreadyExistsError(label); // maybe too terse?
942  }
943 
944  // the actual recording, at last:
945  fLabelToOptionIndex.emplace_hint(iOption, std::move(label), index);
946 
947 } // util::MultipleChoiceSelection<>::recordLabel()
948 
949 // -----------------------------------------------------------------------------
950 template <typename Choices>
951 template <typename... Aliases>
953  std::string alias,
954  Aliases... moreAliases)
955  -> std::enable_if_t<details::AllConvertibleToStrings_v<Aliases...>>
956 {
957  try {
958  recordLabel(std::move(alias), index);
959  if constexpr (sizeof...(moreAliases) > 0U) recordLabels(index, std::move(moreAliases)...);
960  }
961  catch (OptionAlreadyExistsError const&) {
962  unregisterLabel(alias); // if recordLabel() call threw alias is still intact
963  throw;
964  }
965 } // util::MultipleChoiceSelection<>::recordLabels()
966 
967 // -----------------------------------------------------------------------------
968 template <typename Choices>
970 {
971  fLabelToOptionIndex.erase(label);
972 }
973 
974 // -----------------------------------------------------------------------------
975 template <typename Choices>
978 {
979  auto const matchValue = [value](Option_t const& option) { return option.value() == value; };
980  return std::find_if(fOptions.begin(), fOptions.end(), matchValue);
981 } // util::MultipleChoiceSelection<>::findOption(value) const
982 
983 // -----------------------------------------------------------------------------
984 template <typename Choices>
986  typename OptionList_t::iterator
987 {
988  auto const matchValue = [value](Option_t const& option) { return option.value() == value; };
989  return std::find_if(fOptions.begin(), fOptions.end(), matchValue);
990 } // util::MultipleChoiceSelection<>::findOption(value)
991 
992 // -----------------------------------------------------------------------------
993 template <typename Choices>
995 {
996  auto const d = static_cast<std::size_t>(std::distance(fOptions.begin(), findOption(value)));
997  return (d >= size()) ? npos : d;
998 } // util::MultipleChoiceSelection<>::findOptionIndex(value) const
999 
1000 // -----------------------------------------------------------------------------
1001 template <typename Choices>
1002 std::size_t util::MultipleChoiceSelection<Choices>::findOptionIndex(std::string const& label) const
1003 {
1004  auto const iOption = fLabelToOptionIndex.find(label);
1005  return (iOption == fLabelToOptionIndex.end()) ? npos : iOption->second;
1006 } // util::MultipleChoiceSelection<>::findOptionIndex(string) const
1007 
1008 // -----------------------------------------------------------------------------
1009 
1010 // =============================================================================
1011 
1012 #endif // LARDATAALG_UTILITIES_MULTIPLECHOICESELECTION_H
intermediate_table::iterator iterator
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.
Definition: PIDAAlg.h:26
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.
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)
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)
STL namespace.
Base class of util::MultipleChoiceSelection with basics independent of the option type...
Choices Choices_t
Type of the underlying choice.
intermediate_table::const_iterator const_iterator
std::vector< Option_t > OptionList_t
Type of collection of options.
std::ostream & operator<<(std::ostream &out, MultipleChoiceSelectionOption_t< Choices > const &option)
Prints an option into a stream.
std::map< std::string, std::size_t, details::SorterFrom< details::CaseInsensitiveComparer >> OptionLabelMap_t
Type of label index (associative container: label to option index).
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.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
static bool eq_lower(unsigned char a, unsigned char b)
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.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
std::string indent(std::size_t const i)
OptionLabelMap_t fLabelToOptionIndex
Map from labels to option index in fOptions.
Float_t d
Definition: plot.C:235
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.
std::string name() const
Returns the name of the option (i.e. the main label).
double value
Definition: spectrum.C:18
Collection of utilities for dumping data on screen.
Definition: DumperBase.h:28
static bool equal(std::string const &a, std::string const &b)
bool operator()(std::string const &a, std::string const &b) const
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.
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.
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).
bool operator!=(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Never admit a infinite_endcount_iterator to be equal to anything else.
Definition: counter.h:266
std::size_t findOptionIndex(Choices_t value) const
Returns the index of the option with label, or npos if none.
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... > > recordLabels(std::size_t index, std::string alias, Aliases...moreAliases)
virtual const char * what() const noexcept override
bool operator==(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Definition: counter.h:278
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
Choices_t value() const
Returns a copy of the value of the option.