10 #ifndef ICARUSCODE_DECODE_DECODERTOOLS_DETAILS_KEYVALUESDATA_H
11 #define ICARUSCODE_DECODE_DECODERTOOLS_DETAILS_KEYVALUESDATA_H
17 #include <string_view>
23 #include <type_traits>
31 template <
typename T,
typename Enable =
void>
33 template <
typename T,
unsigned int Base = 10U>
193 struct Item:
public std::pair<std::string, std::vector<std::string>> {
195 using pair_t = std::pair<std::string, std::vector<std::string>>;
208 template <
typename T>
229 {
values().push_back(std::move(value));
return *
this; }
230 Item& addValue(std::string_view value)
231 {
return addValue(std::string{ value }); }
235 template <
typename BIter,
typename EIter>
237 {
while (begin != end) addValue(*begin++);
return *
this; }
241 void clear() {
values().clear(); }
254 std::string
const& key()
const noexcept {
return first; }
259 std::vector<std::string>&
values() noexcept {
return second; }
265 std::string
const&
value(std::size_t index = 0)
const noexcept
266 {
return values()[index]; }
271 std::optional<std::string> optionalValue(std::size_t index)
const noexcept;
303 template <
typename T,
typename Conv>
304 T
getAs(std::size_t index, Conv converter)
const;
320 template <
typename T>
321 T
getAs(std::size_t index)
const;
348 template <
typename T,
bool IgnoreFormatErrors = false,
typename Conv>
349 std::optional<T>
getOptionalAs(std::size_t index, Conv converter)
const;
374 template <
typename T,
bool IgnoreFormatErrors = false>
394 template <
typename T>
395 T
getNumber(std::size_t index,
unsigned int base)
const;
396 template <
typename T>
415 template <
typename T>
417 (std::size_t index,
unsigned int base)
const;
418 template <
typename T>
436 template <
typename T,
typename Conv = details::KeyValuesConverter<T>>
437 std::vector<T>
getVector(Conv converter = {})
const;
460 template <
typename T,
typename Conv = details::KeyValuesConverter<T>>
470 {
return key() < other.key(); }
476 template <
typename T,
typename Iter,
typename Conv>
477 std::vector<T>
convertVector(Iter begin, Iter end, Conv converter)
const;
480 template <
typename T>
500 Item*
findItem(std::string
const& key) noexcept;
511 Item
const*
findItem(std::string
const& key)
const noexcept;
514 Item
const&
getItem(std::string
const& key)
const;
517 bool hasItem(std::string
const& key)
const noexcept;
544 std::ostream&
operator<<
563 :
Error(
"Key '" + key +
"': " + msg) {}
572 :
Error(
"KeyValuesData::DuplicateKey: '" + msg +
'\'')
582 std::string
const& key, std::string
const&
s, std::string
const&
tname =
""
585 "conversion of '" + s +
"'"
586 + (
tname.empty()?
"": (
" to type '" +
tname +
"'")) +
" failed"
590 template <
typename T>
592 {
return { key,
s,
typeid(T).
name() }; }
594 template <
typename T>
596 (std::string
const& key, std::size_t index, std::string
const&
s)
625 (key,
"is required to have a size as first value, but it has no values")
631 " first value '" + valueStr +
"' can't be converted into a vector size"
641 WrongSize(std::string
const& key, std::size_t expected, std::size_t actual)
643 std::
to_string(expected) +
" values (except the size) were expected, "
654 namespace icarus::details {
656 template <
typename T,
unsigned int Base >
668 inline std::optional<std::string> icarus::KeyValuesData::Item::optionalValue
669 (std::size_t index)
const noexcept
671 return (index < nValues())? std::optional{
values()[index] }: std::nullopt;
676 template <
typename T,
typename Conv>
678 (std::size_t index, Conv converter)
const
683 auto const& valueStr =
values()[index];
684 auto const number = converter(valueStr);
685 return number? *number:
throw ConversionFailed::makeFor<T>(key(), valueStr);
691 template <
typename T>
697 template <
typename T,
bool IgnoreFormatErrors ,
typename Conv>
699 (std::size_t index, Conv converter)
const
701 if (index <
values().
size())
return std::nullopt;
703 auto const& valueStr =
values()[index];
704 auto const number = converter(valueStr);
705 return (number || IgnoreFormatErrors)
706 ? number:
throw ConversionFailed::makeFor<T>(key(), valueStr);
712 template <
typename T,
bool IgnoreFormatErrors >
714 (std::size_t index)
const
716 return getOptionalAs<T, IgnoreFormatErrors>
722 template <
typename T>
724 (std::size_t index,
unsigned int base)
const
725 {
return getAs<T>(index,
UseBase<T>{ base }); }
729 template <
typename T>
735 template <
typename T>
737 (std::size_t index,
unsigned int base)
const
738 {
return getOptionalAs<T>(index,
UseBase<T>{ base }); }
742 template <
typename T>
744 (std::size_t index)
const
749 template <
typename T,
typename Conv>
751 (Conv converter )
const
754 convertVector<T>(
values().begin(),
values().end(), std::move(converter));
759 template <
typename T,
typename Conv>
761 (Conv converter )
const
766 std::size_t
const n = getNumber<std::size_t>(0U);
767 if (n !=
values().size() - 1)
770 return convertVector<T>
776 template <
typename T,
typename Iter,
typename Conv>
778 (Iter begin, Iter end, Conv converter)
const
784 std::string
const& valueStr = *it;
785 if (std::optional
const number = converter(valueStr))
786 data.push_back(*number);
788 throw ConversionFailed::makeFor<T>
805 template <
typename T,
typename >
820 std::optional<T> operator() (std::string
const&
s)
const
823 static std::optional<T>
convert(std::string
const&
s)
825 if constexpr (std::is_arithmetic_v<T>) {
827 char const *b = s.data(), *
e = b + s.length();
828 return (std::from_chars(b,
e, number).ptr ==
e)
829 ? std::make_optional(number): std::nullopt;
831 else if constexpr(std::is_constructible_v<T, std::string>){
832 return std::make_optional(T{ s });
834 else return std::nullopt;
842 template <
typename T,
unsigned int Base,
typename Enable>
848 unsigned int base { Base };
853 std::optional<T> operator() (std::string
const&
s)
const
856 std::optional<T>
convert(std::string
const&
s)
const
859 char const *b = s.data(), *
e = b + s.length();
860 return (std::from_chars(b,
e, number, base).ptr ==
e)
861 ? std::make_optional(number): std::nullopt;
877 # if (__GNUC__ >= 11)
881 # error "Redundant workaround on std::from_chars() for GCC"
883 # define ICARUSCODE_DECODE_DECODERTOOLS_DETAILS_KEYVALUESDATA_NEEDS_FROMCHARS_FLOAT
887 #ifdef __clang_major__
888 # if (__clang_major__ >= 12) || ((__clang_major__ == 12) && ((__clang_minor__ >= 1) || (__clang_patchlevel__ >= 1)))
892 # error "Redundant workaround on std::from_chars() for GCC"
894 # define ICARUSCODE_DECODE_DECODERTOOLS_DETAILS_KEYVALUESDATA_NEEDS_FROMCHARS_FLOAT
895 # endif // __clang_major__
896 #endif // __clang_major__
898 #ifdef ICARUSCODE_DECODE_DECODERTOOLS_DETAILS_KEYVALUESDATA_NEEDS_FROMCHARS_FLOAT
902 template <
typename T>
907 std::optional<T> operator() (std::string
const&
s)
const
910 static std::optional<T>
convert(std::string
const&
s)
913 std::istringstream sstr{ s };
916 return (sstr && (sstr >>
std::ws).eof())
917 ? std::make_optional(number):
std::nullopt;
927 #endif // ICARUSCODE_DECODE_DECODERTOOLS_DETAILS_KEYVALUESDATA_H
ItemNotFound(std::string const &key)
bool hasItem(std::string const &key) const noexcept
Returns whether an item with the specified key is present.
T getNumber(std::size_t index, unsigned int base) const
Returns the requested value, converted into a number of type T
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Item * findItem(std::string const &key) noexcept
Returns the item with specified key, nullptr if none.
std::pair< std::string, std::vector< std::string >> pair_t
decltype(auto) items() const noexcept
Returns a forward-iterable list of references to items.
Item const & getItem(std::string const &key) const
Returns the item with specified key, throws std::out_of_range if none.
std::optional< T > getOptionalNumber(std::size_t index, unsigned int base) const
Returns the requested value, converted into a number of type T
std::optional< T > convert(std::string const &s) const
std::optional< T > getOptionalAs(std::size_t index, Conv converter) const
Returns the requested value, converted into type T
ErrorOnKey(std::string const &key, std::string const &msg)
std::optional< T > convertStringInto(std::string const &valueStr) const
Conversion functions.
Item & makeItemImpl(std::string key)
Creates, registers and return a new item (assumed not to exist yet).
Representation of a single item of data: a key and several values.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
std::ostream & operator<<(std::ostream &out, IntegerRanges< T, CheckGrowing > const &ranges)
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
daq::details::BoardSetup_t convert(DaqDecoderICARUSPMT::BoardSetupConfig const &config)
Special function fhicl::TableAs uses to convert BoardSetupConfig.
MissingSize(std::string const &key)
Collection of items with key/values structure.
std::vector< T > convertVector(Iter begin, Iter end, Conv converter) const
std::size_t nValues() const noexcept
Returns the number of values currently present.
auto end(FixedBins< T, C > const &) noexcept
ValueNotAvailable(std::string const &key, std::size_t index)
std::vector< T > getVector(Conv converter={}) const
Returns all the values, each converted into type T
typename std::enable_if< B, T >::type enable_if_t
T getAs(std::size_t index, Conv converter) const
Returns the requested value, converted into type T
std::vector< Item > fItems
Collection of data items.
Item(std::string key)
Constructs a new item assigning it a key (which should not be changed).
auto begin(FixedBins< T, C > const &) noexcept
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
bool operator<(Item const &other) const noexcept
Lexicographic order by key (case-sensitive).
MissingSize(std::string const &key, std::string const &valueStr)
static ConversionFailed makeFor(std::string const &key, std::string const &s)
std::size_t size() const noexcept
Returns the number of items in the data.
WrongSize(std::string const &key, std::size_t expected, std::size_t actual)
std::vector< T > getSizedVector(Conv converter=Conv{}) const
Returns all the values, each converted into type T
Item & makeItem(std::string key)
Creates and registers a new item with the specified key.
ConversionFailed(std::string const &key, std::string const &s, std::string const &tname="")
Item & makeOrFetchItem(std::string const &key)
Creates or retrieves an item with the specified key.
DuplicateKey(std::string const &msg)
static std::optional< T > convert(std::string const &s)
bool empty() const noexcept
Returns whether there is no item in data.