utp_templates.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Copyright (c) 2010-2013 BitTorrent, Inc.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. #ifndef __TEMPLATES_H__
  23. #define __TEMPLATES_H__
  24. #include "utp_types.h"
  25. #include <assert.h>
  26. #if defined(POSIX)
  27. /* Allow over-writing FORCEINLINE from makefile because gcc 3.4.4 for buffalo
  28. doesn't seem to support __attribute__((always_inline)) in -O0 build
  29. (strangely, it works in -Os build) */
  30. #ifndef FORCEINLINE
  31. // The always_inline attribute asks gcc to inline the function even if no optimization is being requested.
  32. // This macro should be used exclusive-or with the inline directive (use one or the other but not both)
  33. // since Microsoft uses __forceinline to also mean inline,
  34. // and this code is following a Microsoft compatibility model.
  35. // Just setting the attribute without also specifying the inline directive apparently won't inline the function,
  36. // as evidenced by multiply-defined symbols found at link time.
  37. #define FORCEINLINE inline __attribute__((always_inline))
  38. #endif
  39. #endif
  40. // Utility templates
  41. #undef min
  42. #undef max
  43. template <typename T> static inline T min(T a, T b) { if (a < b) return a; return b; }
  44. template <typename T> static inline T max(T a, T b) { if (a > b) return a; return b; }
  45. template <typename T> static inline T min(T a, T b, T c) { return min(min(a,b),c); }
  46. template <typename T> static inline T max(T a, T b, T c) { return max(max(a,b),c); }
  47. template <typename T> static inline T clamp(T v, T mi, T ma)
  48. {
  49. if (v > ma) v = ma;
  50. if (v < mi) v = mi;
  51. return v;
  52. }
  53. #if (defined(__SVR4) && defined(__sun))
  54. #pragma pack(1)
  55. #else
  56. #pragma pack(push,1)
  57. #endif
  58. namespace aux
  59. {
  60. FORCEINLINE uint16 host_to_network(uint16 i) { return htons(i); }
  61. FORCEINLINE uint32 host_to_network(uint32 i) { return htonl(i); }
  62. FORCEINLINE int32 host_to_network(int32 i) { return htonl(i); }
  63. FORCEINLINE uint16 network_to_host(uint16 i) { return ntohs(i); }
  64. FORCEINLINE uint32 network_to_host(uint32 i) { return ntohl(i); }
  65. FORCEINLINE int32 network_to_host(int32 i) { return ntohl(i); }
  66. }
  67. template <class T>
  68. struct PACKED_ATTRIBUTE big_endian
  69. {
  70. T operator=(T i) { m_integer = aux::host_to_network(i); return i; }
  71. operator T() const { return aux::network_to_host(m_integer); }
  72. private:
  73. T m_integer;
  74. };
  75. typedef big_endian<int32> int32_big;
  76. typedef big_endian<uint32> uint32_big;
  77. typedef big_endian<uint16> uint16_big;
  78. #if (defined(__SVR4) && defined(__sun))
  79. #pragma pack(0)
  80. #else
  81. #pragma pack(pop)
  82. #endif
  83. template<typename T> static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); }
  84. typedef int SortCompareProc(const void *, const void *);
  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. // WARNING: The template parameter MUST be a POD type!
  87. template <typename T, size_t minsize = 16> class Array {
  88. protected:
  89. T *mem;
  90. size_t alloc,count;
  91. public:
  92. Array(size_t init) { Init(init); }
  93. Array() { Init(); }
  94. ~Array() { Free(); }
  95. void inline Init() { mem = NULL; alloc = count = 0; }
  96. void inline Init(size_t init) { Init(); if (init) Resize(init); }
  97. size_t inline GetCount() const { return count; }
  98. size_t inline GetAlloc() const { return alloc; }
  99. void inline SetCount(size_t c) { count = c; }
  100. inline T& operator[](size_t offset) { assert(offset ==0 || offset<alloc); return mem[offset]; }
  101. inline const T& operator[](size_t offset) const { assert(offset ==0 || offset<alloc); return mem[offset]; }
  102. void inline Resize(size_t a) {
  103. if (a == 0) { free(mem); Init(); }
  104. else { mem = (T*)realloc(mem, (alloc=a) * sizeof(T)); }
  105. }
  106. void Grow() { Resize(::max<size_t>(minsize, alloc * 2)); }
  107. inline size_t Append(const T &t) {
  108. if (count >= alloc) Grow();
  109. size_t r=count++;
  110. mem[r] = t;
  111. return r;
  112. }
  113. T inline &Append() {
  114. if (count >= alloc) Grow();
  115. return mem[count++];
  116. }
  117. void inline Compact() {
  118. Resize(count);
  119. }
  120. void inline Free() {
  121. free(mem);
  122. Init();
  123. }
  124. void inline Clear() {
  125. count = 0;
  126. }
  127. bool inline MoveUpLast(size_t index) {
  128. assert(index < count);
  129. size_t c = --count;
  130. if (index != c) {
  131. mem[index] = mem[c];
  132. return true;
  133. }
  134. return false;
  135. }
  136. bool inline MoveUpLastExist(const T &v) {
  137. return MoveUpLast(LookupElementExist(v));
  138. }
  139. size_t inline LookupElement(const T &v) const {
  140. for(size_t i = 0; i != count; i++)
  141. if (mem[i] == v)
  142. return i;
  143. return (size_t) -1;
  144. }
  145. bool inline HasElement(const T &v) const {
  146. return LookupElement(v) != -1;
  147. }
  148. typedef int SortCompareProc(const T *a, const T *b);
  149. void Sort(SortCompareProc* proc, size_t start, size_t end) {
  150. QuickSortT(&mem[start], end - start, proc);
  151. }
  152. void Sort(SortCompareProc* proc, size_t start) {
  153. Sort(proc, start, count);
  154. }
  155. void Sort(SortCompareProc* proc) {
  156. Sort(proc, 0, count);
  157. }
  158. };
  159. #endif //__TEMPLATES_H__