]> git.lizzy.rs Git - dragonfireclient.git/blob - src/porting.h
Merge branch 'master' into master
[dragonfireclient.git] / src / porting.h
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 /*
21         Random portability stuff
22 */
23
24 #pragma once
25
26 #ifdef _WIN32
27 #ifdef _WIN32_WINNT
28 #undef _WIN32_WINNT
29 #endif
30 #define _WIN32_WINNT 0x0501 // We need to do this before any other headers
31 // because those might include sdkddkver.h which defines _WIN32_WINNT if not already set
32 #endif
33
34 #include <string>
35 #include <vector>
36 #include "irrlicht.h"
37 #include "irrlichttypes.h" // u32
38 #include "irrlichttypes_extrabloated.h"
39 #include "debug.h"
40 #include "constants.h"
41 #include "gettime.h"
42
43 #ifdef _MSC_VER
44 #define SWPRINTF_CHARSTRING L"%S"
45 #else
46 #define SWPRINTF_CHARSTRING L"%s"
47 #endif
48
49 // currently not needed
50 // template<typename T> struct alignment_trick { char c; T member; };
51 //#define ALIGNOF(type) offsetof (alignment_trick<type>, member)
52
53 #ifdef _WIN32
54 #include <windows.h>
55
56 #define sleep_ms(x) Sleep(x)
57 #else
58 #include <unistd.h>
59 #include <cstdint> //for uintptr_t
60
61 // Use standard Posix macro for Linux
62 #if (defined(linux) || defined(__linux)) && !defined(__linux__)
63 #define __linux__
64 #endif
65 #if (defined(__linux__) || defined(__GNU__)) && !defined(_GNU_SOURCE)
66 #define _GNU_SOURCE
67 #endif
68
69 #define sleep_ms(x) usleep(x * 1000)
70 #endif
71
72 #ifdef _MSC_VER
73 #define ALIGNOF(x) __alignof(x)
74 #define strtok_r(x, y, z) strtok_s(x, y, z)
75 #define strtof(x, y) (float)strtod(x, y)
76 #define strtoll(x, y, z) _strtoi64(x, y, z)
77 #define strtoull(x, y, z) _strtoui64(x, y, z)
78 #define strcasecmp(x, y) stricmp(x, y)
79 #define strncasecmp(x, y, n) strnicmp(x, y, n)
80 #else
81 #define ALIGNOF(x) __alignof__(x)
82 #endif
83
84 #ifdef __MINGW32__
85 #define strtok_r(x, y, z) mystrtok_r(x, y, z)
86 #endif
87
88 // strlcpy is missing from glibc.  thanks a lot, drepper.
89 // strlcpy is also missing from AIX and HP-UX because they aim to be weird.
90 // We can't simply alias strlcpy to MSVC's strcpy_s, since strcpy_s by
91 // default raises an assertion error and aborts the program if the buffer is
92 // too small.
93 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ||               \
94                 defined(__DragonFly__) || defined(__APPLE__) || defined(__sun) ||        \
95                 defined(sun) || defined(__QNX__) || defined(__QNXNTO__)
96 #define HAVE_STRLCPY
97 #endif
98
99 // So we need to define our own.
100 #ifndef HAVE_STRLCPY
101 #define strlcpy(d, s, n) mystrlcpy(d, s, n)
102 #endif
103
104 #define PADDING(x, y)                                                                    \
105         ((ALIGNOF(y) - ((uintptr_t)(x) & (ALIGNOF(y) - 1))) & (ALIGNOF(y) - 1))
106
107 #if defined(__APPLE__)
108 #include <mach-o/dyld.h>
109 #include <CoreFoundation/CoreFoundation.h>
110 #endif
111
112 #ifndef _WIN32 // Posix
113 #include <sys/time.h>
114 #include <ctime>
115
116 #if defined(__MACH__) && defined(__APPLE__)
117 #include <mach/clock.h>
118 #include <mach/mach.h>
119 #endif
120 #endif
121
122 namespace porting
123 {
124
125 /*
126         Signal handler (grabs Ctrl-C on POSIX systems)
127 */
128
129 void signal_handler_init();
130 // Returns a pointer to a bool.
131 // When the bool is true, program should quit.
132 bool *signal_handler_killstatus();
133
134 /*
135         Path of static data directory.
136 */
137 extern std::string path_share;
138
139 /*
140         Directory for storing user data. Examples:
141         Windows: "C:\Documents and Settings\user\Application Data\<PROJECT_NAME>"
142         Linux: "~/.<PROJECT_NAME>"
143         Mac: "~/Library/Application Support/<PROJECT_NAME>"
144 */
145 extern std::string path_user;
146
147 /*
148         Path to gettext locale files
149 */
150 extern std::string path_locale;
151
152 /*
153         Path to directory for storing caches.
154 */
155 extern std::string path_cache;
156
157 /*
158         Get full path of stuff in data directory.
159         Example: "stone.png" -> "../data/stone.png"
160 */
161 std::string getDataPath(const char *subpath);
162
163 /*
164         Move cache folder from path_user to the
165         system cache location if possible.
166 */
167 void migrateCachePath();
168
169 /*
170         Initialize path_*.
171 */
172 void initializePaths();
173
174 /*
175         Return system information
176         e.g. "Linux/3.12.7 x86_64"
177 */
178 std::string get_sysinfo();
179
180 // Monotonic counter getters.
181
182 #ifdef _WIN32 // Windows
183
184 extern double perf_freq;
185
186 inline u64 os_get_time(double mult)
187 {
188         LARGE_INTEGER t;
189         QueryPerformanceCounter(&t);
190         return static_cast<double>(t.QuadPart) / (perf_freq / mult);
191 }
192
193 // Resolution is <1us.
194 inline u64 getTimeS()
195 {
196         return os_get_time(1);
197 }
198 inline u64 getTimeMs()
199 {
200         return os_get_time(1000);
201 }
202 inline u64 getTimeUs()
203 {
204         return os_get_time(1000 * 1000);
205 }
206 inline u64 getTimeNs()
207 {
208         return os_get_time(1000 * 1000 * 1000);
209 }
210
211 #else // Posix
212
213 inline void os_get_clock(struct timespec *ts)
214 {
215 #if defined(__MACH__) && defined(__APPLE__)
216         // From
217         // http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
218         // OS X does not have clock_gettime, use clock_get_time
219         clock_serv_t cclock;
220         mach_timespec_t mts;
221         host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
222         clock_get_time(cclock, &mts);
223         mach_port_deallocate(mach_task_self(), cclock);
224         ts->tv_sec = mts.tv_sec;
225         ts->tv_nsec = mts.tv_nsec;
226 #elif defined(CLOCK_MONOTONIC_RAW)
227         clock_gettime(CLOCK_MONOTONIC_RAW, ts);
228 #elif defined(_POSIX_MONOTONIC_CLOCK)
229         clock_gettime(CLOCK_MONOTONIC, ts);
230 #else
231         struct timeval tv;
232         gettimeofday(&tv, NULL);
233         TIMEVAL_TO_TIMESPEC(&tv, ts);
234 #endif
235 }
236
237 inline u64 getTimeS()
238 {
239         struct timespec ts;
240         os_get_clock(&ts);
241         return ts.tv_sec;
242 }
243
244 inline u64 getTimeMs()
245 {
246         struct timespec ts;
247         os_get_clock(&ts);
248         return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
249 }
250
251 inline u64 getTimeUs()
252 {
253         struct timespec ts;
254         os_get_clock(&ts);
255         return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
256 }
257
258 inline u64 getTimeNs()
259 {
260         struct timespec ts;
261         os_get_clock(&ts);
262         return ts.tv_sec * 1000000000 + ts.tv_nsec;
263 }
264
265 #endif
266
267 inline u64 getTime(TimePrecision prec)
268 {
269         switch (prec) {
270         case PRECISION_SECONDS:
271                 return getTimeS();
272         case PRECISION_MILLI:
273                 return getTimeMs();
274         case PRECISION_MICRO:
275                 return getTimeUs();
276         case PRECISION_NANO:
277                 return getTimeNs();
278         }
279         FATAL_ERROR("Called getTime with invalid time precision");
280 }
281
282 /**
283  * Delta calculation function arguments.
284  * @param old_time_ms old time for delta calculation
285  * @param new_time_ms new time for delta calculation
286  * @return positive delta value
287  */
288 inline u64 getDeltaMs(u64 old_time_ms, u64 new_time_ms)
289 {
290         if (new_time_ms >= old_time_ms) {
291                 return (new_time_ms - old_time_ms);
292         }
293
294         return (old_time_ms - new_time_ms);
295 }
296
297 inline const char *getPlatformName()
298 {
299         return
300 #if defined(ANDROID)
301                         "Android"
302 #elif defined(__linux__)
303                         "Linux"
304 #elif defined(_WIN32) || defined(_WIN64)
305                         "Windows"
306 #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) ||           \
307                 defined(__OpenBSD__)
308                         "BSD"
309 #elif defined(__APPLE__) && defined(__MACH__)
310 #if TARGET_OS_MAC
311                         "OSX"
312 #elif TARGET_OS_IPHONE
313                         "iOS"
314 #else
315                         "Apple"
316 #endif
317 #elif defined(_AIX)
318                         "AIX"
319 #elif defined(__hpux)
320                         "HP-UX"
321 #elif defined(__sun) || defined(sun)
322 #if defined(__SVR4)
323                         "Solaris"
324 #else
325                         "SunOS"
326 #endif
327 #elif defined(__CYGWIN__)
328                         "Cygwin"
329 #elif defined(__unix__) || defined(__unix)
330 #if defined(_POSIX_VERSION)
331                         "Posix"
332 #else
333                         "Unix"
334 #endif
335 #else
336                         "?"
337 #endif
338                         ;
339 }
340
341 bool secure_rand_fill_buf(void *buf, size_t len);
342
343 // This attaches to the parents process console, or creates a new one if it doesnt exist.
344 void attachOrCreateConsole();
345
346 int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...);
347
348 bool openURL(const std::string &url);
349
350 } // namespace porting
351
352 #ifdef __ANDROID__
353 #include "porting_android.h"
354 #endif