1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
8 /** @file enum_type.hpp Type (helpers) for enums */
9 
10 #ifndef ENUM_TYPE_HPP
11 #define ENUM_TYPE_HPP
12 
13 /** Some enums need to have allowed incrementing (i.e. StationClassID) */
14 #define DECLARE_POSTFIX_INCREMENT(enum_type) \
15 	inline enum_type operator ++(enum_type& e, int) \
16 	{ \
17 		enum_type e_org = e; \
18 		e = (enum_type)((std::underlying_type<enum_type>::type)e + 1); \
19 		return e_org; \
20 	} \
21 	inline enum_type operator --(enum_type& e, int) \
22 	{ \
23 		enum_type e_org = e; \
24 		e = (enum_type)((std::underlying_type<enum_type>::type)e - 1); \
25 		return e_org; \
26 	}
27 
28 
29 
30 /** Operators to allow to work with enum as with type safe bit set in C++ */
31 # define DECLARE_ENUM_AS_BIT_SET(mask_t) \
32 	inline mask_t operator | (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 | m2);} \
33 	inline mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 & m2);} \
34 	inline mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 ^ m2);} \
35 	inline mask_t& operator |= (mask_t& m1, mask_t m2) {m1 = m1 | m2; return m1;} \
36 	inline mask_t& operator &= (mask_t& m1, mask_t m2) {m1 = m1 & m2; return m1;} \
37 	inline mask_t& operator ^= (mask_t& m1, mask_t m2) {m1 = m1 ^ m2; return m1;} \
38 	inline mask_t operator ~(mask_t m) {return (mask_t)(~(std::underlying_type<mask_t>::type)m);}
39 
40 
41 /**
42  * Informative template class exposing basic enumeration properties used by several
43  *  other templates below. Here we have only forward declaration. For each enum type
44  *  we will create specialization derived from MakeEnumPropsT<>.
45  *  i.e.:
46  *    template <> struct EnumPropsT<Track> : MakeEnumPropsT<Track, byte, TRACK_BEGIN, TRACK_END, INVALID_TRACK> {};
47  */
48 template <typename Tenum_t> struct EnumPropsT;
49 
50 /**
51  * Helper template class that makes basic properties of given enumeration type visible
52  *  from outsize. It is used as base class of several EnumPropsT specializations each
53  *  dedicated to one of commonly used enumeration types.
54  *  @param Tenum_t enumeration type that you want to describe
55  *  @param Tstorage_t what storage type would be sufficient (i.e. byte)
56  *  @param Tbegin first valid value from the contiguous range (i.e. TRACK_BEGIN)
57  *  @param Tend one past the last valid value from the contiguous range (i.e. TRACK_END)
58  *  @param Tinvalid value used as invalid value marker (i.e. INVALID_TRACK)
59  *  @param Tnum_bits Number of bits for storing the enum in command parameters
60  */
61 template <typename Tenum_t, typename Tstorage_t, Tenum_t Tbegin, Tenum_t Tend, Tenum_t Tinvalid, uint Tnum_bits = 8 * sizeof(Tstorage_t)>
62 struct MakeEnumPropsT {
63 	typedef Tenum_t type;                     ///< enum type (i.e. Trackdir)
64 	typedef Tstorage_t storage;               ///< storage type (i.e. byte)
65 	static const Tenum_t begin = Tbegin;      ///< lowest valid value (i.e. TRACKDIR_BEGIN)
66 	static const Tenum_t end = Tend;          ///< one after the last valid value (i.e. TRACKDIR_END)
67 	static const Tenum_t invalid = Tinvalid;  ///< what value is used as invalid value (i.e. INVALID_TRACKDIR)
68 	static const uint num_bits = Tnum_bits;   ///< Number of bits for storing the enum in command parameters
69 };
70 
71 #endif /* ENUM_TYPE_HPP */
72