source: trunk/third-party/libutp/templates.h @ 12603

Last change on this file since 12603 was 12603, checked in by jordan, 10 years ago

(trunk, libutp) #4260 "uTP not working when compiler doesn't honor 'pragma pack'" -- apply alus' revised patch for testing.

File size: 4.5 KB
Line 
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// Utility templates
23#undef min
24#undef max
25
26template <typename T> static inline T min(T a, T b) { if (a < b) return a; return b; }
27template <typename T> static inline T max(T a, T b) { if (a > b) return a; return b; }
28
29template <typename T> static inline T min(T a, T b, T c) { return min(min(a,b),c); }
30template <typename T> static inline T max(T a, T b, T c) { return max(max(a,b),c); }
31template <typename T> static inline T clamp(T v, T mi, T ma)
32{
33        if (v > ma) v = ma;
34        if (v < mi) v = mi;
35        return v;
36}
37
38#pragma pack(push,1)
39
40namespace aux
41{
42        FORCEINLINE uint16 host_to_network(uint16 i) { return htons(i); }
43        FORCEINLINE uint32 host_to_network(uint32 i) { return htonl(i); }
44        FORCEINLINE int32 host_to_network(int32 i) { return htonl(i); }
45        FORCEINLINE uint16 network_to_host(uint16 i) { return ntohs(i); }
46        FORCEINLINE uint32 network_to_host(uint32 i) { return ntohl(i); }
47        FORCEINLINE int32 network_to_host(int32 i) { return ntohl(i); }
48}
49
50template <class T>
51struct big_endian
52{
53        T operator=(T i) { m_integer = aux::host_to_network(i); return i; }
54        operator T() const { return aux::network_to_host(m_integer); }
55private:
56        T m_integer;
57};
58
59typedef big_endian<int32> int32_big;
60typedef big_endian<uint32> uint32_big;
61typedef big_endian<uint16> uint16_big;
62
63#pragma pack(pop)
64
65template<typename T> static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); }
66
67typedef int SortCompareProc(const void *, const void *);
68
69template<typename T> static FORCEINLINE void QuickSortT(T *base, size_t num, int (*comp)(const T *, const T *)) { qsort(base, num, sizeof(T), (SortCompareProc*)comp); }
70
71
72// WARNING: The template parameter MUST be a POD type!
73template <typename T, size_t minsize = 16> class Array {
74protected:
75        T *mem;
76        size_t alloc,count;
77
78public:
79        Array(size_t init) { Init(init); }
80        Array() { Init(); }
81        ~Array() { Free(); }
82
83        void inline Init() { mem = NULL; alloc = count = 0; }
84        void inline Init(size_t init) { Init(); if (init) Resize(init); }
85        size_t inline GetCount() const { return count; }
86        size_t inline GetAlloc() const { return alloc; }
87        void inline SetCount(size_t c) { count = c; }
88
89        inline T& operator[](size_t offset) { assert(offset ==0 || offset<alloc); return mem[offset]; }
90        inline const T& operator[](size_t offset) const { assert(offset ==0 || offset<alloc); return mem[offset]; }
91
92        void inline Resize(size_t a) {
93                if (a == 0) { free(mem); Init(); }
94                else { mem = (T*)realloc(mem, (alloc=a) * sizeof(T)); }
95        }
96
97        void Grow() { Resize(::max<size_t>(minsize, alloc * 2)); }
98
99        inline size_t Append(const T &t) {
100                if (count >= alloc) Grow();
101                size_t r=count++;
102                mem[r] = t;
103                return r;
104        }
105
106        T inline &Append() {
107                if (count >= alloc) Grow();
108                return mem[count++];
109        }
110
111        void inline Compact() {
112                Resize(count);
113        }
114
115        void inline Free() {
116                free(mem);
117                Init();
118        }
119
120        void inline Clear() {
121                count = 0;
122        }
123
124        bool inline MoveUpLast(size_t index) {
125                assert(index < count);
126                size_t c = --count;
127                if (index != c) {
128                        mem[index] = mem[c];
129                        return true;
130                }
131                return false;
132        }
133
134        bool inline MoveUpLastExist(const T &v) {
135                return MoveUpLast(LookupElementExist(v));
136        }
137
138        size_t inline LookupElement(const T &v) const {
139                for(size_t i = 0; i != count; i++)
140                        if (mem[i] == v)
141                                return i;
142                return (size_t) -1;
143        }
144
145        bool inline HasElement(const T &v) const {
146                return LookupElement(v) != -1;
147        }
148
149        typedef int SortCompareProc(const T *a, const T *b);
150
151        void Sort(SortCompareProc* proc, size_t start, size_t end) {
152                QuickSortT(&mem[start], end - start, proc);
153        }
154
155        void Sort(SortCompareProc* proc, size_t start) {
156                Sort(proc, start, count);
157        }
158
159        void Sort(SortCompareProc* proc) {
160                Sort(proc, 0, count);
161        }
162};
163
164#endif //__TEMPLATES_H__
Note: See TracBrowser for help on using the repository browser.