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
+
28
+
29
+ #if defined(__linux__) || defined(__CYGWIN__)
30
+ #include < endian.h>
31
+
32
+ #elif defined(__APPLE__)
33
+ #include < libkern/OSByteOrder.h>
34
+
35
+ #define htobe16 (x ) OSSwapHostToBigInt16(x)
36
+ #define htole16 (x ) OSSwapHostToLittleInt16(x)
37
+ #define be16toh (x ) OSSwapBigToHostInt16(x)
38
+ #define le16toh (x ) OSSwapLittleToHostInt16(x)
39
+
40
+ #define htobe32 (x ) OSSwapHostToBigInt32(x)
41
+ #define htole32 (x ) OSSwapHostToLittleInt32(x)
42
+ #define be32toh (x ) OSSwapBigToHostInt32(x)
43
+ #define le32toh (x ) OSSwapLittleToHostInt32(x)
44
+
45
+ #define htobe64 (x ) OSSwapHostToBigInt64(x)
46
+ #define htole64 (x ) OSSwapHostToLittleInt64(x)
47
+ #define be64toh (x ) OSSwapBigToHostInt64(x)
48
+ #define le64toh (x ) OSSwapLittleToHostInt64(x)
49
+
50
+ #elif defined(__OpenBSD__)
51
+ #include < sys/endian.h>
52
+
53
+ #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
54
+ #include < sys/endian.h>
55
+
56
+ #define be16toh (x ) betoh16(x)
57
+ #define le16toh (x ) letoh16(x)
58
+
59
+ #define be32toh (x ) betoh32(x)
60
+ #define le32toh (x ) letoh32(x)
61
+
62
+ #define be64toh (x ) betoh64(x)
63
+ #define le64toh (x ) letoh64(x)
64
+
65
+ #elif defined(_WIN32) || defined(_WIN64)
66
+ #if defined(_MSC_VER) && _MSC_VER > 1300
67
+ #include < intrin.h>
68
+ #define htobe16 (x ) _byteswap_ushort(x)
69
+ #define htole16 (x ) (x)
70
+ #define be16toh (x ) _byteswap_ushort(x)
71
+ #define le16toh (x ) (x)
72
+
73
+ #define htobe32 (x ) _byteswap_ulong(x)
74
+ #define htole32 (x ) (x)
75
+ #define be32toh (x ) _byteswap_ulong(x)
76
+ #define le32toh (x ) (x)
77
+
78
+ #define htobe64 (x ) _byteswap_uint64(x)
79
+ #define htole64 (x ) (x)
80
+ #define be64toh (x ) _byteswap_uint64(x)
81
+ #define le64toh (x ) (x)
82
+ #else
83
+ #include < winsock2.h>
84
+ #define htobe16 (x ) htons(x)
85
+ #define htole16 (x ) (x)
86
+ #define be16toh (x ) ntohs(x)
87
+ #define le16toh (x ) (x)
88
+
89
+ #define htobe32 (x ) htonl(x)
90
+ #define htole32 (x ) (x)
91
+ #define be32toh (x ) ntohl(x)
92
+ #define le32toh (x ) (x)
93
+
94
+ #define htobe64 (x ) ((unsigned __int64)htonl((unsigned long )(x & 0xFFFFFFFF )) << 32 ) | htonl((unsigned long )(x >> 32 ))
95
+ #define htole64 (x ) (x)
96
+ #define be64toh (x ) ((unsigned __int64)ntohl((unsigned long )(x & 0xFFFFFFFF )) << 32 ) | ntohl((unsigned long )(x >> 32 ))
97
+ #define le64toh (x ) (x)
98
+ #endif // _MSC_VER
99
+
100
+ #else
101
+ #error platform not supported
102
+ #endif
103
+
104
+
105
+ // Endian helper function data types
106
+ #if defined(__linux__) || defined(__CYGWIN__)
107
+ typedef uint16_t SwapType16;
108
+ typedef uint32_t SwapType32;
109
+ typedef uint64_t SwapType64;
110
+
111
+ #elif defined(__APPLE__)
112
+ typedef UInt16 SwapType16;
113
+ typedef UInt32 SwapType32;
114
+ typedef UInt64 SwapType64;
115
+
116
+ #elif defined(__OpenBSD__)
117
+ typedef uint16_t SwapType16;
118
+ typedef uint32_t SwapType32;
119
+ typedef uint64_t SwapType64;
120
+
121
+ #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
122
+ typedef uint16_t SwapType16;
123
+ typedef uint32_t SwapType32;
124
+ typedef uint64_t SwapType64;
125
+
126
+ #elif defined(_WIN32) || defined(_WIN64)
127
+ #if defined(_MSC_VER) && _MSC_VER < 1300
128
+ typedef unsigned short SwapType16;
129
+ typedef unsigned long SwapType32;
130
+ typedef unsigned __int64 SwapType64;
131
+ #else
132
+ typedef unsigned short SwapType16;
133
+ typedef unsigned long SwapType32;
134
+ typedef unsigned long long SwapType64;
135
+ #endif // _MSC_VER
136
+
137
+ #else
138
+ #error platform not supported
139
+ #endif
140
+
141
+
142
+ // Endian helper functions
143
+ static_assert (sizeof (SwapType16) == 2, "expected size does not match");
144
+ static_assert (sizeof (SwapType32) == 4, "expected size does not match");
145
+ static_assert (sizeof (SwapType64) == 8, "expected size does not match");
146
+
147
+ namespace Endian
148
+ {
149
+ template <typename Type, size_t Size = sizeof (Type)> struct htobeHelper ;
150
+ template <typename Type, size_t Size = sizeof (Type)> struct htoleHelper ;
151
+ template <typename Type, size_t Size = sizeof (Type)> struct betohHelper ;
152
+ template <typename Type, size_t Size = sizeof (Type)> struct letohHelper ;
153
+
154
+ // 2 byte integer, enum
155
+ template <typename Type> struct htobeHelper <Type, 2 > { static inline Type swap (Type value) { return static_cast <Type>(htobe16 (static_cast <SwapType16>(value))); } };
156
+ template <typename Type> struct htoleHelper <Type, 2 > { static inline Type swap (Type value) { return static_cast <Type>(htole16 (static_cast <SwapType16>(value))); } };
157
+ template <typename Type> struct betohHelper <Type, 2 > { static inline Type swap (Type value) { return static_cast <Type>(be16toh (static_cast <SwapType16>(value))); } };
158
+ template <typename Type> struct letohHelper <Type, 2 > { static inline Type swap (Type value) { return static_cast <Type>(le16toh (static_cast <SwapType16>(value))); } };
159
+ // 4 byte integer, enum
160
+ template <typename Type> struct htobeHelper <Type, 4 > { static inline Type swap (Type value) { return static_cast <Type>(htobe32 (static_cast <SwapType32>(value))); } };
161
+ template <typename Type> struct htoleHelper <Type, 4 > { static inline Type swap (Type value) { return static_cast <Type>(htole32 (static_cast <SwapType32>(value))); } };
162
+ template <typename Type> struct betohHelper <Type, 4 > { static inline Type swap (Type value) { return static_cast <Type>(be32toh (static_cast <SwapType32>(value))); } };
163
+ template <typename Type> struct letohHelper <Type, 4 > { static inline Type swap (Type value) { return static_cast <Type>(le16toh (static_cast <SwapType32>(value))); } };
164
+ // 8 byte integer, enum
165
+ template <typename Type> struct htobeHelper <Type, 8 > { static inline Type swap (Type value) { return static_cast <Type>(htobe64 (static_cast <SwapType64>(value))); } };
166
+ template <typename Type> struct htoleHelper <Type, 8 > { static inline Type swap (Type value) { return static_cast <Type>(htole64 (static_cast <SwapType64>(value))); } };
167
+ template <typename Type> struct betohHelper <Type, 8 > { static inline Type swap (Type value) { return static_cast <Type>(be64toh (static_cast <SwapType64>(value))); } };
168
+ template <typename Type> struct letohHelper <Type, 8 > { static inline Type swap (Type value) { return static_cast <Type>(le16toh (static_cast <SwapType64>(value))); } };
169
+ // float
170
+ template <> struct htobeHelper <float , 4 > { static inline float swap (float value) { SwapType32 v = htobe32 (*reinterpret_cast <SwapType32*>(&value)); return *reinterpret_cast <float *>(&v); } };
171
+ template <> struct htoleHelper <float , 4 > { static inline float swap (float value) { SwapType32 v = htole32 (*reinterpret_cast <SwapType32*>(&value)); return *reinterpret_cast <float *>(&v); } };
172
+ template <> struct betohHelper <float , 4 > { static inline float swap (float value) { SwapType32 v = be32toh (*reinterpret_cast <SwapType32*>(&value)); return *reinterpret_cast <float *>(&v); } };
173
+ template <> struct letohHelper <float , 4 > { static inline float swap (float value) { SwapType32 v = le16toh (*reinterpret_cast <SwapType32*>(&value)); return *reinterpret_cast <float *>(&v); } };
174
+ // double
175
+ template <> struct htobeHelper <double , 8 > { static inline double swap (double value) { SwapType64 v = htobe64 (*reinterpret_cast <SwapType64*>(&value)); return *reinterpret_cast <double *>(&v); } };
176
+ template <> struct htoleHelper <double , 8 > { static inline double swap (double value) { SwapType64 v = htole64 (*reinterpret_cast <SwapType64*>(&value)); return *reinterpret_cast <double *>(&v); } };
177
+ template <> struct betohHelper <double , 8 > { static inline double swap (double value) { SwapType64 v = be64toh (*reinterpret_cast <SwapType64*>(&value)); return *reinterpret_cast <double *>(&v); } };
178
+ template <> struct letohHelper <double , 8 > { static inline double swap (double value) { SwapType64 v = le16toh (*reinterpret_cast <SwapType64*>(&value)); return *reinterpret_cast <double *>(&v); } };
179
+ } // namespace Endian
180
+
181
+ // c++ template functions, takes any 2, 4, 8 bytes, including float, double, enum
182
+
183
+ // Host to big endian
184
+ template <typename Type> inline Type htobe (Type value) { return Endian::htobeHelper<Type>::swap (value); }
185
+ // Host to little endian
186
+ template <typename Type> inline Type htole (Type value) { return Endian::htoleHelper<Type>::swap (value); }
187
+ // Big endian to host
188
+ template <typename Type> inline Type betoh (Type value) { return Endian::betohHelper<Type>::swap (value); }
189
+ // Little endian to host
190
+ template <typename Type> inline Type letoh (Type value) { return Endian::letohHelper<Type>::swap (value); }
191
+
192
+ // Host to big endian
193
+ template <typename Type> inline void htobe_ref (Type &value) { value = Endian::htobeHelper<Type>::swap (value); }
194
+ // Host to little endian
195
+ template <typename Type> inline void htole_ref (Type &value) { value = Endian::htoleHelper<Type>::swap (value); }
196
+ // Big endian to host
197
+ template <typename Type> inline void betoh_ref (Type &value) { value = Endian::betohHelper<Type>::swap (value); }
198
+ // Little endian to host
199
+ template <typename Type> inline void letoh_ref (Type &value) { value = Endian::letohHelper<Type>::swap (value); }
200
+
201
+ #endif // ENDIAN_COMPAT_H
0 commit comments