nostril

A C cli tool for creating nostr events
git clone git://jb55.com/nostril
Log | Files | Refs | Submodules | README | LICENSE

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 */