#pragma once
#include "BuildSettings.h"
#include <string>
OPENMPT_NAMESPACE_BEGIN
template <typename Tenum>
struct enum_traits
{
typedef typename std::make_unsigned<Tenum>::type store_type;
};
template <typename enum_t>
class enum_value_type
{
public:
typedef enum_t enum_type;
typedef enum_value_type value_type;
typedef typename enum_traits<enum_t>::store_type store_type;
private:
store_type bits;
public:
MPT_CONSTEXPR11_FUN enum_value_type() noexcept : bits(0) { }
MPT_CONSTEXPR11_FUN enum_value_type(const enum_value_type &x) noexcept : bits(x.bits) { }
MPT_CONSTEXPR11_FUN enum_value_type(enum_type x) noexcept : bits(static_cast<store_type>(x)) { }
private:
explicit MPT_CONSTEXPR11_FUN enum_value_type(store_type x) noexcept : bits(x) { } MPT_CONSTEXPR11_FUN operator store_type () const noexcept { return bits; } public:
static MPT_CONSTEXPR11_FUN enum_value_type from_bits(store_type bits) noexcept { return value_type(bits); }
MPT_CONSTEXPR11_FUN enum_type as_enum() const noexcept { return static_cast<enum_t>(bits); }
MPT_CONSTEXPR11_FUN store_type as_bits() const noexcept { return bits; }
public:
MPT_CONSTEXPR11_FUN operator bool () const noexcept { return bits != store_type(); }
MPT_CONSTEXPR11_FUN bool operator ! () const noexcept { return bits == store_type(); }
MPT_CONSTEXPR11_FUN const enum_value_type operator ~ () const noexcept { return enum_value_type(~bits); }
friend MPT_CONSTEXPR11_FUN bool operator == (enum_value_type a, enum_value_type b) noexcept { return a.bits == b.bits; }
friend MPT_CONSTEXPR11_FUN bool operator != (enum_value_type a, enum_value_type b) noexcept { return a.bits != b.bits; }
friend MPT_CONSTEXPR11_FUN bool operator == (enum_value_type a, enum_t b) noexcept { return a == enum_value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator != (enum_value_type a, enum_t b) noexcept { return a != enum_value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator == (enum_t a, enum_value_type b) noexcept { return enum_value_type(a) == b; }
friend MPT_CONSTEXPR11_FUN bool operator != (enum_t a, enum_value_type b) noexcept { return enum_value_type(a) != b; }
friend MPT_CONSTEXPR11_FUN const enum_value_type operator | (enum_value_type a, enum_value_type b) noexcept { return enum_value_type(a.bits | b.bits); }
friend MPT_CONSTEXPR11_FUN const enum_value_type operator & (enum_value_type a, enum_value_type b) noexcept { return enum_value_type(a.bits & b.bits); }
friend MPT_CONSTEXPR11_FUN const enum_value_type operator ^ (enum_value_type a, enum_value_type b) noexcept { return enum_value_type(a.bits ^ b.bits); }
friend MPT_CONSTEXPR11_FUN const enum_value_type operator | (enum_value_type a, enum_t b) noexcept { return a | enum_value_type(b); }
friend MPT_CONSTEXPR11_FUN const enum_value_type operator & (enum_value_type a, enum_t b) noexcept { return a & enum_value_type(b); }
friend MPT_CONSTEXPR11_FUN const enum_value_type operator ^ (enum_value_type a, enum_t b) noexcept { return a ^ enum_value_type(b); }
friend MPT_CONSTEXPR11_FUN const enum_value_type operator | (enum_t a, enum_value_type b) noexcept { return enum_value_type(a) | b; }
friend MPT_CONSTEXPR11_FUN const enum_value_type operator & (enum_t a, enum_value_type b) noexcept { return enum_value_type(a) & b; }
friend MPT_CONSTEXPR11_FUN const enum_value_type operator ^ (enum_t a, enum_value_type b) noexcept { return enum_value_type(a) ^ b; }
MPT_CONSTEXPR14_FUN enum_value_type &operator |= (enum_value_type b) noexcept { *this = *this | b; return *this; }
MPT_CONSTEXPR14_FUN enum_value_type &operator &= (enum_value_type b) noexcept { *this = *this & b; return *this; }
MPT_CONSTEXPR14_FUN enum_value_type &operator ^= (enum_value_type b) noexcept { *this = *this ^ b; return *this; }
MPT_CONSTEXPR14_FUN enum_value_type &operator |= (enum_t b) noexcept { *this = *this | b; return *this; }
MPT_CONSTEXPR14_FUN enum_value_type &operator &= (enum_t b) noexcept { *this = *this & b; return *this; }
MPT_CONSTEXPR14_FUN enum_value_type &operator ^= (enum_t b) noexcept { *this = *this ^ b; return *this; }
};
template <typename enum_t>
class Enum
{
public:
typedef Enum self_type;
typedef enum_t enum_type;
typedef enum_value_type<enum_t> value_type;
typedef typename value_type::store_type store_type;
private:
enum_type value;
public:
explicit MPT_CONSTEXPR11_FUN Enum(enum_type val) noexcept : value(val) { }
MPT_CONSTEXPR11_FUN operator enum_type () const noexcept { return value; }
MPT_CONSTEXPR14_FUN Enum &operator = (enum_type val) noexcept { value = val; return *this; }
public:
MPT_CONSTEXPR11_FUN const value_type operator ~ () const { return ~value_type(value); }
friend MPT_CONSTEXPR11_FUN bool operator == (self_type a, self_type b) noexcept { return value_type(a) == value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator != (self_type a, self_type b) noexcept { return value_type(a) != value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator == (self_type a, value_type b) noexcept { return value_type(a) == value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator != (self_type a, value_type b) noexcept { return value_type(a) != value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator == (value_type a, self_type b) noexcept { return value_type(a) == value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator != (value_type a, self_type b) noexcept { return value_type(a) != value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator == (self_type a, enum_type b) noexcept { return value_type(a) == value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator != (self_type a, enum_type b) noexcept { return value_type(a) != value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator == (enum_type a, self_type b) noexcept { return value_type(a) == value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator != (enum_type a, self_type b) noexcept { return value_type(a) != value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (self_type a, self_type b) noexcept { return value_type(a) | value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (self_type a, self_type b) noexcept { return value_type(a) & value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (self_type a, self_type b) noexcept { return value_type(a) ^ value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (self_type a, value_type b) noexcept { return value_type(a) | value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (self_type a, value_type b) noexcept { return value_type(a) & value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (self_type a, value_type b) noexcept { return value_type(a) ^ value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (value_type a, self_type b) noexcept { return value_type(a) | value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (value_type a, self_type b) noexcept { return value_type(a) & value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (value_type a, self_type b) noexcept { return value_type(a) ^ value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (self_type a, enum_type b) noexcept { return value_type(a) | value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (self_type a, enum_type b) noexcept { return value_type(a) & value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (self_type a, enum_type b) noexcept { return value_type(a) ^ value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (enum_type a, self_type b) noexcept { return value_type(a) | value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (enum_type a, self_type b) noexcept { return value_type(a) & value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (enum_type a, self_type b) noexcept { return value_type(a) ^ value_type(b); }
};
template <typename enum_t, typename store_t = typename enum_value_type<enum_t>::store_type >
class FlagSet
{
public:
typedef FlagSet self_type;
typedef enum_t enum_type;
typedef enum_value_type<enum_t> value_type;
typedef store_t store_type;
private:
store_type bits_;
static MPT_CONSTEXPR11_FUN store_type store_from_value(value_type bits) noexcept { return static_cast<store_type>(bits.as_bits()); }
static MPT_CONSTEXPR11_FUN value_type value_from_store(store_type bits) noexcept { return value_type::from_bits(static_cast<typename value_type::store_type>(bits)); }
MPT_CONSTEXPR14_FUN FlagSet & store(value_type bits) noexcept { bits_ = store_from_value(bits); return *this; }
MPT_CONSTEXPR11_FUN value_type load() const noexcept { return value_from_store(bits_); }
public:
MPT_CONSTEXPR11_FUN FlagSet() noexcept : bits_(store_from_value(value_type()))
{
}
MPT_CONSTEXPR11_FUN FlagSet(const FlagSet &flags) noexcept
: bits_(flags.bits_)
{
}
MPT_CONSTEXPR11_FUN FlagSet(value_type flags) noexcept : bits_(store_from_value(value_type(flags)))
{
}
MPT_CONSTEXPR11_FUN FlagSet(enum_type flag) noexcept : bits_(store_from_value(value_type(flag)))
{
}
explicit MPT_CONSTEXPR11_FUN FlagSet(store_type flags) noexcept : bits_(store_from_value(value_type::from_bits(flags)))
{
}
MPT_CONSTEXPR11_FUN explicit operator bool () const noexcept
{
return load();
}
MPT_CONSTEXPR11_FUN operator store_type () const noexcept
{
return load().as_bits();
}
MPT_CONSTEXPR11_FUN value_type value() const noexcept
{
return load();
}
MPT_CONSTEXPR11_FUN operator value_type () const noexcept
{
return load();
}
MPT_CONSTEXPR11_FUN bool operator[] (value_type flags) const noexcept
{
return test(flags);
}
std::string to_string() const noexcept
{
std::string str(size_bits(), '0');
for(size_t x = 0; x < size_bits(); ++x)
{
str[size_bits() - x - 1] = (load() & (1 << x) ? '1' : '0');
}
return str;
}
MPT_CONSTEXPR14_FUN FlagSet &set(value_type flags) noexcept
{
return store(load() | flags);
}
MPT_CONSTEXPR14_FUN FlagSet &set(value_type flags, bool val) noexcept
{
return store((val ? (load() | flags) : (load() & ~flags)));
}
MPT_CONSTEXPR14_FUN FlagSet &reset() noexcept
{
return store(value_type());
}
MPT_CONSTEXPR14_FUN FlagSet &reset(value_type flags) noexcept
{
return store(load() & ~flags);
}
MPT_CONSTEXPR14_FUN FlagSet &flip() noexcept
{
return store(~load());
}
MPT_CONSTEXPR14_FUN FlagSet &flip(value_type flags) noexcept
{
return store(load() ^ flags);
}
MPT_CONSTEXPR11_FUN std::size_t size() const noexcept
{
return sizeof(store_type);
}
MPT_CONSTEXPR11_FUN std::size_t size_bits() const noexcept
{
return size() * 8;
}
MPT_CONSTEXPR11_FUN bool test(value_type flags) const noexcept
{
return (load() & flags);
}
MPT_CONSTEXPR11_FUN bool test_all(value_type flags) const noexcept
{
return (load() & flags) == flags;
}
MPT_CONSTEXPR11_FUN bool test_any_except(value_type flags) const noexcept
{
return (load() & ~flags);
}
MPT_CONSTEXPR11_FUN bool any() const noexcept
{
return load();
}
MPT_CONSTEXPR11_FUN bool none() const noexcept
{
return !load();
}
MPT_CONSTEXPR11_FUN store_type GetRaw() const noexcept
{
return bits_;
}
MPT_CONSTEXPR14_FUN FlagSet & SetRaw(store_type flags) noexcept
{
bits_ = flags;
return *this;
}
MPT_CONSTEXPR14_FUN FlagSet &operator = (value_type flags) noexcept
{
return store(flags);
}
MPT_CONSTEXPR14_FUN FlagSet &operator = (enum_type flag) noexcept
{
return store(flag);
}
MPT_CONSTEXPR14_FUN FlagSet &operator = (FlagSet flags) noexcept
{
return store(flags.load());
}
MPT_CONSTEXPR14_FUN FlagSet &operator &= (value_type flags) noexcept
{
return store(load() & flags);
}
MPT_CONSTEXPR14_FUN FlagSet &operator |= (value_type flags) noexcept
{
return store(load() | flags);
}
MPT_CONSTEXPR14_FUN FlagSet &operator ^= (value_type flags) noexcept
{
return store(load() ^ flags);
}
friend MPT_CONSTEXPR11_FUN bool operator == (self_type a, self_type b) noexcept { return a.load() == b.load(); }
friend MPT_CONSTEXPR11_FUN bool operator != (self_type a, self_type b) noexcept { return a.load() != b.load(); }
friend MPT_CONSTEXPR11_FUN bool operator == (self_type a, value_type b) noexcept { return a.load() == value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator != (self_type a, value_type b) noexcept { return a.load() != value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator == (value_type a, self_type b) noexcept { return value_type(a) == b.load(); }
friend MPT_CONSTEXPR11_FUN bool operator != (value_type a, self_type b) noexcept { return value_type(a) != b.load(); }
friend MPT_CONSTEXPR11_FUN bool operator == (self_type a, enum_type b) noexcept { return a.load() == value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator != (self_type a, enum_type b) noexcept { return a.load() != value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator == (enum_type a, self_type b) noexcept { return value_type(a) == b.load(); }
friend MPT_CONSTEXPR11_FUN bool operator != (enum_type a, self_type b) noexcept { return value_type(a) != b.load(); }
friend MPT_CONSTEXPR11_FUN bool operator == (self_type a, Enum<enum_type> b) noexcept { return a.load() == value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator != (self_type a, Enum<enum_type> b) noexcept { return a.load() != value_type(b); }
friend MPT_CONSTEXPR11_FUN bool operator == (Enum<enum_type> a, self_type b) noexcept { return value_type(a) == b.load(); }
friend MPT_CONSTEXPR11_FUN bool operator != (Enum<enum_type> a, self_type b) noexcept { return value_type(a) != b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (self_type a, self_type b) noexcept { return a.load() | b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (self_type a, self_type b) noexcept { return a.load() & b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (self_type a, self_type b) noexcept { return a.load() ^ b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (self_type a, value_type b) noexcept { return a.load() | value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (self_type a, value_type b) noexcept { return a.load() & value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (self_type a, value_type b) noexcept { return a.load() ^ value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (value_type a, self_type b) noexcept { return value_type(a) | b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (value_type a, self_type b) noexcept { return value_type(a) & b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (value_type a, self_type b) noexcept { return value_type(a) ^ b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (self_type a, enum_type b) noexcept { return a.load() | value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (self_type a, enum_type b) noexcept { return a.load() & value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (self_type a, enum_type b) noexcept { return a.load() ^ value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (enum_type a, self_type b) noexcept { return value_type(a) | b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (enum_type a, self_type b) noexcept { return value_type(a) & b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (enum_type a, self_type b) noexcept { return value_type(a) ^ b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (self_type a, Enum<enum_type> b) noexcept { return a.load() | value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (self_type a, Enum<enum_type> b) noexcept { return a.load() & value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (self_type a, Enum<enum_type> b) noexcept { return a.load() ^ value_type(b); }
friend MPT_CONSTEXPR11_FUN const value_type operator | (Enum<enum_type> a, self_type b) noexcept { return value_type(a) | b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator & (Enum<enum_type> a, self_type b) noexcept { return value_type(a) & b.load(); }
friend MPT_CONSTEXPR11_FUN const value_type operator ^ (Enum<enum_type> a, self_type b) noexcept { return value_type(a) ^ b.load(); }
};
#define MPT_DECLARE_ENUM(enum_t) \
MPT_CONSTEXPR11_FUN enum_value_type<enum_t> operator | (enum_t a, enum_t b) noexcept { return enum_value_type<enum_t>(a) | enum_value_type<enum_t>(b); } \
MPT_CONSTEXPR11_FUN enum_value_type<enum_t> operator & (enum_t a, enum_t b) noexcept { return enum_value_type<enum_t>(a) & enum_value_type<enum_t>(b); } \
MPT_CONSTEXPR11_FUN enum_value_type<enum_t> operator ^ (enum_t a, enum_t b) noexcept { return enum_value_type<enum_t>(a) ^ enum_value_type<enum_t>(b); } \
MPT_CONSTEXPR11_FUN enum_value_type<enum_t> operator ~ (enum_t a) noexcept { return ~enum_value_type<enum_t>(a); } \
#define DECLARE_FLAGSET MPT_DECLARE_ENUM
OPENMPT_NAMESPACE_END