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