endian.h (9531B)
1 /* CC0 (Public domain) */ 2 #ifndef CCAN_ENDIAN_H 3 #define CCAN_ENDIAN_H 4 #include <stdint.h> 5 6 #include "config.h" 7 8 /** 9 * BSWAP_16 - reverse bytes in a constant uint16_t value. 10 * @val: constant value whose bytes to swap. 11 * 12 * Designed to be usable in constant-requiring initializers. 13 * 14 * Example: 15 * struct mystruct { 16 * char buf[BSWAP_16(0x1234)]; 17 * }; 18 */ 19 #define BSWAP_16(val) \ 20 ((((uint16_t)(val) & 0x00ff) << 8) \ 21 | (((uint16_t)(val) & 0xff00) >> 8)) 22 23 /** 24 * BSWAP_32 - reverse bytes in a constant uint32_t value. 25 * @val: constant value whose bytes to swap. 26 * 27 * Designed to be usable in constant-requiring initializers. 28 * 29 * Example: 30 * struct mystruct { 31 * char buf[BSWAP_32(0xff000000)]; 32 * }; 33 */ 34 #define BSWAP_32(val) \ 35 ((((uint32_t)(val) & 0x000000ff) << 24) \ 36 | (((uint32_t)(val) & 0x0000ff00) << 8) \ 37 | (((uint32_t)(val) & 0x00ff0000) >> 8) \ 38 | (((uint32_t)(val) & 0xff000000) >> 24)) 39 40 /** 41 * BSWAP_64 - reverse bytes in a constant uint64_t value. 42 * @val: constantvalue whose bytes to swap. 43 * 44 * Designed to be usable in constant-requiring initializers. 45 * 46 * Example: 47 * struct mystruct { 48 * char buf[BSWAP_64(0xff00000000000000ULL)]; 49 * }; 50 */ 51 #define BSWAP_64(val) \ 52 ((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \ 53 | (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \ 54 | (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \ 55 | (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \ 56 | (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \ 57 | (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \ 58 | (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \ 59 | (((uint64_t)(val) & 0xff00000000000000ULL) >> 56)) 60 61 #if HAVE_BYTESWAP_H 62 #include <byteswap.h> 63 #else 64 /** 65 * bswap_16 - reverse bytes in a uint16_t value. 66 * @val: value whose bytes to swap. 67 * 68 * Example: 69 * // Output contains "1024 is 4 as two bytes reversed" 70 * printf("1024 is %u as two bytes reversed\n", bswap_16(1024)); 71 */ 72 static inline uint16_t bswap_16(uint16_t val) 73 { 74 return BSWAP_16(val); 75 } 76 77 /** 78 * bswap_32 - reverse bytes in a uint32_t value. 79 * @val: value whose bytes to swap. 80 * 81 * Example: 82 * // Output contains "1024 is 262144 as four bytes reversed" 83 * printf("1024 is %u as four bytes reversed\n", bswap_32(1024)); 84 */ 85 static inline uint32_t bswap_32(uint32_t val) 86 { 87 return BSWAP_32(val); 88 } 89 #endif /* !HAVE_BYTESWAP_H */ 90 91 #if !HAVE_BSWAP_64 92 /** 93 * bswap_64 - reverse bytes in a uint64_t value. 94 * @val: value whose bytes to swap. 95 * 96 * Example: 97 * // Output contains "1024 is 1125899906842624 as eight bytes reversed" 98 * printf("1024 is %llu as eight bytes reversed\n", 99 * (unsigned long long)bswap_64(1024)); 100 */ 101 static inline uint64_t bswap_64(uint64_t val) 102 { 103 return BSWAP_64(val); 104 } 105 #endif 106 107 /* Needed for Glibc like endiness check */ 108 #define __LITTLE_ENDIAN 1234 109 #define __BIG_ENDIAN 4321 110 111 /* Sanity check the defines. We don't handle weird endianness. */ 112 #if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN 113 #error "Unknown endian" 114 #elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN 115 #error "Can't compile for both big and little endian." 116 #elif HAVE_LITTLE_ENDIAN 117 #ifndef __BYTE_ORDER 118 #define __BYTE_ORDER __LITTLE_ENDIAN 119 #elif __BYTE_ORDER != __LITTLE_ENDIAN 120 #error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN" 121 #endif 122 #elif HAVE_BIG_ENDIAN 123 #ifndef __BYTE_ORDER 124 #define __BYTE_ORDER __BIG_ENDIAN 125 #elif __BYTE_ORDER != __BIG_ENDIAN 126 #error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN" 127 #endif 128 #endif 129 130 131 #ifdef __CHECKER__ 132 /* sparse needs forcing to remove bitwise attribute from ccan/short_types */ 133 #define ENDIAN_CAST __attribute__((force)) 134 #define ENDIAN_TYPE __attribute__((bitwise)) 135 #else 136 #define ENDIAN_CAST 137 #define ENDIAN_TYPE 138 #endif 139 140 typedef uint64_t ENDIAN_TYPE leint64_t; 141 typedef uint64_t ENDIAN_TYPE beint64_t; 142 typedef uint32_t ENDIAN_TYPE leint32_t; 143 typedef uint32_t ENDIAN_TYPE beint32_t; 144 typedef uint16_t ENDIAN_TYPE leint16_t; 145 typedef uint16_t ENDIAN_TYPE beint16_t; 146 147 #if HAVE_LITTLE_ENDIAN 148 /** 149 * CPU_TO_LE64 - convert a constant uint64_t value to little-endian 150 * @native: constant to convert 151 */ 152 #define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native)) 153 154 /** 155 * CPU_TO_LE32 - convert a constant uint32_t value to little-endian 156 * @native: constant to convert 157 */ 158 #define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native)) 159 160 /** 161 * CPU_TO_LE16 - convert a constant uint16_t value to little-endian 162 * @native: constant to convert 163 */ 164 #define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native)) 165 166 /** 167 * LE64_TO_CPU - convert a little-endian uint64_t constant 168 * @le_val: little-endian constant to convert 169 */ 170 #define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) 171 172 /** 173 * LE32_TO_CPU - convert a little-endian uint32_t constant 174 * @le_val: little-endian constant to convert 175 */ 176 #define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) 177 178 /** 179 * LE16_TO_CPU - convert a little-endian uint16_t constant 180 * @le_val: little-endian constant to convert 181 */ 182 #define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) 183 184 #else /* ... HAVE_BIG_ENDIAN */ 185 #define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native)) 186 #define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native)) 187 #define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native)) 188 #define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) 189 #define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) 190 #define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) 191 #endif /* HAVE_BIG_ENDIAN */ 192 193 #if HAVE_BIG_ENDIAN 194 /** 195 * CPU_TO_BE64 - convert a constant uint64_t value to big-endian 196 * @native: constant to convert 197 */ 198 #define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native)) 199 200 /** 201 * CPU_TO_BE32 - convert a constant uint32_t value to big-endian 202 * @native: constant to convert 203 */ 204 #define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native)) 205 206 /** 207 * CPU_TO_BE16 - convert a constant uint16_t value to big-endian 208 * @native: constant to convert 209 */ 210 #define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native)) 211 212 /** 213 * BE64_TO_CPU - convert a big-endian uint64_t constant 214 * @le_val: big-endian constant to convert 215 */ 216 #define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) 217 218 /** 219 * BE32_TO_CPU - convert a big-endian uint32_t constant 220 * @le_val: big-endian constant to convert 221 */ 222 #define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) 223 224 /** 225 * BE16_TO_CPU - convert a big-endian uint16_t constant 226 * @le_val: big-endian constant to convert 227 */ 228 #define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) 229 230 #else /* ... HAVE_LITTLE_ENDIAN */ 231 #define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native)) 232 #define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native)) 233 #define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native)) 234 #define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) 235 #define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) 236 #define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) 237 #endif /* HAVE_LITTE_ENDIAN */ 238 239 240 /** 241 * cpu_to_le64 - convert a uint64_t value to little-endian 242 * @native: value to convert 243 */ 244 static inline leint64_t cpu_to_le64(uint64_t native) 245 { 246 return CPU_TO_LE64(native); 247 } 248 249 /** 250 * cpu_to_le32 - convert a uint32_t value to little-endian 251 * @native: value to convert 252 */ 253 static inline leint32_t cpu_to_le32(uint32_t native) 254 { 255 return CPU_TO_LE32(native); 256 } 257 258 /** 259 * cpu_to_le16 - convert a uint16_t value to little-endian 260 * @native: value to convert 261 */ 262 static inline leint16_t cpu_to_le16(uint16_t native) 263 { 264 return CPU_TO_LE16(native); 265 } 266 267 /** 268 * le64_to_cpu - convert a little-endian uint64_t value 269 * @le_val: little-endian value to convert 270 */ 271 static inline uint64_t le64_to_cpu(leint64_t le_val) 272 { 273 return LE64_TO_CPU(le_val); 274 } 275 276 /** 277 * le32_to_cpu - convert a little-endian uint32_t value 278 * @le_val: little-endian value to convert 279 */ 280 static inline uint32_t le32_to_cpu(leint32_t le_val) 281 { 282 return LE32_TO_CPU(le_val); 283 } 284 285 /** 286 * le16_to_cpu - convert a little-endian uint16_t value 287 * @le_val: little-endian value to convert 288 */ 289 static inline uint16_t le16_to_cpu(leint16_t le_val) 290 { 291 return LE16_TO_CPU(le_val); 292 } 293 294 /** 295 * cpu_to_be64 - convert a uint64_t value to big endian. 296 * @native: value to convert 297 */ 298 static inline beint64_t cpu_to_be64(uint64_t native) 299 { 300 return CPU_TO_BE64(native); 301 } 302 303 /** 304 * cpu_to_be32 - convert a uint32_t value to big endian. 305 * @native: value to convert 306 */ 307 static inline beint32_t cpu_to_be32(uint32_t native) 308 { 309 return CPU_TO_BE32(native); 310 } 311 312 /** 313 * cpu_to_be16 - convert a uint16_t value to big endian. 314 * @native: value to convert 315 */ 316 static inline beint16_t cpu_to_be16(uint16_t native) 317 { 318 return CPU_TO_BE16(native); 319 } 320 321 /** 322 * be64_to_cpu - convert a big-endian uint64_t value 323 * @be_val: big-endian value to convert 324 */ 325 static inline uint64_t be64_to_cpu(beint64_t be_val) 326 { 327 return BE64_TO_CPU(be_val); 328 } 329 330 /** 331 * be32_to_cpu - convert a big-endian uint32_t value 332 * @be_val: big-endian value to convert 333 */ 334 static inline uint32_t be32_to_cpu(beint32_t be_val) 335 { 336 return BE32_TO_CPU(be_val); 337 } 338 339 /** 340 * be16_to_cpu - convert a big-endian uint16_t value 341 * @be_val: big-endian value to convert 342 */ 343 static inline uint16_t be16_to_cpu(beint16_t be_val) 344 { 345 return BE16_TO_CPU(be_val); 346 } 347 348 /** 349 * be64/be32/be16 - 64/32/16 bit big-endian representation. 350 */ 351 typedef beint64_t be64; 352 typedef beint32_t be32; 353 typedef beint16_t be16; 354 355 /** 356 * le64/le32/le16 - 64/32/16 bit little-endian representation. 357 */ 358 typedef leint64_t le64; 359 typedef leint32_t le32; 360 typedef leint16_t le16; 361 362 363 #endif /* CCAN_ENDIAN_H */