porting.h 8.5 KB

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