1
// Copyright (c) 2008, Niels Martin Hansen
3
// Redistribution and use in source and binary forms, with or without
4
// modification, are permitted provided that the following conditions are met:
6
// * Redistributions of source code must retain the above copyright notice,
7
// this list of conditions and the following disclaimer.
8
// * Redistributions in binary form must reproduce the above copyright notice,
9
// this list of conditions and the following disclaimer in the documentation
10
// and/or other materials provided with the distribution.
11
// * Neither the name of the Aegisub Group nor the names of its contributors
12
// may be used to endorse or promote products derived from this software
13
// without specific prior written permission.
15
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
// POSSIBILITY OF SUCH DAMAGE.
27
// -----------------------------------------------------------------------------
31
// Website: http://www.aegisub.net
32
// Contact: mailto:jiifurusu@gmail.com
37
#ifndef _AEGISUB_ENDIAN_H
38
#define _AEGISUB_ENDIAN_H
43
#ifndef HAVE_LITTLE_ENDIAN
44
# ifndef HAVE_BIG_ENDIAN
45
// We neither have big nor little endian from configuration
46
# ifdef HAVE_UNIVERSAL_ENDIAN
47
// But this is an OS X system building a universal binary
48
// Apple's GCC defines _BIG_ENDIAN when building for PPC
50
# define HAVE_BIG_ENDIAN
52
# define HAVE_LITTLE_ENDIAN
54
# undef HAVE_DYNAMIC_ENDIAN
55
# else // !HAVE_UNIVERSAL_ENDIAN
56
// We aren't building an OS X universal binary
57
// Use the dynamic endian code
58
# ifndef HAVE_DYNAMIC_ENDIAN
59
# define HAVE_DYNAMIC_ENDIAN
61
# endif //HAVE_UNIVERSAL_ENDIAN
62
# endif // HAVE_BIG_ENDIAN
63
#endif // HAVE_LITTLE_ENDIAN
65
#ifdef HAVE_LITTLE_ENDIAN
66
# ifdef HAVE_BIG_ENDIAN
67
# error You cannot have both HAVE_LITTLE_ENDIAN and HAVE_BIG_ENDIAN defined at the same time
77
// Unconditionally reverse endianness
79
// These are only defined for unsigned ints,
80
// Use reinterpret_cast on the values if you need signed values.
82
inline uint16_t Reverse(uint16_t val)
85
((val & 0x00FF) << 8) |
86
((val & 0xFF00) >> 8);
89
inline uint32_t Reverse(uint32_t val)
92
((val & 0x000000FF) << 24) |
93
((val & 0x0000FF00) << 8) |
94
((val & 0x00FF0000) >> 8) |
95
((val & 0xFF000000) >> 24);
98
inline uint64_t Reverse(uint64_t val)
101
((val & 0x00000000000000FF) << 56) |
102
((val & 0x000000000000FF00) << 40) |
103
((val & 0x0000000000FF0000) << 24) |
104
((val & 0x00000000FF000000) << 8) |
105
((val & 0x000000FF00000000) >> 8) |
106
((val & 0x0000FF0000000000) >> 24) |
107
((val & 0x00FF000000000000) >> 40) |
108
((val & 0xFF00000000000000) >> 56);
112
#ifndef HAVE_DYNAMIC_ENDIAN
115
// Regular, fast, templatized conditional reversing
118
inline T LittleToMachine(T val)
120
#ifdef HAVE_BIG_ENDIAN
121
// We're on big endian, reverse little to big
124
// We're on little endian and input is little
130
inline T BigToMachine(T val)
132
#ifdef HAVE_LITTLE_ENDIAN
133
// We're on little endian, reverse big to little
136
// We're on big endian and input is big
142
inline T MachineToLittle(T val)
144
#ifdef HAVE_BIG_ENDIAN
145
// We're on big endian, reverse to little
148
// Already on little, nothing to be done
154
inline T MachineToBig(T val)
156
#ifdef HAVE_LITTLE_ENDIAN
157
// We're on little endian, reverse to big
160
// Already on big, nothing to be done
166
#else // HAVE_DYNAMIC_ENDIAN
169
// Dynamic endianness handling
171
// Exploit that bit-shifting operations always can put bytes into
172
// machine word order, while unions can be used to access bytes
173
// only from an explicitly given byte order.
174
// This is probably slower than when we explicitly know
175
// the endianness of the machine we are on, but it's the same
176
// code for any platform!
179
// Unions to pack together ints and get their physical bytes
197
inline uint16_t MachineToBig(uint16_t val)
200
// Store the bytes into the correct positions in the word
201
pack.byte[0] = (val & 0xFF00) >> 8;
202
pack.byte[1] = val & 0x00FF;
203
// And return a value now encoded as big endian
207
inline uint16_t MachineToLittle(uint16_t val)
210
// Store the bytes into the correct positions in the word
211
pack.byte[0] = val & 0x00FF;
212
pack.byte[1] = (val & 0xFF00) >> 8;
213
// And return a value now encoded as little endian
217
inline uint16_t BigToMachine(uint16_t val)
220
// Put our word into the pack
222
// And produce a machine endian value of it
223
return uint16_t(pack.byte[1]) | (uint16_t(pack.byte[0]) << 8);
226
inline uint16_t LittleToMachine(uint16_t val)
229
// Put our word into the pack
231
// And produce a machine endian value of it
232
return uint16_t(pack.byte[0]) | (uint16_t(pack.byte[1]) << 8);
238
inline uint32_t MachineToBig(uint32_t val)
241
pack.byte[0] = (val & 0xFF000000) >> 24;
242
pack.byte[1] = (val & 0x00FF0000) >> 16;
243
pack.byte[2] = (val & 0x0000FF00) >> 8;
244
pack.byte[3] = val & 0x000000FF ;
248
inline uint32_t MachineToLittle(uint32_t val)
251
pack.byte[0] = val & 0x000000FF ;
252
pack.byte[1] = (val & 0x0000FF00) >> 8;
253
pack.byte[2] = (val & 0x00FF0000) >> 16;
254
pack.byte[3] = (val & 0xFF000000) >> 24;
258
inline uint32_t BigToMachine(uint32_t val)
263
(uint32_t(pack.byte[0]) << 24) |
264
(uint32_t(pack.byte[1]) << 16) |
265
(uint32_t(pack.byte[2]) << 8) |
266
uint32_t(pack.byte[3]);
269
inline uint32_t LittleToMachine(uint32_t val)
274
(uint32_t(pack.byte[3]) << 24) |
275
(uint32_t(pack.byte[2]) << 16) |
276
(uint32_t(pack.byte[1]) << 8) |
277
uint32_t(pack.byte[0]);
283
inline uint64_t MachineToBig(uint64_t val)
286
pack.byte[0] = (val & 0xFF00000000000000) >> 56;
287
pack.byte[1] = (val & 0x00FF000000000000) >> 48;
288
pack.byte[2] = (val & 0x0000FF0000000000) >> 40;
289
pack.byte[3] = (val & 0x000000FF00000000) >> 32;
290
pack.byte[4] = (val & 0x00000000FF000000) >> 24;
291
pack.byte[5] = (val & 0x0000000000FF0000) >> 16;
292
pack.byte[6] = (val & 0x000000000000FF00) >> 8;
293
pack.byte[7] = val & 0x00000000000000FF ;
297
inline uint64_t MachineToLittle(uint64_t val)
300
pack.byte[0] = val & 0x00000000000000FF ;
301
pack.byte[1] = (val & 0x000000000000FF00) >> 8;
302
pack.byte[2] = (val & 0x0000000000FF0000) >> 16;
303
pack.byte[3] = (val & 0x00000000FF000000) >> 24;
304
pack.byte[4] = (val & 0x000000FF00000000) >> 32;
305
pack.byte[5] = (val & 0x0000FF0000000000) >> 40;
306
pack.byte[6] = (val & 0x00FF000000000000) >> 48;
307
pack.byte[7] = (val & 0xFF00000000000000) >> 56;
311
inline uint64_t BigToMachine(uint64_t val)
316
(uint64_t(pack.byte[0]) << 56) |
317
(uint64_t(pack.byte[1]) << 48) |
318
(uint64_t(pack.byte[2]) << 40) |
319
(uint64_t(pack.byte[3]) << 32) |
320
(uint64_t(pack.byte[4]) << 24) |
321
(uint64_t(pack.byte[5]) << 16) |
322
(uint64_t(pack.byte[6]) << 8) |
323
uint64_t(pack.byte[7]);
326
inline uint64_t LittleToMachine(uint64_t val)
331
(uint64_t(pack.byte[7]) << 56) |
332
(uint64_t(pack.byte[6]) << 48) |
333
(uint64_t(pack.byte[5]) << 40) |
334
(uint64_t(pack.byte[4]) << 32) |
335
(uint64_t(pack.byte[3]) << 24) |
336
(uint64_t(pack.byte[2]) << 16) |
337
(uint64_t(pack.byte[1]) << 8) |
338
uint64_t(pack.byte[0]);