RavEngine
Loading...
Searching...
No Matches
endianness.h
1//----------------------------------------------------------------------------//
2// //
3// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
4// and distributed under the MIT License (MIT). //
5// //
6// Copyright (c) Guillaume Blanc //
7// //
8// Permission is hereby granted, free of charge, to any person obtaining a //
9// copy of this software and associated documentation files (the "Software"), //
10// to deal in the Software without restriction, including without limitation //
11// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
12// and/or sell copies of the Software, and to permit persons to whom the //
13// Software is furnished to do so, subject to the following conditions: //
14// //
15// The above copyright notice and this permission notice shall be included in //
16// all copies or substantial portions of the Software. //
17// //
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
21// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
23// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
24// DEALINGS IN THE SOFTWARE. //
25// //
26//----------------------------------------------------------------------------//
27
28#ifndef OZZ_OZZ_BASE_ENDIANNESS_H_
29#define OZZ_OZZ_BASE_ENDIANNESS_H_
30
31// Declares endianness modes and functions to swap data from a mode to another.
32
33#include <cstddef>
34
35#include "ozz/base/platform.h"
36
37namespace ozz {
38
39// Declares supported endianness.
40enum Endianness {
41 kBigEndian,
42 kLittleEndian,
43};
44
45// Get the native endianness of the targeted processor.
46// This function does not rely on a pre-processor definition as no standard
47// definition exists. It is rather implemented as a portable runtime function.
48inline Endianness GetNativeEndianness() {
49 const union {
50 uint16_t s;
51 uint8_t c[2];
52 } u = {1}; // Initializes u.s -> then read u.c.
53 return Endianness(u.c[0]);
54}
55
56// Declare the endian swapper struct that is aimed to be specialized (template
57// meaning) for every type sizes.
58// The swapper provides two functions:
59// - void Swap(_Ty* _ty, size_t _count) swaps the array _ty of _count
60// elements in-place.
61// - _Ty Swap(_Ty _ty) returns a swapped copy of _ty.
62// It can be used directly if _Ty is known or through EndianSwap function.
63// The default value of template attribute _size enables automatic
64// specialization selection.
65template <typename _Ty, size_t _size = sizeof(_Ty)>
67
68// Internal macro used to swap two bytes.
69#define OZZ_BYTE_SWAP(_a, _b) \
70 do { \
71 const ozz::byte temp = (_a); \
72 (_a) = (_b); \
73 (_b) = temp; \
74 } while (0)
75
76// EndianSwapper specialization for 1 byte types.
77template <typename _Ty>
78struct EndianSwapper<_Ty, 1> {
79 OZZ_INLINE static void Swap(_Ty*, size_t) {}
80 OZZ_INLINE static _Ty Swap(_Ty _ty) { return _ty; }
81};
82
83// EndianSwapper specialization for 2 bytes types.
84template <typename _Ty>
85struct EndianSwapper<_Ty, 2> {
86 OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
87 byte* alias = reinterpret_cast<byte*>(_ty);
88 for (size_t i = 0; i < _count * 2; i += 2) {
89 OZZ_BYTE_SWAP(alias[i + 0], alias[i + 1]);
90 }
91 }
92 OZZ_INLINE static _Ty Swap(_Ty _ty) { // Pass by copy to swap _ty in-place.
93 byte* alias = reinterpret_cast<byte*>(&_ty);
94 OZZ_BYTE_SWAP(alias[0], alias[1]);
95 return _ty;
96 }
97};
98
99// EndianSwapper specialization for 4 bytes types.
100template <typename _Ty>
101struct EndianSwapper<_Ty, 4> {
102 OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
103 byte* alias = reinterpret_cast<byte*>(_ty);
104 for (size_t i = 0; i < _count * 4; i += 4) {
105 OZZ_BYTE_SWAP(alias[i + 0], alias[i + 3]);
106 OZZ_BYTE_SWAP(alias[i + 1], alias[i + 2]);
107 }
108 }
109 OZZ_INLINE static _Ty Swap(_Ty _ty) { // Pass by copy to swap _ty in-place.
110 byte* alias = reinterpret_cast<byte*>(&_ty);
111 OZZ_BYTE_SWAP(alias[0], alias[3]);
112 OZZ_BYTE_SWAP(alias[1], alias[2]);
113 return _ty;
114 }
115};
116
117// EndianSwapper specialization for 8 bytes types.
118template <typename _Ty>
119struct EndianSwapper<_Ty, 8> {
120 OZZ_INLINE static void Swap(_Ty* _ty, size_t _count) {
121 byte* alias = reinterpret_cast<byte*>(_ty);
122 for (size_t i = 0; i < _count * 8; i += 8) {
123 OZZ_BYTE_SWAP(alias[i + 0], alias[i + 7]);
124 OZZ_BYTE_SWAP(alias[i + 1], alias[i + 6]);
125 OZZ_BYTE_SWAP(alias[i + 2], alias[i + 5]);
126 OZZ_BYTE_SWAP(alias[i + 3], alias[i + 4]);
127 }
128 }
129 OZZ_INLINE static _Ty Swap(_Ty _ty) { // Pass by copy to swap _ty in-place.
130 byte* alias = reinterpret_cast<byte*>(&_ty);
131 OZZ_BYTE_SWAP(alias[0], alias[7]);
132 OZZ_BYTE_SWAP(alias[1], alias[6]);
133 OZZ_BYTE_SWAP(alias[2], alias[5]);
134 OZZ_BYTE_SWAP(alias[3], alias[4]);
135 return _ty;
136 }
137};
138
139// OZZ_BYTE_SWAP is not useful anymore.
140#undef OZZ_BYTE_SWAP
141
142// Helper function that swaps _count elements of the array _ty in place.
143template <typename _Ty>
144OZZ_INLINE void EndianSwap(_Ty* _ty, size_t _count) {
145 EndianSwapper<_Ty>::Swap(_ty, _count);
146}
147
148// Helper function that swaps _ty in place.
149template <typename _Ty>
150OZZ_INLINE _Ty EndianSwap(_Ty _ty) {
151 return EndianSwapper<_Ty>::Swap(_ty);
152}
153} // namespace ozz
154#endif // OZZ_OZZ_BASE_ENDIANNESS_H_
uint8 uint8_t
Definition fwd.hpp:103
uint16 uint16_t
Definition fwd.hpp:117
Definition endianness.h:66