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