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 | |
---|
34 | template <typename T> static inline T min(T a, T b) { if (a < b) return a; return b; } |
---|
35 | template <typename T> static inline T max(T a, T b) { if (a > b) return a; return b; } |
---|
36 | |
---|
37 | template <typename T> static inline T min(T a, T b, T c) { return min(min(a,b),c); } |
---|
38 | template <typename T> static inline T max(T a, T b, T c) { return max(max(a,b),c); } |
---|
39 | template <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 | |
---|
52 | namespace 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 | |
---|
62 | template <class T> |
---|
63 | struct 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); } |
---|
67 | private: |
---|
68 | T m_integer; |
---|
69 | }; |
---|
70 | |
---|
71 | typedef big_endian<int32> int32_big; |
---|
72 | typedef big_endian<uint32> uint32_big; |
---|
73 | typedef 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 | |
---|
81 | template<typename T> static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); } |
---|
82 | |
---|
83 | typedef int SortCompareProc(const void *, const void *); |
---|
84 | |
---|
85 | template<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! |
---|
89 | template <typename T, size_t minsize = 16> class Array { |
---|
90 | protected: |
---|
91 | T *mem; |
---|
92 | size_t alloc,count; |
---|
93 | |
---|
94 | public: |
---|
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__ |
---|