You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

os.h 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. //
  2. // Copyright(c) 2015 Gabi Melman.
  3. // Distributed under the MIT License (http://opensource.org/licenses/MIT)
  4. //
  5. #pragma once
  6. #include <spdlog/common.h>
  7. #include <cstdio>
  8. #include <ctime>
  9. #include <functional>
  10. #include <string>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <sys/stat.h>
  14. #ifdef _WIN32
  15. #ifndef NOMINMAX
  16. #define NOMINMAX //prevent windows redefining min/max
  17. #endif
  18. #ifndef WIN32_LEAN_AND_MEAN
  19. #define WIN32_LEAN_AND_MEAN
  20. #endif
  21. #include <windows.h>
  22. #ifdef __MINGW32__
  23. #include <share.h>
  24. #endif
  25. #include <sys/types.h>
  26. #include <io.h>
  27. #elif __linux__
  28. #include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
  29. #include <unistd.h>
  30. #include <chrono>
  31. #elif __FreeBSD__
  32. #include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id
  33. #else
  34. #include <thread>
  35. #endif
  36. namespace spdlog
  37. {
  38. namespace details
  39. {
  40. namespace os
  41. {
  42. inline spdlog::log_clock::time_point now()
  43. {
  44. #if defined __linux__ && defined SPDLOG_CLOCK_COARSE
  45. timespec ts;
  46. ::clock_gettime(CLOCK_REALTIME_COARSE, &ts);
  47. return std::chrono::time_point<log_clock, typename log_clock::duration>(
  48. std::chrono::duration_cast<typename log_clock::duration>(
  49. std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec)));
  50. #else
  51. return log_clock::now();
  52. #endif
  53. }
  54. inline std::tm localtime(const std::time_t &time_tt)
  55. {
  56. #ifdef _WIN32
  57. std::tm tm;
  58. localtime_s(&tm, &time_tt);
  59. #else
  60. std::tm tm;
  61. localtime_r(&time_tt, &tm);
  62. #endif
  63. return tm;
  64. }
  65. inline std::tm localtime()
  66. {
  67. std::time_t now_t = time(nullptr);
  68. return localtime(now_t);
  69. }
  70. inline std::tm gmtime(const std::time_t &time_tt)
  71. {
  72. #ifdef _WIN32
  73. std::tm tm;
  74. gmtime_s(&tm, &time_tt);
  75. #else
  76. std::tm tm;
  77. gmtime_r(&time_tt, &tm);
  78. #endif
  79. return tm;
  80. }
  81. inline std::tm gmtime()
  82. {
  83. std::time_t now_t = time(nullptr);
  84. return gmtime(now_t);
  85. }
  86. inline bool operator==(const std::tm& tm1, const std::tm& tm2)
  87. {
  88. return (tm1.tm_sec == tm2.tm_sec &&
  89. tm1.tm_min == tm2.tm_min &&
  90. tm1.tm_hour == tm2.tm_hour &&
  91. tm1.tm_mday == tm2.tm_mday &&
  92. tm1.tm_mon == tm2.tm_mon &&
  93. tm1.tm_year == tm2.tm_year &&
  94. tm1.tm_isdst == tm2.tm_isdst);
  95. }
  96. inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
  97. {
  98. return !(tm1 == tm2);
  99. }
  100. // eol definition
  101. #if !defined (SPDLOG_EOL)
  102. #ifdef _WIN32
  103. #define SPDLOG_EOL "\r\n"
  104. #else
  105. #define SPDLOG_EOL "\n"
  106. #endif
  107. #endif
  108. SPDLOG_CONSTEXPR static const char* eol = SPDLOG_EOL;
  109. SPDLOG_CONSTEXPR static int eol_size = sizeof(SPDLOG_EOL) - 1;
  110. //fopen_s on non windows for writing
  111. inline int fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode)
  112. {
  113. #ifdef _WIN32
  114. #ifdef SPDLOG_WCHAR_FILENAMES
  115. *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYWR);
  116. #else
  117. *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYWR);
  118. #endif
  119. return *fp == nullptr;
  120. #else
  121. *fp = fopen((filename.c_str()), mode.c_str());
  122. return *fp == nullptr;
  123. #endif
  124. }
  125. inline int remove(const filename_t &filename)
  126. {
  127. #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
  128. return _wremove(filename.c_str());
  129. #else
  130. return std::remove(filename.c_str());
  131. #endif
  132. }
  133. inline int rename(const filename_t& filename1, const filename_t& filename2)
  134. {
  135. #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
  136. return _wrename(filename1.c_str(), filename2.c_str());
  137. #else
  138. return std::rename(filename1.c_str(), filename2.c_str());
  139. #endif
  140. }
  141. //Return if file exists
  142. inline bool file_exists(const filename_t& filename)
  143. {
  144. #ifdef _WIN32
  145. #ifdef SPDLOG_WCHAR_FILENAMES
  146. auto attribs = GetFileAttributesW(filename.c_str());
  147. #else
  148. auto attribs = GetFileAttributesA(filename.c_str());
  149. #endif
  150. return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY));
  151. #else //common linux/unix all have the stat system call
  152. struct stat buffer;
  153. return (stat (filename.c_str(), &buffer) == 0);
  154. #endif
  155. }
  156. //Return file size according to open FILE* object
  157. inline size_t filesize(FILE *f)
  158. {
  159. if (f == nullptr)
  160. throw spdlog_ex("Failed getting file size. fd is null");
  161. #ifdef _WIN32
  162. int fd = _fileno(f);
  163. #if _WIN64 //64 bits
  164. struct _stat64 st;
  165. if (_fstat64(fd, &st) == 0)
  166. return st.st_size;
  167. #else //windows 32 bits
  168. long ret = _filelength(fd);
  169. if (ret >= 0)
  170. return static_cast<size_t>(ret);
  171. #endif
  172. #else // unix
  173. int fd = fileno(f);
  174. //64 bits(but not in osx, where fstat64 is deprecated)
  175. #if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__))
  176. struct stat64 st;
  177. if (fstat64(fd, &st) == 0)
  178. return st.st_size;
  179. #else // unix 32 bits or osx
  180. struct stat st;
  181. if (fstat(fd, &st) == 0)
  182. return st.st_size;
  183. #endif
  184. #endif
  185. throw spdlog_ex("Failed getting file size from fd", errno);
  186. }
  187. //Return utc offset in minutes or throw spdlog_ex on failure
  188. inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
  189. {
  190. #ifdef _WIN32
  191. #if _WIN32_WINNT < _WIN32_WINNT_WS08
  192. TIME_ZONE_INFORMATION tzinfo;
  193. auto rv = GetTimeZoneInformation(&tzinfo);
  194. #else
  195. DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
  196. auto rv = GetDynamicTimeZoneInformation(&tzinfo);
  197. #endif
  198. if (rv == TIME_ZONE_ID_INVALID)
  199. throw spdlog::spdlog_ex("Failed getting timezone info. ", errno);
  200. int offset = -tzinfo.Bias;
  201. if (tm.tm_isdst)
  202. offset -= tzinfo.DaylightBias;
  203. else
  204. offset -= tzinfo.StandardBias;
  205. return offset;
  206. #else
  207. #if defined(sun) || defined(__sun)
  208. // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
  209. struct helper
  210. {
  211. static long int calculate_gmt_offset(const std::tm & localtm = details::os::localtime(), const std::tm & gmtm = details::os::gmtime())
  212. {
  213. int local_year = localtm.tm_year + (1900 - 1);
  214. int gmt_year = gmtm.tm_year + (1900 - 1);
  215. long int days = (
  216. // difference in day of year
  217. localtm.tm_yday - gmtm.tm_yday
  218. // + intervening leap days
  219. + ((local_year >> 2) - (gmt_year >> 2))
  220. - (local_year / 100 - gmt_year / 100)
  221. + ((local_year / 100 >> 2) - (gmt_year / 100 >> 2))
  222. // + difference in years * 365 */
  223. + (long int)(local_year - gmt_year) * 365
  224. );
  225. long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour);
  226. long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min);
  227. long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec);
  228. return secs;
  229. }
  230. };
  231. long int offset_seconds = helper::calculate_gmt_offset(tm);
  232. #else
  233. long int offset_seconds = tm.tm_gmtoff;
  234. #endif
  235. return static_cast<int>(offset_seconds / 60);
  236. #endif
  237. }
  238. //Return current thread id as size_t
  239. //It exists because the std::this_thread::get_id() is much slower(espcially under VS 2013)
  240. inline size_t thread_id()
  241. {
  242. #ifdef _WIN32
  243. return static_cast<size_t>(::GetCurrentThreadId());
  244. #elif __linux__
  245. # if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
  246. # define SYS_gettid __NR_gettid
  247. # endif
  248. return static_cast<size_t>(syscall(SYS_gettid));
  249. #elif __FreeBSD__
  250. long tid;
  251. thr_self(&tid);
  252. return static_cast<size_t>(tid);
  253. #else //Default to standard C++11 (OSX and other Unix)
  254. return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id()));
  255. #endif
  256. }
  257. // wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
  258. #if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
  259. #define SPDLOG_FILENAME_T(s) L ## s
  260. inline std::string filename_to_str(const filename_t& filename)
  261. {
  262. std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c;
  263. return c.to_bytes(filename);
  264. }
  265. #else
  266. #define SPDLOG_FILENAME_T(s) s
  267. inline std::string filename_to_str(const filename_t& filename)
  268. {
  269. return filename;
  270. }
  271. #endif
  272. // Return errno string (thread safe)
  273. inline std::string errno_str(int err_num)
  274. {
  275. char buf[256];
  276. SPDLOG_CONSTEXPR auto buf_size = sizeof(buf);
  277. #ifdef _WIN32
  278. if(strerror_s(buf, buf_size, err_num) == 0)
  279. return std::string(buf);
  280. else
  281. return "Unkown error";
  282. #elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || \
  283. ((_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE) // posix version
  284. if (strerror_r(err_num, buf, buf_size) == 0)
  285. return std::string(buf);
  286. else
  287. return "Unkown error";
  288. #else // gnu version (might not use the given buf, so its retval pointer must be used)
  289. return std::string(strerror_r(err_num, buf, buf_size));
  290. #endif
  291. }
  292. } //os
  293. } //details
  294. } //spdlog