427 lines
16 KiB
C++
427 lines
16 KiB
C++
/*
|
|
* Copyright: JessMA Open Source (ldcsaa@gmail.com)
|
|
*
|
|
* Author : Bruce Liang
|
|
* Website : https://github.com/ldcsaa
|
|
* Project : https://github.com/ldcsaa/HP-Socket
|
|
* Blog : http://www.cnblogs.com/ldcsaa
|
|
* Wiki : http://www.oschina.net/p/hp-socket
|
|
* QQ Group : 44636872, 75375912
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "hpsocket/GlobalDef.h"
|
|
#include "hpsocket/GlobalErrno.h"
|
|
#include "SysHelper.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <sysexits.h>
|
|
#include <stdio.h>
|
|
#include <wchar.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <malloc.h>
|
|
#include <alloca.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <atomic>
|
|
#include <utility>
|
|
|
|
using namespace std;
|
|
|
|
#if !defined(__ANDROID__)
|
|
typedef atomic_ulong atomic_tid;
|
|
|
|
#define FPRINTLN(fd, fmt, ...) fprintf((fd), fmt "\n", ##__VA_ARGS__)
|
|
#else
|
|
typedef atomic_long atomic_tid;
|
|
|
|
#if defined(stdout)
|
|
#undef stdout
|
|
#endif
|
|
|
|
#if defined(stderr)
|
|
#undef stderr
|
|
#endif
|
|
|
|
#define stdout nullptr
|
|
#define stderr nullptr
|
|
|
|
#define FPRINTLN(fd, fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
|
|
#endif
|
|
|
|
#define PRINTLN(fmt, ...) FPRINTLN(stdout, fmt, ##__VA_ARGS__)
|
|
|
|
#if defined(DEBUG) && defined(DEBUG_TRACE)
|
|
#define TRACE(fmt, ...) PRINTLN("> TRC (0x%zX, %d) " fmt, (SIZE_T)SELF_THREAD_ID, SELF_NATIVE_THREAD_ID, ##__VA_ARGS__)
|
|
#define ASSERT(expr) ((expr) ? TRUE : (::PrintStackTrace(), assert(FALSE), FALSE))
|
|
#else
|
|
#define TRACE(fmt, ...)
|
|
#define ASSERT(expr) assert(expr)
|
|
#endif
|
|
|
|
#define VERIFY(expr) ((expr) ? TRUE : (::PrintStackTrace(), ERROR_ABORT2(ERROR_VERIFY_CHECK), FALSE))
|
|
#define ASSERT_IS_NO_ERROR(expr) ASSERT(IS_NO_ERROR(expr))
|
|
#define VERIFY_IS_NO_ERROR(expr) VERIFY(IS_NO_ERROR(expr))
|
|
#define ENSURE(expr) VERIFY(expr)
|
|
#define ENSURE_IS_NO_ERROR(expr) VERIFY_IS_NO_ERROR(expr)
|
|
|
|
#define TEMP_FAILURE_RETRY_INT(exp) ((int)TEMP_FAILURE_RETRY(exp))
|
|
|
|
#define NO_EINTR TEMP_FAILURE_RETRY
|
|
#define NO_EINTR_INT TEMP_FAILURE_RETRY_INT
|
|
|
|
#define CHECK_IS_OK(expr) {if(IS_NOT_OK(expr)) return FALSE;}
|
|
#define CHECK_ERROR_FD(fd) {if(IS_INVALID_FD(fd)) return FALSE;}
|
|
#define CHECK_ERROR_INVOKE(expr) {if(!IS_NO_ERROR(expr)) return FALSE;}
|
|
#define CHECK_ERROR_CODE(rs) {if(!IS_NO_ERROR(rs)) {::SetLastError(rs); return FALSE;}}
|
|
#define CHECK_ERROR(expr, code) {if(!(expr)) {::SetLastError(code); return FALSE;}}
|
|
#define CHECK_EINVAL(expr) CHECK_ERROR(expr, ERROR_INVALID_PARAMETER)
|
|
#define ASSERT_CHECK_ERROR(expr, code) {ASSERT(expr); CHECK_ERROR(expr, code);}
|
|
#define ASSERT_CHECK_EINVAL(expr) {ASSERT(expr); CHECK_EINVAL(expr);}
|
|
|
|
#define SUCCEEDED(rs) IS_NO_ERROR(rs)
|
|
#define FAILED(rs) (!SUCCEEDED(rs))
|
|
#define IS_OK(rs) ((BOOL)(rs))
|
|
#define IS_NOT_OK(rs) (!IS_OK(rs))
|
|
|
|
#define IS_ERROR(code) (::GetLastError() == (code))
|
|
#define CONTINUE_IF_ERROR(code) {if(IS_ERROR(code)) continue;}
|
|
#define BREAK_IF_ERROR(code) {if(IS_ERROR(code)) break;}
|
|
|
|
#define IS_WOULDBLOCK_ERROR() IS_ERROR(ERROR_WOULDBLOCK)
|
|
#define CONTINUE_WOULDBLOCK_ERROR() CONTINUE_IF_ERROR(ERROR_WOULDBLOCK)
|
|
#define BREAK_WOULDBLOCK_ERROR() BREAK_IF_ERROR(ERROR_WOULDBLOCK)
|
|
#define IS_IO_PENDING_ERROR() IS_ERROR(ERROR_IO_PENDING)
|
|
#define CONTINUE_IO_PENDING_ERROR() CONTINUE_IF_ERROR(ERROR_IO_PENDING)
|
|
#define BREAK_IO_PENDING_ERROR() BREAK_IF_ERROR(ERROR_IO_PENDING)
|
|
#define IS_INTR_ERROR() IS_ERROR(ERROR_INTR)
|
|
#define CONTINUE_INTR_ERROR() CONTINUE_IF_ERROR(ERROR_INTR)
|
|
#define BREAK_INTR_ERROR() BREAK_IF_ERROR(ERROR_INTR)
|
|
|
|
#define EqualMemory(dest, src, len) (!memcmp((dest), (src), (len)))
|
|
#define MoveMemory(dest, src, len) memmove((dest), (src), (len))
|
|
#define CopyMemory(dest, src, len) memcpy((dest), (src), (len))
|
|
#define FillMemory(dest, len, ch) memset((dest), (ch), (len))
|
|
#define ZeroMemory(dest, len) FillMemory((dest), (len), 0)
|
|
#define ZeroObject(obj) ZeroMemory((&(obj)), sizeof(obj))
|
|
|
|
inline void SetLastError(int code) {errno = code;}
|
|
inline int GetLastError() {return errno;}
|
|
inline LPCSTR GetErrorStr(int code) {return strerror(code);}
|
|
inline LPCSTR GetLastErrorStr() {return GetErrorStr(errno);}
|
|
inline void PrintError(LPCSTR subject) {perror(subject);}
|
|
|
|
#define EXECUTE_RESET_ERROR(expr) (::SetLastError(0), (expr))
|
|
#define EXECUTE_RESTORE_ERROR(expr) {int __le_ = ::GetLastError(); (expr); ::SetLastError(__le_);}
|
|
#define EXECUTE_RESTORE_ERROR_RT(T, expr)\
|
|
({int __le_ = ::GetLastError(); T __rs_ = (expr); ::SetLastError(__le_); __rs_;})
|
|
#define ENSURE_ERROR(def_code) ({int __le_ = ::GetLastError(); if(__le_ == NO_ERROR) __le_ = (def_code); __le_;})
|
|
#define ENSURE_ERROR_CANCELLED ENSURE_ERROR(ERROR_CANCELLED)
|
|
#define TRIGGER(expr) EXECUTE_RESET_ERROR((expr))
|
|
|
|
#define _msize(p) malloc_usable_size(p)
|
|
#define CreateLocalObjects(T, n) ((T*)alloca(sizeof(T) * (n)))
|
|
#define CreateLocalObject(T) CreateLocalObjects(T, 1)
|
|
#define CallocObjects(T, n) ((T*)calloc((n), sizeof(T)))
|
|
|
|
#define MALLOC(T, n) ((T*)malloc(sizeof(T) * (n)))
|
|
#define REALLOC(T, p, n) ((T*)realloc((PVOID)(p), sizeof(T) * (n)))
|
|
#define FREE(p) free((PVOID)(p))
|
|
#define CALLOC(n, s) calloc((n), (s))
|
|
|
|
#define InterlockedExchangeAdd(p, n) __atomic_fetch_add((p), (n), memory_order_seq_cst)
|
|
#define InterlockedExchangeSub(p, n) __atomic_fetch_sub((p), (n), memory_order_seq_cst)
|
|
#define InterlockedAdd(p, n) __atomic_add_fetch((p), (n), memory_order_seq_cst)
|
|
#define InterlockedSub(p, n) __atomic_sub_fetch((p), (n), memory_order_seq_cst)
|
|
#define InterlockedIncrement(p) InterlockedAdd((p), 1)
|
|
#define InterlockedDecrement(p) InterlockedSub((p), 1)
|
|
|
|
#define ERROR_EXIT2(code, err) EXIT((code), (err), __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
|
#define ERROR__EXIT2(code, err) _EXIT((code), (err), __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
|
#define ERROR_ABORT2(err) ABORT((err), __FILE__, __LINE__, __PRETTY_FUNCTION__)
|
|
|
|
#define ERROR_EXIT(code) ERROR_EXIT2((code), -1)
|
|
#define ERROR__EXIT(code) ERROR__EXIT2((code), -1)
|
|
#define ERROR_ABORT() ERROR_ABORT2(-1)
|
|
|
|
#define IS_VALID_FD(fd) ((fd) != INVALID_FD)
|
|
#define IS_INVALID_FD(fd) (!IS_VALID_FD(fd))
|
|
|
|
#define IS_VALID_PVOID(pv) ((pv) != INVALID_PVOID)
|
|
#define IS_INVALID_PVOID(pv) (!IS_VALID_PVOID(pv))
|
|
|
|
#define TO_PVOID(v) ((PVOID)(UINT_PTR)(v))
|
|
#define FROM_PVOID(T, pv) ((T)(UINT_PTR)(pv))
|
|
|
|
#define IS_NULL(v) ((v) == nullptr)
|
|
#define IS_NOT_NULL(v) (!IS_NULL(v))
|
|
|
|
#define stricmp strcasecmp
|
|
#define strnicmp strncasecmp
|
|
#define wcsicmp wcscasecmp
|
|
#define wcsnicmp wcsncasecmp
|
|
|
|
#ifdef _UNICODE
|
|
#define tstrchr wcschr
|
|
#define tstrrchr wcsrchr
|
|
#define tstrstr wcsstr
|
|
#define tstrpbrk wcspbrk
|
|
#define tstrtok wcstok
|
|
|
|
#define stscanf swscanf
|
|
#define tstrlen wcslen
|
|
#define tstrcpy wcscpy
|
|
#define tstrcmp wcscmp
|
|
#define tstricmp wcsicmp
|
|
#define tstrncpy wcsncpy
|
|
#define tstrncmp wcsncmp
|
|
#define tstrnicmp wcsnicmp
|
|
#define tstrspn wcsspn
|
|
#define tstrcspn wcscspn
|
|
#define wsprintf swprintf
|
|
#else
|
|
#define tstrchr strchr
|
|
#define tstrrchr strrchr
|
|
#define tstrstr strstr
|
|
#define tstrpbrk strpbrk
|
|
#define tstrtok strtok_r
|
|
|
|
#define stscanf sscanf
|
|
#define tstrlen strlen
|
|
#define tstrcpy strcpy
|
|
#define tstrcmp strcmp
|
|
#define tstricmp stricmp
|
|
#define tstrncpy strncpy
|
|
#define tstrncmp strncmp
|
|
#define tstrnicmp strnicmp
|
|
#define tstrspn strspn
|
|
#define tstrcspn strcspn
|
|
#define wsprintf sprintf
|
|
#endif
|
|
|
|
inline const char* StrChr(const char* s, char c) {return strchr(s, c);}
|
|
inline const char* StrRChr(const char* s, char c) {return strrchr(s, c);}
|
|
inline const char* StrStr(const char* h, const char* n) {return strstr(h, n);}
|
|
inline const char* StrPBrk(const char* s, const char* a) {return strpbrk(s, a);}
|
|
inline const wchar_t* StrChr(const wchar_t* s, wchar_t c) {return wcschr(s, c);}
|
|
inline const wchar_t* StrRChr(const wchar_t* s, wchar_t c) {return wcsrchr(s, c);}
|
|
inline const wchar_t* StrStr(const wchar_t* h, const wchar_t* n) {return wcsstr(h, n);}
|
|
inline const wchar_t* StrPBrk(const wchar_t* s, const wchar_t* a) {return wcspbrk(s, a);}
|
|
inline LPSTR StrSep2(LPSTR* lpStr, LPCSTR lpDelim = " \t\r\n") {LPSTR lpTok; while((lpTok = strsep(lpStr, lpDelim)) != nullptr && lpTok[0] == 0); return lpTok;}
|
|
inline LPSTR TrimLeft(LPSTR* lpStr, LPCSTR lpDelim = " \t\r\n") {while((*lpStr)[0] != 0 && ::StrChr(lpDelim, (*lpStr)[0]) != nullptr) ++(*lpStr); return (*lpStr);}
|
|
inline LPSTR TrimRitht(LPSTR* lpStr, LPCSTR lpDelim = " \t\r\n")
|
|
{
|
|
LPSTR lpEnd = (*lpStr) + strlen(*lpStr) - 1;
|
|
LPSTR lpCur = lpEnd;
|
|
|
|
while(lpCur >= (*lpStr) && ::StrChr(lpDelim, lpCur[0]) != nullptr)
|
|
--lpCur;
|
|
|
|
if(lpCur != lpEnd)
|
|
lpCur[1] = 0;
|
|
|
|
return (*lpStr);
|
|
}
|
|
|
|
inline BOOL IsStrEmptyA(LPCSTR lpsz) {return (lpsz == nullptr || lpsz[0] == 0);}
|
|
inline BOOL IsStrEmptyW(LPCWSTR lpsz) {return (lpsz == nullptr || lpsz[0] == 0);}
|
|
inline BOOL IsStrNotEmptyA(LPCSTR lpsz) {return !IsStrEmptyA(lpsz);}
|
|
inline BOOL IsStrNotEmptyW(LPCWSTR lpsz){return !IsStrEmptyW(lpsz);}
|
|
inline LPCSTR SafeStrA(LPCSTR lpsz) {return (lpsz != nullptr) ? lpsz : "";}
|
|
inline LPCWSTR SafeStrW(LPCWSTR lpsz) {return (lpsz != nullptr) ? lpsz : L"";}
|
|
|
|
#ifdef _UNICODE
|
|
#define IsStrEmpty(lpsz) IsStrEmptyW(lpsz)
|
|
#define IsStrNotEmpty(lpsz) IsStrNotEmptyW(lpsz)
|
|
#define SafeStr(lpsz) SafeStrW(lpsz)
|
|
#else
|
|
#define IsStrEmpty(lpsz) IsStrEmptyA(lpsz)
|
|
#define IsStrNotEmpty(lpsz) IsStrNotEmptyA(lpsz)
|
|
#define SafeStr(lpsz) SafeStrA(lpsz)
|
|
#endif
|
|
|
|
inline int lstrlen(LPCTSTR p) {return (int)tstrlen(p);}
|
|
inline LPTSTR lstrcpy(LPTSTR d, LPCTSTR s) {return tstrcpy(d, s);}
|
|
inline LPTSTR lstrncpy(LPTSTR d, LPCTSTR s, size_t n) {return tstrncpy(d, s, n);}
|
|
inline int lstrcmp(LPCTSTR s1, LPCTSTR s2) {return tstrcmp(s1, s2);}
|
|
inline int lstrncmp(LPCTSTR s1, LPCTSTR s2, size_t n) {return tstrncmp(s1, s2, n);}
|
|
inline int lstricmp(LPCTSTR s1, LPCTSTR s2) {return tstricmp(s1, s2);}
|
|
inline int lstrnicmp(LPCTSTR s1, LPCTSTR s2, size_t n) {return tstrnicmp(s1, s2, n);}
|
|
inline int lstrspn(LPCTSTR s, LPCTSTR accept) {return (int)tstrspn(s, accept);}
|
|
inline int lstrcspn(LPCTSTR s, LPCTSTR accept) {return (int)tstrcspn(s, accept);}
|
|
|
|
template <typename T, size_t N> char (&_ArraySizeHelper(T(&arr)[N]))[N];
|
|
template <typename T, size_t N> char (&_ArraySizeHelper(const T(&arr)[N]))[N];
|
|
|
|
#define ARRAY_SIZE(arr) (sizeof(_ArraySizeHelper(arr)))
|
|
|
|
#ifndef _countof
|
|
#define _countof(arr) ARRAY_SIZE(arr)
|
|
#endif
|
|
|
|
#ifndef __countof
|
|
#define __countof(arr) ARRAY_SIZE(arr)
|
|
#endif
|
|
|
|
#define THREAD_YIELD_CYCLE 63
|
|
#define THREAD_SWITCH_CYCLE 4095
|
|
|
|
inline void YieldThread(UINT i = THREAD_YIELD_CYCLE)
|
|
{
|
|
if((i & THREAD_SWITCH_CYCLE) == THREAD_SWITCH_CYCLE)
|
|
::SwitchToThread();
|
|
else if((i & THREAD_YIELD_CYCLE) == THREAD_YIELD_CYCLE)
|
|
::YieldProcessor();
|
|
}
|
|
|
|
INT WaitFor(DWORD dwMillSecond, DWORD dwSecond = 0, BOOL bExceptThreadInterrupted = FALSE);
|
|
INT Sleep(DWORD dwMillSecond, DWORD dwSecond = 0, BOOL bExceptThreadInterrupted = FALSE);
|
|
|
|
__time64_t _time64(time_t* ptm = nullptr);
|
|
__time64_t _mkgmtime64(tm* ptm);
|
|
tm* _gmtime64(tm* ptm, __time64_t* pt);
|
|
|
|
DWORD TimeGetTime();
|
|
ULLONG TimeGetTime64();
|
|
DWORD GetTimeGap32(DWORD dwOriginal, DWORD dwCurrent = 0);
|
|
ULLONG GetTimeGap64(ULLONG ullOriginal, ULONGLONG ullCurrent = 0);
|
|
LLONG TimevalToMillisecond(const timeval& tv);
|
|
timeval& MillisecondToTimeval(LLONG ms, timeval& tv);
|
|
LLONG TimespecToMillisecond(const timespec& ts);
|
|
timespec& MillisecondToTimespec(LLONG ms, timespec& ts);
|
|
timeval& GetFutureTimeval(LLONG ms, timeval& tv, struct timezone* ptz = nullptr);
|
|
timespec& GetFutureTimespec(LLONG ms, timespec& ts, clockid_t clkid = CLOCK_MONOTONIC);
|
|
|
|
FD CreateTimer(LLONG llInterval, LLONG llStart = -1, BOOL bRealTimeClock = FALSE);
|
|
BOOL ReadTimer(FD tmr, ULLONG* pVal = nullptr, BOOL* pRs = nullptr);
|
|
|
|
BOOL fcntl_SETFL(FD fd, INT fl, BOOL bSet = TRUE);
|
|
|
|
void PrintStackTrace();
|
|
void EXIT(int iExitCode = 0, int iErrno = -1, LPCSTR lpszFile = nullptr, int iLine = 0, LPCSTR lpszFunc = nullptr, LPCSTR lpszTitle = nullptr);
|
|
void _EXIT(int iExitCode = 0, int iErrno = -1, LPCSTR lpszFile = nullptr, int iLine = 0, LPCSTR lpszFunc = nullptr, LPCSTR lpszTitle = nullptr);
|
|
void ABORT(int iErrno = -1, LPCSTR lpszFile = nullptr, int iLine = 0, LPCSTR lpszFunc = nullptr, LPCSTR lpszTitle = nullptr);
|
|
|
|
/* ¹¤×÷Ïß³ÌÃû³Æ×î´ó³¤¶È */
|
|
#define MAX_THREAD_NAME_LENGTH 15
|
|
|
|
BOOL SetSequenceThreadName(THR_ID tid, LPCTSTR lpszPrefix, volatile UINT& vuiSeq);
|
|
BOOL SetThreadName(THR_ID tid, LPCTSTR lpszPrefix, UINT uiSequence);
|
|
BOOL SetThreadName(THR_ID tid, LPCTSTR lpszName);
|
|
|
|
template<typename T, typename = enable_if_t<is_integral<T>::value>>
|
|
inline bool IS_INFINITE(T v)
|
|
{
|
|
return v == (T)INFINITE;
|
|
}
|
|
|
|
template<typename T, typename = enable_if_t<is_integral<T>::value>>
|
|
inline bool IS_HAS_ERROR(T v)
|
|
{
|
|
return v == (T)HAS_ERROR;
|
|
}
|
|
|
|
template<typename T, typename = enable_if_t<is_integral<T>::value>>
|
|
inline bool IS_NO_ERROR(T v)
|
|
{
|
|
return v == (T)NO_ERROR;
|
|
}
|
|
|
|
template<typename T>
|
|
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)
|
|
{
|
|
__atomic_compare_exchange_n(_Tgt, &_Exp, _Value, _bWeek, m1, m2);
|
|
return _Exp;
|
|
}
|
|
|
|
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>>
|
|
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)
|
|
{
|
|
return (V*)(ULONG_PTR)InterlockedCompareExchange((volatile ULONG_PTR*)(volatile PVOID*)_Tgt, (ULONG_PTR)(PVOID)_Value, (ULONG_PTR)(PVOID)_Exp, _bWeek, m1, m2);
|
|
}
|
|
|
|
template<typename T, typename ... A>
|
|
inline T* ConstructObject(T* p, A&& ... args)
|
|
{
|
|
return new (p) T(forward<A>(args) ...);
|
|
}
|
|
|
|
template<typename T>
|
|
inline void DestructObject(T* p)
|
|
{
|
|
p->T::~T();
|
|
}
|
|
|
|
template<typename T1, typename T2, typename = enable_if_t<is_same<decay_t<T1>, decay_t<T2>>::value>>
|
|
inline void CopyPlainObject(T1* p1, const T2* p2)
|
|
{
|
|
CopyMemory(p1, p2, sizeof(T1));
|
|
}
|
|
|
|
template<typename T, typename C, typename = enable_if_t<is_integral<T>::value && (is_same<C, char>::value || is_same<C, wchar_t>::value)>>
|
|
C* _n_2_c(T value, C* lpszDest, int radix)
|
|
{
|
|
static const C* dig = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
|
|
bool neg = false;
|
|
|
|
if(is_signed<T>::value && value < 0)
|
|
{
|
|
value = -value;
|
|
neg = true;
|
|
}
|
|
|
|
int n = 0;
|
|
|
|
do
|
|
{
|
|
lpszDest[n++] = dig[value % radix];
|
|
value /= radix;
|
|
} while(value);
|
|
|
|
if(neg) lpszDest[n++] = '-';
|
|
lpszDest[n] = 0;
|
|
|
|
C c, *p, *q;
|
|
for(p = lpszDest, q = p + n - 1; p < q; ++p, --q)
|
|
c = *p, *p = *q, *q = c;
|
|
|
|
return lpszDest;
|
|
}
|
|
|
|
#define itoa(v, p, r) _n_2_c<INT, char>((v), (p), (r))
|
|
#define ltoa(v, p, r) _n_2_c<LONG, char>((v), (p), (r))
|
|
#define lltoa(v, p, r) _n_2_c<LLONG, char>((v), (p), (r))
|
|
#define uitoa(v, p, r) _n_2_c<UINT, char>((v), (p), (r))
|
|
#define ultoa(v, p, r) _n_2_c<ULONG, char>((v), (p), (r))
|
|
#define ulltoa(v, p, r) _n_2_c<ULLONG, char>((v), (p), (r))
|
|
#define itow(v, p, r) _n_2_c<INT, wchar_t>((v), (p), (r))
|
|
#define ltow(v, p, r) _n_2_c<LONG, wchar_t>((v), (p), (r))
|
|
#define lltow(v, p, r) _n_2_c<LLONG, wchar_t>((v), (p), (r))
|
|
#define uitow(v, p, r) _n_2_c<UINT, wchar_t>((v), (p), (r))
|
|
#define ultow(v, p, r) _n_2_c<ULONG, wchar_t>((v), (p), (r))
|
|
#define ulltow(v, p, r) _n_2_c<ULLONG, wchar_t>((v), (p), (r))
|
|
|
|
#define HEX_CHAR_TO_VALUE(c) (c <= '9' ? c - '0' : (c <= 'F' ? c - 'A' + 0x0A : c - 'a' + 0X0A))
|
|
#define HEX_DOUBLE_CHAR_TO_VALUE(pc) ((BYTE)(((HEX_CHAR_TO_VALUE(*(pc))) << 4) | (HEX_CHAR_TO_VALUE(*((pc) + 1)))))
|
|
#define HEX_VALUE_TO_CHAR(n) (n <= 9 ? n + '0' : (n <= 'F' ? n + 'A' - 0X0A : n + 'a' - 0X0A))
|
|
#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));}
|