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