CbmRoot
Loading...
Searching...
No Matches
EnumDict.h
Go to the documentation of this file.
1/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Felix Weiglhofer [committer] */
4#ifndef CBM_ALGO_BASE_UTIL_SERIALIZABLEENUM_H
5#define CBM_ALGO_BASE_UTIL_SERIALIZABLEENUM_H
6
7#include <boost/algorithm/string/predicate.hpp>
8
9#include <algorithm>
10#include <iosfwd>
11#include <optional>
12#include <stdexcept>
13#include <string_view>
14#include <vector>
15
16#include <fmt/format.h>
17#include <xpu/defines.h>
18
19namespace cbm::algo
20{
21 namespace detail
22 {
23 template<typename T>
24 using EnumDict_t = std::vector<std::pair<std::string_view, T>>;
25
26 template<typename T>
27 inline const EnumDict_t<T> EnumDict;
28
29 template<typename T>
30 struct EnumHasDict : std::false_type {
31 };
32
33 template<typename T>
34 inline constexpr bool EnumHasDict_v = EnumHasDict<T>::value;
35
36 template<typename T, typename = std::enable_if_t<detail::EnumHasDict_v<T>>>
37 std::vector<std::string_view> ValidEntries()
38 {
39 std::vector<std::string_view> entries;
40 for (const auto& pair : EnumDict<T>) {
41 entries.push_back(pair.first);
42 }
43 return entries;
44 }
45
46 void RaiseUnknownEntry(std::string_view str, const std::vector<std::string_view>& validEntries);
47 } // namespace detail
48
49 template<typename T, typename = std::enable_if_t<detail::EnumHasDict_v<T>>>
50 std::optional<T> FromString(std::string_view str, bool caseSensitive = false)
51 {
52 const auto& dict = detail::EnumDict<T>;
53 auto it = std::find_if(dict.begin(), dict.end(), [&](const auto& pair) {
54 if (caseSensitive)
55 return pair.first == str;
56 else
57 return boost::iequals(pair.first, str);
58 });
59 if (it == dict.end()) return std::nullopt;
60 return it->second;
61 }
62
63 template<typename T, typename = std::enable_if_t<detail::EnumHasDict_v<T>>>
64 std::string_view ToString(T t)
65 {
66 const auto& dict = detail::EnumDict<T>;
67 auto it = std::find_if(dict.begin(), dict.end(), [t](const auto& pair) { return pair.second == t; });
68 if (it == dict.end()) throw std::runtime_error(fmt::format("Entry {} for enum missing!", static_cast<int>(t)));
69 return it->first;
70 }
71} // namespace cbm::algo
72
73#if XPU_IS_CPU
98#define CBM_ENUM_DICT(type, ...) \
99 template<> \
100 inline const cbm::algo::detail::EnumDict_t<type> cbm::algo::detail::EnumDict<type> = {__VA_ARGS__}; \
101 template<> \
102 struct cbm::algo::detail::EnumHasDict<type> : std::true_type { \
103 }
104#else // XPU_IS_CPU
105// Disable macro in GPU code, causes some issues with nvcc
106#define CBM_ENUM_DICT(type, ...)
107#endif // XPU_IS_CPU
108
109// Stream operators for enums
110// Placed in global namespace to be found by ADL e.g. for std::ostream_iterator
111namespace std
112{
113 template<typename T, typename = std::enable_if_t<cbm::algo::detail::EnumHasDict_v<T>>>
114 std::ostream& operator<<(std::ostream& os, T t)
115 {
116 os << cbm::algo::ToString(t);
117 return os;
118 }
119
120 template<typename T, typename = std::enable_if_t<cbm::algo::detail::EnumHasDict_v<T>>>
121 std::istream& operator>>(std::istream& is, T& t)
122 {
123 std::string str;
124 is >> str;
125 auto maybet = cbm::algo::FromString<T>(str);
126
127 if (!maybet) {
129 }
130 t = *maybet;
131
132 return is;
133 }
134} // namespace std
135
136#endif //CBM_ALGO_BASE_UTIL_SERIALIZABLEENUM_H
std::vector< std::pair< std::string_view, T > > EnumDict_t
Definition EnumDict.h:24
void RaiseUnknownEntry(std::string_view str, const std::vector< std::string_view > &validEntries)
Definition EnumDict.cxx:8
constexpr bool EnumHasDict_v
Definition EnumDict.h:34
std::vector< std::string_view > ValidEntries()
Definition EnumDict.h:37
const EnumDict_t< T > EnumDict
Definition EnumDict.h:27
std::string_view ToString(T t)
Definition EnumDict.h:64
std::optional< T > FromString(std::string_view str, bool caseSensitive=false)
Definition EnumDict.h:50
Hash for CbmL1LinkKey.
std::ostream & operator<<(std::ostream &os, const std::vector< T > &v)
std::istream & operator>>(std::istream &is, T &t)
Definition EnumDict.h:121