~ubuntu-branches/ubuntu/trusty/aegisub/trusty

« back to all changes in this revision

Viewing changes to src/aegisub_endian.h

  • Committer: Package Import Robot
  • Author(s): Sebastian Reichel
  • Date: 2012-03-16 22:58:00 UTC
  • Revision ID: package-import@ubuntu.com-20120316225800-yfb8h9e5n04rk46a
Tags: upstream-2.1.9
ImportĀ upstreamĀ versionĀ 2.1.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2008, Niels Martin Hansen
 
2
//
 
3
// Redistribution and use in source and binary forms, with or without
 
4
// modification, are permitted provided that the following conditions are met:
 
5
//
 
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.
 
14
//
 
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.
 
26
//
 
27
// -----------------------------------------------------------------------------
 
28
//
 
29
// AEGISUB
 
30
//
 
31
// Website: http://www.aegisub.net
 
32
// Contact: mailto:jiifurusu@gmail.com
 
33
//
 
34
 
 
35
#pragma once
 
36
 
 
37
#ifndef _AEGISUB_ENDIAN_H
 
38
#define _AEGISUB_ENDIAN_H
 
39
 
 
40
 
 
41
// Sanity check
 
42
 
 
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
 
49
#   ifdef _BIG_ENDIAN
 
50
#    define HAVE_BIG_ENDIAN
 
51
#   else
 
52
#    define HAVE_LITTLE_ENDIAN
 
53
#   endif
 
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
 
60
#   endif
 
61
#  endif //HAVE_UNIVERSAL_ENDIAN
 
62
# endif // HAVE_BIG_ENDIAN
 
63
#endif // HAVE_LITTLE_ENDIAN
 
64
 
 
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
 
68
# endif
 
69
#endif
 
70
 
 
71
 
 
72
#include <stdint.h>
 
73
 
 
74
 
 
75
namespace Endian {
 
76
 
 
77
        // Unconditionally reverse endianness
 
78
 
 
79
        // These are only defined for unsigned ints,
 
80
        // Use reinterpret_cast on the values if you need signed values.
 
81
 
 
82
        inline uint16_t Reverse(uint16_t val)
 
83
        {
 
84
                return
 
85
                        ((val & 0x00FF) << 8) |
 
86
                        ((val & 0xFF00) >> 8);
 
87
        }
 
88
 
 
89
        inline uint32_t Reverse(uint32_t val)
 
90
        {
 
91
                return
 
92
                        ((val & 0x000000FF) << 24) |
 
93
                        ((val & 0x0000FF00) <<  8) |
 
94
                        ((val & 0x00FF0000) >>  8) |
 
95
                        ((val & 0xFF000000) >> 24);
 
96
        }
 
97
 
 
98
        inline uint64_t Reverse(uint64_t val)
 
99
        {
 
100
                return
 
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);
 
109
        }
 
110
 
 
111
 
 
112
#ifndef HAVE_DYNAMIC_ENDIAN
 
113
 
 
114
 
 
115
        // Regular, fast, templatized conditional reversing
 
116
 
 
117
        template <class T>
 
118
        inline T LittleToMachine(T val)
 
119
        {
 
120
#ifdef HAVE_BIG_ENDIAN
 
121
                // We're on big endian, reverse little to big
 
122
                return Reverse(val);
 
123
#else
 
124
                // We're on little endian and input is little
 
125
                return val;
 
126
#endif
 
127
        }
 
128
 
 
129
        template <class T>
 
130
        inline T BigToMachine(T val)
 
131
        {
 
132
#ifdef HAVE_LITTLE_ENDIAN
 
133
                // We're on little endian, reverse big to little
 
134
                return Reverse(val);
 
135
#else
 
136
                // We're on big endian and input is big
 
137
                return val;
 
138
#endif
 
139
        }
 
140
 
 
141
        template <class T>
 
142
        inline T MachineToLittle(T val)
 
143
        {
 
144
#ifdef HAVE_BIG_ENDIAN
 
145
                // We're on big endian, reverse to little
 
146
                return Reverse(val);
 
147
#else
 
148
                // Already on little, nothing to be done
 
149
                return val;
 
150
#endif
 
151
        }
 
