1#ifndef __TEMPLATES_H__ 2#define __TEMPLATES_H__ 3 4#include "utypes.h" 5#include <assert.h> 6 7#if defined(POSIX) 8/* Allow over-writing FORCEINLINE from makefile because gcc 3.4.4 for buffalo 9 doesn't seem to support __attribute__((always_inline)) in -O0 build 10 (strangely, it works in -Os build) */ 11#ifndef FORCEINLINE 12// The always_inline attribute asks gcc to inline the function even if no optimization is being requested. 13// This macro should be used exclusive-or with the inline directive (use one or the other but not both) 14// since Microsoft uses __forceinline to also mean inline, 15// and this code is following a Microsoft compatibility model. 16// Just setting the attribute without also specifying the inline directive apparently won't inline the function, 17// as evidenced by multiply-defined symbols found at link time. 18#define FORCEINLINE inline __attribute__((always_inline)) 19#endif 20#endif 21 22#ifdef __GNUC__ 23// Used for gcc tool chains accepting but not supporting pragma pack 24// See http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html 25#define PACKED_ATTRIBUTE __attribute__((__packed__)) 26#else 27#define PACKED_ATTRIBUTE 28#endif 29 30// Utility templates 31#undef min 32#undef max 33 34template <typename T> static inline T min(T a, T b) { if (a < b) return a; return b; } 35template <typename T> static inline T max(T a, T b) { if (a > b) return a; return b; } 36 37template <typename T> static inline T min(T a, T b, T c) { return min(min(a,b),c); } 38template <typename T> static inline T max(T a, T b, T c) { return max(max(a,b),c); } 39template <typename T> static inline T clamp(T v, T mi, T ma) 40{ 41 if (v > ma) v = ma; 42 if (v < mi) v = mi; 43 return v; 44} 45 46#if (defined(__SVR4) && defined(__sun)) 47#pragma pack(1) 48#else 49#pragma pack(push,1) 50#endif 51 52namespace aux 53{ 54 FORCEINLINE uint16 host_to_network(uint16 i) { return htons(i); } 55 FORCEINLINE uint32 host_to_network(uint32 i) { return htonl(i); } 56 FORCEINLINE int32 host_to_network(int32 i) { return htonl(i); } 57 FORCEINLINE uint16 network_to_host(uint16 i) { return ntohs(i); } 58 FORCEINLINE uint32 network_to_host(uint32 i) { return ntohl(i); } 59 FORCEINLINE int32 network_to_host(int32 i) { return ntohl(i); } 60} 61 62template <class T> 63struct PACKED_ATTRIBUTE big_endian 64{ 65 T operator=(T i) { m_integer = aux::host_to_network(i); return i; } 66 operator T() const { return aux::network_to_host(m_integer); } 67private: 68 T m_integer; 69}; 70 71typedef big_endian<int32> int32_big; 72typedef big_endian<uint32> uint32_big; 73typedef big_endian<uint16> uint16_big; 74 75#if (defined(__SVR4) && defined(__sun)) 76#pragma pack(0) 77#else 78#pragma pack(pop) 79#endif 80 81template<typename T> static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); } 82 83typedef int SortCompareProc(const void *, const void *); 84 85template<typename T> static FORCEINLINE void QuickSortT(T *base, size_t num, int (*comp)(const T *, const T *)) { qsort(base, num, sizeof(T), (SortCompareProc*)comp); } 86 87 88// WARNING: The template parameter MUST be a POD type! 89template <typename T, size_t minsize = 16> class Array { 90protected: 91 T *mem; 92 size_t alloc,count; 93 94public: 95 Array(size_t init) { Init(init); } 96 Array() { Init(); } 97 ~Array() { Free(); } 98 99 void inline Init() { mem = NULL; alloc = count = 0; } 100 void inline Init(size_t init) { Init(); if (init) Resize(init); } 101 size_t inline GetCount() const { return count; } 102 size_t inline GetAlloc() const { return alloc; } 103 void inline SetCount(size_t c) { count = c; } 104 105 inline T& operator[](size_t offset) { assert(offset ==0 || offset<alloc); return mem[offset]; } 106 inline const T& operator[](size_t offset) const { assert(offset ==0 || offset<alloc); return mem[offset]; } 107 108 void inline Resize(size_t a) { 109 if (a == 0) { free(mem); Init(); } 110 else { mem = (T*)realloc(mem, (alloc=a) * sizeof(T)); } 111 } 112 113 void Grow() { Resize(::max<size_t>(minsize, alloc * 2)); } 114 115 inline size_t Append(const T &t) { 116 if (count >= alloc) Grow(); 117 size_t r=count++; 118 mem[r] = t; 119 return r; 120 } 121 122 T inline &Append() { 123 if (count >= alloc) Grow(); 124 return mem[count++]; 125 } 126 127 void inline Compact() { 128 Resize(count); 129 } 130 131 void inline Free() { 132 free(mem); 133 Init(); 134 } 135 136 void inline Clear() { 137 count = 0; 138 } 139 140 bool inline MoveUpLast(size_t index) { 141 assert(index < count); 142 size_t c = --count; 143 if (index != c) { 144 mem[index] = mem[c]; 145 return true; 146 } 147 return false; 148 } 149 150 bool inline MoveUpLastExist(const T &v) { 151 return MoveUpLast(LookupElementExist(v)); 152 } 153 154 size_t inline LookupElement(const T &v) const { 155 for(size_t i = 0; i != count; i++) 156 if (mem[i] == v) 157 return i; 158 return (size_t) -1; 159 } 160 161 bool inline HasElement(const T &v) const { 162 return LookupElement(v) != -1; 163 } 164 165 typedef int SortCompareProc(const T *a, const T *b); 166 167 void Sort(SortCompareProc* proc, size_t start, size_t end) { 168 QuickSortT(&mem[start], end - start, proc); 169 } 170 171 void Sort(SortCompareProc* proc, size_t start) { 172 Sort(proc, start, count); 173 } 174 175 void Sort(SortCompareProc* proc) { 176 Sort(proc, 0, count); 177 } 178}; 179 180#endif //__TEMPLATES_H__ 181