1 #pragma once 2 #include <cassert> 3 #include <cstring> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <sstream> 7 #include <fcntl.h> 8 #include <sys/stat.h> 9 10 #ifndef PLOG_ENABLE_WCHAR_INPUT 11 # ifdef _WIN32 12 # define PLOG_ENABLE_WCHAR_INPUT 1 13 # else 14 # define PLOG_ENABLE_WCHAR_INPUT 0 15 # endif 16 #endif 17 18 #ifdef _WIN32 19 # include <plog/WinApi.h> 20 # include <time.h> 21 # include <sys/timeb.h> 22 # include <io.h> 23 # include <share.h> 24 #elif defined(__rtems__) 25 # include <unistd.h> 26 # include <rtems.h> 27 # if PLOG_ENABLE_WCHAR_INPUT 28 # include <iconv.h> 29 # endif 30 #else 31 # include <unistd.h> 32 # include <sys/syscall.h> 33 # include <sys/time.h> 34 # include <pthread.h> 35 # if PLOG_ENABLE_WCHAR_INPUT 36 # include <iconv.h> 37 # endif 38 #endif 39 40 #ifdef _WIN32 41 # define _PLOG_NSTR(x) L##x 42 # define PLOG_NSTR(x) _PLOG_NSTR(x) 43 #else 44 # define PLOG_NSTR(x) x 45 #endif 46 47 namespace plog 48 { 49 namespace util 50 { 51 #ifdef _WIN32 52 typedef std::wstring nstring; 53 typedef std::wostringstream nostringstream; 54 typedef std::wistringstream nistringstream; 55 typedef wchar_t nchar; 56 #else 57 typedef std::string nstring; 58 typedef std::ostringstream nostringstream; 59 typedef std::istringstream nistringstream; 60 typedef char nchar; 61 #endif 62 localtime_s(struct tm * t,const time_t * time)63 inline void localtime_s(struct tm* t, const time_t* time) 64 { 65 #if defined(_WIN32) && defined(__BORLANDC__) 66 ::localtime_s(time, t); 67 #elif defined(_WIN32) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) 68 *t = *::localtime(time); 69 #elif defined(_WIN32) 70 ::localtime_s(t, time); 71 #else 72 ::localtime_r(time, t); 73 #endif 74 } 75 gmtime_s(struct tm * t,const time_t * time)76 inline void gmtime_s(struct tm* t, const time_t* time) 77 { 78 #if defined(_WIN32) && defined(__BORLANDC__) 79 ::gmtime_s(time, t); 80 #elif defined(_WIN32) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) 81 *t = *::gmtime(time); 82 #elif defined(_WIN32) 83 ::gmtime_s(t, time); 84 #else 85 ::gmtime_r(time, t); 86 #endif 87 } 88 89 #ifdef _WIN32 90 typedef timeb Time; 91 ftime(Time * t)92 inline void ftime(Time* t) 93 { 94 ::ftime(t); 95 } 96 #else 97 struct Time 98 { 99 time_t time; 100 unsigned short millitm; 101 }; 102 ftime(Time * t)103 inline void ftime(Time* t) 104 { 105 timeval tv; 106 ::gettimeofday(&tv, NULL); 107 108 t->time = tv.tv_sec; 109 t->millitm = static_cast<unsigned short>(tv.tv_usec / 1000); 110 } 111 #endif 112 gettid()113 inline unsigned int gettid() 114 { 115 #ifdef _WIN32 116 return GetCurrentThreadId(); 117 #elif defined(__linux__) 118 return static_cast<unsigned int>(::syscall(__NR_gettid)); 119 #elif defined(__FreeBSD__) 120 long tid; 121 syscall(SYS_thr_self, &tid); 122 return static_cast<unsigned int>(tid); 123 #elif defined(__rtems__) 124 return rtems_task_self(); 125 #elif defined(__APPLE__) 126 uint64_t tid64; 127 pthread_threadid_np(NULL, &tid64); 128 return static_cast<unsigned int>(tid64); 129 #endif 130 } 131 132 #ifdef _WIN32 vasprintf(char ** strp,const char * format,va_list ap)133 inline int vasprintf(char** strp, const char* format, va_list ap) 134 { 135 int len = _vscprintf(format, ap); 136 if (len < 0) 137 { 138 return -1; 139 } 140 141 char* str = static_cast<char*>(malloc(len + 1)); 142 if (!str) 143 { 144 return -1; 145 } 146 147 #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) 148 int retval = _vsnprintf(str, len + 1, format, ap); 149 #else 150 int retval = _vsnprintf_s(str, len + 1, len, format, ap); 151 #endif 152 if (retval < 0) 153 { 154 free(str); 155 return -1; 156 } 157 158 *strp = str; 159 return retval; 160 } 161 vaswprintf(wchar_t ** strp,const wchar_t * format,va_list ap)162 inline int vaswprintf(wchar_t** strp, const wchar_t* format, va_list ap) 163 { 164 int len = _vscwprintf(format, ap); 165 if (len < 0) 166 { 167 return -1; 168 } 169 170 wchar_t* str = static_cast<wchar_t*>(malloc((len + 1) * sizeof(wchar_t))); 171 if (!str) 172 { 173 return -1; 174 } 175 176 #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) 177 int retval = _vsnwprintf(str, len + 1, format, ap); 178 #else 179 int retval = _vsnwprintf_s(str, len + 1, len, format, ap); 180 #endif 181 if (retval < 0) 182 { 183 free(str); 184 return -1; 185 } 186 187 *strp = str; 188 return retval; 189 } 190 #endif 191 192 #if PLOG_ENABLE_WCHAR_INPUT && !defined(_WIN32) toNarrow(const wchar_t * wstr)193 inline std::string toNarrow(const wchar_t* wstr) 194 { 195 size_t wlen = ::wcslen(wstr); 196 std::string str(wlen * sizeof(wchar_t), 0); 197 198 if (!str.empty()) 199 { 200 const char* in = reinterpret_cast<const char*>(&wstr[0]); 201 char* out = &str[0]; 202 size_t inBytes = wlen * sizeof(wchar_t); 203 size_t outBytes = str.size(); 204 205 iconv_t cd = ::iconv_open("UTF-8", "WCHAR_T"); 206 ::iconv(cd, const_cast<char**>(&in), &inBytes, &out, &outBytes); 207 ::iconv_close(cd); 208 209 str.resize(str.size() - outBytes); 210 } 211 212 return str; 213 } 214 #endif 215 216 #ifdef _WIN32 toWide(const char * str)217 inline std::wstring toWide(const char* str) 218 { 219 size_t len = ::strlen(str); 220 std::wstring wstr(len, 0); 221 222 if (!wstr.empty()) 223 { 224 int wlen = MultiByteToWideChar(codePage::kActive, 0, str, static_cast<int>(len), &wstr[0], static_cast<int>(wstr.size())); 225 wstr.resize(wlen); 226 } 227 228 return wstr; 229 } 230 toNarrow(const std::wstring & wstr,long page)231 inline std::string toNarrow(const std::wstring& wstr, long page) 232 { 233 std::string str(wstr.size() * sizeof(wchar_t), 0); 234 235 if (!str.empty()) 236 { 237 int len = WideCharToMultiByte(page, 0, wstr.c_str(), static_cast<int>(wstr.size()), &str[0], static_cast<int>(str.size()), 0, 0); 238 str.resize(len); 239 } 240 241 return str; 242 } 243 #endif 244 processFuncName(const char * func)245 inline std::string processFuncName(const char* func) 246 { 247 #if (defined(_WIN32) && !defined(__MINGW32__)) || defined(__OBJC__) 248 return std::string(func); 249 #else 250 const char* funcBegin = func; 251 const char* funcEnd = ::strchr(funcBegin, '('); 252 253 if (!funcEnd) 254 { 255 return std::string(func); 256 } 257 258 for (const char* i = funcEnd - 1; i >= funcBegin; --i) // search backwards for the first space char 259 { 260 if (*i == ' ') 261 { 262 funcBegin = i + 1; 263 break; 264 } 265 } 266 267 return std::string(funcBegin, funcEnd); 268 #endif 269 } 270 findExtensionDot(const nchar * fileName)271 inline const nchar* findExtensionDot(const nchar* fileName) 272 { 273 #ifdef _WIN32 274 return std::wcsrchr(fileName, L'.'); 275 #else 276 return std::strrchr(fileName, '.'); 277 #endif 278 } 279 splitFileName(const nchar * fileName,nstring & fileNameNoExt,nstring & fileExt)280 inline void splitFileName(const nchar* fileName, nstring& fileNameNoExt, nstring& fileExt) 281 { 282 const nchar* dot = findExtensionDot(fileName); 283 284 if (dot) 285 { 286 fileNameNoExt.assign(fileName, dot); 287 fileExt.assign(dot + 1); 288 } 289 else 290 { 291 fileNameNoExt.assign(fileName); 292 fileExt.clear(); 293 } 294 } 295 296 class NonCopyable 297 { 298 protected: NonCopyable()299 NonCopyable() 300 { 301 } 302 303 private: 304 NonCopyable(const NonCopyable&); 305 NonCopyable& operator=(const NonCopyable&); 306 }; 307 308 class File : NonCopyable 309 { 310 public: File()311 File() : m_file(-1) 312 { 313 } 314 File(const nchar * fileName)315 File(const nchar* fileName) : m_file(-1) 316 { 317 open(fileName); 318 } 319 ~File()320 ~File() 321 { 322 close(); 323 } 324 open(const nchar * fileName)325 off_t open(const nchar* fileName) 326 { 327 #if defined(_WIN32) && (defined(__BORLANDC__) || defined(__MINGW32__)) 328 m_file = ::_wsopen(fileName, _O_CREAT | _O_WRONLY | _O_BINARY, SH_DENYWR, _S_IREAD | _S_IWRITE); 329 #elif defined(_WIN32) 330 ::_wsopen_s(&m_file, fileName, _O_CREAT | _O_WRONLY | _O_BINARY, _SH_DENYWR, _S_IREAD | _S_IWRITE); 331 #else 332 m_file = ::open(fileName, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 333 #endif 334 return seek(0, SEEK_END); 335 } 336 write(const void * buf,size_t count)337 int write(const void* buf, size_t count) 338 { 339 #ifdef _WIN32 340 return m_file != -1 ? ::_write(m_file, buf, static_cast<unsigned int>(count)) : -1; 341 #else 342 return m_file != -1 ? static_cast<int>(::write(m_file, buf, count)) : -1; 343 #endif 344 } 345 346 template<class CharType> write(const std::basic_string<CharType> & str)347 int write(const std::basic_string<CharType>& str) 348 { 349 return write(str.data(), str.size() * sizeof(CharType)); 350 } 351 seek(off_t offset,int whence)352 off_t seek(off_t offset, int whence) 353 { 354 #ifdef _WIN32 355 return m_file != -1 ? ::_lseek(m_file, offset, whence) : -1; 356 #else 357 return m_file != -1 ? ::lseek(m_file, offset, whence) : -1; 358 #endif 359 } 360 close()361 void close() 362 { 363 if (m_file != -1) 364 { 365 #ifdef _WIN32 366 ::_close(m_file); 367 #else 368 ::close(m_file); 369 #endif 370 m_file = -1; 371 } 372 } 373 unlink(const nchar * fileName)374 static int unlink(const nchar* fileName) 375 { 376 #ifdef _WIN32 377 return ::_wunlink(fileName); 378 #else 379 return ::unlink(fileName); 380 #endif 381 } 382 rename(const nchar * oldFilename,const nchar * newFilename)383 static int rename(const nchar* oldFilename, const nchar* newFilename) 384 { 385 #ifdef _WIN32 386 return MoveFileW(oldFilename, newFilename); 387 #else 388 return ::rename(oldFilename, newFilename); 389 #endif 390 } 391 392 private: 393 int m_file; 394 }; 395 396 class Mutex : NonCopyable 397 { 398 public: Mutex()399 Mutex() 400 { 401 #ifdef _WIN32 402 InitializeCriticalSection(&m_sync); 403 #elif defined(__rtems__) 404 rtems_semaphore_create(0, 1, 405 RTEMS_PRIORITY | 406 RTEMS_BINARY_SEMAPHORE | 407 RTEMS_INHERIT_PRIORITY, 1, &m_sync); 408 #else 409 ::pthread_mutex_init(&m_sync, 0); 410 #endif 411 } 412 ~Mutex()413 ~Mutex() 414 { 415 #ifdef _WIN32 416 DeleteCriticalSection(&m_sync); 417 #elif defined(__rtems__) 418 rtems_semaphore_delete(m_sync); 419 #else 420 ::pthread_mutex_destroy(&m_sync); 421 #endif 422 } 423 424 friend class MutexLock; 425 426 private: lock()427 void lock() 428 { 429 #ifdef _WIN32 430 EnterCriticalSection(&m_sync); 431 #elif defined(__rtems__) 432 rtems_semaphore_obtain(m_sync, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 433 #else 434 ::pthread_mutex_lock(&m_sync); 435 #endif 436 } 437 unlock()438 void unlock() 439 { 440 #ifdef _WIN32 441 LeaveCriticalSection(&m_sync); 442 #elif defined(__rtems__) 443 rtems_semaphore_release(m_sync); 444 #else 445 ::pthread_mutex_unlock(&m_sync); 446 #endif 447 } 448 449 private: 450 #ifdef _WIN32 451 CRITICAL_SECTION m_sync; 452 #else 453 pthread_mutex_t m_sync; 454 #endif 455 }; 456 457 class MutexLock : NonCopyable 458 { 459 public: MutexLock(Mutex & mutex)460 MutexLock(Mutex& mutex) : m_mutex(mutex) 461 { 462 m_mutex.lock(); 463 } 464 ~MutexLock()465 ~MutexLock() 466 { 467 m_mutex.unlock(); 468 } 469 470 private: 471 Mutex& m_mutex; 472 }; 473 474 template<class T> 475 class Singleton : NonCopyable 476 { 477 public: Singleton()478 Singleton() 479 { 480 assert(!m_instance); 481 m_instance = static_cast<T*>(this); 482 } 483 ~Singleton()484 ~Singleton() 485 { 486 assert(m_instance); 487 m_instance = 0; 488 } 489 getInstance()490 static T* getInstance() 491 { 492 return m_instance; 493 } 494 495 private: 496 static T* m_instance; 497 }; 498 499 template<class T> 500 T* Singleton<T>::m_instance = NULL; 501 } 502 } 503