-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathswap.h
More file actions
185 lines (162 loc) · 3.28 KB
/
swap.h
File metadata and controls
185 lines (162 loc) · 3.28 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright 2017 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <cstring>
#include <type_traits>
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
#elif defined(__linux__)
#include <byteswap.h>
#elif defined(__FreeBSD__)
#include <sys/endian.h>
#elif defined(__OpenBSD__)
#include <endian.h>
#endif
#include "types.h"
namespace Common
{
inline u8 swap8(u8 data)
{
return data;
}
inline u32 swap24(const u8* data)
{
return (data[0] << 16) | (data[1] << 8) | data[2];
}
#if defined(ANDROID) || defined(__OpenBSD__)
#undef swap16
#undef swap32
#undef swap64
#endif
#ifdef _WIN32
inline u16 swap16(u16 data)
{
return _byteswap_ushort(data);
}
inline u32 swap32(u32 data)
{
return _byteswap_ulong(data);
}
inline u64 swap64(u64 data)
{
return _byteswap_uint64(data);
}
#elif __linux__
inline u16 swap16(u16 data)
{
return bswap_16(data);
}
inline u32 swap32(u32 data)
{
return bswap_32(data);
}
inline u64 swap64(u64 data)
{
return bswap_64(data);
}
#elif __APPLE__
inline __attribute__((always_inline)) u16 swap16(u16 data)
{
return OSSwapInt16(data);
}
inline __attribute__((always_inline)) u32 swap32(u32 data)
{
return OSSwapInt32(data);
}
inline __attribute__((always_inline)) u64 swap64(u64 data)
{
return OSSwapInt64(data);
}
#elif __FreeBSD__
inline u16 swap16(u16 data)
{
return bswap16(data);
}
inline u32 swap32(u32 data)
{
return bswap32(data);
}
inline u64 swap64(u64 data)
{
return bswap64(data);
}
#else
// Slow generic implementation.
inline u16 swap16(u16 data)
{
return (data >> 8) | (data << 8);
}
inline u32 swap32(u32 data)
{
return (swap16(data) << 16) | swap16(data >> 16);
}
inline u64 swap64(u64 data)
{
return ((u64)swap32(data) << 32) | swap32(data >> 32);
}
#endif
inline u16 swap16(const u8* data)
{
u16 value;
std::memcpy(&value, data, sizeof(u16));
return swap16(value);
}
inline u32 swap32(const u8* data)
{
u32 value;
std::memcpy(&value, data, sizeof(u32));
return swap32(value);
}
inline u64 swap64(const u8* data)
{
u64 value;
std::memcpy(&value, data, sizeof(u64));
return swap64(value);
}
template <int count>
void swap(u8*);
template <>
inline void swap<1>(u8* data)
{
}
template <>
inline void swap<2>(u8* data)
{
const u16 value = swap16(data);
std::memcpy(data, &value, sizeof(u16));
}
template <>
inline void swap<4>(u8* data)
{
const u32 value = swap32(data);
std::memcpy(data, &value, sizeof(u32));
}
template <>
inline void swap<8>(u8* data)
{
const u64 value = swap64(data);
std::memcpy(data, &value, sizeof(u64));
}
template <typename T>
inline T FromBigEndian(T data)
{
static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
return data;
}
template <typename value_type>
struct BigEndianValue
{
static_assert(std::is_arithmetic<value_type>(), "value_type must be an arithmetic type");
BigEndianValue() = default;
explicit BigEndianValue(value_type val) { *this = val; }
operator value_type() const { return FromBigEndian(raw); }
BigEndianValue& operator=(value_type v)
{
raw = FromBigEndian(v);
return *this;
}
private:
value_type raw;
};
} // Namespace Common