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