3#include "elementa/license.inc"
4#include "elementa/checks.inc"
6#ifndef ELEMENTA_BASE_ENUMS_H
7#define ELEMENTA_BASE_ENUMS_H
13#include <initializer_list>
155template <
typename BaseID,
class HelperIDString>
181 {
if (end) v_ = EnumExtPriv::kValue(BaseID::kAll_);
184 typename std::underlying_type<BaseID>::type f;
185 for (f=0; f<EnumExtPriv::kValue(BaseID::kAll_); f++)
186 if (comb_.has(EnumExtPriv::id(f)))
break;
197 {
return(EnumExtPriv::id(v_)); }
201 {
while (v_ < EnumExtPriv::kValue(BaseID::kAll_))
202 { ++v_;
if (v_ == EnumExtPriv::kValue(BaseID::kAll_))
break;
203 if (comb_.has(EnumExtPriv::id(v_)))
break; }
212 {
return((v_ != o.v_) || (comb_ != o.comb_)); }
216 {
return((v_ == o.v_) && (comb_ == o.comb_)); }
221 typename std::underlying_type<BaseID>::type v_;
225 using Initializer = std::initializer_list<BaseID>;
241 { activate(BaseID::kAll_); }
248 {
for (BaseID f: init) { add(f);
if (f==BaseID::kAll_)
break;} }
252 bool operator!=(
const Combination &o)
const noexcept
253 {
return(bset_ != o.bset_); }
254 bool operator==(
const Combination &o)
const noexcept
255 {
return(bset_ == o.bset_); }
257 size_t size(
void)
const noexcept
258 {
return(bset_.count()); }
260 bool empty(
void)
const noexcept
261 {
return(bset_.count() == 0); }
264 {
return(bset_.any()); }
267 {
return(bset_.all()); }
269 bool has(BaseID f)
const
270 {
if (f==BaseID::kAll_)
return(all());
271 else return(bset_.test(EnumExtPriv::kValue(f))); }
272 bool has(
const Combination & otf)
const
273 {
return((bset_ & otf.bset_) == otf.bset_); }
275 bool hasIntersection(
const Combination & otf)
const
276 {
return((bset_ & otf.bset_).any()); }
279 {
if (f==BaseID::kAll_) bset_.set();
280 else bset_.set(EnumExtPriv::kValue(f)); }
281 void add(
const Combination & tf)
282 { bset_ |= tf.bset_; }
284 void remove(BaseID f)
285 {
if (f==BaseID::kAll_) bset_.reset();
286 else bset_.reset(EnumExtPriv::kValue(f)); }
287 void remove(
const Combination & tf)
288 { bset_ &= tf.bset_; }
291 std::string
to_string(std::string delim=
", ") const noexcept
305 Iterator end(
void)
const noexcept
306 {
return(Iterator(*
this,
true)); }
313 std::bitset< EnumExtPriv::kValue(BaseID::kAll_) > bset_{};
326 Iterator(BaseID val =
static_cast<BaseID
>(0))
noexcept:
327 v_(EnumExtPriv::kValue(val))
336 {
return(EnumExtPriv::id(v_)); }
340 {
if (v_ < EnumExtPriv::kValue(BaseID::kAll_)) v_++;
return(*
this);}
348 {
return(v_ != o.v_); }
352 {
return(v_ == o.v_); }
356 typename std::underlying_type<BaseID>::type v_;
360 static constexpr size_t kSize(
void)
noexcept
361 {
return(
static_cast<size_t>(EnumExtPriv::kValue(BaseID::kAll_))); }
364 static BaseID
first(
void) {
return(
id(0)); }
368 {
return(
id(EnumExtPriv::kValue(BaseID::kAll_) - 1)); }
371#if (ELE_PRE_CPPVER != 2011) && (ELE_PRE_CPPVER != 2014)
372 static constexpr BaseID
Nth(
size_t n)
374 static BaseID
Nth(
size_t n)
376 {
return(
id(
static_cast<typename std::underlying_type<BaseID>::type
>(
380 static constexpr size_t pos(BaseID
id) {
return(kValue(
id)); }
386 auto res = BaseID::kAll_;
388 for (
auto m:
theEnum())
if (
IdName(m) == name) { res = m;
break; }
397 static std::string
IdName(BaseID
id,
bool leavek =
false)
398 {
static std::vector<std::string> strs;
399 static int status{0};
400 static std::string nullstr;
402 if (
id == BaseID::kAll_)
return(
"<All>");
405 strs = std::move(
split(std::string{HelperIDString::IdNames()},
','));
406 if (
static_cast<size_t>(strs.size()) !=
407 static_cast<size_t>(EnumExtPriv::kValue(BaseID::kAll_)))
411 size_t ind = EnumExtPriv::kValue(
id);
412 if ((status != 1) || (ind >= strs.size()))
return(
"<enum-error>");
413 const auto & res = strs[EnumExtPriv::kValue(
id)];
414 if (leavek || (res.size() < 2) ||
415 (res[0] !=
'k') || (res[1] <
'A') || (res[1] >
'Z'))
return(res);
416 return(res.substr(1));
424 {
return(HelperIDString::IdNames()); }
449 Iterator begin(
void)
const noexcept
450 {
return(Iterator()); }
452 Iterator end(
void)
const noexcept
453 {
return(Iterator(BaseID::kAll_)); }
462 static constexpr typename std::underlying_type<BaseID>::type
463 kValue(BaseID
id)
noexcept
465 static_cast<typename std::underlying_type<BaseID>::type
>(
id)); }
467#if (ELE_PRE_CPPVER != 2011) && (ELE_PRE_CPPVER != 2014)
468 static constexpr BaseID id(
typename std::underlying_type<BaseID>::type v)
471 static BaseID id(
typename std::underlying_type<BaseID>::type v)
473 {
if (v >= EnumExtPriv::kValue(BaseID::kAll_))
474 throw(std::out_of_range(
""));
475 return(
static_cast<BaseID
>(v)); }
477 EnumExtPriv(
void) =
default;
502#define ELE_CLASS_ENUM(NameEnumClass,...) \
503 enum class NameEnumClass { __VA_ARGS__ , kAll_ }; \
504 struct NameEnumClass##HelperIDString \
506 static const char * IdNames(void) noexcept \
507 { return(#__VA_ARGS__); } \
509 using NameEnumClass##Enum = elementa::base::EnumExtPriv<\
511 NameEnumClass##HelperIDString>
Iterator over the elements of a combination.
Iterator(const Combination &c, bool end=false) noexcept
Create an iterator on the given combination.
BaseID operator*(void) const
De-referencing the iterator gives the value.
Iterator operator++(int) noexcept
Postfix increment: return, then increment.
Iterator & operator++(void) noexcept
Increment iterator (pre-fix: first increment, then return)
bool operator==(const Iterator &o) const noexcept
Iterator equality.
bool operator!=(const Iterator &o) const noexcept
Iterator unequality.
A combination of several IDs. Not thread-safe.
Combination(const Initializer &init)
Constructor from a set of flags.
std::string to_string(std::string delim=", ") const noexcept
Return a string with the names of all the IDs in the combination.
Iterator over the elements of an extended enum.
BaseID operator*(void) const
De-referencing the iterator gives the value.
bool operator!=(const Iterator &o) const noexcept
Iterator unequality.
bool operator==(const Iterator &o) const noexcept
Iterator equality.
Iterator operator++(int) noexcept
Postfix increment: return, then increment.
Iterator & operator++(void) noexcept
Increment iterator (pre-fix: first increment, then return).
static constexpr BaseID Nth(size_t n)
Return the n-th ID, or throw if out of range.
static BaseID first(void)
Return the first ID.
static constexpr std::string kAllIdNames(void) noexcept
Return a copy of all the ID names of the extended enum.
static constexpr size_t kSize(void) noexcept
Return the number of IDs defined in the enum.
BaseID IDBase
Just to leave the BaseID available here.
static std::string IdName(BaseID id, bool leavek=false)
Return the string corresponding to the ID keyword, or "" if not defined.
static BaseID findByName(const std::string &name)
Return the ID of a given enum from its name as a string.
static EnumExtPriv & theEnum(void) noexcept
Access to the singleton object of this class.
static constexpr size_t pos(BaseID id)
Return the position of the given ID, from 0, in the enum.
static BaseID last(void)
Return the last ID.
Implementation of all extended enum features. You will use its methods.
std::vector< std::string > split(const std::string &s, char delim)
Split a string through a given delimiter.