nostril

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

endian.h (9551B)


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