1 /* byte_order-allInOne.h */
15 /* if x86 compatible cpu */
16 #if defined(i386) || defined(__i386__) || defined(__i486__) || \
17 defined(__i586__) || defined(__i686__) || defined(__pentium__) || \
18 defined(__pentiumpro__) || defined(__pentium4__) || \
19 defined(__nocona__) || defined(prescott) || defined(__core2__) || \
20 defined(__k6__) || defined(__k8__) || defined(__athlon__) || \
21 defined(__amd64) || defined(__amd64__) || \
22 defined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \
23 defined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64)
24 /* detect if x86-64 instruction set is supported */
25 # if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \
26 defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
34 /* detect CPU endianness */
35 #if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
36 __BYTE_ORDER == __LITTLE_ENDIAN) || \
37 (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
38 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
39 defined(CPU_IA32) || defined(CPU_X64) || \
40 defined(__ia64) || defined(__ia64__) || defined(__alpha__) || defined(_M_ALPHA) || \
41 defined(vax) || defined(MIPSEL) || defined(_ARM_) || defined(__arm__)
42 # define CPU_LITTLE_ENDIAN
43 # define IS_BIG_ENDIAN 0
44 # define IS_LITTLE_ENDIAN 1
45 #elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
46 __BYTE_ORDER == __BIG_ENDIAN) || \
47 (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
48 __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
49 defined(__sparc) || defined(__sparc__) || defined(sparc) || \
50 defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \
51 defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \
52 defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \
53 defined(__hpux) || defined(_MIPSEB) || defined(mc68000) || \
54 defined(__s390__) || defined(__s390x__) || defined(sel)
55 # define CPU_BIG_ENDIAN
56 # define IS_BIG_ENDIAN 1
57 # define IS_LITTLE_ENDIAN 0
59 # error "Can't detect CPU architechture"
63 # define __has_builtin(x) 0
66 #define IS_ALIGNED_32(p) (0 == (3 & ((const char*)(p) - (const char*)0)))
67 #define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))
70 #define ALIGN_ATTR(n) __declspec(align(n))
71 #elif defined(__GNUC__)
72 #define ALIGN_ATTR(n) __attribute__((aligned (n)))
74 #define ALIGN_ATTR(n) /* nothing */
78 #if defined(_MSC_VER) || defined(__BORLANDC__)
79 #define I64(x) x##ui64
85 #ifndef __STRICT_ANSI__
86 #define RHASH_INLINE inline
87 #elif defined(__GNUC__)
88 #define RHASH_INLINE __inline__
93 /* define rhash_ctz - count traling zero bits */
94 #if (defined(__GNUC__) && __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) || \
95 (defined(__clang__) && __has_builtin(__builtin_ctz))
96 /* GCC >= 3.4 or clang */
97 # define rhash_ctz(x) __builtin_ctz(x)
99 unsigned rhash_ctz(unsigned); /* define as function */
102 /* bswap definitions */
103 #if (defined(__GNUC__) && (__GNUC__ >= 4) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)) || \
104 (defined(__clang__) && __has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64))
105 /* GCC >= 4.3 or clang */
106 # define bswap_32(x) __builtin_bswap32(x)
107 # define bswap_64(x) __builtin_bswap64(x)
108 #elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */
109 # define bswap_32(x) _byteswap_ulong((unsigned long)x)
110 # define bswap_64(x) _byteswap_uint64((__int64)x)
112 /* fallback to generic bswap definition */
113 static RHASH_INLINE uint32_t bswap_32(uint32_t x)
115 # if defined(__GNUC__) && defined(CPU_IA32) && !defined(__i386__) && !defined(RHASH_NO_ASM)
116 __asm("bswap\t%0" : "=r" (x) : "0" (x)); /* gcc x86 version */
119 x = ((x << 8) & 0xFF00FF00u) | ((x >> 8) & 0x00FF00FFu);
120 return (x >> 16) | (x << 16);
123 static RHASH_INLINE uint64_t bswap_64(uint64_t x)
130 r.l[0] = bswap_32(w.l[1]);
131 r.l[1] = bswap_32(w.l[0]);
134 #endif /* bswap definitions */
136 #ifdef CPU_BIG_ENDIAN
137 # define be2me_32(x) (x)
138 # define be2me_64(x) (x)
139 # define le2me_32(x) bswap_32(x)
140 # define le2me_64(x) bswap_64(x)
142 # define be32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
143 # define le32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
144 # define be64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
145 # define le64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
146 # define me64_to_be_str(to, from, length) memcpy((to), (from), (length))
147 # define me64_to_le_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
149 #else /* CPU_BIG_ENDIAN */
150 # define be2me_32(x) bswap_32(x)
151 # define be2me_64(x) bswap_64(x)
152 # define le2me_32(x) (x)
153 # define le2me_64(x) (x)
155 # define be32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))
156 # define le32_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
157 # define be64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))
158 # define le64_copy(to, index, from, length) memcpy((to) + (index), (from), (length))
159 # define me64_to_be_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))
160 # define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
161 #endif /* CPU_BIG_ENDIAN */
163 /* ROTL/ROTR macros rotate a 32/64-bit word left/right by n bits */
164 #define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))
165 #define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))
166 #define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
167 #define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n))))
171 #endif /* __cplusplus */
173 #endif /* BYTE_ORDER_H */
176 // Apdated from byte_order.c
177 /* byte_order.c - byte order related platform dependent routines,
179 * Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
181 * Permission is hereby granted, free of charge, to any person obtaining a
182 * copy of this software and associated documentation files (the "Software"),
183 * to deal in the Software without restriction, including without limitation
184 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
185 * and/or sell copies of the Software, and to permit persons to whom the
186 * Software is furnished to do so.
188 * This program is distributed in the hope that it will be useful, but
189 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
190 * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
195 # if _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) /* if MSVC++ >= 2002 on x86/x64 */
197 # pragma intrinsic(_BitScanForward)
200 * Returns index of the trailing bit of x.
202 * @param x the number to process
203 * @return zero-based index of the trailing bit
205 inline unsigned rhash_ctz(unsigned x)
208 unsigned char isNonzero = _BitScanForward(&index, x); /* MSVC intrinsic */
209 return (isNonzero ? (unsigned)index : 0);
211 # else /* _MSC_VER >= 1300... */
214 * Returns index of the trailing bit of a 32-bit number.
215 * This is a plain C equivalent for GCC __builtin_ctz() bit scan.
217 * @param x the number to process
218 * @return zero-based index of the trailing bit
220 inline unsigned rhash_ctz(unsigned x)
222 /* array for conversion to bit position */
223 static unsigned char bit_pos[32] = {
224 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
225 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
228 /* The De Bruijn bit-scan was devised in 1997, according to Donald Knuth
229 * by Martin Lauter. The constant 0x077CB531UL is a De Bruijn sequence,
230 * which produces a unique pattern of bits into the high 5 bits for each
231 * possible bit position that it is multiplied against.
232 * See http://graphics.stanford.edu/~seander/bithacks.html
233 * and http://chessprogramming.wikispaces.com/BitScan */
234 return (unsigned)bit_pos[((uint32_t)((x & -x) * 0x077CB531U)) >> 27];
236 # endif /* _MSC_VER >= 1300... */
237 #endif /* rhash_ctz */
240 * Copy a memory block with simultaneous exchanging byte order.
241 * The byte order is changed from little-endian 32-bit integers
242 * to big-endian (or vice-versa).
244 * @param to the pointer where to copy memory block
245 * @param index the index to start writing from
246 * @param from the source block to copy
247 * @param length length of the memory block
249 inline void rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length)
251 /* if all pointers and length are 32-bits aligned */
252 if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | index | length ) & 3) ) {
253 /* copy memory as 32-bit words */
254 const uint32_t* src = (const uint32_t*)from;
255 const uint32_t* end = (const uint32_t*)((const char*)src + length);
256 uint32_t* dst = (uint32_t*)((char*)to + index);
257 for (; src < end; dst++, src++)
258 *dst = bswap_32(*src);
260 const char* src = (const char*)from;
261 for (length += index; (size_t)index < length; index++)
262 ((char*)to)[index ^ 3] = *(src++);
267 * Copy a memory block with changed byte order.
268 * The byte order is changed from little-endian 64-bit integers
269 * to big-endian (or vice-versa).
271 * @param to the pointer where to copy memory block
272 * @param index the index to start writing from
273 * @param from the source block to copy
274 * @param length length of the memory block
276 inline void rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length)
278 /* if all pointers and length are 64-bits aligned */
279 if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | index | length ) & 7) ) {
280 /* copy aligned memory block as 64-bit integers */
281 const uint64_t* src = (const uint64_t*)from;
282 const uint64_t* end = (const uint64_t*)((const char*)src + length);
283 uint64_t* dst = (uint64_t*)((char*)to + index);
284 while (src < end) *(dst++) = bswap_64( *(src++) );
286 const char* src = (const char*)from;
287 for (length += index; (size_t)index < length; index++) ((char*)to)[index ^ 7] = *(src++);
292 * Copy data from a sequence of 64-bit words to a binary string of given length,
293 * while changing byte order.
295 * @param to the binary string to receive data
296 * @param from the source sequence of 64-bit words
297 * @param length the size in bytes of the data being copied
299 inline void rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length)
301 /* if all pointers and length are 64-bits aligned */
302 if ( 0 == (( (int)((char*)to - (char*)0) | ((char*)from - (char*)0) | length ) & 7) ) {
303 /* copy aligned memory block as 64-bit integers */
304 const uint64_t* src = (const uint64_t*)from;
305 const uint64_t* end = (const uint64_t*)((const char*)src + length);
306 uint64_t* dst = (uint64_t*)to;
307 while (src < end) *(dst++) = bswap_64( *(src++) );
310 char* dst = (char*)to;
311 for (index = 0; index < length; index++) *(dst++) = ((char*)from)[index ^ 7];
316 * Exchange byte order in the given array of 32-bit integers.
318 * @param arr the array to process
319 * @param length array length
321 inline void rhash_u32_mem_swap(unsigned *arr, int length)
323 unsigned* end = arr + length;
324 for (; arr < end; arr++) {
325 *arr = bswap_32(*arr);