damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

pendian.h (5284B)


      1 #ifndef PENDIAN_H
      2 #define PENDIAN_H
      3 
      4 #ifdef __cplusplus
      5 extern "C" {
      6 #endif
      7 
      8 /*
      9  * Defines platform optimized (as per linux <endian.h>
     10  *
     11  *     le16toh, le32to, le64toh, be16toh, be32toh, be64toh
     12  *     htole16, htole32, htole64, htobe16, htobe32, htobe64
     13  *
     14  * Falls back to auto-detect endian conversion which is also fast
     15  * if fast byteswap operation was detected.
     16  *
     17  * Also defines platform optimized:
     18  *
     19  *     bswap16, bswap32, bswap64,
     20  *
     21  * with fall-back to shift-or implementation.
     22  *
     23  * For convenience also defines:
     24  *
     25  *     le8to, be8toh, htole8, htobe8
     26  *     bswap8
     27  *
     28  * The convience functions makes is simpler to define conversion macros
     29  * based on type size.
     30  *
     31  * NOTE: this implementation expects arguments with no side-effects and
     32  * with appropriately sized unsigned arguments. These are expected to be
     33  * used with typesafe wrappers.
     34  */
     35 
     36 #ifndef UINT8_MAX
     37 #include "pstdint.h"
     38 #endif
     39 
     40 #if defined(__linux__)
     41 #include <endian.h>
     42 #elif defined(__OpenBSD__) || defined(__FreeBSD__)
     43 #include <sys/endian.h>
     44 #endif
     45 
     46 #include "pendian_detect.h"
     47 
     48 #if defined(_MSC_VER)
     49 #if _MSC_VER >= 1300
     50 #include <stdlib.h>
     51 #define bswap16 _byteswap_ushort
     52 #define bswap32 _byteswap_ulong
     53 #define bswap64 _byteswap_uint64
     54 #endif
     55 #elif defined(__clang__)
     56 #if __has_builtin(__builtin_bswap16)
     57 #ifndef bswap16
     58 #define bswap16 __builtin_bswap16
     59 #endif
     60 #endif
     61 #if __has_builtin(__builtin_bswap32)
     62 #ifndef bswap32
     63 #define bswap32 __builtin_bswap32
     64 #endif
     65 #endif
     66 #if __has_builtin(__builtin_bswap64)
     67 #ifndef bswap64
     68 #define bswap64 __builtin_bswap64
     69 #endif
     70 #endif
     71 #elif defined(__OpenBSD__) || defined(__FreeBSD__)
     72 #ifndef bswap16
     73 #define bswap16 swap16
     74 #endif
     75 #ifndef bswap32
     76 #define bswap32 swap32
     77 #endif
     78 #ifndef bswap64
     79 #define bswap64 swap64
     80 #endif
     81 #elif defined(__GNUC__)  /* Supported since at least GCC 4.4 */
     82 #ifndef bswap32
     83 #define bswap32 __builtin_bswap32
     84 #endif
     85 #ifndef bswap64
     86 #define bswap64 __builtin_bswap64
     87 #endif
     88 #endif
     89 
     90 #ifndef bswap16
     91 #define bswap16(v)                                                          \
     92       (((uint16_t)(v) << 8) | ((uint16_t)(v) >> 8))
     93 #endif
     94 
     95 #ifndef bswap32
     96 #define bswap32(v)                                                          \
     97       ((((uint32_t)(v) << 24))                                              \
     98           | (((uint32_t)(v) << 8) & UINT32_C(0x00FF0000))                   \
     99           | (((uint32_t)(v) >> 8) & UINT32_C(0x0000FF00))                   \
    100           | (((uint32_t)(v) >> 24)))
    101 #endif
    102 
    103 #ifndef bswap64
    104 #define bswap64(v)                                                          \
    105       ((((uint64_t)(v) << 56))                                              \
    106           | (((uint64_t)(v) << 40) & UINT64_C(0x00FF000000000000))          \
    107           | (((uint64_t)(v) << 24) & UINT64_C(0x0000FF0000000000))          \
    108           | (((uint64_t)(v) << 8) & UINT64_C(0x000000FF00000000))           \
    109           | (((uint64_t)(v) >> 8) & UINT64_C(0x00000000FF000000))           \
    110           | (((uint64_t)(v) >> 24) & UINT64_C(0x0000000000FF0000))          \
    111           | (((uint64_t)(v) >> 40) & UINT64_C(0x000000000000FF00))          \
    112           | (((uint64_t)(v) >> 56)))
    113 #endif
    114 
    115 #ifndef bswap8
    116 #define bswap8(v) ((uint8_t)(v))
    117 #endif
    118 
    119 #if !defined(le16toh) && defined(letoh16)
    120 #define le16toh letoh16
    121 #define le32toh letoh32
    122 #define le64toh letoh64
    123 #endif
    124 
    125 #if !defined(be16toh) && defined(betoh16)
    126 #define be16toh betoh16
    127 #define be32toh betoh32
    128 #define be64toh betoh64
    129 #endif
    130 
    131 /* Assume it goes for all. */
    132 #if !defined(le16toh)
    133 
    134 #if defined(__LITTLE_ENDIAN__)
    135 
    136 #define le16toh(v) (v)
    137 #define le32toh(v) (v)
    138 #define le64toh(v) (v)
    139 
    140 #define htole16(v) (v)
    141 #define htole32(v) (v)
    142 #define htole64(v) (v)
    143 
    144 #define be16toh(v) bswap16(v)
    145 #define be32toh(v) bswap32(v)
    146 #define be64toh(v) bswap64(v)
    147 
    148 #define htobe16(v) bswap16(v)
    149 #define htobe32(v) bswap32(v)
    150 #define htobe64(v) bswap64(v)
    151 
    152 #elif defined(__BIG_ENDIAN__)
    153 
    154 #define le16toh(v) bswap16(v)
    155 #define le32toh(v) bswap32(v)
    156 #define le64toh(v) bswap64(v)
    157 
    158 #define htole16(v) bswap16(v)
    159 #define htole32(v) bswap32(v)
    160 #define htole64(v) bswap64(v)
    161 
    162 #define be16toh(v) (v)
    163 #define be32toh(v) (v)
    164 #define be64toh(v) (v)
    165 
    166 #define htobe16(v) (v)
    167 #define htobe32(v) (v)
    168 #define htobe64(v) (v)
    169 
    170 #else
    171 
    172 static const int __pendian_test = 1;
    173 
    174 #define le16toh(v) (*(char *)&__pendian_test ? (v) : bswap16(v))
    175 #define le32toh(v) (*(char *)&__pendian_test ? (v) : bswap32(v))
    176 #define le64toh(v) (*(char *)&__pendian_test ? (v) : bswap64(v))
    177 
    178 #define htole16(v) (*(char *)&__pendian_test ? (v) : bswap16(v))
    179 #define htole32(v) (*(char *)&__pendian_test ? (v) : bswap32(v))
    180 #define htole64(v) (*(char *)&__pendian_test ? (v) : bswap64(v))
    181 
    182 #define be16toh(v) (*(char *)&__pendian_test ? bswap16(v) : (v))
    183 #define be32toh(v) (*(char *)&__pendian_test ? bswap32(v) : (v))
    184 #define be64toh(v) (*(char *)&__pendian_test ? bswap64(v) : (v))
    185 
    186 #define htobe16(v) (*(char *)&__pendian_test ? bswap16(v) : (v))
    187 #define htobe32(v) (*(char *)&__pendian_test ? bswap32(v) : (v))
    188 #define htobe64(v) (*(char *)&__pendian_test ? bswap64(v) : (v))
    189 
    190 #endif
    191 
    192 #endif /* le16toh */
    193 
    194 /* Helpers not part of Linux <endian.h> */
    195 #if !defined(le8toh)
    196 #define le8toh(n) (n)
    197 #define htole8(n) (n)
    198 #define be8toh(n) (n)
    199 #define htobe8(n) (n)
    200 #endif
    201 
    202 #ifdef __cplusplus
    203 }
    204 #endif
    205 
    206 #endif /* PENDIAN_H */