summaryrefslogtreecommitdiff
path: root/lib/util/byteswap.h
blob: 13fbc23363169c494d837961bf9760a184029b96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "../internal.h"

/* Run-time endianness detection is easier and more reliable than trying to
 * figure it out from preprocessor defines. A sane compiler should optimize the
 * run-time code away when inlined, so there should be no overhead from
 * checking endianness. */
static inline bool ypc__bigendian() {
    union { uint16_t l; char c[2]; } u;
    u.l = 1;
    return u.c[0] == 0;
}


static inline uint16_t ypc__swap16(uint16_t v) {
#if defined(_MSC_VER)
    return _byteswap_short(v);
#else
    return (v>>8) | (v<<8);
#endif
}


static inline uint32_t ypc__swap32(uint32_t v) {
#if defined(_MSC_VER)
    return _byteswap_ulong(v);
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
    return __builtin_bswap32(v);
#else
    return ypc__swap16(v >> 16) | ((uint32_t)ypc__swap16(v) << 16);
#endif
}


static inline uint64_t ypc__swap64(uint64_t v) {
#if defined(_MSC_VER)
    return _byteswap_uint64(v);
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
    return __builtin_bswap64(v);
#else
    return ypc__swap32(v >> 32) | ((uint64_t)ypc__swap32(v) << 32);
#endif
}


/* Conversion between host<->network byte order */
static inline uint16_t ypc__hn16(uint16_t v) { return ypc__bigendian() ? v : ypc__swap16(v); }
static inline uint32_t ypc__hn32(uint32_t v) { return ypc__bigendian() ? v : ypc__swap32(v); }
static inline uint64_t ypc__hn64(uint64_t v) { return ypc__bigendian() ? v : ypc__swap64(v); }