src/helpers.hpp
branchNewGRF_ports
changeset 6872 1c4a4a609f85
parent 6871 5a9dc001e1ad
child 6873 86bf4ccb580d
equal deleted inserted replaced
6871:5a9dc001e1ad 6872:1c4a4a609f85
     1 /* $Id$ */
       
     2 
       
     3 /** @file helpers.hpp */
       
     4 
       
     5 #ifndef HELPERS_HPP
       
     6 #define HELPERS_HPP
       
     7 
       
     8 #include "macros.h"
       
     9 
       
    10 /** When allocating using malloc/calloc in C++ it is usually needed to cast the return value
       
    11 *  from void* to the proper pointer type. Another alternative would be MallocT<> as follows */
       
    12 template <typename T> FORCEINLINE T* MallocT(size_t num_elements)
       
    13 {
       
    14 	T *t_ptr = (T*)malloc(num_elements * sizeof(T));
       
    15 	return t_ptr;
       
    16 }
       
    17 /** When allocating using malloc/calloc in C++ it is usually needed to cast the return value
       
    18 *  from void* to the proper pointer type. Another alternative would be MallocT<> as follows */
       
    19 template <typename T> FORCEINLINE T* CallocT(size_t num_elements)
       
    20 {
       
    21 	T *t_ptr = (T*)calloc(num_elements, sizeof(T));
       
    22 	return t_ptr;
       
    23 }
       
    24 /** When allocating using malloc/calloc in C++ it is usually needed to cast the return value
       
    25 *  from void* to the proper pointer type. Another alternative would be MallocT<> as follows */
       
    26 template <typename T> FORCEINLINE T* ReallocT(T* t_ptr, size_t num_elements)
       
    27 {
       
    28 	t_ptr = (T*)realloc(t_ptr, num_elements * sizeof(T));
       
    29 	return t_ptr;
       
    30 }
       
    31 
       
    32 
       
    33 /** type safe swap operation */
       
    34 template<typename T> void Swap(T& a, T& b)
       
    35 {
       
    36 	T t = a;
       
    37 	a = b;
       
    38 	b = t;
       
    39 }
       
    40 
       
    41 
       
    42 /** Some enums need to have allowed incrementing (i.e. StationClassID) */
       
    43 #define DECLARE_POSTFIX_INCREMENT(type) \
       
    44 	FORCEINLINE type operator ++(type& e, int) \
       
    45 	{ \
       
    46 		type e_org = e; \
       
    47 		e = (type)((int)e + 1); \
       
    48 		return e_org; \
       
    49 	} \
       
    50 	FORCEINLINE type operator --(type& e, int) \
       
    51 	{ \
       
    52 		type e_org = e; \
       
    53 		e = (type)((int)e - 1); \
       
    54 		return e_org; \
       
    55 	}
       
    56 
       
    57 
       
    58 
       
    59 /** Operators to allow to work with enum as with type safe bit set in C++ */
       
    60 # define DECLARE_ENUM_AS_BIT_SET(mask_t) \
       
    61 	FORCEINLINE mask_t operator | (mask_t m1, mask_t m2) {return (mask_t)((int)m1 | m2);} \
       
    62 	FORCEINLINE mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((int)m1 & m2);} \
       
    63 	FORCEINLINE mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((int)m1 ^ m2);} \
       
    64 	FORCEINLINE mask_t& operator |= (mask_t& m1, mask_t m2) {m1 = m1 | m2; return m1;} \
       
    65 	FORCEINLINE mask_t& operator &= (mask_t& m1, mask_t m2) {m1 = m1 & m2; return m1;} \
       
    66 	FORCEINLINE mask_t& operator ^= (mask_t& m1, mask_t m2) {m1 = m1 ^ m2; return m1;} \
       
    67 	FORCEINLINE mask_t operator ~(mask_t m) {return (mask_t)(~(int)m);}
       
    68 
       
    69 
       
    70 /** Informative template class exposing basic enumeration properties used by several
       
    71  *  other templates below. Here we have only forward declaration. For each enum type
       
    72  *  we will create specialization derived from MakeEnumPropsT<>.
       
    73  *  i.e.:
       
    74  *    template <> struct EnumPropsT<Track> : MakeEnumPropsT<Track, byte, TRACK_BEGIN, TRACK_END, INVALID_TRACK> {};
       
    75  *  followed by:
       
    76  *    typedef TinyEnumT<Track> TrackByte;
       
    77  */
       
    78 template <typename Tenum_t> struct EnumPropsT;
       
    79 
       
    80 /** Helper template class that makes basic properties of given enumeration type visible
       
    81  *  from outsize. It is used as base class of several EnumPropsT specializations each
       
    82  *  dedicated to one of commonly used enumeration types.
       
    83  *  @param Tenum_t enumeration type that you want to describe
       
    84  *  @param Tstorage_t what storage type would be sufficient (i.e. byte)
       
    85  *  @param Tbegin first valid value from the contiguous range (i.e. TRACK_BEGIN)
       
    86  *  @param Tend one past the last valid value from the contiguous range (i.e. TRACK_END)
       
    87  *  @param Tinvalid value used as invalid value marker (i.e. INVALID_TRACK)
       
    88  */
       
    89 template <typename Tenum_t, typename Tstorage_t, Tenum_t Tbegin, Tenum_t Tend, Tenum_t Tinvalid>
       
    90 struct MakeEnumPropsT {
       
    91 	typedef Tenum_t type;                     ///< enum type (i.e. Trackdir)
       
    92 	typedef Tstorage_t storage;               ///< storage type (i.e. byte)
       
    93 	static const Tenum_t begin = Tbegin;      ///< lowest valid value (i.e. TRACKDIR_BEGIN)
       
    94 	static const Tenum_t end = Tend;          ///< one after the last valid value (i.e. TRACKDIR_END)
       
    95 	static const Tenum_t invalid = Tinvalid;  ///< what value is used as invalid value (i.e. INVALID_TRACKDIR)
       
    96 };
       
    97 
       
    98 
       
    99 
       
   100 /** In some cases we use byte or uint16 to store values that are defined as enum. It is
       
   101 	*  necessary in order to control the sizeof() such values. Some compilers make enum
       
   102 	*  the same size as int (4 or 8 bytes instead of 1 or 2). As a consequence the strict
       
   103 	*  compiler type-checking causes errors like:
       
   104 	*     'HasPowerOnRail' : cannot convert parameter 1 from 'byte' to 'RailType' when
       
   105 	*  u->u.rail.railtype is passed as argument or type RailType. In such cases it is better
       
   106 	*  to teach the compiler that u->u.rail.railtype is to be treated as RailType. */
       
   107 template <typename Tenum_t> struct TinyEnumT;
       
   108 
       
   109 /** The general declaration of TinyEnumT<> (above) */
       
   110 template <typename Tenum_t> struct TinyEnumT
       
   111 {
       
   112 	typedef Tenum_t enum_type;                      ///< expose our enumeration type (i.e. Trackdir) to outside
       
   113 	typedef EnumPropsT<Tenum_t> Props;              ///< make easier access to our enumeration propeties
       
   114 	typedef typename Props::storage storage_type;   ///< small storage type
       
   115 	static const enum_type begin = Props::begin;    ///< enum beginning (i.e. TRACKDIR_BEGIN)
       
   116 	static const enum_type end = Props::end;        ///< enum end (i.e. TRACKDIR_END)
       
   117 	static const enum_type invalid = Props::invalid;///< invalid value (i.e. INVALID_TRACKDIR)
       
   118 
       
   119 	storage_type m_val;  ///< here we hold the actual value in small (i.e. byte) form
       
   120 
       
   121 	/** Cast operator - invoked then the value is assigned to the Tenum_t type */
       
   122 	FORCEINLINE operator enum_type () const
       
   123 	{
       
   124 		return (enum_type)m_val;
       
   125 	}
       
   126 
       
   127 	/** Assignment operator (from Tenum_t type) */
       
   128 	FORCEINLINE TinyEnumT& operator = (enum_type e)
       
   129 	{
       
   130 		m_val = (storage_type)e; return *this;
       
   131 	}
       
   132 
       
   133 	/** postfix ++ operator on tiny type */
       
   134 	FORCEINLINE TinyEnumT operator ++ (int)
       
   135 	{
       
   136 		TinyEnumT org = *this;
       
   137 		if (++m_val >= end) m_val -= (storage_type)(end - begin);
       
   138 		return org;
       
   139 	}
       
   140 
       
   141 	/** prefix ++ operator on tiny type */
       
   142 	FORCEINLINE TinyEnumT& operator ++ ()
       
   143 	{
       
   144 		if (++m_val >= end) m_val -= (storage_type)(end - begin);
       
   145 		return *this;
       
   146 	}
       
   147 };
       
   148 
       
   149 /**
       
   150  * Overflow safe template for integers, i.e. integers that will never overflow
       
   151  * you multiply the maximum value with 2, or add 2, or substract somethng from
       
   152  * the minimum value, etc.
       
   153  * @param T     the type these integers are stored with.
       
   154  * @param T_MAX the maximum value for the integers.
       
   155  * @param T_MIN the minimum value for the integers.
       
   156  */
       
   157 template <class T, T T_MAX, T T_MIN>
       
   158 class OverflowSafeInt
       
   159 {
       
   160 private:
       
   161 	/** The non-overflow safe backend to store the value in. */
       
   162 	T m_value;
       
   163 public:
       
   164 	OverflowSafeInt() : m_value(0) { }
       
   165 
       
   166 	OverflowSafeInt(const OverflowSafeInt& other) { this->m_value = other.m_value; }
       
   167 	OverflowSafeInt(const int64 int_)             { this->m_value = int_; }
       
   168 
       
   169 	FORCEINLINE OverflowSafeInt& operator = (const OverflowSafeInt& other) { this->m_value = other.m_value; return *this; }
       
   170 
       
   171 	FORCEINLINE OverflowSafeInt operator - () const { return OverflowSafeInt(-this->m_value); }
       
   172 
       
   173 	/**
       
   174 	 * Safe implementation of addition.
       
   175 	 * @param other the amount to add
       
   176 	 * @note when the addition would yield more than T_MAX (or less than T_MIN),
       
   177 	 *       it will be T_MAX (respectively T_MIN).
       
   178 	 */
       
   179 	FORCEINLINE OverflowSafeInt& operator += (const OverflowSafeInt& other)
       
   180 	{
       
   181 		if ((T_MAX - abs(other.m_value)) < abs(this->m_value) &&
       
   182 				(this->m_value < 0) == (other.m_value < 0)) {
       
   183 			this->m_value = (this->m_value < 0) ? T_MIN : T_MAX ;
       
   184 		} else {
       
   185 			this->m_value += other.m_value;
       
   186 		}
       
   187 		return *this;
       
   188 	}
       
   189 
       
   190 	/* Operators for addition and substraction */
       
   191 	FORCEINLINE OverflowSafeInt  operator +  (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result += other; return result; }
       
   192 	FORCEINLINE OverflowSafeInt  operator +  (const int              other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
       
   193 	FORCEINLINE OverflowSafeInt  operator +  (const uint             other) const { OverflowSafeInt result = *this; result += (int64)other; return result; }
       
   194 	FORCEINLINE OverflowSafeInt& operator -= (const OverflowSafeInt& other)       { return *this += (-other); }
       
   195 	FORCEINLINE OverflowSafeInt  operator -  (const OverflowSafeInt& other) const { OverflowSafeInt result = *this; result -= other; return result; }
       
   196 	FORCEINLINE OverflowSafeInt  operator -  (const int              other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; }
       
   197 	FORCEINLINE OverflowSafeInt  operator -  (const uint             other) const { OverflowSafeInt result = *this; result -= (int64)other; return result; }
       
   198 
       
   199 	FORCEINLINE OverflowSafeInt& operator ++ () { return *this += 1; }
       
   200 	FORCEINLINE OverflowSafeInt& operator -- () { return *this += -1; }
       
   201 	FORCEINLINE OverflowSafeInt operator ++ (int) { OverflowSafeInt org = *this; *this += 1; return org; }
       
   202 	FORCEINLINE OverflowSafeInt operator -- (int) { OverflowSafeInt org = *this; *this += -1; return org; }
       
   203 
       
   204 	/**
       
   205 	 * Safe implementation of multiplication.
       
   206 	 * @param factor the factor to multiply this with.
       
   207 	 * @note when the multiplication would yield more than T_MAX (or less than T_MIN),
       
   208 	 *       it will be T_MAX (respectively T_MIN).
       
   209 	 */
       
   210 	FORCEINLINE OverflowSafeInt& operator *= (const int factor)
       
   211 	{
       
   212 		if (factor != 0 && (T_MAX / abs(factor)) < abs(this->m_value)) {
       
   213 			 this->m_value = ((this->m_value < 0) == (factor < 0)) ? T_MAX : T_MIN ;
       
   214 		} else {
       
   215 			this->m_value *= factor ;
       
   216 		}
       
   217 		return *this;
       
   218 	}
       
   219 
       
   220 	/* Operators for multiplication */
       
   221 	FORCEINLINE OverflowSafeInt operator * (const int64  factor) const { OverflowSafeInt result = *this; result *= factor; return result; }
       
   222 	FORCEINLINE OverflowSafeInt operator * (const int    factor) const { OverflowSafeInt result = *this; result *= (int64)factor; return result; }
       
   223 	FORCEINLINE OverflowSafeInt operator * (const uint   factor) const { OverflowSafeInt result = *this; result *= (int64)factor; return result; }
       
   224 	FORCEINLINE OverflowSafeInt operator * (const uint16 factor) const { OverflowSafeInt result = *this; result *= (int64)factor; return result; }
       
   225 	FORCEINLINE OverflowSafeInt operator * (const byte   factor) const { OverflowSafeInt result = *this; result *= (int64)factor; return result; }
       
   226 
       
   227 	/* Operators for division */
       
   228 	FORCEINLINE OverflowSafeInt& operator /= (const int              divisor)       { this->m_value /= divisor; return *this; }
       
   229 	FORCEINLINE OverflowSafeInt  operator /  (const OverflowSafeInt& divisor) const { OverflowSafeInt result = *this; result /= divisor.m_value; return result; }
       
   230 	FORCEINLINE OverflowSafeInt  operator /  (const int              divisor) const { OverflowSafeInt result = *this; result /= divisor; return result; }
       
   231 	FORCEINLINE OverflowSafeInt  operator /  (const uint             divisor) const { OverflowSafeInt result = *this; result /= (int)divisor; return result; }
       
   232 
       
   233 	/* Operators for modulo */
       
   234 	FORCEINLINE OverflowSafeInt& operator %= (const int  divisor)       { this->m_value %= divisor; return *this; }
       
   235 	FORCEINLINE OverflowSafeInt  operator %  (const int  divisor) const { OverflowSafeInt result = *this; result %= divisor; return result; }
       
   236 
       
   237 	/* Operators for shifting */
       
   238 	FORCEINLINE OverflowSafeInt& operator <<= (const int shift)       { this->m_value <<= shift; return *this; }
       
   239 	FORCEINLINE OverflowSafeInt  operator <<  (const int shift) const { OverflowSafeInt result = *this; result <<= shift; return result; }
       
   240 	FORCEINLINE OverflowSafeInt& operator >>= (const int shift)       { this->m_value >>= shift; return *this; }
       
   241 	FORCEINLINE OverflowSafeInt  operator >>  (const int shift) const { OverflowSafeInt result = *this; result >>= shift; return result; }
       
   242 
       
   243 	/* Operators for (in)equality when comparing overflow safe ints */
       
   244 	FORCEINLINE bool operator == (const OverflowSafeInt& other) const { return this->m_value == other.m_value; }
       
   245 	FORCEINLINE bool operator != (const OverflowSafeInt& other) const { return !(*this == other); }
       
   246 	FORCEINLINE bool operator >  (const OverflowSafeInt& other) const { return this->m_value > other.m_value; }
       
   247 	FORCEINLINE bool operator >= (const OverflowSafeInt& other) const { return this->m_value >= other.m_value; }
       
   248 	FORCEINLINE bool operator <  (const OverflowSafeInt& other) const { return !(*this >= other); }
       
   249 	FORCEINLINE bool operator <= (const OverflowSafeInt& other) const { return !(*this > other); }
       
   250 
       
   251 	/* Operators for (in)equality when comparing non-overflow safe ints */
       
   252 	FORCEINLINE bool operator == (const int other) const { return this->m_value == other; }
       
   253 	FORCEINLINE bool operator != (const int other) const { return !(*this == other); }
       
   254 	FORCEINLINE bool operator >  (const int other) const { return this->m_value > other; }
       
   255 	FORCEINLINE bool operator >= (const int other) const { return this->m_value >= other; }
       
   256 	FORCEINLINE bool operator <  (const int other) const { return !(*this >= other); }
       
   257 	FORCEINLINE bool operator <= (const int other) const { return !(*this > other); }
       
   258 
       
   259 	FORCEINLINE operator int64 () const { return this->m_value; }
       
   260 };
       
   261 
       
   262 /* Sometimes we got int64 operator OverflowSafeInt instead of vice versa. Handle that properly */
       
   263 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator + (int64 a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return b + a; }
       
   264 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator - (int64 a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return -b + a; }
       
   265 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator * (int64 a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return b * a; }
       
   266 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator / (int64 a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return (OverflowSafeInt<T, T_MAX, T_MIN>)a / (int)b; }
       
   267 
       
   268 /* Sometimes we got int operator OverflowSafeInt instead of vice versa. Handle that properly */
       
   269 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator + (int   a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return b + a; }
       
   270 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator - (int   a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return -b + a; }
       
   271 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator * (int   a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return b * a; }
       
   272 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator / (int   a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return (OverflowSafeInt<T, T_MAX, T_MIN>)a / (int)b; }
       
   273 
       
   274 /* Sometimes we got uint operator OverflowSafeInt instead of vice versa. Handle that properly */
       
   275 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator + (uint  a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return b + a; }
       
   276 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator - (uint  a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return -b + a; }
       
   277 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator * (uint  a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return b * a; }
       
   278 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator / (uint  a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return (OverflowSafeInt<T, T_MAX, T_MIN>)a / (int)b; }
       
   279 
       
   280 /* Sometimes we got byte operator OverflowSafeInt instead of vice versa. Handle that properly */
       
   281 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator + (byte  a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return b + a; }
       
   282 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator - (byte  a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return -b + a; }
       
   283 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator * (byte  a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return b * a; }
       
   284 template <class T, int64 T_MAX, int64 T_MIN> FORCEINLINE OverflowSafeInt<T, T_MAX, T_MIN> operator / (byte  a, OverflowSafeInt<T, T_MAX, T_MIN> b) { return (OverflowSafeInt<T, T_MAX, T_MIN>)a / (int)b; }
       
   285 
       
   286 #endif /* HELPERS_HPP */