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