1
+ /*
2
+ ** Command & Conquer Generals Zero Hour(tm)
3
+ ** Copyright 2025 TheSuperHackers
4
+ **
5
+ ** This program is free software: you can redistribute it and/or modify
6
+ ** it under the terms of the GNU General Public License as published by
7
+ ** the Free Software Foundation, either version 3 of the License, or
8
+ ** (at your option) any later version.
9
+ **
10
+ ** This program is distributed in the hope that it will be useful,
11
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ ** GNU General Public License for more details.
14
+ **
15
+ ** You should have received a copy of the GNU General Public License
16
+ ** along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ // This file contains macros to help with endian conversions between different endian systems.
20
+ #pragma once
21
+
22
+ // VC6 does not support pragma once
23
+ #ifndef ENDIAN_COMPAT_H
24
+ #define ENDIAN_COMPAT_H
25
+
26
+ #include < Utility/CppMacros.h>
27
+ #include < Utility/stdint_adapter.h>
28
+
29
+
30
+ #if defined(__linux__) || defined(__CYGWIN__)
31
+ #include < endian.h>
32
+
33
+ #elif defined(__APPLE__)
34
+ #include < libkern/OSByteOrder.h>
35
+
36
+ #define htobe16 (x ) OSSwapHostToBigInt16(x)
37
+ #define htole16 (x ) OSSwapHostToLittleInt16(x)
38
+ #define be16toh (x ) OSSwapBigToHostInt16(x)
39
+ #define le16toh (x ) OSSwapLittleToHostInt16(x)
40
+
41
+ #define htobe32 (x ) OSSwapHostToBigInt32(x)
42
+ #define htole32 (x ) OSSwapHostToLittleInt32(x)
43
+ #define be32toh (x ) OSSwapBigToHostInt32(x)
44
+ #define le32toh (x ) OSSwapLittleToHostInt32(x)
45
+
46
+ #define htobe64 (x ) OSSwapHostToBigInt64(x)
47
+ #define htole64 (x ) OSSwapHostToLittleInt64(x)
48
+ #define be64toh (x ) OSSwapBigToHostInt64(x)
49
+ #define le64toh (x ) OSSwapLittleToHostInt64(x)
50
+
51
+ #elif defined(__OpenBSD__)
52
+ #include < sys/endian.h>
53
+
54
+ #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
55
+ #include < sys/endian.h>
56
+
57
+ #define be16toh (x ) betoh16(x)
58
+ #define le16toh (x ) letoh16(x)
59
+
60
+ #define be32toh (x ) betoh32(x)
61
+ #define le32toh (x ) letoh32(x)
62
+
63
+ #define be64toh (x ) betoh64(x)
64
+ #define le64toh (x ) letoh64(x)
65
+
66
+ #elif defined(_WIN32) || defined(_WIN64)
67
+ #if !(defined(_MSC_VER) && _MSC_VER < 1300)
68
+ #include < intrin.h>
69
+ #define htobe16 (x ) _byteswap_ushort(x)
70
+ #define htole16 (x ) (x)
71
+ #define be16toh (x ) _byteswap_ushort(x)
72
+ #define le16toh (x ) (x)
73
+
74
+ #define htobe32 (x ) _byteswap_ulong(x)
75
+ #define htole32 (x ) (x)
76
+ #define be32toh (x ) _byteswap_ulong(x)
77
+ #define le32toh (x ) (x)
78
+
79
+ #define htobe64 (x ) _byteswap_uint64(x)
80
+ #define htole64 (x ) (x)
81
+ #define be64toh (x ) _byteswap_uint64(x)
82
+ #define le64toh (x ) (x)
83
+ #else
84
+ #define bswap16 (x ) ( (uint16_t )( ((x & 0xFF00 ) >> 8 ) | ((x & 0x00FF ) << 8 ) ) )
85
+ #define bswap32 (x ) ( ((x & 0xFF000000 ) >> 24 ) | \
86
+ ((x & 0x00FF0000 ) >> 8 ) | \
87
+ ((x & 0x0000FF00 ) << 8 ) | \
88
+ ((x & 0x000000FF ) << 24 ) )
89
+ #define bswap64 (x ) ( (((uint64_t )(x) & 0xFF00000000000000 ) >> 56 ) | \
90
+ (((uint64_t )(x) & 0x00FF000000000000 ) >> 40 ) | \
91
+ (((uint64_t )(x) & 0x0000FF0000000000 ) >> 24 ) | \
92
+ (((uint64_t )(x) & 0x000000FF00000000 ) >> 8 ) | \
93
+ (((uint64_t )(x) & 0x00000000FF000000 ) << 8 ) | \
94
+ (((uint64_t )(x) & 0x0000000000FF0000 ) << 24 ) | \
95
+ (((uint64_t )(x) & 0x000000000000FF00 ) << 40 ) | \
96
+ (((uint64_t )(x) & 0x00000000000000FF ) << 56 ) )
97
+
98
+ #define htobe16 (x ) bswap16(x)
99
+ #define htole16 (x ) (x)
100
+ #define be16toh (x ) bswap16(x)
101
+ #define le16toh (x ) (x)
102
+
103
+ #define htobe32 (x ) bswap32(x)
104
+ #define htole32 (x ) (x)
105
+ #define be32toh (x ) bswap32(x)
106
+ #define le32toh (x ) (x)
107
+
108
+ #define htobe64 (x ) bswap64(x)
109
+ #define htole64 (x ) (x)
110
+ #define be64toh (x ) bswap64(x)
111
+ #define le64toh (x ) (x)
112
+
113
+ #endif // _MSC_VER
114
+
115
+ #else
116
+ #error platform not supported
117
+ #endif
118
+
119
+
120
+ // Endian helper function data types
121
+ #if defined(__linux__) || defined(__CYGWIN__)
122
+ typedef uint16_t SwapType16;
123
+ typedef uint32_t SwapType32;
124
+ typedef uint64_t SwapType64;
125
+
126
+ #elif defined(__APPLE__)
127
+ typedef UInt16 SwapType16;
128
+ typedef UInt32 SwapType32;
129
+ typedef UInt64 SwapType64;
130
+
131
+ #elif defined(__OpenBSD__)
132
+ typedef uint16_t SwapType16;
133
+ typedef uint32_t SwapType32;
134
+ typedef uint64_t SwapType64;
135
+
136
+ #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
137
+ typedef uint16_t SwapType16;
138
+ typedef uint32_t SwapType32;
139
+ typedef uint64_t SwapType64;
140
+
141
+ #elif defined(_WIN32) || defined(_WIN64)
142
+ typedef uint16_t SwapType16;
143
+ typedef uint32_t SwapType32;
144
+ typedef uint64_t SwapType64;
145
+
146
+ #else
147
+ #error platform not supported
148
+ #endif
149
+
150
+
151
+ // Endian helper functions
152
+ static_assert (sizeof (SwapType16) == 2, "expected size does not match");
153
+ static_assert (sizeof (SwapType32) == 4, "expected size does not match");
154
+ static_assert (sizeof (SwapType64) == 8, "expected size does not match");
155
+
156
+ // VC6 compatible overloaded endian functions
157
+ #if defined(_MSC_VER) && _MSC_VER < 1300
158
+
159
+ // Big endian to host
160
+ inline int16_t betoh (int16_t value) { return be16toh (value); }
161
+ inline uint16_t betoh (uint16_t value) { return be16toh (value); }
162
+ inline int32_t betoh (int32_t value) { return be32toh (value); }
163
+ inline uint32_t betoh (uint32_t value) { return be32toh (value); }
164
+ inline int64_t betoh (int64_t value) { return be64toh (value); }
165
+ inline uint64_t betoh (uint64_t value) { return be64toh (value); }
166
+ // Host to big endian
167
+ inline int16_t htobe (int16_t value) { return htobe16 (value); }
168
+ inline uint16_t htobe (uint16_t value) { return htobe16 (value); }
169
+ inline int32_t htobe (int32_t value) { return htobe32 (value); }
170
+ inline uint32_t htobe (uint32_t value) { return htobe32 (value); }
171
+ inline int64_t htobe (int64_t value) { return htobe64 (value); }
172
+ inline uint64_t htobe (uint64_t value) { return htobe64 (value); }
173
+ // Little endian to host
174
+ inline int16_t letoh (int16_t value) { return le16toh (value); }
175
+ inline uint16_t letoh (uint16_t value) { return le16toh (value); }
176
+ inline int32_t letoh (int32_t value) { return le32toh (value); }
177
+ inline uint32_t letoh (uint32_t value) { return le32toh (value); }
178
+ inline int64_t letoh (int64_t value) { return le64toh (value); }
179
+ inline uint64_t letoh (uint64_t value) { return le64toh (value); }
180
+ // Host to little endian
181
+ inline int16_t htole (int16_t value) { return htole16 (value); }
182
+ inline uint16_t htole (uint16_t value) { return htole16 (value); }
183
+ inline int32_t htole (int32_t value) { return htole32 (value); }
184
+ inline uint32_t htole (uint32_t value) { return htole32 (value); }
185
+ inline int64_t htole (int64_t value) { return htole64 (value); }
186
+ inline uint64_t htole (uint64_t value) { return htole64 (value); }
187
+
188
+ #else
189
+
190
+ namespace Endian
191
+ {
192
+ template <typename Type, size_t Size = sizeof (Type)> struct htobeHelper ;
193
+ template <typename Type, size_t Size = sizeof (Type)> struct htoleHelper ;
194
+ template <typename Type, size_t Size = sizeof (Type)> struct betohHelper ;
195
+ template <typename Type, size_t Size = sizeof (Type)> struct letohHelper ;
196
+
197
+ // 2 byte integer, enum
198
+ template <typename Type> struct htobeHelper <Type, 2 > { static inline Type swap (Type value) { return static_cast <Type>(htobe16 (static_cast <SwapType16>(value))); } };
199
+ template <typename Type> struct htoleHelper <Type, 2 > { static inline Type swap (Type value) { return static_cast <Type>(htole16 (static_cast <SwapType16>(value))); } };
200
+ template <typename Type> struct betohHelper <Type, 2 > { static inline Type swap (Type value) { return static_cast <Type>(be16toh (static_cast <SwapType16>(value))); } };
201
+ template <typename Type> struct letohHelper <Type, 2 > { static inline Type swap (Type value) { return static_cast <Type>(le16toh (static_cast <SwapType16>(value))); } };
202
+ // 4 byte integer, enum
203
+ template <typename Type> struct htobeHelper <Type, 4 > { static inline Type swap (Type value) { return static_cast <Type>(htobe32 (static_cast <SwapType32>(value))); } };
204
+ template <typename Type> struct htoleHelper <Type, 4 > { static inline Type swap (Type value) { return static_cast <Type>(htole32 (static_cast <SwapType32>(value))); } };
205
+ template <typename Type> struct betohHelper <Type, 4 > { static inline Type swap (Type value) { return static_cast <Type>(be32toh (static_cast <SwapType32>(value))); } };
206
+ template <typename Type> struct letohHelper <Type, 4 > { static inline Type swap (Type value) { return static_cast <Type>(le16toh (static_cast <SwapType32>(value))); } };
207
+ // 8 byte integer, enum
208
+ template <typename Type> struct htobeHelper <Type, 8 > { static inline Type swap (Type value) { return static_cast <Type>(htobe64 (static_cast <SwapType64>(value))); } };
209
+ template <typename Type> struct htoleHelper <Type, 8 > { static inline Type swap (Type value) { return static_cast <Type>(htole64 (static_cast <SwapType64>(value))); } };
210
+ template <typename Type> struct betohHelper <Type, 8 > { static inline Type swap (Type value) { return static_cast <Type>(be64toh (static_cast <SwapType64>(value))); } };
211
+ template <typename Type> struct letohHelper <Type, 8 > { static inline Type swap (Type value) { return static_cast <Type>(le16toh (static_cast <SwapType64>(value))); } };
212
+ // float
213
+ template <> struct htobeHelper <float , 4 > { static inline float swap (float value) { SwapType32 v = htobe32 (*reinterpret_cast <SwapType32*>(&value)); return *reinterpret_cast <float *>(&v); } };
214
+ template <> struct htoleHelper <float , 4 > { static inline float swap (float value) { SwapType32 v = htole32 (*reinterpret_cast <SwapType32*>(&value)); return *reinterpret_cast <float *>(&v); } };
215
+ template <> struct betohHelper <float , 4 > { static inline float swap (float value) { SwapType32 v = be32toh (*reinterpret_cast <SwapType32*>(&value)); return *reinterpret_cast <float *>(&v); } };
216
+ template <> struct letohHelper <float , 4 > { static inline float swap (float value) { SwapType32 v = le16toh (*reinterpret_cast <SwapType32*>(&value)); return *reinterpret_cast <float *>(&v); } };
217
+ // double
218
+ template <> struct htobeHelper <double , 8 > { static inline double swap (double value) { SwapType64 v = htobe64 (*reinterpret_cast <SwapType64*>(&value)); return *reinterpret_cast <double *>(&v); } };
219
+ template <> struct htoleHelper <double , 8 > { static inline double swap (double value) { SwapType64 v = htole64 (*reinterpret_cast <SwapType64*>(&value)); return *reinterpret_cast <double *>(&v); } };
220
+ template <> struct betohHelper <double , 8 > { static inline double swap (double value) { SwapType64 v = be64toh (*reinterpret_cast <SwapType64*>(&value)); return *reinterpret_cast <double *>(&v); } };
221
+ template <> struct letohHelper <double , 8 > { static inline double swap (double value) { SwapType64 v = le16toh (*reinterpret_cast <SwapType64*>(&value)); return *reinterpret_cast <double *>(&v); } };
222
+ } // namespace Endian
223
+
224
+ // c++ template functions, takes any 2, 4, 8 bytes, including float, double, enum
225
+
226
+ // Host to big endian
227
+ template <typename Type> inline Type htobe (Type value) { return Endian::htobeHelper<Type>::swap (value); }
228
+ // Host to little endian
229
+ template <typename Type> inline Type htole (Type value) { return Endian::htoleHelper<Type>::swap (value); }
230
+ // Big endian to host
231
+ template <typename Type> inline Type betoh (Type value) { return Endian::betohHelper<Type>::swap (value); }
232
+ // Little endian to host
233
+ template <typename Type> inline Type letoh (Type value) { return Endian::letohHelper<Type>::swap (value); }
234
+
235
+ // Host to big endian
236
+ template <typename Type> inline void htobe_ref (Type &value) { value = Endian::htobeHelper<Type>::swap (value); }
237
+ // Host to little endian
238
+ template <typename Type> inline void htole_ref (Type &value) { value = Endian::htoleHelper<Type>::swap (value); }
239
+ // Big endian to host
240
+ template <typename Type> inline void betoh_ref (Type &value) { value = Endian::betohHelper<Type>::swap (value); }
241
+ // Little endian to host
242
+ template <typename Type> inline void letoh_ref (Type &value) { value = Endian::letohHelper<Type>::swap (value); }
243
+
244
+ #endif // _MSC_VER < 1300
245
+
246
+ #endif // ENDIAN_COMPAT_H
0 commit comments