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