hendian.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #ifndef HV_ENDIAN_H_
  2. #define HV_ENDIAN_H_
  3. #include "hplatform.h"
  4. #if defined(OS_MAC)
  5. #include <libkern/OSByteOrder.h>
  6. #define htobe16(v) OSSwapHostToBigInt16(v)
  7. #define htobe32(v) OSSwapHostToBigInt32(v)
  8. #define htobe64(v) OSSwapHostToBigInt64(v)
  9. #define be16toh(v) OSSwapBigToHostInt16(v)
  10. #define be32toh(v) OSSwapBigToHostInt32(v)
  11. #define be64toh(v) OSSwapBigToHostInt64(v)
  12. #define htole16(v) OSSwapHostToLittleInt16(v)
  13. #define htole32(v) OSSwapHostToLittleInt32(v)
  14. #define htole64(v) OSSwapHostToLittleInt64(v)
  15. #define le16toh(v) OSSwapLittleToHostInt16(v)
  16. #define le32toh(v) OSSwapLittleToHostInt32(v)
  17. #define le64toh(v) OSSwapLittleToHostInt64(v)
  18. #elif defined(OS_WIN)
  19. #if _WIN32_WINNT < _WIN32_WINNT_WIN8
  20. /*
  21. * Byte order conversion functions for 64-bit integers and 32 + 64 bit
  22. * floating-point numbers. IEEE big-endian format is used for the
  23. * network floating point format.
  24. */
  25. #define _WS2_32_WINSOCK_SWAP_LONG(l) \
  26. ( ( ((l) >> 24) & 0x000000FFL ) | \
  27. ( ((l) >> 8) & 0x0000FF00L ) | \
  28. ( ((l) << 8) & 0x00FF0000L ) | \
  29. ( ((l) << 24) & 0xFF000000L ) )
  30. #define _WS2_32_WINSOCK_SWAP_LONGLONG(l) \
  31. ( ( ((l) >> 56) & 0x00000000000000FFLL ) | \
  32. ( ((l) >> 40) & 0x000000000000FF00LL ) | \
  33. ( ((l) >> 24) & 0x0000000000FF0000LL ) | \
  34. ( ((l) >> 8) & 0x00000000FF000000LL ) | \
  35. ( ((l) << 8) & 0x000000FF00000000LL ) | \
  36. ( ((l) << 24) & 0x0000FF0000000000LL ) | \
  37. ( ((l) << 40) & 0x00FF000000000000LL ) | \
  38. ( ((l) << 56) & 0xFF00000000000000LL ) )
  39. #ifndef htonll
  40. __inline unsigned __int64 htonll ( unsigned __int64 Value )
  41. {
  42. const unsigned __int64 Retval = _WS2_32_WINSOCK_SWAP_LONGLONG (Value);
  43. return Retval;
  44. }
  45. #endif /* htonll */
  46. #ifndef ntohll
  47. __inline unsigned __int64 ntohll ( unsigned __int64 Value )
  48. {
  49. const unsigned __int64 Retval = _WS2_32_WINSOCK_SWAP_LONGLONG (Value);
  50. return Retval;
  51. }
  52. #endif /* ntohll */
  53. #ifndef htonf
  54. __inline unsigned __int32 htonf ( float Value )
  55. {
  56. unsigned __int32 Tempval;
  57. unsigned __int32 Retval;
  58. Tempval = *(unsigned __int32*)(&Value);
  59. Retval = _WS2_32_WINSOCK_SWAP_LONG (Tempval);
  60. return Retval;
  61. }
  62. #endif /* htonf */
  63. #ifndef ntohf
  64. __inline float ntohf ( unsigned __int32 Value )
  65. {
  66. const unsigned __int32 Tempval = _WS2_32_WINSOCK_SWAP_LONG (Value);
  67. float Retval;
  68. *((unsigned __int32*)&Retval) = Tempval;
  69. return Retval;
  70. }
  71. #endif /* ntohf */
  72. #ifndef htond
  73. __inline unsigned __int64 htond ( double Value )
  74. {
  75. unsigned __int64 Tempval;
  76. unsigned __int64 Retval;
  77. Tempval = *(unsigned __int64*)(&Value);
  78. Retval = _WS2_32_WINSOCK_SWAP_LONGLONG (Tempval);
  79. return Retval;
  80. }
  81. #endif /* htond */
  82. #ifndef ntohd
  83. __inline double ntohd ( unsigned __int64 Value )
  84. {
  85. const unsigned __int64 Tempval = _WS2_32_WINSOCK_SWAP_LONGLONG (Value);
  86. double Retval;
  87. *((unsigned __int64*)&Retval) = Tempval;
  88. return Retval;
  89. }
  90. #endif /* ntohd */
  91. #endif
  92. #define htobe16(v) htons(v)
  93. #define htobe32(v) htonl(v)
  94. #define htobe64(v) htonll(v)
  95. #define be16toh(v) ntohs(v)
  96. #define be32toh(v) ntohl(v)
  97. #define be64toh(v) ntohll(v)
  98. #if (BYTE_ORDER == LITTLE_ENDIAN)
  99. #define htole16(v) (v)
  100. #define htole32(v) (v)
  101. #define htole64(v) (v)
  102. #define le16toh(v) (v)
  103. #define le32toh(v) (v)
  104. #define le64toh(v) (v)
  105. #elif (BYTE_ORDER == BIG_ENDIAN)
  106. #define htole16(v) __builtin_bswap16(v)
  107. #define htole32(v) __builtin_bswap32(v)
  108. #define htole64(v) __builtin_bswap64(v)
  109. #define le16toh(v) __builtin_bswap16(v)
  110. #define le32toh(v) __builtin_bswap32(v)
  111. #define le64toh(v) __builtin_bswap64(v)
  112. #endif
  113. #elif HAVE_ENDIAN_H
  114. #include <endian.h>
  115. #elif HAVE_SYS_ENDIAN_H
  116. #include <sys/endian.h>
  117. #else
  118. #warning "Not found endian.h!"
  119. #endif
  120. #define PI8(p) *(int8_t*)(p)
  121. #define PI16(p) *(int16_t*)(p)
  122. #define PI32(p) *(int32_t*)(p)
  123. #define PI64(p) *(int64_t*)(p)
  124. #define PU8(p) *(uint8_t*)(p)
  125. #define PU16(p) *(uint16_t*)(p)
  126. #define PU32(p) *(uint32_t*)(p)
  127. #define PU64(p) *(uint64_t*)(p)
  128. #define PF32(p) *(float*)(p)
  129. #define PF64(p) *(double*)(p)
  130. #define GET_BE16(p) be16toh(PU16(p))
  131. #define GET_BE32(p) be32toh(PU32(p))
  132. #define GET_BE64(p) be64toh(PU64(p))
  133. #define GET_LE16(p) le16toh(PU16(p))
  134. #define GET_LE32(p) le32toh(PU32(p))
  135. #define GET_LE64(p) le64toh(PU64(p))
  136. #define PUT_BE16(p, v) PU16(p) = htobe16(v)
  137. #define PUT_BE32(p, v) PU32(p) = htobe32(v)
  138. #define PUT_BE64(p, v) PU64(p) = htobe64(v)
  139. #define PUT_LE16(p, v) PU16(p) = htole16(v)
  140. #define PUT_LE32(p, v) PU32(p) = htole32(v)
  141. #define PUT_LE64(p, v) PU64(p) = htole64(v)
  142. // NOTE: uint8_t* p = (uint8_t*)buf;
  143. #define POP_BE8(p, v) v = *p; ++p
  144. #define POP_BE16(p, v) v = be16toh(PU16(p)); p += 2
  145. #define POP_BE32(p, v) v = be32toh(PU32(p)); p += 4
  146. #define POP_BE64(p, v) v = be64toh(PU64(p)); p += 8
  147. #define POP_LE8(p, v) v= *p; ++p
  148. #define POP_LE16(p, v) v = le16toh(PU16(p)); p += 2
  149. #define POP_LE32(p, v) v = le32toh(PU32(p)); p += 4
  150. #define POP_LE64(p, v) v = le64toh(PU64(p)); p += 8
  151. #define PUSH_BE8(p, v) *p = v; ++p
  152. #define PUSH_BE16(p, v) PU16(p) = htobe16(v); p += 2
  153. #define PUSH_BE32(p, v) PU32(p) = htobe32(v); p += 4
  154. #define PUSH_BE64(p, v) PU64(p) = htobe64(v); p += 8
  155. #define PUSH_LE8(p, v) *p = v; ++p
  156. #define PUSH_LE16(p, v) PU16(p) = htole16(v); p += 2
  157. #define PUSH_LE32(p, v) PU32(p) = htole32(v); p += 4
  158. #define PUSH_LE64(p, v) PU64(p) = htole64(v); p += 8
  159. // NOTE: NET_ENDIAN = BIG_ENDIAN
  160. #define POP8(p, v) POP_BE8(p, v)
  161. #define POP16(p, v) POP_BE16(p, v)
  162. #define POP32(p, v) POP_BE32(p, v)
  163. #define POP64(p, v) POP_BE64(p, v)
  164. #define POP_N(p, v, n) memcpy(v, p, n); p += n
  165. #define PUSH8(p, v) PUSH_BE8(p, v)
  166. #define PUSH16(p, v) PUSH_BE16(p, v)
  167. #define PUSH32(p, v) PUSH_BE32(p, v)
  168. #define PUSH64(p, v) PUSH_BE64(p, v)
  169. #define PUSH_N(p, v, n) memcpy(p, v, n); p += n
  170. static inline int detect_endian() {
  171. union {
  172. char c;
  173. short s;
  174. } u;
  175. u.s = 0x1122;
  176. return u.c ==0x11 ? BIG_ENDIAN : LITTLE_ENDIAN;
  177. }
  178. #ifdef __cplusplus
  179. template <typename T>
  180. uint8_t* serialize(uint8_t* buf, T value, int host_endian = LITTLE_ENDIAN, int buf_endian = BIG_ENDIAN) {
  181. size_t size = sizeof(T);
  182. uint8_t* pDst = buf;
  183. uint8_t* pSrc = (uint8_t*)&value;
  184. if (host_endian == buf_endian) {
  185. memcpy(pDst, pSrc, size);
  186. }
  187. else {
  188. for (int i = 0; i < size; ++i) {
  189. pDst[i] = pSrc[size-i-1];
  190. }
  191. }
  192. return buf+size;
  193. }
  194. template <typename T>
  195. uint8_t* deserialize(uint8_t* buf, T* value, int host_endian = LITTLE_ENDIAN, int buf_endian = BIG_ENDIAN) {
  196. size_t size = sizeof(T);
  197. uint8_t* pSrc = buf;
  198. uint8_t* pDst = (uint8_t*)value;
  199. if (host_endian == buf_endian) {
  200. memcpy(pDst, pSrc, size);
  201. }
  202. else {
  203. for (int i = 0; i < size; ++i) {
  204. pDst[i] = pSrc[size-i-1];
  205. }
  206. }
  207. return buf+size;
  208. }
  209. #endif // __cplusplus
  210. #endif // HV_ENDIAN_H_