152
 
 
153
        template <class T>
 
154
        inline T MachineToBig(T val)
 
155
        {
 
156
#ifdef HAVE_LITTLE_ENDIAN
 
157
                // We're on little endian, reverse to big
 
158
                return Reverse(val);
 
159
#else
 
160
                // Already on big, nothing to be done
 
161
                return val;
 
162
#endif
 
163
        }
 
164
 
 
165
 
 
166
#else // HAVE_DYNAMIC_ENDIAN
 
167
 
 
168
 
 
169
        // Dynamic endianness handling
 
170
 
 
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!
 
177
 
 
178
 
 
179
        // Unions to pack together ints and get their physical bytes
 
180
 
 
181
        union bytes16 {
 
182
                uint8_t byte[2];
 
183
                uint16_t word;
 
184
        };
 
185
        union bytes32 {
 
186
                uint8_t byte[4];
 
187
                uint32_t word;
 
188
        };
 
189
        union bytes64 {
 
190
                uint8_t byte[8];
 
191
                uint64_t word;
 
192
        };
 
193
 
 
194
 
 
195
        // 16 bit words
 
196
 
 
197
        inline uint16_t MachineToBig(uint16_t val)
 
198
        {
 
199
                bytes16 pack;
 
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
 
204
                return pack.word;
 
205
        }
 
206
 
 
207
        inline uint16_t MachineToLittle(uint16_t val)
 
208
        {
 
209
                bytes16 pack;
 
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
 
214
                return pack.word;
 
215
        }
 
216
 
 
217
        inline uint16_t BigToMachine(uint16_t val)
 
218
        {
 
219
                bytes16 pack;
 
220
                // Put our word into the pack
 
221
                pack.word = val;
 
222
                // And produce a machine endian value of it
 
223
                return uint16_t(pack.byte[1]) | (uint16_t(pack.byte[0]) << 8);
 
224
        }
 
225
 
 
226
        inline uint16_t LittleToMachine(uint16_t val)
 
227
        {
 
228
                bytes16 pack;
 
229
                // Put our word into the pack
 
230
                pack.word = val;
 
231
                // And produce a machine endian value of it
 
232
                return uint16_t(pack.byte[0]) | (uint16_t(pack.byte[1]) << 8);
 
233
        }
 
234
 
 
235
 
 
236
        // 32 bit words
 
237
 
 
238
        inline uint32_t MachineToBig(uint32_t val)
 
239
        {
 
240
                bytes32 pack;
 
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       ;
 
245
                return pack.word;
 
246
        }
 
247
 
 
248
        inline uint32_t MachineToLittle(uint32_t val)
 
249
        {
 
250
                bytes32 pack;
 
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;
 
255
                return pack.word;
 
256
        }
 
257
 
 
258
        inline uint32_t BigToMachine(uint32_t val)
 
259
        {
 
260
                bytes32 pack;
 
261
                pack.word = val;
 
262
                return
 
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]);
 
267
        }
 
268
 
 
269
        inline uint32_t LittleToMachine(uint32_t val)
 
270
        {
 
271
                bytes32 pack;
 
272
                pack.word = val;
 
273
                return
 
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]);
 
278
        }
 
279
 
 
280
 
 
281
        // 64 bit words
 
282
 
 
283
        inline uint64_t MachineToBig(uint64_t val)
 
284
        {
 
285
                bytes64 pack;
 
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       ;
 
294
                return pack.word;
 
295
        }
 
296
 
 
297
        inline uint64_t MachineToLittle(uint64_t val)
 
298
        {
 
299
                bytes64 pack;
 
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;
 
308
                return pack.word;
 
309
        }
 
310
 
 
311
        inline uint64_t BigToMachine(uint64_t val)
 
312
        {
 
313
                bytes64 pack;
 
314
                pack.word = val;
 
315
                return
 
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]);
 
324
        }
 
325
 
 
326
        inline uint64_t LittleToMachine(uint64_t val)
 
327
        {
 
328
                bytes64 pack;
 
329
                pack.word = val;
 
330
                return
 
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]);
 
339
        }
 
340
 
 
341
 
 
342
#endif
 
343
 
 
344
};
 
345
 
 
346
#endif