FuncHelper.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Author : Bruce Liang
  5. * Website : https://github.com/ldcsaa
  6. * Project : https://github.com/ldcsaa/HP-Socket
  7. * Blog : http://www.cnblogs.com/ldcsaa
  8. * Wiki : http://www.oschina.net/p/hp-socket
  9. * QQ Group : 44636872, 75375912
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. */
  23. #pragma once
  24. #include "hpsocket/GlobalDef.h"
  25. #include "hpsocket/GlobalErrno.h"
  26. #include "SysHelper.h"
  27. #include <stdlib.h>
  28. #include <sysexits.h>
  29. #include <stdio.h>
  30. #include <wchar.h>
  31. #include <time.h>
  32. #include <errno.h>
  33. #include <fcntl.h>
  34. #include <malloc.h>
  35. #include <alloca.h>
  36. #include <assert.h>
  37. #include <string.h>
  38. #include <unistd.h>
  39. #include <sys/time.h>
  40. #include <atomic>
  41. #include <utility>
  42. using namespace std;
  43. #if !defined(__ANDROID__)
  44. typedef atomic_ulong atomic_tid;
  45. #define FPRINTLN(fd, fmt, ...) fprintf((fd), fmt "\n", ##__VA_ARGS__)
  46. #else
  47. typedef atomic_long atomic_tid;
  48. #if defined(stdout)
  49. #undef stdout
  50. #endif
  51. #if defined(stderr)
  52. #undef stderr
  53. #endif
  54. #define stdout nullptr
  55. #define stderr nullptr
  56. #define FPRINTLN(fd, fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
  57. #endif
  58. #define PRINTLN(fmt, ...) FPRINTLN(stdout, fmt, ##__VA_ARGS__)
  59. #if defined(DEBUG) && defined(DEBUG_TRACE)
  60. #define TRACE(fmt, ...) PRINTLN("> TRC (0x%zX, %d) " fmt, (SIZE_T)SELF_THREAD_ID, SELF_NATIVE_THREAD_ID, ##__VA_ARGS__)
  61. #define ASSERT(expr) ((expr) ? TRUE : (::PrintStackTrace(), assert(FALSE), FALSE))
  62. #else
  63. #define TRACE(fmt, ...)
  64. #define ASSERT(expr) assert(expr)
  65. #endif
  66. #define VERIFY(expr) ((expr) ? TRUE : (::PrintStackTrace(), ERROR_ABORT2(ERROR_VERIFY_CHECK), FALSE))
  67. #define ASSERT_IS_NO_ERROR(expr) ASSERT(IS_NO_ERROR(expr))
  68. #define VERIFY_IS_NO_ERROR(expr) VERIFY(IS_NO_ERROR(expr))
  69. #define ENSURE(expr) VERIFY(expr)
  70. #define ENSURE_IS_NO_ERROR(expr) VERIFY_IS_NO_ERROR(expr)
  71. #define TEMP_FAILURE_RETRY_INT(exp) ((int)TEMP_FAILURE_RETRY(exp))
  72. #define NO_EINTR TEMP_FAILURE_RETRY
  73. #define NO_EINTR_INT TEMP_FAILURE_RETRY_INT
  74. #define CHECK_IS_OK(expr) {if(IS_NOT_OK(expr)) return FALSE;}
  75. #define CHECK_ERROR_FD(fd) {if(IS_INVALID_FD(fd)) return FALSE;}
  76. #define CHECK_ERROR_INVOKE(expr) {if(!IS_NO_ERROR(expr)) return FALSE;}
  77. #define CHECK_ERROR_CODE(rs) {if(!IS_NO_ERROR(rs)) {::SetLastError(rs); return FALSE;}}
  78. #define CHECK_ERROR(expr, code) {if(!(expr)) {::SetLastError(code); return FALSE;}}
  79. #define CHECK_EINVAL(expr) CHECK_ERROR(expr, ERROR_INVALID_PARAMETER)
  80. #define ASSERT_CHECK_ERROR(expr, code) {ASSERT(expr); CHECK_ERROR(expr, code);}
  81. #define ASSERT_CHECK_EINVAL(expr) {ASSERT(expr); CHECK_EINVAL(expr);}
  82. #define SUCCEEDED(rs) IS_NO_ERROR(rs)
  83. #define FAILED(rs) (!SUCCEEDED(rs))
  84. #define IS_OK(rs) ((BOOL)(rs))
  85. #define IS_NOT_OK(rs) (!IS_OK(rs))
  86. #define IS_ERROR(code) (::GetLastError() == (code))
  87. #define CONTINUE_IF_ERROR(code) {if(IS_ERROR(code)) continue;}
  88. #define BREAK_IF_ERROR(code) {if(IS_ERROR(code)) break;}
  89. #define IS_WOULDBLOCK_ERROR() IS_ERROR(ERROR_WOULDBLOCK)
  90. #define CONTINUE_WOULDBLOCK_ERROR() CONTINUE_IF_ERROR(ERROR_WOULDBLOCK)
  91. #define BREAK_WOULDBLOCK_ERROR() BREAK_IF_ERROR(ERROR_WOULDBLOCK)
  92. #define IS_IO_PENDING_ERROR() IS_ERROR(ERROR_IO_PENDING)
  93. #define CONTINUE_IO_PENDING_ERROR() CONTINUE_IF_ERROR(ERROR_IO_PENDING)
  94. #define BREAK_IO_PENDING_ERROR() BREAK_IF_ERROR(ERROR_IO_PENDING)
  95. #define IS_INTR_ERROR() IS_ERROR(ERROR_INTR)
  96. #define CONTINUE_INTR_ERROR() CONTINUE_IF_ERROR(ERROR_INTR)
  97. #define BREAK_INTR_ERROR() BREAK_IF_ERROR(ERROR_INTR)
  98. #define EqualMemory(dest, src, len) (!memcmp((dest), (src), (len)))
  99. #define MoveMemory(dest, src, len) memmove((dest), (src), (len))
  100. #define CopyMemory(dest, src, len) memcpy((dest), (src), (len))
  101. #define FillMemory(dest, len, ch) memset((dest), (ch), (len))
  102. #define ZeroMemory(dest, len) FillMemory((dest), (len), 0)
  103. #define ZeroObject(obj) ZeroMemory((&(obj)), sizeof(obj))
  104. inline void SetLastError(int code) {errno = code;}
  105. inline int GetLastError() {return errno;}
  106. inline LPCSTR GetErrorStr(int code) {return strerror(code);}
  107. inline LPCSTR GetLastErrorStr() {return GetErrorStr(errno);}
  108. inline void PrintError(LPCSTR subject) {perror(subject);}
  109. #define EXECUTE_RESET_ERROR(expr) (::SetLastError(0), (expr))
  110. #define EXECUTE_RESTORE_ERROR(expr) {int __le_ = ::GetLastError(); (expr); ::SetLastError(__le_);}
  111. #define EXECUTE_RESTORE_ERROR_RT(T, expr)\
  112. ({int __le_ = ::GetLastError(); T __rs_ = (expr); ::SetLastError(__le_); __rs_;})
  113. #define ENSURE_ERROR(def_code) ({int __le_ = ::GetLastError(); if(__le_ == NO_ERROR) __le_ = (def_code); __le_;})
  114. #define ENSURE_ERROR_CANCELLED ENSURE_ERROR(ERROR_CANCELLED)
  115. #define TRIGGER(expr) EXECUTE_RESET_ERROR((expr))
  116. #define _msize(p) malloc_usable_size(p)
  117. #define CreateLocalObjects(T, n) ((T*)alloca(sizeof(T) * (n)))
  118. #define CreateLocalObject(T) CreateLocalObjects(T, 1)
  119. #define CallocObjects(T, n) ((T*)calloc((n), sizeof(T)))
  120. #define MALLOC(T, n) ((T*)malloc(sizeof(T) * (n)))
  121. #define REALLOC(T, p, n) ((T*)realloc((PVOID)(p), sizeof(T) * (n)))
  122. #define FREE(p) free((PVOID)(p))
  123. #define CALLOC(n, s) calloc((n), (s))
  124. #define InterlockedExchangeAdd(p, n) __atomic_fetch_add((p), (n), memory_order_seq_cst)
  125. #define InterlockedExchangeSub(p, n) __atomic_fetch_sub((p), (n), memory_order_seq_cst)
  126. #define InterlockedAdd(p, n) __atomic_add_fetch((p), (n), memory_order_seq_cst)
  127. #define InterlockedSub(p, n) __atomic_sub_fetch((p), (n), memory_order_seq_cst)
  128. #define InterlockedIncrement(p) InterlockedAdd((p), 1)
  129. #define InterlockedDecrement(p) InterlockedSub((p), 1)
  130. #define ERROR_EXIT2(code, err) EXIT((code), (err), __FILE__, __LINE__, __PRETTY_FUNCTION__)
  131. #define ERROR__EXIT2(code, err) _EXIT((code), (err), __FILE__, __LINE__, __PRETTY_FUNCTION__)
  132. #define ERROR_ABORT2(err) ABORT((err), __FILE__, __LINE__, __PRETTY_FUNCTION__)
  133. #define ERROR_EXIT(code) ERROR_EXIT2((code), -1)
  134. #define ERROR__EXIT(code) ERROR__EXIT2((code), -1)
  135. #define ERROR_ABORT() ERROR_ABORT2(-1)
  136. #define IS_VALID_FD(fd) ((fd) != INVALID_FD)
  137. #define IS_INVALID_FD(fd) (!IS_VALID_FD(fd))
  138. #define IS_VALID_PVOID(pv) ((pv) != INVALID_PVOID)
  139. #define IS_INVALID_PVOID(pv) (!IS_VALID_PVOID(pv))
  140. #define TO_PVOID(v) ((PVOID)(UINT_PTR)(v))
  141. #define FROM_PVOID(T, pv) ((T)(UINT_PTR)(pv))
  142. #define IS_NULL(v) ((v) == nullptr)
  143. #define IS_NOT_NULL(v) (!IS_NULL(v))
  144. #define stricmp strcasecmp
  145. #define strnicmp strncasecmp
  146. #define wcsicmp wcscasecmp
  147. #define wcsnicmp wcsncasecmp
  148. #ifdef _UNICODE
  149. #define tstrchr wcschr
  150. #define tstrrchr wcsrchr
  151. #define tstrstr wcsstr
  152. #define tstrpbrk wcspbrk
  153. #define tstrtok wcstok
  154. #define stscanf swscanf
  155. #define tstrlen wcslen
  156. #define tstrcpy wcscpy
  157. #define tstrcmp wcscmp
  158. #define tstricmp wcsicmp
  159. #define tstrncpy wcsncpy
  160. #define tstrncmp wcsncmp
  161. #define tstrnicmp wcsnicmp
  162. #define tstrspn wcsspn
  163. #define tstrcspn wcscspn
  164. #define wsprintf swprintf
  165. #else
  166. #define tstrchr strchr
  167. #define tstrrchr strrchr
  168. #define tstrstr strstr
  169. #define tstrpbrk strpbrk
  170. #define tstrtok strtok_r
  171. #define stscanf sscanf
  172. #define tstrlen strlen
  173. #define tstrcpy strcpy
  174. #define tstrcmp strcmp
  175. #define tstricmp stricmp
  176. #define tstrncpy strncpy
  177. #define tstrncmp strncmp
  178. #define tstrnicmp strnicmp
  179. #define tstrspn strspn
  180. #define tstrcspn strcspn
  181. #define wsprintf sprintf
  182. #endif
  183. inline const char* StrChr(const char* s, char c) {return strchr(s, c);}
  184. inline const char* StrRChr(const char* s, char c) {return strrchr(s, c);}
  185. inline const char* StrStr(const char* h, const char* n) {return strstr(h, n);}
  186. inline const char* StrPBrk(const char* s, const char* a) {return strpbrk(s, a);}
  187. inline const wchar_t* StrChr(const wchar_t* s, wchar_t c) {return wcschr(s, c);}
  188. inline const wchar_t* StrRChr(const wchar_t* s, wchar_t c) {return wcsrchr(s, c);}
  189. inline const wchar_t* StrStr(const wchar_t* h, const wchar_t* n) {return wcsstr(h, n);}
  190. inline const wchar_t* StrPBrk(const wchar_t* s, const wchar_t* a) {return wcspbrk(s, a);}
  191. inline LPSTR StrSep2(LPSTR* lpStr, LPCSTR lpDelim = " \t\r\n") {LPSTR lpTok; while((lpTok = strsep(lpStr, lpDelim)) != nullptr && lpTok[0] == 0); return lpTok;}
  192. inline LPSTR TrimLeft(LPSTR* lpStr, LPCSTR lpDelim = " \t\r\n") {while((*lpStr)[0] != 0 && ::StrChr(lpDelim, (*lpStr)[0]) != nullptr) ++(*lpStr); return (*lpStr);}
  193. inline LPSTR TrimRitht(LPSTR* lpStr, LPCSTR lpDelim = " \t\r\n")
  194. {
  195. LPSTR lpEnd = (*lpStr) + strlen(*lpStr) - 1;
  196. LPSTR lpCur = lpEnd;
  197. while(lpCur >= (*lpStr) && ::StrChr(lpDelim, lpCur[0]) != nullptr)
  198. --lpCur;
  199. if(lpCur != lpEnd)
  200. lpCur[1] = 0;
  201. return (*lpStr);
  202. }
  203. inline BOOL IsStrEmptyA(LPCSTR lpsz) {return (lpsz == nullptr || lpsz[0] == 0);}
  204. inline BOOL IsStrEmptyW(LPCWSTR lpsz) {return (lpsz == nullptr || lpsz[0] == 0);}
  205. inline BOOL IsStrNotEmptyA(LPCSTR lpsz) {return !IsStrEmptyA(lpsz);}
  206. inline BOOL IsStrNotEmptyW(LPCWSTR lpsz){return !IsStrEmptyW(lpsz);}
  207. inline LPCSTR SafeStrA(LPCSTR lpsz) {return (lpsz != nullptr) ? lpsz : "";}
  208. inline LPCWSTR SafeStrW(LPCWSTR lpsz) {return (lpsz != nullptr) ? lpsz : L"";}
  209. #ifdef _UNICODE
  210. #define IsStrEmpty(lpsz) IsStrEmptyW(lpsz)
  211. #define IsStrNotEmpty(lpsz) IsStrNotEmptyW(lpsz)
  212. #define SafeStr(lpsz) SafeStrW(lpsz)
  213. #else
  214. #define IsStrEmpty(lpsz) IsStrEmptyA(lpsz)
  215. #define IsStrNotEmpty(lpsz) IsStrNotEmptyA(lpsz)
  216. #define SafeStr(lpsz) SafeStrA(lpsz)
  217. #endif
  218. inline int lstrlen(LPCTSTR p) {return (int)tstrlen(p);}
  219. inline LPTSTR lstrcpy(LPTSTR d, LPCTSTR s) {return tstrcpy(d, s);}
  220. inline LPTSTR lstrncpy(LPTSTR d, LPCTSTR s, size_t n) {return tstrncpy(d, s, n);}
  221. inline int lstrcmp(LPCTSTR s1, LPCTSTR s2) {return tstrcmp(s1, s2);}
  222. inline int lstrncmp(LPCTSTR s1, LPCTSTR s2, size_t n) {return tstrncmp(s1, s2, n);}
  223. inline int lstricmp(LPCTSTR s1, LPCTSTR s2) {return tstricmp(s1, s2);}
  224. inline int lstrnicmp(LPCTSTR s1, LPCTSTR s2, size_t n) {return tstrnicmp(s1, s2, n);}
  225. inline int lstrspn(LPCTSTR s, LPCTSTR accept) {return (int)tstrspn(s, accept);}
  226. inline int lstrcspn(LPCTSTR s, LPCTSTR accept) {return (int)tstrcspn(s, accept);}
  227. template <typename T, size_t N> char (&_ArraySizeHelper(T(&arr)[N]))[N];
  228. template <typename T, size_t N> char (&_ArraySizeHelper(const T(&arr)[N]))[N];
  229. #define ARRAY_SIZE(arr) (sizeof(_ArraySizeHelper(arr)))
  230. #ifndef _countof
  231. #define _countof(arr) ARRAY_SIZE(arr)
  232. #endif
  233. #ifndef __countof
  234. #define __countof(arr) ARRAY_SIZE(arr)
  235. #endif
  236. #define THREAD_YIELD_CYCLE 63
  237. #define THREAD_SWITCH_CYCLE 4095
  238. inline void YieldThread(UINT i = THREAD_YIELD_CYCLE)
  239. {
  240. if((i & THREAD_SWITCH_CYCLE) == THREAD_SWITCH_CYCLE)
  241. ::SwitchToThread();
  242. else if((i & THREAD_YIELD_CYCLE) == THREAD_YIELD_CYCLE)
  243. ::YieldProcessor();
  244. }
  245. INT WaitFor(DWORD dwMillSecond, DWORD dwSecond = 0, BOOL bExceptThreadInterrupted = FALSE);
  246. INT Sleep(DWORD dwMillSecond, DWORD dwSecond = 0, BOOL bExceptThreadInterrupted = FALSE);
  247. __time64_t _time64(time_t* ptm = nullptr);
  248. __time64_t _mkgmtime64(tm* ptm);
  249. tm* _gmtime64(tm* ptm, __time64_t* pt);
  250. DWORD TimeGetTime();
  251. ULLONG TimeGetTime64();
  252. DWORD GetTimeGap32(DWORD dwOriginal, DWORD dwCurrent = 0);
  253. ULLONG GetTimeGap64(ULLONG ullOriginal, ULONGLONG ullCurrent = 0);
  254. LLONG TimevalToMillisecond(const timeval& tv);
  255. timeval& MillisecondToTimeval(LLONG ms, timeval& tv);
  256. LLONG TimespecToMillisecond(const timespec& ts);
  257. timespec& MillisecondToTimespec(LLONG ms, timespec& ts);
  258. timeval& GetFutureTimeval(LLONG ms, timeval& tv, struct timezone* ptz = nullptr);
  259. timespec& GetFutureTimespec(LLONG ms, timespec& ts, clockid_t clkid = CLOCK_MONOTONIC);
  260. FD CreateTimer(LLONG llInterval, LLONG llStart = -1, BOOL bRealTimeClock = FALSE);
  261. BOOL ReadTimer(FD tmr, ULLONG* pVal = nullptr, BOOL* pRs = nullptr);
  262. BOOL fcntl_SETFL(FD fd, INT fl, BOOL bSet = TRUE);
  263. void PrintStackTrace();
  264. void EXIT(int iExitCode = 0, int iErrno = -1, LPCSTR lpszFile = nullptr, int iLine = 0, LPCSTR lpszFunc = nullptr, LPCSTR lpszTitle = nullptr);
  265. void _EXIT(int iExitCode = 0, int iErrno = -1, LPCSTR lpszFile = nullptr, int iLine = 0, LPCSTR lpszFunc = nullptr, LPCSTR lpszTitle = nullptr);
  266. void ABORT(int iErrno = -1, LPCSTR lpszFile = nullptr, int iLine = 0, LPCSTR lpszFunc = nullptr, LPCSTR lpszTitle = nullptr);
  267. /* ¹¤×÷Ïß³ÌÃû³Æ×î´ó³¤¶È */
  268. #define MAX_THREAD_NAME_LENGTH 15
  269. BOOL SetSequenceThreadName(THR_ID tid, LPCTSTR lpszPrefix, volatile UINT& vuiSeq);
  270. BOOL SetThreadName(THR_ID tid, LPCTSTR lpszPrefix, UINT uiSequence);
  271. BOOL SetThreadName(THR_ID tid, LPCTSTR lpszName);
  272. template<typename T, typename = enable_if_t<is_integral<T>::value>>
  273. inline bool IS_INFINITE(T v)
  274. {
  275. return v == (T)INFINITE;
  276. }
  277. template<typename T, typename = enable_if_t<is_integral<T>::value>>
  278. inline bool IS_HAS_ERROR(T v)
  279. {
  280. return v == (T)HAS_ERROR;
  281. }
  282. template<typename T, typename = enable_if_t<is_integral<T>::value>>
  283. inline bool IS_NO_ERROR(T v)
  284. {
  285. return v == (T)NO_ERROR;
  286. }
  287. template<typename T>
  288. inline T InterlockedCompareExchange(volatile T* _Tgt, T _Value, T _Exp, BOOL _bWeek = FALSE, memory_order m1 = memory_order_seq_cst, memory_order m2 = memory_order_seq_cst)
  289. {
  290. __atomic_compare_exchange_n(_Tgt, &_Exp, _Value, _bWeek, m1, m2);
  291. return _Exp;
  292. }
  293. template<typename T, typename V, typename E, typename = enable_if_t<is_same<decay_t<T>, decay_t<V>>::value && is_same<decay_t<V>, decay_t<E>>::value>>
  294. inline V* InterlockedCompareExchangePointer(volatile T** _Tgt, V* _Value, E* _Exp, BOOL _bWeek = FALSE, memory_order m1 = memory_order_seq_cst, memory_order m2 = memory_order_seq_cst)
  295. {
  296. return (V*)(ULONG_PTR)InterlockedCompareExchange((volatile ULONG_PTR*)(volatile PVOID*)_Tgt, (ULONG_PTR)(PVOID)_Value, (ULONG_PTR)(PVOID)_Exp, _bWeek, m1, m2);
  297. }
  298. template<typename T, typename ... A>
  299. inline T* ConstructObject(T* p, A&& ... args)
  300. {
  301. return new (p) T(forward<A>(args) ...);
  302. }
  303. template<typename T>
  304. inline void DestructObject(T* p)
  305. {
  306. p->T::~T();
  307. }
  308. template<typename T1, typename T2, typename = enable_if_t<is_same<decay_t<T1>, decay_t<T2>>::value>>
  309. inline void CopyPlainObject(T1* p1, const T2* p2)
  310. {
  311. CopyMemory(p1, p2, sizeof(T1));
  312. }
  313. template<typename T, typename C, typename = enable_if_t<is_integral<T>::value && (is_same<C, char>::value || is_same<C, wchar_t>::value)>>
  314. C* _n_2_c(T value, C* lpszDest, int radix)
  315. {
  316. static const C* dig = "0123456789abcdefghijklmnopqrstuvwxyz";
  317. bool neg = false;
  318. if(is_signed<T>::value && value < 0)
  319. {
  320. value = -value;
  321. neg = true;
  322. }
  323. int n = 0;
  324. do
  325. {
  326. lpszDest[n++] = dig[value % radix];
  327. value /= radix;
  328. } while(value);
  329. if(neg) lpszDest[n++] = '-';
  330. lpszDest[n] = 0;
  331. C c, *p, *q;
  332. for(p = lpszDest, q = p + n - 1; p < q; ++p, --q)
  333. c = *p, *p = *q, *q = c;
  334. return lpszDest;
  335. }
  336. #define itoa(v, p, r) _n_2_c<INT, char>((v), (p), (r))
  337. #define ltoa(v, p, r) _n_2_c<LONG, char>((v), (p), (r))
  338. #define lltoa(v, p, r) _n_2_c<LLONG, char>((v), (p), (r))
  339. #define uitoa(v, p, r) _n_2_c<UINT, char>((v), (p), (r))
  340. #define ultoa(v, p, r) _n_2_c<ULONG, char>((v), (p), (r))
  341. #define ulltoa(v, p, r) _n_2_c<ULLONG, char>((v), (p), (r))
  342. #define itow(v, p, r) _n_2_c<INT, wchar_t>((v), (p), (r))
  343. #define ltow(v, p, r) _n_2_c<LONG, wchar_t>((v), (p), (r))
  344. #define lltow(v, p, r) _n_2_c<LLONG, wchar_t>((v), (p), (r))
  345. #define uitow(v, p, r) _n_2_c<UINT, wchar_t>((v), (p), (r))
  346. #define ultow(v, p, r) _n_2_c<ULONG, wchar_t>((v), (p), (r))
  347. #define ulltow(v, p, r) _n_2_c<ULLONG, wchar_t>((v), (p), (r))
  348. #define HEX_CHAR_TO_VALUE(c) (c <= '9' ? c - '0' : (c <= 'F' ? c - 'A' + 0x0A : c - 'a' + 0X0A))
  349. #define HEX_DOUBLE_CHAR_TO_VALUE(pc) ((BYTE)(((HEX_CHAR_TO_VALUE(*(pc))) << 4) | (HEX_CHAR_TO_VALUE(*((pc) + 1)))))
  350. #define HEX_VALUE_TO_CHAR(n) (n <= 9 ? n + '0' : (n <= 'F' ? n + 'A' - 0X0A : n + 'a' - 0X0A))
  351. #define HEX_VALUE_TO_DOUBLE_CHAR(pc, n) {*(pc) = (BYTE)HEX_VALUE_TO_CHAR((n >> 4)); *((pc) + 1) = (BYTE)HEX_VALUE_TO_CHAR((n & 0X0F));}