1 /** 2 * @file 3 * @brief Global (ick) enums. 4 **/ 5 6 #pragma once 7 8 #include "macros.h" 9 10 #include <iterator> 11 #include <type_traits> // underlying_type<>, enable_if<> 12 13 // Provide a last_exponent static member variable only if the LastExponent 14 // template parameter is nonnegative. 15 template<int LastExponent, bool Provided = LastExponent >= 0> 16 struct _enum_bitfield_exponent_base { }; 17 18 template<int LastExponent> 19 struct _enum_bitfield_exponent_base<LastExponent, true> 20 { 21 static constexpr int last_exponent = LastExponent; 22 }; 23 24 // If LastExponent is nonnegative, is the last exponent that will 25 // be iterated over by range() 26 template<class E, int LastExponent = -1> 27 class enum_bitfield : public _enum_bitfield_exponent_base<LastExponent> 28 { 29 public: 30 typedef typename std::underlying_type<E>::type underlying_type; 31 typedef enum_bitfield<E, LastExponent> field_type; 32 underlying_type flags; 33 private: 34 explicit constexpr enum_bitfield(underlying_type rawflags) 35 : flags(rawflags) 36 {} 37 public: 38 /// Get the flag corresponding to the given bit position (0 = LSB). 39 static constexpr E exponent(int pos) 40 { 41 return static_cast<E>(underlying_type(1) << pos); 42 } 43 44 constexpr enum_bitfield() : flags(0) {} 45 constexpr enum_bitfield(E flag) : flags(underlying_type(flag)) {} 46 template<class ... Es> 47 constexpr enum_bitfield(E flag, E flag2, Es... rest) 48 : flags(enum_bitfield(flag2, rest...).flags | underlying_type(flag)) {} 49 50 explicit constexpr operator underlying_type () const { return flags; } 51 explicit constexpr operator bool () const { return flags; } 52 constexpr bool operator==(field_type other) const 53 { 54 return flags == other.flags; 55 } 56 constexpr bool operator!=(field_type other) const 57 { 58 return !(*this == other); 59 } 60 61 field_type &operator|=(field_type other) 62 { 63 flags |= other.flags; 64 return *this; 65 } 66 67 field_type &operator&=(field_type other) 68 { 69 flags &= other.flags; 70 return *this; 71 } 72 73 field_type &operator^=(field_type other) 74 { 75 flags ^= other.flags; 76 return *this; 77 } 78 79 constexpr field_type operator|(field_type other) const 80 { 81 return field_type(flags | other.flags); 82 } 83 84 constexpr field_type operator&(field_type other) const 85 { 86 return field_type(flags & other.flags); 87 } 88 89 constexpr field_type operator^(field_type other) const 90 { 91 return field_type(flags ^ other.flags); 92 } 93 94 constexpr field_type operator~() const 95 { 96 return field_type(~flags); 97 } 98 99 struct range 100 { 101 class iterator : public std::iterator<std::forward_iterator_tag, const E> 102 { 103 private: 104 int exp_; 105 public: 106 constexpr iterator() : exp_(0) { } 107 constexpr iterator(int exp) : exp_(exp) { } 108 constexpr E operator*() const { return exponent(exp_); } 109 constexpr bool operator==(const iterator &other) const 110 { 111 return exp_ == other.exp_; 112 } 113 constexpr bool operator!=(const iterator &other) const 114 { 115 return !(*this == other); 116 } 117 iterator &operator++() { ++exp_; return *this; } 118 iterator operator++(int) 119 { 120 iterator copy = *this; 121 ++(*this); 122 return copy; 123 } 124 }; 125 126 const int final; 127 128 constexpr range(int last_exp) : final(last_exp) {} 129 130 // Only create the default constructor if we got a nonnegative 131 // LastExponent template parameter. 132 template<typename std::enable_if<LastExponent >= 0, int>::type = 0> 133 constexpr range() : final(LastExponent) {} 134 135 constexpr iterator begin() const { return iterator(); } 136 constexpr iterator end() const { return final + 1; } 137 }; 138 }; 139 140 #define DEF_BITFIELD_OPERATORS(fieldT, flagT, ...) \ 141 inline constexpr fieldT operator|(flagT a, flagT b) { return fieldT(a) | b; } \ 142 inline constexpr fieldT operator|(flagT a, fieldT b) { return fieldT(a) | b; } \ 143 inline constexpr fieldT operator&(flagT a, flagT b) { return fieldT(a) & b; } \ 144 inline constexpr fieldT operator&(flagT a, fieldT b) { return fieldT(a) & b; } \ 145 inline constexpr fieldT operator^(flagT a, flagT b) { return fieldT(a) ^ b; } \ 146 inline constexpr fieldT operator^(flagT a, fieldT b) { return fieldT(a) ^ b; } \ 147 inline constexpr fieldT operator~(flagT a) { return ~fieldT(a); } \ 148 COMPILE_CHECK(is_enum<flagT>::value) 149 // The last line above is really just to eat a semicolon; template 150 // substitution of enum_bitfield would have already failed. 151 152 // Work around MSVC's idiosyncratic interpretation of __VA_ARGS__ as a 153 // single macro argument: http://stackoverflow.com/questions/5134523 154 #define EXPANDMACRO(x) x 155 /** 156 * Define fieldT as a bitfield of the enum flagT, and make bitwise 157 * operators on flagT yield a fieldT. 158 * 159 * This macro produces a typedef and several inline function definitions; 160 * use it only at file/namespace scope. It requires a trailing semicolon. 161 * 162 * The operations ~, |, ^, and (binary) & on flags or fields yield a field. 163 * Fields also support &=, |=, and ^=. Fields can be explicitly converted to 164 * an integer of the enum's underlying type, or to bool. Note that in C++ 165 * using a bitfield expression as the condition of a control structure, 166 * or as an operand of a logical operator, counts as explicit conversion 167 * to bool. 168 * 169 * @param fieldT An identifier naming the bitfield type to define. 170 * @param flagT An identifier naming the enum type to use as a flag. 171 * Could theoretically be a more complex type expression, but 172 * I wouldn't try anything trickier than scope resolution. 173 * @param lastExp The last exponent over which fieldT::range() should 174 * iterate. If unspecified or negative, the bitfield will not 175 * have the last_exponent static member variable, and the 176 * bitfield's nested range class will not have a default 177 * constructor. 178 */ 179 #define DEF_BITFIELD(fieldT, ...) \ 180 typedef enum_bitfield<__VA_ARGS__> fieldT; \ 181 EXPANDMACRO(DEF_BITFIELD_OPERATORS(fieldT, __VA_ARGS__, )) 182 // The trailing comma suppresses "ISO C99 requires rest arguments to be used" 183 184 // The rest of this file should probably move elsewhere 185 // normal tile size in px 186 enum 187 { 188 TILE_X = 32, 189 TILE_Y = 32, 190 }; 191 192 // Don't change this without also modifying the data save/load routines. 193 enum 194 { 195 NUM_MAX_DOLLS = 10, 196 }; 197