Lluvia
enums.h
Go to the documentation of this file.
1 
8 #ifndef LLUVIA_CORE_ENUMS_H_
9 #define LLUVIA_CORE_ENUMS_H_
10 
11 #include <algorithm>
12 #include <array>
13 #include <cstdint>
14 #include <stdexcept>
15 #include <string>
16 #include <tuple>
17 #include <typeinfo>
18 #include <vector>
19 
20 namespace ll {
21 
22 // Every lluvia enum should by typed as enum_t
23 using enum_t = uint32_t;
24 
25 // This class is copied from vk::Flags in vulkan.hpp
26 template <typename BitType, typename MaskType = enum_t>
27 class Flags {
28 
29 public:
30  Flags() = default;
31  Flags(const Flags<BitType, MaskType>& f) = default;
33 
34  constexpr Flags(BitType bit) noexcept
35  : m_mask {static_cast<MaskType>(bit)}
36  {
37  }
38 
39  constexpr explicit Flags(MaskType mask)
40  : m_mask {mask}
41  {
42  }
43 
44  ~Flags() = default;
45 
46  // relational operators
47  constexpr bool operator<(Flags<BitType, MaskType> const& rhs) const noexcept
48  {
49  return m_mask < rhs.m_mask;
50  }
51 
52  constexpr bool operator<=(Flags<BitType, MaskType> const& rhs) const noexcept
53  {
54  return m_mask <= rhs.m_mask;
55  }
56 
57  constexpr bool operator>(Flags<BitType, MaskType> const& rhs) const noexcept
58  {
59  return m_mask > rhs.m_mask;
60  }
61 
62  constexpr bool operator>=(Flags<BitType, MaskType> const& rhs) const noexcept
63  {
64  return m_mask >= rhs.m_mask;
65  }
66 
67  constexpr bool operator==(Flags<BitType, MaskType> const& rhs) const noexcept
68  {
69  return m_mask == rhs.m_mask;
70  }
71 
72  constexpr bool operator!=(Flags<BitType, MaskType> const& rhs) const noexcept
73  {
74  return m_mask != rhs.m_mask;
75  }
76 
77  // logical operator
78  constexpr bool operator!() const noexcept
79  {
80  return !m_mask;
81  }
82 
83  // bitwise operators
84  constexpr Flags<BitType, MaskType> operator&(Flags<BitType, MaskType> const& rhs) const noexcept
85  {
86  return Flags<BitType, MaskType>(m_mask & rhs.m_mask);
87  }
88 
89  constexpr Flags<BitType, MaskType> operator|(Flags<BitType, MaskType> const& rhs) const noexcept
90  {
91  return Flags<BitType, MaskType>(m_mask | rhs.m_mask);
92  }
93 
94  constexpr Flags<BitType, MaskType> operator^(Flags<BitType, MaskType> const& rhs) const noexcept
95  {
96  return Flags<BitType, MaskType>(m_mask ^ rhs.m_mask);
97  }
98 
99  // constexpr Flags<BitType, MaskType> operator~() const noexcept {
100  // return Flags<BitType, MaskType>(m_mask ^ FlagTraits<BitType>::allFlags);
101  // }
102 
103  // assignment operators
105  {
106  m_mask = rhs.m_mask;
107  return *this;
108  }
109 
111  {
112  m_mask |= rhs.m_mask;
113  return *this;
114  }
115 
117  {
118  m_mask &= rhs.m_mask;
119  return *this;
120  }
121 
123  {
124  m_mask ^= rhs.m_mask;
125  return *this;
126  }
127 
128  // cast operators
129  explicit constexpr operator bool() const noexcept
130  {
131  return !!m_mask;
132  }
133 
134  explicit constexpr operator MaskType() const noexcept
135  {
136  return m_mask;
137  }
138 
139 private:
140  MaskType m_mask {0};
141 };
142 
143 namespace impl {
144 
145  template <typename E, std::size_t N, const std::array<std::tuple<const char*, E>, N>& values>
146  inline std::string enumToString(E&& value) noexcept
147  {
148 
149  auto compare = [&value](const std::tuple<const char*, E>& e) {
150  return std::get<1>(e) == value;
151  };
152 
153  auto it = std::find_if(values.cbegin(), values.cend(), compare);
154 
155  return std::get<0>(*it);
156  }
157 
158  template <typename E, std::size_t N, const std::array<std::tuple<const char*, E>, N>& values>
159  inline std::string enumToString(const E& value) noexcept
160  {
161 
162  auto compare = [&value](const std::tuple<const char*, E>& e) {
163  return std::get<1>(e) == value;
164  };
165 
166  auto it = std::find_if(values.cbegin(), values.cend(), compare);
167 
168  return std::get<0>(*it);
169  }
170 
171  template <typename E, typename T, std::size_t N, const std::array<std::tuple<const char*, E>, N>& values>
172  inline E stringToEnum(T&& stringValue)
173  {
174 
175  static_assert(std::is_convertible<T, std::string>(), "T must be a string-like type");
176 
177  auto compare = [&stringValue](const std::tuple<const char*, E>& e) {
178  return std::get<0>(e) == stringValue;
179  };
180 
181  auto it = std::find_if(values.cbegin(), values.cend(), compare);
182 
183  if (it == values.cend()) {
184  throw std::out_of_range("invalid string value [" + stringValue + "] for enum type " + typeid(E).name());
185  }
186 
187  return std::get<1>(*it);
188  }
189 
190  template <typename E, typename Ebits, std::size_t N, const std::array<std::tuple<const char*, Ebits>, N>& values>
191  inline E vectorStringToFlags(const std::vector<std::string>& flagsVector) noexcept
192  {
193 
194  auto flags = E {};
195 
196  for (const auto& strFlag : flagsVector) {
197 
198  for (const auto& flagPair : values) {
199 
200  if (std::get<0>(flagPair) == strFlag) {
201  flags |= std::get<1>(flagPair);
202  break;
203  }
204  }
205  }
206 
207  return flags;
208  }
209 
210  template <typename E, typename Ebits, std::size_t N, const std::array<std::tuple<const char*, Ebits>, N>& values>
211  inline std::vector<std::string> flagsToVectorString(E flags) noexcept
212  {
213 
214  auto flagsVector = std::vector<std::string> {};
215 
216  for (const auto& flagPair : values) {
217 
218  const auto& vFlags = std::get<1>(flagPair);
219 
220  if ((flags & vFlags) == vFlags) {
221  flagsVector.push_back(std::get<0>(flagPair));
222  }
223  }
224 
225  return flagsVector;
226  }
227 
228 } // namespace impl
229 } // namespace ll
230 
231 #endif // LLUVIA_CORE_ENUMS_H_
Definition: enums.h:27
Flags< BitType, MaskType > & operator&=(Flags< BitType, MaskType > const &rhs) noexcept
Definition: enums.h:116
constexpr bool operator!=(Flags< BitType, MaskType > const &rhs) const noexcept
Definition: enums.h:72
constexpr bool operator>=(Flags< BitType, MaskType > const &rhs) const noexcept
Definition: enums.h:62
constexpr bool operator<=(Flags< BitType, MaskType > const &rhs) const noexcept
Definition: enums.h:52
constexpr Flags< BitType, MaskType > operator&(Flags< BitType, MaskType > const &rhs) const noexcept
Definition: enums.h:84
Flags< BitType, MaskType > & operator=(Flags< BitType, MaskType > const &rhs) noexcept
Definition: enums.h:104
Flags(Flags< BitType, MaskType > &&f)=default
Flags< BitType, MaskType > & operator|=(Flags< BitType, MaskType > const &rhs) noexcept
Definition: enums.h:110
constexpr bool operator!() const noexcept
Definition: enums.h:78
constexpr Flags< BitType, MaskType > operator^(Flags< BitType, MaskType > const &rhs) const noexcept
Definition: enums.h:94
constexpr Flags< BitType, MaskType > operator|(Flags< BitType, MaskType > const &rhs) const noexcept
Definition: enums.h:89
constexpr bool operator<(Flags< BitType, MaskType > const &rhs) const noexcept
Definition: enums.h:47
Flags()=default
Flags(const Flags< BitType, MaskType > &f)=default
constexpr bool operator==(Flags< BitType, MaskType > const &rhs) const noexcept
Definition: enums.h:67
constexpr Flags(MaskType mask)
Definition: enums.h:39
~Flags()=default
Flags< BitType, MaskType > & operator^=(Flags< BitType, MaskType > const &rhs) noexcept
Definition: enums.h:122
constexpr bool operator>(Flags< BitType, MaskType > const &rhs) const noexcept
Definition: enums.h:57
constexpr Flags(BitType bit) noexcept
Definition: enums.h:34
E stringToEnum(T &&stringValue)
Definition: enums.h:172
std::string enumToString(E &&value) noexcept
Definition: enums.h:146
E vectorStringToFlags(const std::vector< std::string > &flagsVector) noexcept
Definition: enums.h:191
std::vector< std::string > flagsToVectorString(E flags) noexcept
Definition: enums.h:211
Definition: Buffer.h:28
uint32_t enum_t
Definition: enums.h:23