Plasma Engine  2.0
Loading...
Searching...
No Matches
EndianHelper.h
1#pragma once
2
3#include <Foundation/Basics.h>
4
6struct PL_FOUNDATION_DLL plEndianHelper
7{
8
12 static inline bool IsBigEndian()
13 {
14 const int i = 1;
15 return (*(char*)&i) == 0;
16 }
17
21 static inline bool IsLittleEndian() { return !IsBigEndian(); }
22
24 static inline void SwitchWords(plUInt16* pWords, plUInt32 uiCount) // [tested]
25 {
26 for (plUInt32 i = 0; i < uiCount; i++)
27 pWords[i] = Switch(pWords[i]);
28 }
29
31 static inline void SwitchDWords(plUInt32* pDWords, plUInt32 uiCount) // [tested]
32 {
33 for (plUInt32 i = 0; i < uiCount; i++)
34 pDWords[i] = Switch(pDWords[i]);
35 }
36
38 static inline void SwitchQWords(plUInt64* pQWords, plUInt32 uiCount) // [tested]
39 {
40 for (plUInt32 i = 0; i < uiCount; i++)
41 pQWords[i] = Switch(pQWords[i]);
42 }
43
45 static PL_ALWAYS_INLINE plUInt16 Switch(plUInt16 uiWord) // [tested]
46 {
47 return (((uiWord & 0xFF) << 8) | ((uiWord >> 8) & 0xFF));
48 }
49
51 static PL_ALWAYS_INLINE plUInt32 Switch(plUInt32 uiDWord) // [tested]
52 {
53 return (((uiDWord & 0xFF) << 24) | (((uiDWord >> 8) & 0xFF) << 16) | (((uiDWord >> 16) & 0xFF) << 8) | ((uiDWord >> 24) & 0xFF));
54 }
55
57 static PL_ALWAYS_INLINE plUInt64 Switch(plUInt64 uiQWord) // [tested]
58 {
59 return (((uiQWord & 0xFF) << 56) | ((uiQWord & 0xFF00) << 40) | ((uiQWord & 0xFF0000) << 24) | ((uiQWord & 0xFF000000) << 8) |
60 ((uiQWord & 0xFF00000000) >> 8) | ((uiQWord & 0xFF0000000000) >> 24) | ((uiQWord & 0xFF000000000000) >> 40) |
61 ((uiQWord & 0xFF00000000000000) >> 56));
62 }
63
65 template <typename T>
66 static void SwitchInPlace(T* pValue) // [tested]
67 {
68 static_assert(
69 (sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8), "Switch in place only works for type equivalents of plUInt16, plUInt32, plUInt64!");
70
71 if (sizeof(T) == 2)
72 {
73 struct TAnd16BitUnion
74 {
75 union
76 {
77 plUInt16 BitValue;
78 T TValue;
79 };
80 };
81
82 TAnd16BitUnion Temp;
83 Temp.TValue = *pValue;
84 Temp.BitValue = Switch(Temp.BitValue);
85
86 *pValue = Temp.TValue;
87 }
88 else if (sizeof(T) == 4)
89 {
90 struct TAnd32BitUnion
91 {
92 union
93 {
94 plUInt32 BitValue;
95 T TValue;
96 };
97 };
98
99 TAnd32BitUnion Temp;
100 Temp.TValue = *pValue;
101 Temp.BitValue = Switch(Temp.BitValue);
102
103 *pValue = Temp.TValue;
104 }
105 else if (sizeof(T) == 8)
106 {
107 struct TAnd64BitUnion
108 {
109 union
110 {
111 plUInt64 BitValue;
112 T TValue;
113 };
114 };
115
116 TAnd64BitUnion Temp;
117 Temp.TValue = *pValue;
118 Temp.BitValue = Switch(Temp.BitValue);
119
120 *pValue = Temp.TValue;
121 }
122 }
123
124#if PL_ENABLED(PL_PLATFORM_LITTLE_ENDIAN)
125
126 static PL_ALWAYS_INLINE void LittleEndianToNative(plUInt16* /*pWords*/, plUInt32 /*uiCount*/)
127 {
128 }
129
130 static PL_ALWAYS_INLINE void NativeToLittleEndian(plUInt16* /*pWords*/, plUInt32 /*uiCount*/) {}
131
132 static PL_ALWAYS_INLINE void LittleEndianToNative(plUInt32* /*pDWords*/, plUInt32 /*uiCount*/) {}
133
134 static PL_ALWAYS_INLINE void NativeToLittleEndian(plUInt32* /*pDWords*/, plUInt32 /*uiCount*/) {}
135
136 static PL_ALWAYS_INLINE void LittleEndianToNative(plUInt64* /*pQWords*/, plUInt32 /*uiCount*/) {}
137
138 static PL_ALWAYS_INLINE void NativeToLittleEndian(plUInt64* /*pQWords*/, plUInt32 /*uiCount*/) {}
139
140 static PL_ALWAYS_INLINE void BigEndianToNative(plUInt16* pWords, plUInt32 uiCount) { SwitchWords(pWords, uiCount); }
141
142 static PL_ALWAYS_INLINE void NativeToBigEndian(plUInt16* pWords, plUInt32 uiCount) { SwitchWords(pWords, uiCount); }
143
144 static PL_ALWAYS_INLINE void BigEndianToNative(plUInt32* pDWords, plUInt32 uiCount) { SwitchDWords(pDWords, uiCount); }
145
146 static PL_ALWAYS_INLINE void NativeToBigEndian(plUInt32* pDWords, plUInt32 uiCount) { SwitchDWords(pDWords, uiCount); }
147
148 static PL_ALWAYS_INLINE void BigEndianToNative(plUInt64* pQWords, plUInt32 uiCount) { SwitchQWords(pQWords, uiCount); }
149
150 static PL_ALWAYS_INLINE void NativeToBigEndian(plUInt64* pQWords, plUInt32 uiCount) { SwitchQWords(pQWords, uiCount); }
151
152#elif PL_ENABLED(PL_PLATFORM_BIG_ENDIAN)
153
154 static PL_ALWAYS_INLINE void LittleEndianToNative(plUInt16* pWords, plUInt32 uiCount)
155 {
156 SwitchWords(pWords, uiCount);
157 }
158
159 static PL_ALWAYS_INLINE void NativeToLittleEndian(plUInt16* pWords, plUInt32 uiCount) { SwitchWords(pWords, uiCount); }
160
161 static PL_ALWAYS_INLINE void LittleEndianToNative(plUInt32* pDWords, plUInt32 uiCount) { SwitchDWords(pDWords, uiCount); }
162
163 static PL_ALWAYS_INLINE void NativeToLittleEndian(plUInt32* pDWords, plUInt32 uiCount) { SwitchDWords(pDWords, uiCount); }
164
165 static PL_ALWAYS_INLINE void LittleEndianToNative(plUInt64* pQWords, plUInt32 uiCount) { SwitchQWords(pQWords, uiCount); }
166
167 static PL_ALWAYS_INLINE void NativeToLittleEndian(plUInt64* pQWords, plUInt32 uiCount) { SwitchQWords(pQWords, uiCount); }
168
169 static PL_ALWAYS_INLINE void BigEndianToNative(plUInt16* /*pWords*/, plUInt32 /*uiCount*/) {}
170
171 static PL_ALWAYS_INLINE void NativeToBigEndian(plUInt16* /*pWords*/, plUInt32 /*uiCount*/) {}
172
173 static PL_ALWAYS_INLINE void BigEndianToNative(plUInt32* /*pWords*/, plUInt32 /*uiCount*/) {}
174
175 static PL_ALWAYS_INLINE void NativeToBigEndian(plUInt32* /*pWords*/, plUInt32 /*uiCount*/) {}
176
177 static PL_ALWAYS_INLINE void BigEndianToNative(plUInt64* /*pWords*/, plUInt32 /*uiCount*/) {}
178
179 static PL_ALWAYS_INLINE void NativeToBigEndian(plUInt64* /*pWords*/, plUInt32 /*uiCount*/) {}
180
181#endif
182
183
191 static void SwitchStruct(void* pDataPointer, const char* szFormat);
192
194 template <typename T>
195 static void SwitchStruct(T* pDataPointer, const char* szFormat) // [tested]
196 {
197 SwitchStruct(static_cast<void*>(pDataPointer), szFormat);
198 }
199
207 static void SwitchStructs(void* pDataPointer, const char* szFormat, plUInt32 uiStride, plUInt32 uiCount); // [tested]
208
210 template <typename T>
211 static void SwitchStructs(T* pDataPointer, const char* szFormat, plUInt32 uiCount) // [tested]
212 {
213 SwitchStructs(static_cast<void*>(pDataPointer), szFormat, sizeof(T), uiCount);
214 }
215};
Collection of helper methods when working with endianess "problems".
Definition EndianHelper.h:7
static void SwitchDWords(plUInt32 *pDWords, plUInt32 uiCount)
Switches endianess of the given array of double words (32 bit values).
Definition EndianHelper.h:31
static PL_ALWAYS_INLINE plUInt16 Switch(plUInt16 uiWord)
Returns a single switched word (16 bit value).
Definition EndianHelper.h:45
static bool IsBigEndian()
Returns true if called on a big endian system, false otherwise.
Definition EndianHelper.h:12
static PL_ALWAYS_INLINE plUInt32 Switch(plUInt32 uiDWord)
Returns a single switched double word (32 bit value).
Definition EndianHelper.h:51
static void SwitchQWords(plUInt64 *pQWords, plUInt32 uiCount)
Switches endianess of the given array of quad words (64 bit values).
Definition EndianHelper.h:38
static void SwitchStructs(T *pDataPointer, const char *szFormat, plUInt32 uiCount)
Templated helper method for SwitchStructs.
Definition EndianHelper.h:211
static PL_ALWAYS_INLINE plUInt64 Switch(plUInt64 uiQWord)
Returns a single switched quad word (64 bit value).
Definition EndianHelper.h:57
static void SwitchInPlace(T *pValue)
Switches a value in place (template accepts pointers for 2, 4 & 8 byte data types)
Definition EndianHelper.h:66
static bool IsLittleEndian()
Returns true if called on a little endian system, false otherwise.
Definition EndianHelper.h:21
static void SwitchStruct(T *pDataPointer, const char *szFormat)
Templated helper method for SwitchStruct.
Definition EndianHelper.h:195
static void SwitchWords(plUInt16 *pWords, plUInt32 uiCount)
Switches endianess of the given array of words (16 bit values).
Definition EndianHelper.h:24