tdb2: copy tdb1's changed expansion logic.
[ccan] / ccan / endian / endian.h
1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
2 #ifndef CCAN_ENDIAN_H
3 #define CCAN_ENDIAN_H
4 #include <stdint.h>
5 #include "config.h"
6
7 #if HAVE_BYTESWAP_H
8 #include <byteswap.h>
9 #else
10 /**
11  * bswap_16 - reverse bytes in a uint16_t value.
12  * @val: value whose bytes to swap.
13  *
14  * Example:
15  *      // Output contains "1024 is 4 as two bytes reversed"
16  *      printf("1024 is %u as two bytes reversed\n", bswap_16(1024));
17  */
18 static inline uint16_t bswap_16(uint16_t val)
19 {
20         return ((val & (uint16_t)0x00ffU) << 8)
21                 | ((val & (uint16_t)0xff00U) >> 8);
22 }
23
24 /**
25  * bswap_32 - reverse bytes in a uint32_t value.
26  * @val: value whose bytes to swap.
27  *
28  * Example:
29  *      // Output contains "1024 is 262144 as four bytes reversed"
30  *      printf("1024 is %u as four bytes reversed\n", bswap_32(1024));
31  */
32 static inline uint32_t bswap_32(uint32_t val)
33 {
34         return ((val & (uint32_t)0x000000ffUL) << 24)
35                 | ((val & (uint32_t)0x0000ff00UL) <<  8)
36                 | ((val & (uint32_t)0x00ff0000UL) >>  8)
37                 | ((val & (uint32_t)0xff000000UL) >> 24);
38 }
39 #endif /* !HAVE_BYTESWAP_H */
40
41 #if !HAVE_BSWAP_64
42 /**
43  * bswap_64 - reverse bytes in a uint64_t value.
44  * @val: value whose bytes to swap.
45  *
46  * Example:
47  *      // Output contains "1024 is 1125899906842624 as eight bytes reversed"
48  *      printf("1024 is %llu as eight bytes reversed\n",
49  *              (unsigned long long)bswap_64(1024));
50  */
51 static inline uint64_t bswap_64(uint64_t val)
52 {
53         return ((val & (uint64_t)0x00000000000000ffULL) << 56)
54                 | ((val & (uint64_t)0x000000000000ff00ULL) << 40)
55                 | ((val & (uint64_t)0x0000000000ff0000ULL) << 24)
56                 | ((val & (uint64_t)0x00000000ff000000ULL) <<  8)
57                 | ((val & (uint64_t)0x000000ff00000000ULL) >>  8)
58                 | ((val & (uint64_t)0x0000ff0000000000ULL) >> 24)
59                 | ((val & (uint64_t)0x00ff000000000000ULL) >> 40)
60                 | ((val & (uint64_t)0xff00000000000000ULL) >> 56);
61 }
62 #endif
63
64 /* Sanity check the defines.  We don't handle weird endianness. */
65 #if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN
66 #error "Unknown endian"
67 #elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN
68 #error "Can't compile for both big and little endian."
69 #endif
70
71 /**
72  * cpu_to_le64 - convert a uint64_t value to little-endian
73  * @native: value to convert
74  */
75 static inline uint64_t cpu_to_le64(uint64_t native)
76 {
77 #if HAVE_LITTLE_ENDIAN
78         return native;
79 #else
80         return bswap_64(native);
81 #endif
82 }
83
84 /**
85  * cpu_to_le32 - convert a uint32_t value to little-endian
86  * @native: value to convert
87  */
88 static inline uint32_t cpu_to_le32(uint32_t native)
89 {
90 #if HAVE_LITTLE_ENDIAN
91         return native;
92 #else
93         return bswap_32(native);
94 #endif
95 }
96
97 /**
98  * cpu_to_le16 - convert a uint16_t value to little-endian
99  * @native: value to convert
100  */
101 static inline uint16_t cpu_to_le16(uint16_t native)
102 {
103 #if HAVE_LITTLE_ENDIAN
104         return native;
105 #else
106         return bswap_16(native);
107 #endif
108 }
109
110 /**
111  * le64_to_cpu - convert a little-endian uint64_t value
112  * @le_val: little-endian value to convert
113  */
114 static inline uint64_t le64_to_cpu(uint64_t le_val)
115 {
116 #if HAVE_LITTLE_ENDIAN
117         return le_val;
118 #else
119         return bswap_64(le_val);
120 #endif
121 }
122
123 /**
124  * le32_to_cpu - convert a little-endian uint32_t value
125  * @le_val: little-endian value to convert
126  */
127 static inline uint32_t le32_to_cpu(uint32_t le_val)
128 {
129 #if HAVE_LITTLE_ENDIAN
130         return le_val;
131 #else
132         return bswap_32(le_val);
133 #endif
134 }
135
136 /**
137  * le16_to_cpu - convert a little-endian uint16_t value
138  * @le_val: little-endian value to convert
139  */
140 static inline uint16_t le16_to_cpu(uint16_t le_val)
141 {
142 #if HAVE_LITTLE_ENDIAN
143         return le_val;
144 #else
145         return bswap_16(le_val);
146 #endif
147 }
148
149 /**
150  * cpu_to_be64 - convert a uint64_t value to big endian.
151  * @native: value to convert
152  */
153 static inline uint64_t cpu_to_be64(uint64_t native)
154 {
155 #if HAVE_LITTLE_ENDIAN
156         return bswap_64(native);
157 #else
158         return native;
159 #endif
160 }
161
162 /**
163  * cpu_to_be32 - convert a uint32_t value to big endian.
164  * @native: value to convert
165  */
166 static inline uint32_t cpu_to_be32(uint32_t native)
167 {
168 #if HAVE_LITTLE_ENDIAN
169         return bswap_32(native);
170 #else
171         return native;
172 #endif
173 }
174
175 /**
176  * cpu_to_be16 - convert a uint16_t value to big endian.
177  * @native: value to convert
178  */
179 static inline uint16_t cpu_to_be16(uint16_t native)
180 {
181 #if HAVE_LITTLE_ENDIAN
182         return bswap_16(native);
183 #else
184         return native;
185 #endif
186 }
187
188 /**
189  * be64_to_cpu - convert a big-endian uint64_t value
190  * @be_val: big-endian value to convert
191  */
192 static inline uint64_t be64_to_cpu(uint64_t be_val)
193 {
194 #if HAVE_LITTLE_ENDIAN
195         return bswap_64(be_val);
196 #else
197         return be_val;
198 #endif
199 }
200
201 /**
202  * be32_to_cpu - convert a big-endian uint32_t value
203  * @be_val: big-endian value to convert
204  */
205 static inline uint32_t be32_to_cpu(uint32_t be_val)
206 {
207 #if HAVE_LITTLE_ENDIAN
208         return bswap_32(be_val);
209 #else
210         return be_val;
211 #endif
212 }
213
214 /**
215  * be16_to_cpu - convert a big-endian uint16_t value
216  * @be_val: big-endian value to convert
217  */
218 static inline uint16_t be16_to_cpu(uint16_t be_val)
219 {
220 #if HAVE_LITTLE_ENDIAN
221         return bswap_16(be_val);
222 #else
223         return be_val;
224 #endif
225 }
226
227 #endif /* CCAN_ENDIAN_H */