rubidium@5587: /* $Id$ */ rubidium@5587: rubidium@8100: /** @file enum_type.hpp Type (helpers) for enums */ rubidium@5587: rubidium@8100: #ifndef ENUM_TYPE_HPP rubidium@8100: #define ENUM_TYPE_HPP rubidium@5587: rubidium@5587: /** Some enums need to have allowed incrementing (i.e. StationClassID) */ rubidium@5587: #define DECLARE_POSTFIX_INCREMENT(type) \ rubidium@5587: FORCEINLINE type operator ++(type& e, int) \ rubidium@5587: { \ rubidium@5587: type e_org = e; \ rubidium@5587: e = (type)((int)e + 1); \ rubidium@5587: return e_org; \ rubidium@5587: } \ rubidium@5587: FORCEINLINE type operator --(type& e, int) \ rubidium@5587: { \ rubidium@5587: type e_org = e; \ rubidium@5587: e = (type)((int)e - 1); \ rubidium@5587: return e_org; \ rubidium@5587: } rubidium@5587: rubidium@5587: rubidium@5587: rubidium@5587: /** Operators to allow to work with enum as with type safe bit set in C++ */ rubidium@5587: # define DECLARE_ENUM_AS_BIT_SET(mask_t) \ rubidium@5587: FORCEINLINE mask_t operator | (mask_t m1, mask_t m2) {return (mask_t)((int)m1 | m2);} \ rubidium@5587: FORCEINLINE mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((int)m1 & m2);} \ rubidium@5587: FORCEINLINE mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((int)m1 ^ m2);} \ rubidium@5587: FORCEINLINE mask_t& operator |= (mask_t& m1, mask_t m2) {m1 = m1 | m2; return m1;} \ rubidium@5587: FORCEINLINE mask_t& operator &= (mask_t& m1, mask_t m2) {m1 = m1 & m2; return m1;} \ rubidium@5587: FORCEINLINE mask_t& operator ^= (mask_t& m1, mask_t m2) {m1 = m1 ^ m2; return m1;} \ rubidium@5587: FORCEINLINE mask_t operator ~(mask_t m) {return (mask_t)(~(int)m);} rubidium@5587: rubidium@5587: rubidium@5587: /** Informative template class exposing basic enumeration properties used by several rubidium@5587: * other templates below. Here we have only forward declaration. For each enum type KUDr@6129: * we will create specialization derived from MakeEnumPropsT<>. KUDr@6130: * i.e.: KUDr@6130: * template <> struct EnumPropsT : MakeEnumPropsT {}; KUDr@6130: * followed by: KUDr@6130: * typedef TinyEnumT TrackByte; KUDr@6129: */ rubidium@5587: template struct EnumPropsT; rubidium@5587: rubidium@5587: /** Helper template class that makes basic properties of given enumeration type visible rubidium@5587: * from outsize. It is used as base class of several EnumPropsT specializations each KUDr@6129: * dedicated to one of commonly used enumeration types. KUDr@6129: * @param Tenum_t enumeration type that you want to describe KUDr@6129: * @param Tstorage_t what storage type would be sufficient (i.e. byte) KUDr@6129: * @param Tbegin first valid value from the contiguous range (i.e. TRACK_BEGIN) KUDr@6129: * @param Tend one past the last valid value from the contiguous range (i.e. TRACK_END) KUDr@6129: * @param Tinvalid value used as invalid value marker (i.e. INVALID_TRACK) KUDr@6129: */ rubidium@5587: template rubidium@5587: struct MakeEnumPropsT { rubidium@5587: typedef Tenum_t type; ///< enum type (i.e. Trackdir) rubidium@5587: typedef Tstorage_t storage; ///< storage type (i.e. byte) rubidium@5587: static const Tenum_t begin = Tbegin; ///< lowest valid value (i.e. TRACKDIR_BEGIN) rubidium@5587: static const Tenum_t end = Tend; ///< one after the last valid value (i.e. TRACKDIR_END) rubidium@5587: static const Tenum_t invalid = Tinvalid; ///< what value is used as invalid value (i.e. INVALID_TRACKDIR) rubidium@5587: }; rubidium@5587: rubidium@5587: rubidium@5587: rubidium@5587: /** In some cases we use byte or uint16 to store values that are defined as enum. It is rubidium@5587: * necessary in order to control the sizeof() such values. Some compilers make enum rubidium@5587: * the same size as int (4 or 8 bytes instead of 1 or 2). As a consequence the strict rubidium@8969: * compiler type - checking causes errors like: rubidium@5587: * 'HasPowerOnRail' : cannot convert parameter 1 from 'byte' to 'RailType' when rubidium@5587: * u->u.rail.railtype is passed as argument or type RailType. In such cases it is better rubidium@5587: * to teach the compiler that u->u.rail.railtype is to be treated as RailType. */ rubidium@5587: template struct TinyEnumT; rubidium@5587: rubidium@5587: /** The general declaration of TinyEnumT<> (above) */ rubidium@5587: template struct TinyEnumT rubidium@5587: { rubidium@5587: typedef Tenum_t enum_type; ///< expose our enumeration type (i.e. Trackdir) to outside rubidium@5587: typedef EnumPropsT Props; ///< make easier access to our enumeration propeties rubidium@5587: typedef typename Props::storage storage_type; ///< small storage type rubidium@5587: static const enum_type begin = Props::begin; ///< enum beginning (i.e. TRACKDIR_BEGIN) rubidium@5587: static const enum_type end = Props::end; ///< enum end (i.e. TRACKDIR_END) rubidium@5587: static const enum_type invalid = Props::invalid;///< invalid value (i.e. INVALID_TRACKDIR) rubidium@5587: rubidium@5587: storage_type m_val; ///< here we hold the actual value in small (i.e. byte) form rubidium@5587: rubidium@5587: /** Cast operator - invoked then the value is assigned to the Tenum_t type */ rubidium@5587: FORCEINLINE operator enum_type () const rubidium@5587: { rubidium@5587: return (enum_type)m_val; rubidium@5587: } rubidium@5587: rubidium@5587: /** Assignment operator (from Tenum_t type) */ rubidium@5587: FORCEINLINE TinyEnumT& operator = (enum_type e) rubidium@5587: { rubidium@5587: m_val = (storage_type)e; return *this; rubidium@5587: } rubidium@5587: rubidium@5587: /** postfix ++ operator on tiny type */ truelight@7838: FORCEINLINE TinyEnumT operator ++ (int) truelight@7838: { truelight@7838: TinyEnumT org = *this; truelight@7838: if (++m_val >= end) m_val -= (storage_type)(end - begin); truelight@7838: return org; truelight@7838: } truelight@7838: truelight@7838: /** prefix ++ operator on tiny type */ truelight@7838: FORCEINLINE TinyEnumT& operator ++ () rubidium@5587: { rubidium@5587: if (++m_val >= end) m_val -= (storage_type)(end - begin); rubidium@5587: return *this; rubidium@5587: } rubidium@5587: }; rubidium@5587: rubidium@5587: #endif /* HELPERS_HPP */