1 #ifndef ENDIAN_SWAP_H
2 #define ENDIAN_SWAP_H
3 
4 #include <stdint.h>
5 #include <inttypes.h>
6 #include "assert_helpers.h"
7 
8 #ifdef BOWTIE_64BIT_INDEX
9 #   define endianSwapU(x) endianSwapU64(x)
10 #   define endianSwapI(x) endianSwapI64(x)
11 #else
12 #   define endianSwapU(x) endianSwapU32(x)
13 #   define endianSwapI(x) endianSwapI32(x)
14 #endif
15 
16 
17 /**
18  * Return true iff the machine running this program is big-endian.
19  */
currentlyBigEndian()20 static inline bool currentlyBigEndian() {
21 	static uint8_t endianCheck[] = {1, 0, 0, 0};
22 	return *((uint32_t*)endianCheck) != 1;
23 }
24 
25 /**
26  * Return copy of uint32_t argument with byte order reversed.
27  */
endianSwapU32(uint32_t u)28 static inline uint32_t endianSwapU32(uint32_t u) {
29 	uint32_t tmp = 0;
30 	tmp |= ((u >> 24) & (0xff <<  0));
31 	tmp |= ((u >>  8) & (0xff <<  8));
32 	tmp |= ((u <<  8) & (0xff << 16));
33 	tmp |= ((u << 24) & (0xff << 24));
34 	return tmp;
35 }
36 
37 /**
38  * Return copy of uint64_t argument with byte order reversed.
39  */
endianSwapU64(uint64_t u)40 static inline uint64_t endianSwapU64(uint64_t u) {
41 	uint64_t tmp = 0;
42 	tmp |= ((u >> 56) & (0xffull <<  0));
43 	tmp |= ((u >> 40) & (0xffull <<  8));
44 	tmp |= ((u >> 24) & (0xffull << 16));
45 	tmp |= ((u >>  8) & (0xffull << 24));
46 	tmp |= ((u <<  8) & (0xffull << 32));
47 	tmp |= ((u << 24) & (0xffull << 40));
48 	tmp |= ((u << 40) & (0xffull << 48));
49 	tmp |= ((u << 56) & (0xffull << 56));
50 	return tmp;
51 }
52 
53 
54 /**
55  * Return copy of int32_t argument with byte order reversed.
56  */
endianSwapI32(int32_t i)57 static inline int32_t endianSwapI32(int32_t i) {
58 	int32_t tmp = 0;
59 	tmp |= ((i >> 24) & (0xff <<  0));
60 	tmp |= ((i >>  8) & (0xff <<  8));
61 	tmp |= ((i <<  8) & (0xff << 16));
62 	tmp |= ((i << 24) & (0xff << 24));
63 	return tmp;
64 }
65 
66 /**
67  * Return copy of int64_t argument with byte order reversed.
68  */
endianSwapI64(int64_t u)69 static inline int64_t endianSwapI64(int64_t u) {
70         int64_t tmp = 0;
71         tmp |= ((u >> 56) & (0xffull <<  0));
72         tmp |= ((u >> 40) & (0xffull <<  8));
73         tmp |= ((u >> 24) & (0xffull << 16));
74         tmp |= ((u >>  8) & (0xffull << 24));
75         tmp |= ((u <<  8) & (0xffull << 32));
76         tmp |= ((u << 24) & (0xffull << 40));
77         tmp |= ((u << 40) & (0xffull << 48));
78         tmp |= ((u << 56) & (0xffull << 56));
79         return tmp;
80 }
81 
82 /**
83  * Convert uint32_t/uint64_t argument to the specified endianness.  It's assumed
84  * that u currently has the endianness of the current machine.
85  */
86 template <typename T>
endianizeU(T u,bool toBig)87 static inline T endianizeU(T u, bool toBig) {
88 	if(toBig == currentlyBigEndian()) {
89 		return u;
90 	}
91 	if(sizeof(T) == 4) {
92 		return endianSwapU32((uint32_t)u);
93 	} else if(sizeof(T) == 8) {
94 		return endianSwapU64((uint64_t)u);
95 	} else {
96 		assert(false);
97 	}
98 }
99 
100 /**
101  * Convert int32_t/int64_t argument to the specified endianness.  It's assumed
102  * that u currently has the endianness of the current machine.
103  */
104 template <typename T>
endianizeI(T i,bool toBig)105 static inline T endianizeI(T i, bool toBig) {
106 	if(toBig == currentlyBigEndian()) {
107 		return i;
108 	}
109 	if(sizeof(T) == 4) {
110 		return endianSwapI32((int32_t)i);
111 	} else if(sizeof(T) == 8) {
112 		return endianSwapI64((int64_t)i);
113 	} else {
114 		assert(false);
115 	}
116 }
117 
118 #endif
119