aboutsummaryrefslogtreecommitdiffstats
path: root/util/system/byteorder.h
blob: 94b9fea515268a5b21ed38636070e7116fabe72d (plain) (blame)
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#pragma once

#include "defaults.h"

//#define USE_GENERIC_ENDIAN_CVT

#if defined(_linux_) && !defined(USE_GENERIC_ENDIAN_CVT)
    #include <byteswap.h>
#elif defined(_darwin_)
    #if defined(_arm_) || defined(__IOS__)
        #include <architecture/byte_order.h>
    #else
        #include <machine/byte_order.h>
    #endif
#else
    #include <util/generic/utility.h>
#endif

#if defined(_linux_) && !defined(USE_GENERIC_ENDIAN_CVT)
    #define SwapBytes16 bswap_16
    #define SwapBytes32 bswap_32
    #define SwapBytes64 bswap_64
#elif defined(_darwin_)
    #ifdef _arm_
        #define SwapBytes16 _OSSwapInt16
        #define SwapBytes32 _OSSwapInt32
        #define SwapBytes64 _OSSwapInt64
    #else
        #define SwapBytes16 OSSwapInt16
        #define SwapBytes32 OSSwapInt32
        #define SwapBytes64 OSSwapInt64
    #endif
#endif

#ifndef SwapBytes16
inline ui16 SwapBytes16(ui16 val) noexcept {
    #define byte_n(__val, __n) ((((unsigned char*)(&__val))[__n]))
    DoSwap(byte_n(val, 0), byte_n(val, 1));
    return val;
    #undef byte_n
}
#endif

#ifndef SwapBytes32
inline ui32 SwapBytes32(ui32 val) noexcept {
    #define byte_n(__val, __n) ((((unsigned char*)(&__val))[__n]))
    DoSwap(byte_n(val, 0), byte_n(val, 3));
    DoSwap(byte_n(val, 1), byte_n(val, 2));
    return val;
    #undef byte_n
}
#endif

#ifndef SwapBytes64
inline ui64 SwapBytes64(ui64 val) noexcept {
    union {
        ui64 val;
        ui32 p[2];
    } tmp, ret;

    tmp.val = val;
    ret.p[0] = SwapBytes32(tmp.p[1]);
    ret.p[1] = SwapBytes32(tmp.p[0]);

    return ret.val;
}
#endif

//for convenience
static inline ui8 SwapBytes8(ui8 v) noexcept {
    return v;
}

namespace NSwapBytes {
    template <unsigned N>
    struct TSwapBytesHelper {
    };

#define DEF_SB(X)                             \
    template <>                               \
    struct TSwapBytesHelper<X> {              \
        template <class T>                    \
        static inline T Swap(T t) noexcept {  \
            return (T)SwapBytes##X((ui##X)t); \
        }                                     \
    };

    DEF_SB(8)
    DEF_SB(16)
    DEF_SB(32)
    DEF_SB(64)

#undef DEF_SB
}

template <class T>
inline T SwapBytes(T val) noexcept {
    return NSwapBytes::TSwapBytesHelper<sizeof(T) * 8>::Swap(val);
}

template <class T>
inline T LittleToBig(T val) noexcept {
    return SwapBytes(val);
}

template <class T>
inline T BigToLittle(T val) noexcept {
    return LittleToBig(val);
}

template <class T>
inline T HostToInet(T val) noexcept {
#if defined(_big_endian_)
    return val;
#elif defined(_little_endian_)
    return LittleToBig(val);
#else
    #error todo
#endif
}

template <class T>
inline T InetToHost(T val) noexcept {
    return HostToInet(val);
}

template <class T>
inline T HostToLittle(T val) noexcept {
#if defined(_big_endian_)
    return BigToLittle(val);
#elif defined(_little_endian_)
    return val;
#else
    #error todo
#endif
}

template <class T>
inline T LittleToHost(T val) noexcept {
    return HostToLittle(val);
}