Branch data Line data Source code
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 : : */ 71 : : static 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 : : */ 84 : : static 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 : : */ 100 : : static 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 : : #define __LITTLE_ENDIAN 1234 108 : : #define __BIG_ENDIAN 4321 109 : : 110 : : /* Sanity check the defines. We don't handle weird endianness. */ 111 : : #if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN 112 : : #error "Unknown endian" 113 : : #elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN 114 : : #error "Can't compile for both big and little endian." 115 : : #elif HAVE_LITTLE_ENDIAN 116 : : #ifndef __BYTE_ORDER 117 : : #define __BYTE_ORDER __LITTLE_ENDIAN 118 : : #elif __BYTE_ORDER != __LITTLE_ENDIAN 119 : : #error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN" 120 : : #endif 121 : : #elif HAVE_BIG_ENDIAN 122 : : #ifndef __BYTE_ORDER 123 : : #define __BYTE_ORDER __BIG_ENDIAN 124 : : #elif __BYTE_ORDER != __BIG_ENDIAN 125 : : #error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN" 126 : : #endif 127 : : #endif 128 : : 129 : : 130 : : #ifdef __CHECKER__ 131 : : /* sparse needs forcing to remove bitwise attribute from ccan/short_types */ 132 : : #define ENDIAN_CAST __attribute__((force)) 133 : : #define ENDIAN_TYPE __attribute__((bitwise)) 134 : : #else 135 : : #define ENDIAN_CAST 136 : : #define ENDIAN_TYPE 137 : : #endif 138 : : 139 : : typedef uint64_t ENDIAN_TYPE leint64_t; 140 : : typedef uint64_t ENDIAN_TYPE beint64_t; 141 : : typedef uint32_t ENDIAN_TYPE leint32_t; 142 : : typedef uint32_t ENDIAN_TYPE beint32_t; 143 : : typedef uint16_t ENDIAN_TYPE leint16_t; 144 : : typedef uint16_t ENDIAN_TYPE beint16_t; 145 : : 146 : : #if HAVE_LITTLE_ENDIAN 147 : : /** 148 : : * CPU_TO_LE64 - convert a constant uint64_t value to little-endian 149 : : * @native: constant to convert 150 : : */ 151 : : #define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native)) 152 : : 153 : : /** 154 : : * CPU_TO_LE32 - convert a constant uint32_t value to little-endian 155 : : * @native: constant to convert 156 : : */ 157 : : #define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native)) 158 : : 159 : : /** 160 : : * CPU_TO_LE16 - convert a constant uint16_t value to little-endian 161 : : * @native: constant to convert 162 : : */ 163 : : #define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native)) 164 : : 165 : : /** 166 : : * LE64_TO_CPU - convert a little-endian uint64_t constant 167 : : * @le_val: little-endian constant to convert 168 : : */ 169 : : #define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) 170 : : 171 : : /** 172 : : * LE32_TO_CPU - convert a little-endian uint32_t constant 173 : : * @le_val: little-endian constant to convert 174 : : */ 175 : : #define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) 176 : : 177 : : /** 178 : : * LE16_TO_CPU - convert a little-endian uint16_t constant 179 : : * @le_val: little-endian constant to convert 180 : : */ 181 : : #define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) 182 : : 183 : : #else /* ... HAVE_BIG_ENDIAN */ 184 : : #define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native)) 185 : : #define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native)) 186 : : #define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native)) 187 : : #define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) 188 : : #define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) 189 : : #define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) 190 : : #endif /* HAVE_BIG_ENDIAN */ 191 : : 192 : : #if HAVE_BIG_ENDIAN 193 : : /** 194 : : * CPU_TO_BE64 - convert a constant uint64_t value to big-endian 195 : : * @native: constant to convert 196 : : */ 197 : : #define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native)) 198 : : 199 : : /** 200 : : * CPU_TO_BE32 - convert a constant uint32_t value to big-endian 201 : : * @native: constant to convert 202 : : */ 203 : : #define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native)) 204 : : 205 : : /** 206 : : * CPU_TO_BE16 - convert a constant uint16_t value to big-endian 207 : : * @native: constant to convert 208 : : */ 209 : : #define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native)) 210 : : 211 : : /** 212 : : * BE64_TO_CPU - convert a big-endian uint64_t constant 213 : : * @le_val: big-endian constant to convert 214 : : */ 215 : : #define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val)) 216 : : 217 : : /** 218 : : * BE32_TO_CPU - convert a big-endian uint32_t constant 219 : : * @le_val: big-endian constant to convert 220 : : */ 221 : : #define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val)) 222 : : 223 : : /** 224 : : * BE16_TO_CPU - convert a big-endian uint16_t constant 225 : : * @le_val: big-endian constant to convert 226 : : */ 227 : : #define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val)) 228 : : 229 : : #else /* ... HAVE_LITTLE_ENDIAN */ 230 : : #define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native)) 231 : : #define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native)) 232 : : #define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native)) 233 : : #define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val) 234 : : #define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val) 235 : : #define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val) 236 : : #endif /* HAVE_LITTE_ENDIAN */ 237 : : 238 : : 239 : : /** 240 : : * cpu_to_le64 - convert a uint64_t value to little-endian 241 : : * @native: value to convert 242 : : */ 243 : 2 : static inline leint64_t cpu_to_le64(uint64_t native) 244 : : { 245 : 2 : return CPU_TO_LE64(native); 246 : : } 247 : : 248 : : /** 249 : : * cpu_to_le32 - convert a uint32_t value to little-endian 250 : : * @native: value to convert 251 : : */ 252 : 40 : static inline leint32_t cpu_to_le32(uint32_t native) 253 : : { 254 : 40 : return CPU_TO_LE32(native); 255 : : } 256 : : 257 : : /** 258 : : * cpu_to_le16 - convert a uint16_t value to little-endian 259 : : * @native: value to convert 260 : : */ 261 : 1070 : static inline leint16_t cpu_to_le16(uint16_t native) 262 : : { 263 : 1070 : return CPU_TO_LE16(native); 264 : : } 265 : : 266 : : /** 267 : : * le64_to_cpu - convert a little-endian uint64_t value 268 : : * @le_val: little-endian value to convert 269 : : */ 270 : 2 : static inline uint64_t le64_to_cpu(leint64_t le_val) 271 : : { 272 : 2 : return LE64_TO_CPU(le_val); 273 : : } 274 : : 275 : : /** 276 : : * le32_to_cpu - convert a little-endian uint32_t value 277 : : * @le_val: little-endian value to convert 278 : : */ 279 : 371 : static inline uint32_t le32_to_cpu(leint32_t le_val) 280 : : { 281 : 371 : return LE32_TO_CPU(le_val); 282 : : } 283 : : 284 : : /** 285 : : * le16_to_cpu - convert a little-endian uint16_t value 286 : : * @le_val: little-endian value to convert 287 : : */ 288 : 2241 : static inline uint16_t le16_to_cpu(leint16_t le_val) 289 : : { 290 : 2241 : return LE16_TO_CPU(le_val); 291 : : } 292 : : 293 : : /** 294 : : * cpu_to_be64 - convert a uint64_t value to big endian. 295 : : * @native: value to convert 296 : : */ 297 : 15005900 : static inline beint64_t cpu_to_be64(uint64_t native) 298 : : { 299 : 15005900 : return CPU_TO_BE64(native); 300 : : } 301 : : 302 : : /** 303 : : * cpu_to_be32 - convert a uint32_t value to big endian. 304 : : * @native: value to convert 305 : : */ 306 : 28693577 : static inline beint32_t cpu_to_be32(uint32_t native) 307 : : { 308 : 28693577 : return CPU_TO_BE32(native); 309 : : } 310 : : 311 : : /** 312 : : * cpu_to_be16 - convert a uint16_t value to big endian. 313 : : * @native: value to convert 314 : : */ 315 : 13430909 : static inline beint16_t cpu_to_be16(uint16_t native) 316 : : { 317 : 13430909 : return CPU_TO_BE16(native); 318 : : } 319 : : 320 : : /** 321 : : * be64_to_cpu - convert a big-endian uint64_t value 322 : : * @be_val: big-endian value to convert 323 : : */ 324 : 117640649 : static inline uint64_t be64_to_cpu(beint64_t be_val) 325 : : { 326 : 117640649 : return BE64_TO_CPU(be_val); 327 : : } 328 : : 329 : : /** 330 : : * be32_to_cpu - convert a big-endian uint32_t value 331 : : * @be_val: big-endian value to convert 332 : : */ 333 : 37449896 : static inline uint32_t be32_to_cpu(beint32_t be_val) 334 : : { 335 : 37449869 : return BE32_TO_CPU(be_val); 336 : : } 337 : : 338 : : /** 339 : : * be16_to_cpu - convert a big-endian uint16_t value 340 : : * @be_val: big-endian value to convert 341 : : */ 342 : 21469896 : static inline uint16_t be16_to_cpu(beint16_t be_val) 343 : : { 344 : 21469896 : return BE16_TO_CPU(be_val); 345 : : } 346 : : 347 : : /* Whichever they include first, they get these definitions. */ 348 : : #ifdef CCAN_SHORT_TYPES_H 349 : : /** 350 : : * be64/be32/be16 - 64/32/16 bit big-endian representation. 351 : : */ 352 : : typedef beint64_t be64; 353 : : typedef beint32_t be32; 354 : : typedef beint16_t be16; 355 : : 356 : : /** 357 : : * le64/le32/le16 - 64/32/16 bit little-endian representation. 358 : : */ 359 : : typedef leint64_t le64; 360 : : typedef leint32_t le32; 361 : : typedef leint16_t le16; 362 : : #endif 363 : : #endif /* CCAN_ENDIAN_H */