1// tPlatform.h 
2// 
3// Tacent platform defines, architecture, and endianness detection. The Tacent library has some preprocessor define 
4// requirements. One of PLATFORM_NNN, ARCHITECTURE_NNN, and CONFIG_NNN need to be defined. If you haven't bothered 
5// to define these in the project file with a /D switch, an attempt is made to define them automatically for you. 
6// 
7// Copyright (c) 2004-2006, 2015, 2017, 2020 Tristan Grimmer. 
8// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby 
9// granted, provided that the above copyright notice and this permission notice appear in all copies. 
10// 
11// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 
12// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
13// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
14// AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
15// PERFORMANCE OF THIS SOFTWARE. 
16 
17#pragma once 
18#include <stdio.h> 
19#include <stdlib.h> 
20// No Tacent headers here. tPlatform.h is where the buck stops. 
21 
22 
23// Attempt to auto-detect platform. 
24#if (!defined(PLATFORM_WINDOWS) && !defined(PLATFORM_LINUX) && !defined(PLATFORM_MACOS) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_IOS)) 
25 #if (defined(_M_AMD64) || defined(_M_IX86) || defined(_WIN32) || defined(_WIN64)) 
26 #define PLATFORM_WINDOWS 
27 #elif defined(__linux__) 
28 #define PLATFORM_LINUX 
29 #endif 
30#endif 
31 
32 
33// Attempt to auto-detect archetecture. 
34#if (!defined(ARCHITECTURE_X64) && !defined(ARCHITECTURE_X86) && !defined(ARCHITECTURE_ARM)) 
35 #if (defined(_M_AMD64) || defined(_WIN64) || defined(__x86_64__)) 
36 #define ARCHITECTURE_X64 // For x86_64 
37 #elif defined(__i386) 
38 #define ARCHITECTURE_X86 
39 #endif 
40#endif 
41 
42 
43// Debug and Release configurations are only autodetected on windows. 
44#if (!defined(CONFIG_DEBUG) && !defined(CONFIG_DEVELOP) && !defined(CONFIG_PROFILE) && !defined(CONFIG_RELEASE) && !defined(CONFIG_SHIP)) 
45 #if defined(_DEBUG) 
46 #define CONFIG_DEBUG 
47 #endif 
48 #if defined(NDEBUG) 
49 #define CONFIG_RELEASE 
50 #endif 
51#endif 
52 
53 
54// Turn off some annoying windows warnings. 
55#if (defined(PLATFORM_WINDOWS) && !defined(_CRT_SECURE_NO_DEPRECATE)) 
56 #define _CRT_SECURE_NO_DEPRECATE 
57#endif 
58 
59 
60// Sanity check. Required defines must be present. 
61#if (!defined(PLATFORM_WINDOWS) && !defined(PLATFORM_LINUX) && !defined(PLATFORM_MACOS) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_IOS)) 
62 #error You must define a supported platform. 
63#endif 
64#if (!defined(ARCHITECTURE_X64) && !defined(ARCHITECTURE_ARM)) 
65 #error You must define a supported architecture. 
66#endif 
67#if (!defined(CONFIG_DEBUG) && !defined(CONFIG_DEVELOP) && !defined(CONFIG_PROFILE) && !defined(CONFIG_RELEASE) && !defined(CONFIG_SHIP)) 
68 #error You must define a supported configuration. 
69#endif 
70 
71 
72// Define the endianness. 
73#if (defined(PLATFORM_WINDOWS) || defined(PLATFORM_LINUX) || defined(PLATFORM_MACOS) || defined(PLATFORM_ANDROID) || defined(PLATFORM_IOS)) 
74 #define ENDIAN_LITTLE 
75#else 
76 #define ENDIAN_BIG 
77#endif 
78 
79 
80#if defined(PLATFORM_WINDOWS) 
81 #include <xmmintrin.h> 
82#endif 
83 
84 
85// Many objects have a Pod member function that returns a plain-old-data version of itself. Useful for cases where POD 
86// is required, like to printf functions. 
87#define tPod(x) (x.Pod()) 
88#define tAlign16 __declspec(align(16)) 
89#define tIsAligned16(addr) ((uint64(addr) & 0xF) == 0) 
90 
91 
92typedef unsigned char uchar
93typedef signed char schar
94typedef unsigned int uint
95typedef unsigned short ushort
96typedef unsigned long ulong
97 
98 
99// Use the following integral types ONLY when you are relying on the specified number of bits. If you need more than 
100// 64 use a tBitField. 
101typedef signed char int8
102typedef unsigned char uint8
103typedef short int16
104typedef unsigned short uint16
105typedef int int32
106typedef unsigned int uint32
107typedef long long int int64
108typedef unsigned long long int uint64
109 
110 
111// Simple low-level file IO. 
112typedef FILE* tFileHandle
113 
114 
115enum class tPlatform 
116
117 Invalid = -1
118 First
119 Windows = First
120 Linux, // Linux. 
121 MacOS, // Apple's desktop OS. It's no longer called OSX. 
122 Android, // Google Android. 
123 iOS, // Apple iOS. 
124 All, // Not counted as a separate platform. 
125 NumPlatforms = All 
126}; 
127 
128// Platforms as bitfields. 
129enum tPlatformFlag 
130
131 tPlatformFlag_None
132 tPlatformFlag_Windows = 1 << int(tPlatform::Windows), 
133 tPlatformFlag_Linux = 1 << int(tPlatform::Linux), 
134 tPlatformFlag_MacOS = 1 << int(tPlatform::MacOS), 
135 tPlatformFlag_Android = 1 << int(tPlatform::Android), 
136 tPlatformFlag_iOS = 1 << int(tPlatform::iOS), 
137 tPlatformFlag_All = 0xFFFFFFFF 
138}; 
139 
140struct tString
141tPlatform tGetPlatform(); // Based on required platform defines. 
142tPlatform tGetPlatform(const tString&); 
143const char* tGetPlatformName(tPlatform); 
144const char* tGetPlatformNameLong(tPlatform); 
145 
146enum class tArchitecture 
147
148 Invalid = -1
149 x64, // Desktop (not Itanium) 64bit architecture. i.e. AMD64. 
150 A64, // Arm 64 bit. Also known as AArch64. 
151 NumArchitectures 
152}; 
153tArchitecture tGetArchitecture(); // Based on defines. 
154const char* tGetArchitectureName(tArchitecture); 
155const char* tGetArchitectureNameLong(tArchitecture); 
156 
157enum class tEndianness 
158
159 Invalid = -1
160 Big
161 Little 
162}; 
163 
164// If you want to know the endianness based on the platform define just test for ENDIAN_BIG or ENDIAN_LITTLE. 
165tEndianness tGetEndianness(tPlatform); // Returns the native endianness of the tPlatform. 
166tEndianness tGetEndianness(); // Performs a test on the current architecture. 
167 
168// These calls allow endianness swapping of variously sized types. 
169template<typename T> inline T tGetSwapEndian(const T&); 
170template<typename T> inline void tSwapEndian(T&); 
171template<typename T> inline void tSwapEndian(T*, int numItems); 
172 
173// Converts to and from external data representation (XDR/Network) which is big-endian. Does not rely on the 
174// PLATFORM define by performing an endianness test. 
175template<typename T> inline T tNtoH(T val); 
176template<typename T> inline T tHtoN(T val); 
177 
178 
179// Implementation below this line. 
180 
181 
182template<typename T> inline T tGetSwapEndian(const T& val
183
184 union endianAccessor 
185
186 T Data
187 uint8 Bytes[sizeof(T)]; 
188 }; 
189 endianAccessor& src = (endianAccessor&)val
190 endianAccessor dst
191 for (int d = 0; d < int(sizeof(T)); d++) 
192 dst.Bytes[d] = src.Bytes[sizeof(T) - d - 1]; 
193 
194 return dst.Data; 
195
196 
197 
198template<typename T> inline void tSwapEndian(T& val
199
200 union endianAccessor 
201
202 T Data
203 uint8 Bytes[sizeof(T)]; 
204 }; 
205 endianAccessor& srcDst = (endianAccessor&)val
206 int numBytes = sizeof(T); 
207 for (int s = 0; s < (numBytes >> 1); s++) 
208
209 uint8& a = srcDst.Bytes[s]; 
210 uint8& b = srcDst.Bytes[numBytes - 1 - s]; 
211 uint8 t = a
212 a = b
213 b = t
214
215
216 
217 
218template<typename T> inline void tSwapEndian(T* a, int numItems
219
220 for (int i = 0; i < numItems; i++) 
221 tSwapEndian(a[i]); 
222
223 
224 
225inline tEndianness tGetEndianness() 
226
227 union 
228
229 uint8 c[2]; 
230 uint16 u
231 } a
232 
233 a.c[1] = 0
234 a.c[0] = 1
235 
236 if (a.u == 1
237 return tEndianness::Little
238 
239 return tEndianness::Big
240
241 
242 
243template<typename T> inline T tNtoH(T val
244
245 if (tGetEndianness() == tEndianness::Big
246 return val
247 
248 return tGetSwapEndian(val); 
249
250 
251 
252template<typename T> inline T tHtoN(T val
253
254 return NtoH(val); 
255
256 
257 
258// These defines mitigate Windows all-capital naming ugliness. 
259#ifdef PLATFORM_WINDOWS 
260#define ApiEntry APIENTRY 
261#define WinBitmap BITMAP 
262#define WinBitmapInfo BITMAPINFO 
263#define WinBitmapInfoHeader BITMAPINFOHEADER 
264#define ColorRef COLORREF 
265#define CreateStruct CREATESTRUCT 
266#define dWord DWORD 
267#define False FALSE 
268#define FileTime FILETIME 
269#define GlyphMetrics GLYPHMETRICS 
270#define hBitmap HBITMAP 
271#define hDc HDC 
272#define hFont HFONT 
273#define hGlrc HGLRC 
274#define hPBufferARB HPBUFFERARB 
275#define HiWord HIWORD 
276#define hResult HRESULT 
277#define hWinIcon HICON 
278#define hWinCursor HCURSOR 
279#define WindowHandle HWND 
280#define IconInfo ICONINFO 
281#define Infinite INFINITE 
282#define ItemIdList ITEMIDLIST 
283#define LargeInteger LARGE_INTEGER 
284#define Long LONG 
285#define LongPtr LONG_PTR 
286#define LoWord LOWORD 
287#define WinLParam LPARAM 
288#define lpCItemIdList LPCITEMIDLIST 
289#define lpCRect LPCRECT 
290#define lpEnumIdList LPENUMIDLIST 
291#define lpItemIdList LPITEMIDLIST 
292#define lpMalloc LPMALLOC 
293#define lpShellFolder LPSHELLFOLDER 
294#define lpVoid LPVOID 
295#define lResult LRESULT 
296#define MakeWord MAKEWORD 
297#define MaxPath MAX_PATH 
298#define Nmhdr NMHDR 
299#define OleChar OLECHAR 
300#define PixelFormatDescriptor PIXELFORMATDESCRIPTOR 
301#define Point POINT 
302#ifndef MAX_PLUGIN 
303#define Rect RECT 
304#endif 
305#define ShellFolder SHELLFOLDER 
306#define ShFileInfo SHFILEINFO 
307#define SystemTime SYSTEMTIME 
308#define WinSize SIZE 
309#define True TRUE 
310#define tStr TSTR 
311#define tChar TCHAR 
312#define WaitFailed WAIT_FAILED 
313#define WaitObject0 WAIT_OBJECT_0 
314#define WaitTimeout WAIT_TIMEOUT 
315#define Win32FindData WIN32_FIND_DATA 
316#define WinApi WINAPI 
317#define WinBool BOOL 
318#define WinHandle HANDLE 
319#define WinInstance HINSTANCE 
320#define WinIntPtr INT_PTR 
321#define WinMessage MSG 
322#define WinProc PROC 
323#define WinSocket SOCKET 
324#define WinWord WORD 
325#define WinCallback CALLBACK 
326#define WinWParam WPARAM 
327#define WsaData WSADATA 
328#define WinUUID __uuidof 
329#define CriticalSection CRITICAL_SECTION 
330#define snprintf _snprintf 
331inline bool WinSucceeded(long hresult) { return (hresult >= 0) ? true : false; } 
332inline bool WinFailed(long hresult) { return (hresult < 0) ? true : false; } 
333#endif 
334