src/helpers.hpp
branchcustombridgeheads
changeset 5650 aefc131bf5ce
child 5860 7fdc9b423ba1
equal deleted inserted replaced
5649:55c8267c933f 5650:aefc131bf5ce
       
     1 /* $Id$ */
       
     2 
       
     3 #ifndef HELPERS_HPP
       
     4 #define HELPERS_HPP
       
     5 
       
     6 /** @file helpers.hpp */
       
     7 #include "macros.h"
       
     8 
       
     9 #ifdef __cplusplus
       
    10 
       
    11 /** When allocating using malloc/calloc in C++ it is usually needed to cast the return value
       
    12 *  from void* to the proper pointer type. Another alternative would be MallocT<> as follows */
       
    13 template <typename T> FORCEINLINE bool MallocT(T** t_ptr, size_t num_elements)
       
    14 {
       
    15 	*t_ptr = (T*)malloc(num_elements * sizeof(T));
       
    16 	return (*t_ptr != NULL);
       
    17 }
       
    18 /** When allocating using malloc/calloc in C++ it is usually needed to cast the return value
       
    19 *  from void* to the proper pointer type. Another alternative would be MallocT<> as follows */
       
    20 template <typename T> FORCEINLINE bool CallocT(T** t_ptr, size_t num_elements)
       
    21 {
       
    22 	*t_ptr = (T*)calloc(num_elements, sizeof(T));
       
    23 	return (*t_ptr != NULL);
       
    24 }
       
    25 /** When allocating using malloc/calloc in C++ it is usually needed to cast the return value
       
    26 *  from void* to the proper pointer type. Another alternative would be MallocT<> as follows */
       
    27 template <typename T> FORCEINLINE bool ReallocT(T** t_ptr, size_t num_elements)
       
    28 {
       
    29 	*t_ptr = (T*)realloc(*t_ptr, num_elements * sizeof(T));
       
    30 	return (*t_ptr != NULL);
       
    31 }
       
    32 
       
    33 /** type safe swap operation */
       
    34 template <typename T> void SwapT(T *a, T *b);
       
    35 
       
    36 template <typename T> FORCEINLINE void SwapT(T *a, T *b)
       
    37 {
       
    38 	T t = *a;
       
    39 	*a = *b;
       
    40 	*b = t;
       
    41 }
       
    42 
       
    43 
       
    44 /** returns the absolute value of (scalar) variable. @note assumes variable to be signed */
       
    45 template <typename T> static inline T myabs(T a) { return a < (T)0 ? -a : a; }
       
    46 /** returns the (absolute) difference between two (scalar) variables */
       
    47 template <typename T> static inline T delta(T a, T b) { return a < b ? b - a : a - b; }
       
    48 
       
    49 /** Some enums need to have allowed incrementing (i.e. StationClassID) */
       
    50 #define DECLARE_POSTFIX_INCREMENT(type) \
       
    51 	FORCEINLINE type operator ++(type& e, int) \
       
    52 	{ \
       
    53 		type e_org = e; \
       
    54 		e = (type)((int)e + 1); \
       
    55 		return e_org; \
       
    56 	} \
       
    57 	FORCEINLINE type operator --(type& e, int) \
       
    58 	{ \
       
    59 		type e_org = e; \
       
    60 		e = (type)((int)e - 1); \
       
    61 		return e_org; \
       
    62 	}
       
    63 
       
    64 
       
    65 
       
    66 /** Operators to allow to work with enum as with type safe bit set in C++ */
       
    67 # define DECLARE_ENUM_AS_BIT_SET(mask_t) \
       
    68 	FORCEINLINE mask_t operator | (mask_t m1, mask_t m2) {return (mask_t)((int)m1 | m2);} \
       
    69 	FORCEINLINE mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((int)m1 & m2);} \
       
    70 	FORCEINLINE mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((int)m1 ^ m2);} \
       
    71 	FORCEINLINE mask_t& operator |= (mask_t& m1, mask_t m2) {m1 = m1 | m2; return m1;} \
       
    72 	FORCEINLINE mask_t& operator &= (mask_t& m1, mask_t m2) {m1 = m1 & m2; return m1;} \
       
    73 	FORCEINLINE mask_t& operator ^= (mask_t& m1, mask_t m2) {m1 = m1 ^ m2; return m1;} \
       
    74 	FORCEINLINE mask_t operator ~(mask_t m) {return (mask_t)(~(int)m);}
       
    75 
       
    76 /** probably redundant enum combining operators (as we have conversion functions)
       
    77  *  but the old code is full of such arithmetics */
       
    78 # define DECLARE_ENUM_AS_BIT_INDEX(idx_t, mask_t) \
       
    79 	FORCEINLINE mask_t operator << (int m, idx_t i) {return (mask_t)(m << (int)i);} \
       
    80 	FORCEINLINE mask_t operator << (mask_t m, int i) {return (mask_t)(((int)m) << i);} \
       
    81 	FORCEINLINE mask_t operator >> (mask_t m, int i) {return (mask_t)(((int)m) >> i);}
       
    82 
       
    83 
       
    84 /** Informative template class exposing basic enumeration properties used by several
       
    85  *  other templates below. Here we have only forward declaration. For each enum type
       
    86  *  we will create specialization derived from MakeEnumPropsT<>. */
       
    87 template <typename Tenum_t> struct EnumPropsT;
       
    88 
       
    89 /** Helper template class that makes basic properties of given enumeration type visible
       
    90  *  from outsize. It is used as base class of several EnumPropsT specializations each
       
    91  *  dedicated to one of commonly used enumeration types. */
       
    92 template <typename Tenum_t, typename Tstorage_t, Tenum_t Tbegin, Tenum_t Tend, Tenum_t Tinvalid>
       
    93 struct MakeEnumPropsT {
       
    94 	typedef Tenum_t type;                     ///< enum type (i.e. Trackdir)
       
    95 	typedef Tstorage_t storage;               ///< storage type (i.e. byte)
       
    96 	static const Tenum_t begin = Tbegin;      ///< lowest valid value (i.e. TRACKDIR_BEGIN)
       
    97 	static const Tenum_t end = Tend;          ///< one after the last valid value (i.e. TRACKDIR_END)
       
    98 	static const Tenum_t invalid = Tinvalid;  ///< what value is used as invalid value (i.e. INVALID_TRACKDIR)
       
    99 };
       
   100 
       
   101 
       
   102 
       
   103 /** In some cases we use byte or uint16 to store values that are defined as enum. It is
       
   104 	*  necessary in order to control the sizeof() such values. Some compilers make enum
       
   105 	*  the same size as int (4 or 8 bytes instead of 1 or 2). As a consequence the strict
       
   106 	*  compiler type-checking causes errors like:
       
   107 	*     'HasPowerOnRail' : cannot convert parameter 1 from 'byte' to 'RailType' when
       
   108 	*  u->u.rail.railtype is passed as argument or type RailType. In such cases it is better
       
   109 	*  to teach the compiler that u->u.rail.railtype is to be treated as RailType. */
       
   110 template <typename Tenum_t> struct TinyEnumT;
       
   111 
       
   112 /** The general declaration of TinyEnumT<> (above) */
       
   113 template <typename Tenum_t> struct TinyEnumT
       
   114 {
       
   115 	typedef Tenum_t enum_type;                      ///< expose our enumeration type (i.e. Trackdir) to outside
       
   116 	typedef EnumPropsT<Tenum_t> Props;              ///< make easier access to our enumeration propeties
       
   117 	typedef typename Props::storage storage_type;   ///< small storage type
       
   118 	static const enum_type begin = Props::begin;    ///< enum beginning (i.e. TRACKDIR_BEGIN)
       
   119 	static const enum_type end = Props::end;        ///< enum end (i.e. TRACKDIR_END)
       
   120 	static const enum_type invalid = Props::invalid;///< invalid value (i.e. INVALID_TRACKDIR)
       
   121 
       
   122 	storage_type m_val;  ///< here we hold the actual value in small (i.e. byte) form
       
   123 
       
   124 	/** Cast operator - invoked then the value is assigned to the Tenum_t type */
       
   125 	FORCEINLINE operator enum_type () const
       
   126 	{
       
   127 		return (enum_type)m_val;
       
   128 	}
       
   129 
       
   130 	/** Assignment operator (from Tenum_t type) */
       
   131 	FORCEINLINE TinyEnumT& operator = (enum_type e)
       
   132 	{
       
   133 		m_val = (storage_type)e; return *this;
       
   134 	}
       
   135 
       
   136 	/** postfix ++ operator on tiny type */
       
   137 	FORCEINLINE TinyEnumT& operator ++ (int)
       
   138 	{
       
   139 		if (++m_val >= end) m_val -= (storage_type)(end - begin);
       
   140 		return *this;
       
   141 	}
       
   142 };
       
   143 
       
   144 template <typename Tenum_t> FORCEINLINE void SwapT(TinyEnumT<Tenum_t> *a, TinyEnumT<Tenum_t> *b)
       
   145 {
       
   146 	SwapT(&a->m_val, &b->m_val);
       
   147 }
       
   148 
       
   149 template <typename T> FORCEINLINE T ClrBitT(T t, int bit_index)
       
   150 {
       
   151 	int val = t;
       
   152 	CLRBIT(val, bit_index);
       
   153 	return (T)val;
       
   154 }
       
   155 
       
   156 template <typename T> FORCEINLINE T SetBitT(T t, int bit_index)
       
   157 {
       
   158 	int val = t;
       
   159 	SETBIT(val, bit_index);
       
   160 	return (T)val;
       
   161 }
       
   162 
       
   163 template <typename T> FORCEINLINE T ToggleBitT(T t, int bit_index)
       
   164 {
       
   165 	int val = t;
       
   166 	TOGGLEBIT(val, bit_index);
       
   167 	return (T)val;
       
   168 }
       
   169 
       
   170 #else // __cplusplus
       
   171 
       
   172 #define DECLARE_POSTFIX_INCREMENT(E)
       
   173 #define DECLARE_ENUM_AS_BIT_SET(E)
       
   174 #define DECLARE_ENUM_AS_BIT_INDEX(E1,E2)
       
   175 
       
   176 #endif  // __cplusplus
       
   177 
       
   178 #endif /* HELPERS_HPP */