This commit is contained in:
aixianling
2025-01-09 17:45:40 +08:00
commit 5c9f1dae4a
3482 changed files with 1146531 additions and 0 deletions

121
sdk/utils/BufferAllocator.h Normal file
View File

@@ -0,0 +1,121 @@
#pragma once
#include <Tick.h>
#ifdef _DEBUG
#define _BUFFER_TRACE
#endif
#include <_osdef.h>
#include <Tick.h>
#include <string.h>
#include "Lock.h"
using namespace wylib::time::tick64;
class CBufferAllocator
{
public:
static const DWORD SmallBufferSize = 64; //小块内存块大小
static const DWORD MiddleBufferSize = 256; //中等内存块大小
static const DWORD LargeBufferSize = 1024; //大块内存块大小
#pragma pack(push, 1)
typedef struct tagBuffer
{
size_t dwSize; //内存数据段大小
tagBuffer* pPrevBuffer;//指向上一个内存块的指针
TICKCOUNT dwFreeTick; //即将被销毁的时间
#ifdef _BUFFER_TRACE
tagBuffer* pNextBuffer;//指向上下个内存块的指针,用于调试
struct
{
const char* lpFile; //申请内存块的代码位置,用于调试
int nLine;
}al, fl;
BOOL boUsing; //是否使用的标记
#endif
}BUFFER, *PBUFFER;
#pragma pack(pop)
struct BufferStatic
{
size_t dwAllocSize;
size_t dwFreeSize;
};
typedef struct tagAllocatorMemoryInfo
{
BufferStatic SmallBuffer;
BufferStatic MiddleBuffer;
BufferStatic LargeBuffer;
BufferStatic SuperBuffer;
}ALLOCATOR_MEMORY_INFO, *PALLOCATPR_MEMORY_INFOR;
private:
//CRITICAL_SECTION m_BufferLock; //内存块申请锁
wylib::sync::lock::CCSLock m_BufferLock; //加锁
PBUFFER m_pLastSmallBuffer; //指向最后一个空闲的小型内存块的指针
PBUFFER m_pLastMiddleBuffer; //指向最后一个空闲的中型内存块的指针
PBUFFER m_pLastLargeBuffer; //指向最后一个空闲的大型内存块的指针
PBUFFER m_pLastSuperBuffer; //指向最后一个空闲的超级内存块的指针
#ifdef _BUFFER_TRACE
PBUFFER m_pLastAllocedBuffer; //指向最后一个被申请的内存块
#endif
size_t m_dwAllocedSmallSize; //已被申请的小型内存块大小
size_t m_dwAllocedMiddleSize; //已被申请的中型内存块大小
size_t m_dwAllocedLargeSize; //已被申请的大型内存块大小
size_t m_dwAllocedSuperSize; //已被申请的超级内存块大小
size_t m_dwFreedSmallSize; //已被释放的小型内存块大小
size_t m_dwFreedMiddleSize; //已被释放的中型内存块大小
size_t m_dwFreedLargeSize; //已被释放的大型内存块大小
size_t m_dwFreedSuperSize; //已被释放的超级内存块大小
public:
CBufferAllocator();
~CBufferAllocator();
#ifndef _BUFFER_TRACE
PVOID AllocBuffer(size_t dwSize);
PVOID ReallocBuffer(LPVOID ptr, size_t dwNewSize);
VOID FreeBuffer(PVOID ptr);
#else
PVOID _AllocBuffer(size_t dwSize, const char* lpFile, int nLine);
PVOID _ReallocBuffer(LPVOID ptr, size_t dwNewSize, const char* lpFile, int nLine);
VOID _FreeBuffer(PVOID ptr, const char* lpFile, int nLine);
#define AllocBuffer(dwSize) _AllocBuffer(dwSize, __FILE__, __LINE__)
#define ReallocBuffer(ptr, dwNewSize) _ReallocBuffer(ptr, dwNewSize, __FILE__, __LINE__)
#define FreeBuffer(ptr) _FreeBuffer(ptr, __FILE__, __LINE__)
#endif
VOID GetMemoryInfo(CBufferAllocator::PALLOCATPR_MEMORY_INFOR pMemoryInfo);
// bIgnoreInterval:是否忽略间隔。如果忽略时间间隔,不管是否时间间隔到,都强制删除
VOID CheckFreeBuffers(bool bIgnoreInterval = false);
};
class DataBuffer
{
public:
CBufferAllocator *m_pAllocator;
size_t m_dwSize;
char *pData;//内存块指针
char *ptr;//写内存指针
char *pEnd;//内存块结束指针
char *pReadPtr;//读内存指针
#ifdef _BUFFER_TRACE
DataBuffer(CBufferAllocator *pAllocator, size_t dwSize, const char *_FILE, const int _LINE);
#else
DataBuffer(CBufferAllocator *pAllocator, size_t dwSize);
#endif
~DataBuffer();
};
#ifdef _BUFFER_TRACE
#define DATA_BUFFER_VAR(_allocator, _name, _size) DataBuffer _name((_allocator), (_size), __FILE__, __LINE__)
#else
#define DATA_BUFFER_VAR(_allocator, _name, _size) DataBuffer _name((_allocator), (_size))
#endif

View File

@@ -0,0 +1,493 @@
#include <stdlib.h>
#include <stdio.h>
#ifdef WIN32
#include <Windows.h>
#include <tchar.h>
#endif
#include <_ast.h>
#include <_memchk.h>
#include <Tick.h>
#include "Lock.h"
#include "ShareUtil.h"
#include "BufferAllocator.h"
static const DWORD dwBufferFreeTick = 30 * 1000;//标记为释放的的内存块的延时销毁时间
CBufferAllocator::CBufferAllocator()
{
m_pLastSmallBuffer = NULL;
m_pLastMiddleBuffer = NULL;
m_pLastLargeBuffer = NULL;
m_pLastSuperBuffer = NULL;
#ifdef _BUFFER_TRACE
m_pLastAllocedBuffer = NULL;
#endif
m_dwAllocedSmallSize = 0;
m_dwAllocedMiddleSize = 0;
m_dwAllocedLargeSize = 0;
m_dwAllocedSuperSize = 0;
m_dwFreedSmallSize = 0;
m_dwFreedMiddleSize = 0;
m_dwFreedLargeSize = 0;
m_dwFreedSuperSize = 0;
//InitializeCriticalSection( &m_BufferLock );
}
CBufferAllocator::~CBufferAllocator()
{
PBUFFER pBuffer, pPrevBuffer;
pBuffer = m_pLastSmallBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
free( pBuffer );
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastMiddleBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
free( pBuffer );
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastLargeBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
free( pBuffer );
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastSuperBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
free( pBuffer );
pBuffer = pPrevBuffer;
}
#ifdef _BUFFER_TRACE
pBuffer = m_pLastAllocedBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
TRACE( _T("%s(%d) : 申请的内存块没有释放pointer Addr=%d\n"), pBuffer->al.lpFile, pBuffer->al.nLine,(INT_PTR)pBuffer );
free( pBuffer );
pBuffer = pPrevBuffer;
//Assert(FALSE);//有内存泄漏,提醒
}
#endif
//DeleteCriticalSection( &m_BufferLock );
}
#ifndef _BUFFER_TRACE
PVOID CBufferAllocator::AllocBuffer(size_t dwSize)
#else
PVOID CBufferAllocator::_AllocBuffer(size_t dwSize, const char *lpFile, int nLine)
#endif
{
if(m_dwFreedSuperSize >100000000 || m_dwFreedLargeSize > 100000000)
{
CheckFreeBuffers(true);
}
PBUFFER pBuffer, pPrev, pResult = NULL;
//EnterCriticalSection( &m_BufferLock );
m_BufferLock.Lock();
if ( dwSize <= SmallBufferSize )
{
if ( m_pLastSmallBuffer )
{
pResult = m_pLastSmallBuffer;
m_pLastSmallBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
m_dwFreedSmallSize -= SmallBufferSize;
}
else
{
#ifdef _BUFFER_TRACE
pResult = (PBUFFER)malloc( SmallBufferSize + sizeof(*pResult) + sizeof(INT) );
#else
pResult = (PBUFFER)malloc( SmallBufferSize + sizeof(*pResult) );
#endif
pResult->dwSize = SmallBufferSize;
pResult->pPrevBuffer = NULL;
#ifdef _BUFFER_TRACE
pResult->boUsing = FALSE;
pResult->pNextBuffer = NULL;
#endif
}
m_dwAllocedSmallSize += SmallBufferSize;
}
else if ( dwSize <= MiddleBufferSize )
{
if ( m_pLastMiddleBuffer )
{
pResult = m_pLastMiddleBuffer;
m_pLastMiddleBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
m_dwFreedMiddleSize -= MiddleBufferSize;
}
else
{
#ifdef _BUFFER_TRACE
pResult = (PBUFFER)malloc( MiddleBufferSize + sizeof(*pResult) + sizeof(INT) );
#else
pResult = (PBUFFER)malloc( MiddleBufferSize + sizeof(*pResult) );
#endif
pResult->dwSize = MiddleBufferSize;
pResult->pPrevBuffer = NULL;
#ifdef _BUFFER_TRACE
pResult->boUsing = FALSE;
pResult->pNextBuffer = NULL;
#endif
}
m_dwAllocedMiddleSize += MiddleBufferSize;
}
else if ( dwSize <= LargeBufferSize )
{
if ( m_pLastLargeBuffer )
{
pResult = m_pLastLargeBuffer;
m_pLastLargeBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
m_dwFreedLargeSize -= LargeBufferSize;
}
else
{
#ifdef _BUFFER_TRACE
pResult = (PBUFFER)malloc( LargeBufferSize + sizeof(*pResult) + sizeof(INT) );
#else
pResult = (PBUFFER)malloc( LargeBufferSize + sizeof(*pResult) );
#endif
pResult->dwSize = LargeBufferSize;
pResult->pPrevBuffer = NULL;
#ifdef _BUFFER_TRACE
pResult->boUsing = FALSE;
pResult->pNextBuffer = NULL;
#endif
}
m_dwAllocedLargeSize += LargeBufferSize;
}
else
{
pPrev = NULL;
pBuffer = m_pLastSuperBuffer;
while ( pBuffer )
{
if ( pBuffer->dwSize >= dwSize )
{
pResult = pBuffer;
#ifdef _BUFFER_TRACE
Assert( !pResult->boUsing );
#endif
if ( pResult == m_pLastSuperBuffer )
{
m_pLastSuperBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
}
else if ( pPrev )
{
pPrev->pPrevBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
}
m_dwFreedSuperSize -= pResult->dwSize;
break;
}
pPrev = pBuffer;
pBuffer = pBuffer->pPrevBuffer;
}
if ( !pResult )
{
dwSize = (dwSize + 511) & (~511);
#ifdef _BUFFER_TRACE
pResult = (PBUFFER)malloc( dwSize + sizeof(*pResult) + sizeof(INT) );
#else
pResult = (PBUFFER)malloc( dwSize + sizeof(*pResult) );
#endif
pResult->dwSize = dwSize;
pResult->pPrevBuffer = NULL;
#ifdef _BUFFER_TRACE
pResult->boUsing = FALSE;
pResult->pNextBuffer = NULL;
#endif
}
m_dwAllocedSuperSize += pResult->dwSize;
}
#ifdef _BUFFER_TRACE
if ( pResult )
{
Assert( !pResult->boUsing );
pResult->boUsing = TRUE;
pResult->al.lpFile = lpFile;
pResult->al.nLine = nLine;
pResult->fl.lpFile = NULL;
pResult->fl.nLine = 0;
pResult->dwFreeTick = 0;
*((PINT)((char*)(pResult + 1) + pResult->dwSize)) = 0xCC55EE33;
if ( m_pLastAllocedBuffer ) m_pLastAllocedBuffer->pNextBuffer = pResult;
pResult->pPrevBuffer = m_pLastAllocedBuffer;
pResult->pNextBuffer = NULL;
m_pLastAllocedBuffer = pResult;
}
#endif
//LeaveCriticalSection( &m_BufferLock );
m_BufferLock.Unlock();
return pResult ? pResult + 1 : NULL;
}
#ifndef _BUFFER_TRACE
PVOID CBufferAllocator::ReallocBuffer(PVOID ptr, size_t dwNewSize)
#else
PVOID CBufferAllocator::_ReallocBuffer(PVOID ptr, size_t dwNewSize, const char* lpFile, int nLine)
#endif
{
if (dwNewSize == 0)
{
FreeBuffer(ptr);
return NULL;
}
PBUFFER pBuffer;
if (ptr)
{
pBuffer = ((PBUFFER)ptr) - 1;
if (dwNewSize <= pBuffer->dwSize)
return ptr;
}
PVOID pResult;
#ifndef _BUFFER_TRACE
pResult = AllocBuffer(dwNewSize);
if (ptr)
{
memcpy(pResult, ptr, pBuffer->dwSize);
FreeBuffer(ptr);
}
#else
pResult = _AllocBuffer(dwNewSize, lpFile, NULL);
if (ptr)
{
memcpy(pResult, ptr, pBuffer->dwSize);
_FreeBuffer(ptr, lpFile, NULL);
}
#endif
return pResult;
}
#ifndef _BUFFER_TRACE
VOID CBufferAllocator::FreeBuffer(PVOID ptr)
#else
VOID CBufferAllocator::_FreeBuffer(PVOID ptr, const char* lpFile, int nLine)
#endif
{
PBUFFER pBuffer;
if (!ptr) return;
pBuffer = ((PBUFFER)ptr) - 1;
//EnterCriticalSection( &m_BufferLock );
m_BufferLock.Lock();
#ifdef _BUFFER_TRACE
if ( !pBuffer->boUsing )
{
//TRACE( _T(__FUNCTION__)_T(" 试图释放已经被标记为释放的内存块(%X,大小:%d),申请位置:%s(%d),释放位置:%s(%d)\n"),
// pBuffer, pBuffer->dwSize, pBuffer->al.lpFile, pBuffer->al.nLine,
// pBuffer->fl.lpFile, pBuffer->fl.nLine );
OutputMsg(rmError, _T(" %s试图释放已经被标记为释放的内存块(%X,大小:%d),申请位置:%s(%d),释放位置:%s(%d)\n"),
__FUNCTION__,pBuffer, pBuffer->dwSize, pBuffer->al.lpFile, pBuffer->al.nLine,
pBuffer->fl.lpFile, pBuffer->fl.nLine );
}
Assert( pBuffer->boUsing );
pBuffer->boUsing = FALSE;
Assert(*((PINT)((char*)(pBuffer + 1) + pBuffer->dwSize)) == 0xCC55EE33);
if ( pBuffer->pPrevBuffer )
pBuffer->pPrevBuffer->pNextBuffer = pBuffer->pNextBuffer;
if ( pBuffer->pNextBuffer )
pBuffer->pNextBuffer->pPrevBuffer = pBuffer->pPrevBuffer;
if ( pBuffer == m_pLastAllocedBuffer )
m_pLastAllocedBuffer = pBuffer->pPrevBuffer;
pBuffer->pPrevBuffer = NULL;
pBuffer->pNextBuffer = NULL;
pBuffer->fl.lpFile = lpFile;
pBuffer->fl.nLine = nLine;
#endif
pBuffer->dwFreeTick = _getTickCount() + dwBufferFreeTick;
if ( pBuffer->dwSize == SmallBufferSize )
{
pBuffer->pPrevBuffer = m_pLastSmallBuffer;
m_pLastSmallBuffer = pBuffer;
m_dwAllocedSmallSize -= SmallBufferSize;
m_dwFreedSmallSize += SmallBufferSize;
}
else if ( pBuffer->dwSize == MiddleBufferSize )
{
pBuffer->pPrevBuffer = m_pLastMiddleBuffer;
m_pLastMiddleBuffer = pBuffer;
m_dwAllocedMiddleSize -= MiddleBufferSize;
m_dwFreedMiddleSize += MiddleBufferSize;
}
else if ( pBuffer->dwSize == LargeBufferSize )
{
pBuffer->pPrevBuffer = m_pLastLargeBuffer;
m_pLastLargeBuffer = pBuffer;
m_dwAllocedLargeSize -= LargeBufferSize;
m_dwFreedLargeSize += LargeBufferSize;
}
else
{
pBuffer->pPrevBuffer = m_pLastSuperBuffer;
m_pLastSuperBuffer = pBuffer;
m_dwAllocedSuperSize -= pBuffer->dwSize;
m_dwFreedSuperSize += pBuffer->dwSize;
}
//LeaveCriticalSection( &m_BufferLock );
m_BufferLock.Unlock();
}
VOID CBufferAllocator::GetMemoryInfo(CBufferAllocator::PALLOCATPR_MEMORY_INFOR pMemoryInfo)
{
pMemoryInfo->SmallBuffer.dwAllocSize = m_dwAllocedSmallSize;
pMemoryInfo->SmallBuffer.dwFreeSize = m_dwFreedSmallSize;
pMemoryInfo->MiddleBuffer.dwAllocSize = m_dwAllocedMiddleSize;
pMemoryInfo->MiddleBuffer.dwFreeSize = m_dwFreedMiddleSize;
pMemoryInfo->LargeBuffer.dwAllocSize = m_dwAllocedLargeSize;
pMemoryInfo->LargeBuffer.dwFreeSize = m_dwFreedLargeSize;
pMemoryInfo->SuperBuffer.dwAllocSize = m_dwAllocedSuperSize;
pMemoryInfo->SuperBuffer.dwFreeSize = m_dwFreedSuperSize;
}
VOID CBufferAllocator::CheckFreeBuffers(bool bIgnoreInterval)
{
PBUFFER pBuffer, pPrevBuffer, pLastBuffer;
LONGLONG dwTick = _getTickCount();
//EnterCriticalSection( &m_BufferLock );
m_BufferLock.Lock();
pBuffer = m_pLastSmallBuffer;
pLastBuffer = NULL;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
if (bIgnoreInterval || dwTick >= pBuffer->dwFreeTick)
{
if ( pBuffer == m_pLastSmallBuffer )
m_pLastSmallBuffer = pPrevBuffer;
if ( pLastBuffer )
pLastBuffer->pPrevBuffer = pPrevBuffer;
m_dwFreedSmallSize -= pBuffer->dwSize;
free( pBuffer );
}
else pLastBuffer = pBuffer;
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastMiddleBuffer;
pLastBuffer = NULL;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
if (bIgnoreInterval || dwTick >= pBuffer->dwFreeTick)
{
if ( pBuffer == m_pLastMiddleBuffer )
m_pLastMiddleBuffer = pPrevBuffer;
if ( pLastBuffer )
pLastBuffer->pPrevBuffer = pPrevBuffer;
m_dwFreedMiddleSize -= pBuffer->dwSize;
free( pBuffer );
}
else pLastBuffer = pBuffer;
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastLargeBuffer;
pLastBuffer = NULL;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
if (bIgnoreInterval || dwTick >= pBuffer->dwFreeTick)
{
if ( pBuffer == m_pLastLargeBuffer )
m_pLastLargeBuffer = pPrevBuffer;
if ( pLastBuffer )
pLastBuffer->pPrevBuffer = pPrevBuffer;
m_dwFreedLargeSize -= pBuffer->dwSize;
free( pBuffer );
}
else pLastBuffer = pBuffer;
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastSuperBuffer;
pLastBuffer = NULL;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
if (bIgnoreInterval || dwTick >= pBuffer->dwFreeTick)
{
if ( pBuffer == m_pLastSuperBuffer )
m_pLastSuperBuffer = pPrevBuffer;
if ( pLastBuffer )
pLastBuffer->pPrevBuffer = pPrevBuffer;
m_dwFreedSuperSize -= pBuffer->dwSize;
free( pBuffer );
}
else pLastBuffer = pBuffer;
pBuffer = pPrevBuffer;
}
//LeaveCriticalSection( &m_BufferLock );
m_BufferLock.Unlock();
}
#ifdef _BUFFER_TRACE
DataBuffer::DataBuffer(CBufferAllocator *pAllocator, size_t dwSize, const char *_FILE, const int _LINE)
#else
DataBuffer::DataBuffer(CBufferAllocator *pAllocator, size_t dwSize)
#endif
{
m_pAllocator = pAllocator;
m_dwSize = dwSize;
#ifdef _BUFFER_TRACE
pData = (char*)pAllocator->_AllocBuffer(dwSize, _FILE, _LINE);
#else
pData = (char*)pAllocator->AllocBuffer(dwSize);
#endif
ptr = pReadPtr = pData;
pEnd = pData + dwSize;
}
DataBuffer::~DataBuffer()
{
m_pAllocator->FreeBuffer( pData );
}

87
sdk/utils/CRC16.cpp Normal file
View File

@@ -0,0 +1,87 @@
/************************************************************
* crc16的checksum计算
* 如果g_ulTable没有初始化第一次使用的时候将初始化
***********************************************************/
#define CRC16_POLYNOMIAL 0x1021 // CRC_16校验方式的多项式.
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
static ulong g_ulTable[256];
static bool has_inited = false;
#include "_osdef.h"
// CRC_16方式校验的初始化函数, 计算CRC_16余数表.
void CRC16Init(void)
{
if (has_inited) return;
uint nRemainder;
int n, m;
ulong *pulTable = g_ulTable;
for(n = 0; n < 256; n ++)
{
nRemainder = (uint)n << 8;
for(m = 8; m > 0; m --)
{
if(nRemainder & 0x8000)
{
nRemainder = (nRemainder << 1) ^ CRC16_POLYNOMIAL;
}
else
{
nRemainder = (nRemainder << 1);
}
}
*(pulTable + n) = nRemainder;
}
has_inited =true;
}
// 反转数据的比特位, 反转后MSB为1.
// 反转前: 1110100011101110 0010100111100000
// 反转后: 1111001010001110 1110001011100000
unsigned int CRCBitReflect(ulong ulData, int nBits)
{
ulong ulResult = 0x00000000L;
int n;
for(n = 0; n < nBits; n ++)
{
if(ulData & 0x00000001L)
{
ulResult |= (ulong)(1L << ((nBits - 1) - n));
}
ulData = (ulData >> 1);
}
return(ulResult);
}
// 以CRC_16方式计算一个数据块的CRC值.
// pucData - 待校验的数据块指针.
// nBytes - 数据块大小, 单位是字节.
// 返回值是无符号的长整型, 其中低16位有效.
unsigned int CRC16Calc( unsigned char *pucData, size_t nBytes)
{
uint nRemainder, nRet;
uchar index;
if (has_inited ==false)
{
CRC16Init(); //如果没有初始化就初始化以下
}
ulong *pulTable = g_ulTable;
nRemainder = 0x0000;
for(size_t n = 0; n < nBytes; n ++)
{
index = (uchar)CRCBitReflect(*(pucData + n), 8) ^ (nRemainder >> 8);
nRemainder = (uint)*(pulTable + index) ^ (nRemainder << 8);
}
nRet = (uint)CRCBitReflect(nRemainder, 16) ^ 0x0000;
return(nRet);
}

12
sdk/utils/CRC16.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef _CRC_H_
#define _CRC_H_
// 以CRC_16方式计算一个数据块的CRC值.
// pData - 待校验的数据块指针.
// nBytes - 数据块大小, 单位是字节.
// 返回值是无符号的长整型, 其中低16位有效.
unsigned int CRC16Calc(unsigned char *pData, size_t nBytes);
#endif

78
sdk/utils/CRCUpdate.cpp Normal file
View File

@@ -0,0 +1,78 @@
#include "crc.h"
// Table of CRC-32's of all single-byte values (made by make_crc_table)
const unsigned int crc_table[256] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
/*
const uLong * get_crc_table()
{ return (const uLong *)crc_table;
}
*/
#define CRC_DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
#define CRC_DO2(buf) CRC_DO1(buf); CRC_DO1(buf);
#define CRC_DO4(buf) CRC_DO2(buf); CRC_DO2(buf);
#define CRC_DO8(buf) CRC_DO4(buf); CRC_DO4(buf);
unsigned int CRC32Update(unsigned int crc, const void *buf, int len)
{
char * cBuff = (char*)buf;
if (cBuff == 0) return 0L;
crc = crc ^ 0xffffffffL;
while (len >= 8) {CRC_DO8(cBuff); len -= 8;}
if (len) do {CRC_DO1(cBuff);} while (--len);
return crc ^ 0xffffffffL;
}

243
sdk/utils/EDCode.cpp Normal file
View File

@@ -0,0 +1,243 @@
#include <string.h>
#include "EDCode.h"
#define BUFFERSIZE 20480
char EncBuf[BUFFERSIZE], TempBuf[BUFFERSIZE];
//
//void Encode6BitBuf(const char *src, char *dest, int srclen, int destlen)
//{
// int restcount, destpos;
// unsigned char made, ch, rest;
// restcount = 0;
// rest = 0;
// destpos = 0;
// for (int I=0; I<srclen;++I)
// {
// if (destpos >= destlen)
// break;
// ch = (unsigned char)src[I];
// made = (unsigned char)((rest | (ch >> (2+restcount))) & 0x3F);
// rest = (unsigned char)(((ch << (8 - (2+restcount))) >> 2) & 0x3F);
// restcount += 2;
// if (restcount < 6)
// {
// dest[destpos] = made + 0x3C;
// destpos++;
// }
// else
// {
// if (destpos < destlen-1)
// {
// dest[destpos] = made + 0x3C;
// dest[destpos+1] = rest + 0x3C;
// destpos += 2;
// }
// else
// {
// dest[destpos] = made + 0x3C;
// destpos++;
// }
// restcount = 0;
// rest = 0;
// }
// }
// if (restcount)
// {
// dest[destpos] = rest + 0x3C;
// destpos++;
// }
// dest[destpos] = 0;
//}
//
//void Decode6BitBuf(const char *source, char *buf, int buflen)
//{
// const
// unsigned char Masks[5] = {0xFC, 0xF8, 0xF0, 0xE0, 0xC0};
// int len, bitpos, madebit, bufpos;
// int ch, tmp, _unsigned char;
// len = (int)strlen(source);
// bitpos = 2;
// madebit = bufpos = tmp = ch = 0;
// for (int I=0;I<len;++I)
// {
// if ((source[I] - 0x3C) >= 0)
// ch = (unsigned char)(source[I] - 0x3C);
// else
// {
// bufpos = 0;
// break;
// }
// if (bufpos >= buflen)
// break;
// if ((madebit+6) >= 8)
// {
// _unsigned char = (unsigned char)(tmp | ((ch & 0x3F) >> (6-bitpos)));
// buf[bufpos] = _unsigned char;
// bufpos++;
// madebit = 0;
// if (bitpos < 6)
// bitpos += 2;
// else
// {
// bitpos = 2;
// continue;
// }
// }
// tmp = (unsigned char)((unsigned char)(ch << bitpos) & Masks[bitpos-2]); // #### ##--
// madebit += 8-bitpos;
// }
// buf[bufpos] = 0;
//}
const char EncryptMinChar = 0x3C; //编码后的最小值
//3编4方式的如果值需要保持在0..7F范围内则此值的范围是3C..40
unsigned int Encode6BitBuf(const char *pSrc, char *pDest, unsigned int dwSrcSize, unsigned int dwMaxSize)
{
//前端掩码
static const unsigned char btFrontMasks[4] = { 0xFF, 0xF8, 0xE0, 0x80 };
static const unsigned char btBehindMasks[4] = { 0x00, 0x01, 0x07, 0x1F };
static const unsigned char btBitMasks[4] = { 0x00, 0x06, 0x18, 0x60 };
char btSrc, btNew, btIdx, btFront, btBehind;
unsigned int dwSizeLeft;
dwSizeLeft = dwMaxSize;
if ( dwSizeLeft )
{
btIdx = 3;
btNew = 0;
while (dwSrcSize)
{
btSrc = *pSrc;
btNew = btNew | (btSrc & btBitMasks[btIdx]); //取第 btIdx 位
btFront = (btSrc & btFrontMasks[btIdx]) >> 2; //保存 btIdx 前的位
btBehind= btSrc & btBehindMasks[btIdx]; //保存 btIdx 后的位
*pDest = (btFront | btBehind ) + EncryptMinChar;
dwSizeLeft--;
if (!dwSizeLeft)
break;
pDest++;
btIdx--;
if ( !btIdx )
{
*pDest = (btNew >> 1) + EncryptMinChar;
dwSizeLeft--;
if (!dwSizeLeft)
break;
pDest++;
btIdx = 3;
btNew = 0;
}
pSrc++;
dwSrcSize--;
}
if ( !dwSrcSize && (btIdx != 3) )//remaind
{
*pDest = (btNew >> 1) + EncryptMinChar;;
dwSizeLeft--;
pDest++;
}
if ( dwSizeLeft )
pDest[0] = 0;
}
return dwMaxSize - dwSizeLeft;
}
unsigned int Decode6BitBuf(const char *pSrc, char *pDest, unsigned int dwSrcSize, unsigned int dwMaxSize)
{
//前端掩码
static const unsigned char btFrontMasks[4] = { 0xFF, 0xFE, 0xF8, 0xE0 };
static const unsigned char btBehindMasks[4]= { 0x00, 0x01, 0x07, 0x1F };
static const unsigned char btBitMasks[4] = { 0x00, 0x06, 0x18, 0x60 };
char btSrc, btFront, btBehind, btBits, btIdx;
unsigned int dwSizeLeft;
dwSizeLeft = dwMaxSize;
if ( dwSizeLeft )
{
btIdx = 3;
while ( dwSrcSize > 1 )
{
if ( btIdx == 3 )
{
btBits = (dwSrcSize > 3) ? pSrc[3] : pSrc[dwSrcSize-1];
btBits = (btBits - EncryptMinChar) << 1;
}
btSrc = *pSrc - EncryptMinChar;
btFront = (btSrc & btFrontMasks[btIdx]) << 2;
btBehind= btSrc & btBehindMasks[btIdx];
*pDest = btFront | btBehind | (btBits & btBitMasks[btIdx]);
dwSizeLeft--;
if ( !dwSizeLeft )
break;
pDest++;
btIdx--;
if ( !btIdx )
{
dwSrcSize--;
if ( !dwSrcSize )
break;
pSrc++;
btIdx = 3;
}
dwSrcSize--;
pSrc++;
}
if ( dwSizeLeft )
pDest[0] = 0;
}
return dwMaxSize - dwSizeLeft;
}
char * EnCodeBuffer(const void *InBuf, size_t BufSize)
{
if ( BufSize >= BUFFERSIZE )
BufSize = BUFFERSIZE - 1;
Encode6BitBuf((char*)InBuf, (char*)&EncBuf, (unsigned int)BufSize, BUFFERSIZE);
return EncBuf;
}
void DeCodeBuffer(const void *InBuf, void *OutBuf, size_t SrcSize, size_t MaxSize)
{
Decode6BitBuf ((char*)InBuf, (char*)EncBuf, (unsigned int)SrcSize, BUFFERSIZE);
memcpy(OutBuf, &EncBuf[0], MaxSize);
}
unsigned int GetEncryptedSize(unsigned int dwSize)
{
unsigned int Result = dwSize + dwSize / 3;
if ( dwSize % 3 )
Result++;
return Result;
}
unsigned int GetDecryptedSize(unsigned int dwSize)
{
unsigned int Result = dwSize / 4 * 3;
if ( dwSize & 3 )
Result += (dwSize & 3) - 1;
return Result;
}

27
sdk/utils/EDCode.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef EDCODE_H
#define EDCODE_H
//#include <windows.h>
extern "C"
{
/*
#ifndef STDCALL
#define STDCALL __stdcall
#endif
*/
unsigned int Encode6BitBuf(const char *pSrc, char *pDest, unsigned int dwSrcSize, unsigned int dwMaxSize);
unsigned int Decode6BitBuf(const char *pSrc, char *pDest, unsigned int dwSrcSize, unsigned int dwMaxSize);
unsigned int GetEncryptedSize(unsigned int dwSize);
unsigned int GetDecryptedSize(unsigned int dwSize);
#define EncodeBuffer( i, o, si, so ) (Encode6BitBuf( (char*)(i), (char*)(o), (DWORD)(si), (DWORD)(so) ))
#define DecodeBuffer( i, o, si, so ) (Decode6BitBuf( (char*)(i), (char*)(o), (DWORD)(si), (DWORD)(so)))
}
#endif

86
sdk/utils/Encrypt.cpp Normal file
View File

@@ -0,0 +1,86 @@
/*/////////////////////////////////////////////////////////////////////////
文件名: Encrypt.cpp
功能描述: 数据加解密的处理
创建人: xiaoql
创建时间: 2010年06月04日
/////////////////////////////////////////////////////////////////////////*/
//#include <Windows.h>
//#include "CRC.h"
#include "Encrypt.h"
#include <time.h>
#include "wrand.h"
void Encrypt::SetSelfSalt(unsigned int salt)
{
if (salt)
{
m_nSelfSalt = salt;
}
}
unsigned int Encrypt::GenSalt()
{
unsigned int salt =0;
//srand((int) time( NULL ) );
do
{
salt = (unsigned int) wrandvalue();
}while (! salt);
return salt;
}
void Encrypt::SetTargetSalt(unsigned int salt,bool isClient)
{
m_nTargetSalt =salt;
if (m_nSelfSalt ==0)
{
m_nSelfSalt =GenSalt();
}
GenKey(isClient);
}
//先随便使用一个加密算法进行数据加密
void Encrypt::GenKey(bool isClient)
{
if (m_nSelfSalt && m_nTargetSalt)
{
if(isClient)
{
m_nKey =( m_nSelfSalt ^ m_nTargetSalt) + m_nSelfSalt + 8654 ;
}
else
{
m_nKey =( m_nSelfSalt ^ m_nTargetSalt) + m_nTargetSalt + 8654 ;
}
*((PINT)m_sKeybuff) = m_nKey;
}
}
bool Encrypt::Encode(char *pInBuff,size_t len,char *pOutBuff)
{
if (m_nSelfSalt && m_nTargetSalt )
{
for (size_t i=0;i< len; i++)
{
pOutBuff[i] = pInBuff[i] ^ m_sKeybuff[i&3];
}
return true;
}
else
{
return false;
}
}
bool Encrypt::Decode(char *pInBuff,size_t len,char * pOutBuff)
{
//当前的加密算法和解密算法是一样的,反向操作
return Encode(pInBuff,len,pOutBuff);
}

79
sdk/utils/Encrypt.h Normal file
View File

@@ -0,0 +1,79 @@
#pragma once
#include <string.h>
#include "_osdef.h"
#include "CRC16.h"
class Encrypt
{
public:
Encrypt()
{
Reset();
}
//重置
inline void Reset()
{
memset(this,0,sizeof(*this));
}
void SetSelfSalt(unsigned int salt); //设置自己的随机数
/*
* Comments: 设置目标的key
* Parameter: unsigned int salt:目标的salt
* Parameter: bool isClient:自身是作为客户端还是服务器使用了不对称的key生成算法
* @Return void:
*/
void SetTargetSalt(unsigned int salt,bool isClient=false); //设置通信方的随机数,同时会生成key
unsigned int GetSelfSalt(){return m_nSelfSalt;} //获取自身的随机数
unsigned int GetTargetSalt() {return m_nTargetSalt; } //获取目标的随机数
bool Encode( char *pInBuff,size_t len,char *pOutBuff ); //加密数据
bool Decode( char *pInBuff,size_t len,char *pOutBuff ); //解密数据
inline bool IsKeyCrcCorrect( WORD nKeyCRC) //
{
return (GetKeyCRC()== nKeyCRC);
}
inline static UINT_PTR CRC16(LPCVOID lpBuffer, size_t len) //计算CRC-16的Checksum
{
return CRC16Calc((unsigned char *)lpBuffer,len);
}
inline unsigned int GetKey()
{
return m_nKey;
}
WORD GetKeyCRC() //获取key的crc值
{
return (CRC16(m_sKeybuff,4) & 0xffff);
}
unsigned int GenSalt(); // 产生salt
//增长checksum
inline void IncreaseCheckSum()
{
m_wCheckSum += 1;
}
inline WORD GetCheckSum()
{
return m_wCheckSum;
}
private:
void GenKey(bool isClient=false); //产生密钥
private:
unsigned int m_nSelfSalt; //自己产生的随机数
unsigned int m_nTargetSalt; //通信方的随机数
unsigned int m_nKey; //密钥
unsigned char m_sKeybuff[4] ; //密钥的buff添加这个为了方便计算
WORD m_wCheckSum; //一个数,自增长的,用于防止重复发包
};

460
sdk/utils/FileLogger.cpp Normal file
View File

@@ -0,0 +1,460 @@
#include <new>
#include <stdio.h>
#ifdef WIN32
#include <tchar.h>
#include <Windows.h>
#endif
#include <stdarg.h>
#include <_ast.h>
#include <_memchk.h>
#include <Tick.h>
#include <Lock.h>
#include <QueueList.h>
#include <Thread.h>
#include <Stream.h>
#include <RefClass.hpp>
#include "ShareUtil.h"
#include <BufferAllocator.h>
#include "DataPacket.hpp"
#include "FileLogger.h"
#include <time.h>
#include <FDOP.h>
using namespace wylib::sync::lock;
using namespace wylib::container;
using namespace wylib::stream;
class COPMToFile :
protected wylib::thread::CBaseThread
{
public:
COPMToFile(LPCTSTR lpLogFilePath):
wylib::thread::CBaseThread("COPMToFile")
{
char dirName[512];
FDOP::ExtractFileDirectory(lpLogFilePath,dirName,sizeof(dirName));
FDOP::DeepCreateDirectory(dirName);
m_fFile =new wylib::stream::CFileStream(lpLogFilePath,CFileStream::faWrite |
CFileStream::faShareRead , CFileStream::AlwaysCreate);
m_nRefer = 1;
m_WriteMsgList.setLock(&m_WriteMsgLock);
m_FreeMsgList.setLock(&m_FreeMsgLock);
//将写指针调整到文件末尾
m_fFile->seek(0, CFileStream::soEnd);
StartWorkThread();
m_bNeedDump = false;
#ifdef WIN32
m_hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
}
//增加引用计数,函数返回增加引用后的引用计数值
inline LONG addRef()
{
return InterlockedIncrement(&m_nRefer);
}
//减少引用计数,函数返回减少引用后的引用计数值
//当减少引用后引用计数为0则自动销毁对象自身。
inline LONG release()
{
LONG n = InterlockedDecrement(&m_nRefer);
if ( n == 0 )
delete this;
return n;
}
~COPMToFile()
{
INT_PTR i;
//终止数据写入线程
/*resume();
terminate();
waitFor();*/
StopWorkThread();
//销毁写入列表中的数据包
m_WriteMsgList.flush();
for (i=m_WriteMsgList.count()-1; i>-1; --i)
{
m_WriteMsgList[i]->~CDataPacket();
}
m_WriteMsgList.empty();
//销毁空闲列表中的数据包
for (i=m_FreeMsgList.count()-1; i>-1; --i)
{
m_FreeMsgList[i]->~CDataPacket();
}
m_FreeMsgList.empty();
//释放数据包内存
for (i=m_MsgPackMemList.count()-1; i>-1; --i)
{
m_Allocator.FreeBuffer(m_MsgPackMemList[i]);
}
m_MsgPackMemList.empty();
}
void addMsg(SHAREOUTPUTMSGTYPE eMsgType, LPCTSTR sText, INT_PTR nTextLen)
{
static const int PackBlockSize = 256;
CDataPacket *pPacket;
SYSTEMTIME sysTime;
m_FreeMsgList.lock();
INT_PTR nCount = m_FreeMsgList.count();
//如果空闲数据包队列没有数据了则申请PackBlockSize个数据包
if ( nCount <= 0 )
{
pPacket = (CDataPacket*)m_Allocator.AllocBuffer(sizeof(*pPacket) * PackBlockSize);
m_MsgPackMemList.add(pPacket);
for (int i=0; i<PackBlockSize; ++i )
{
new(pPacket)CDataPacket(&m_Allocator);
m_FreeMsgList.add(pPacket);
pPacket++;
}
nCount = PackBlockSize;
}
//从空闲数据包队列中取出最后一个
nCount--;
pPacket = m_FreeMsgList[nCount];
m_FreeMsgList.trunc(nCount);
m_FreeMsgList.unlock();
//清空数据
pPacket->setPosition(0);
//写入消息类型
*pPacket << eMsgType;
//写入时间
GetLocalTime(&sysTime);
pPacket->writeBuf(&sysTime, sizeof(sysTime));
//写入消息内容
*pPacket << (WORD)nTextLen;
pPacket->writeBuf(sText, nTextLen * sizeof(*sText));
*pPacket << (TCHAR)0;//写入终止符
//数据包追加到写数据列表中
m_WriteMsgList.append(pPacket);
}
void Dump()
{
m_bNeedDump = true;
}
protected:
VOID OnRountine()
{
while ( !terminated() )
{
if (m_bNeedDump)
{
DumpImpl();
m_bNeedDump = false;
}
ProcessMessages();
Sleep(16);
}
}
//处理所有日志记录
VOID ProcessMessages()
{
INT_PTR i, nCount;
SHAREOUTPUTMSGTYPE msgType;
size_t nMsgLen, nTmsLen;
LPCTSTR sMsg;
SYSTEMTIME sysTime;
TCHAR sTimeStr[64];
char sMsgBuf[4096];
m_WriteMsgList.flush();
nCount = m_WriteMsgList.count();
for (i=0; i<nCount; ++i)
{
CDataPacket &pack = *(m_WriteMsgList[i]);
pack.setPosition(0);
pack >> msgType;
pack >> sysTime;
#ifdef UNICODE
nMsgLen = pack.readWideString(NULL, 0);
#else
nMsgLen = pack.readString(NULL, 0);
#endif
pack >> sMsg;
if (sMsg)
{
nTmsLen = _stprintf( sTimeStr, _T("[%02d-%02d-%02d %02d:%02d:%02d]"), sysTime.wYear - 2000, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond );
//转换为ASC编码
#ifdef WIN32
convertToACP(sMsg, nMsgLen, sMsgBuf, ArrayCount(sMsgBuf));
//显示此消息
displayMessage(msgType, sTimeStr, sMsgBuf, nMsgLen);
//转换为UTF-8编码
nMsgLen = convertToUTF8(sMsg, nMsgLen, sMsgBuf, ArrayCount(sMsgBuf));
writeMessage(msgType, sTimeStr, nTmsLen, sMsgBuf, nMsgLen);
#else
displayMessage(msgType, sTimeStr, sMsg, nMsgLen);
writeMessage(msgType, sTimeStr, nTmsLen, sMsg, nMsgLen);
#endif
//向文件写入此消息
}
else if (IsDebuggerPresent())
{
DebugBreak();
}
}
//将写入列表的数据包全部还原回空闲列表中
m_FreeMsgList.lock();
m_FreeMsgList.addArray(m_WriteMsgList, nCount);
m_WriteMsgList.trunc(0);
m_FreeMsgList.unlock();
}
//向文件写入消息记录
void writeMessage(SHAREOUTPUTMSGTYPE msgType, const char* sTimeStr, const size_t nTmsLen, const char* sMsgBuf, const size_t nMsgLen)
{
static struct
{
LPCTSTR sBegin, sEnd;
size_t sizeBegin, sizeEnd;
}
FormatTags[] =
{
{ _T(""), _T("\n"), _tcslen(FormatTags[0].sBegin) * sizeof(FormatTags[0].sBegin[0]), _tcslen(FormatTags[0].sEnd) * sizeof(FormatTags[0].sEnd[0]), },
{ _T("[WRN]"), _T("\n"), _tcslen(FormatTags[1].sBegin) * sizeof(FormatTags[1].sBegin[0]), _tcslen(FormatTags[1].sEnd) * sizeof(FormatTags[1].sEnd[0]), },
{ _T("[TIP]"), _T("\n"), _tcslen(FormatTags[2].sBegin) * sizeof(FormatTags[2].sBegin[0]), _tcslen(FormatTags[2].sEnd) * sizeof(FormatTags[2].sEnd[0]), },
{ _T("[ERR]"), _T("\n"), _tcslen(FormatTags[3].sBegin) * sizeof(FormatTags[3].sBegin[0]), _tcslen(FormatTags[3].sEnd) * sizeof(FormatTags[3].sEnd[0]), },
};
m_fFile->write(sTimeStr, nTmsLen * sizeof(*sTimeStr));
if ( FormatTags[msgType].sizeBegin > 0 )
m_fFile->write(FormatTags[msgType].sBegin, FormatTags[msgType].sizeBegin);
m_fFile->write(sMsgBuf, nMsgLen * sizeof(*sMsgBuf));
if ( FormatTags[msgType].sizeEnd > 0 )
m_fFile->write(FormatTags[msgType].sEnd, FormatTags[msgType].sizeEnd);
}
//显示日志消息
void displayMessage(SHAREOUTPUTMSGTYPE msgType, const char* sTimeStr, const char* sMsgBuf, const size_t nMsgLen)
{
#ifdef WIN32
WORD wColorAttrs;
switch ( msgType )
{
case rmWaning:
wColorAttrs = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
break;
case rmError:
wColorAttrs = FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
//case rmSystem:
// wColorAttrs = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
// break;
default:
wColorAttrs = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
}
SetConsoleTextAttribute(m_hStdOut, wColorAttrs);
printf(sTimeStr);
switch ( msgType )
{
case rmWaning: printf( ("[WRN]") ); break;
case rmTip: printf( ("[TIP]") ); break;
case rmError: printf( ("[ERR]") ); break;
}
puts(sMsgBuf);
#else
switch ( msgType )
{
case rmWaning:
printf("\033[0;34m%s[WRN]%s\033[0m\r\n",sTimeStr,sMsgBuf);
break;
case rmError:
printf("\033[0;31m%s[ERR]%s\033[0m\r\n",sTimeStr,sMsgBuf);
break;
case rmTip:
printf("%s[TIP]%s\r\n",sTimeStr,sMsgBuf);
break;
default:
printf("%s%s\r\n",sTimeStr,sMsgBuf);
break;
}
#endif
}
#ifdef WIN32
//转换文字编码为UTF-8
size_t convertToUTF8(const char* lpMsg, const size_t nMsgLen, char *pBuffer, const size_t BufferLen)
{
WCHAR sWCBuf[4096];
DWORD cch = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, lpMsg, (int)nMsgLen, sWCBuf, ArrayCount(sWCBuf)-1);
if ( cch <= 0 )
cch = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, lpMsg, (int)nMsgLen, sWCBuf, ArrayCount(sWCBuf)-1);
if ( cch > 0 )
{
cch = (DWORD)WideCharToMultiByte(CP_UTF8, 0, sWCBuf, cch, pBuffer, (int)(BufferLen-1), NULL, NULL);
if ( cch > 0 )
{
pBuffer[cch] = 0;
return cch;
}
}
return 0;
}
//转换文字编码为ASC
size_t convertToACP(const char* lpMsg, const size_t nMsgLen, char *pBuffer, const size_t BufferLen)
{
WCHAR sWCBuf[4096];
DWORD cch = (DWORD)MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, lpMsg, (int)nMsgLen, sWCBuf, ArrayCount(sWCBuf)-1);
if ( cch > 0 )
{
cch = (DWORD)WideCharToMultiByte(CP_ACP, 0, sWCBuf, cch, pBuffer, int(BufferLen-1), NULL, NULL);
if ( cch > 0 )
{
pBuffer[cch] = 0;
return cch;
}
}
//本身就是ACP
else
{
cch = (DWORD)__min(BufferLen-1, nMsgLen);
memcpy(pBuffer, lpMsg, cch);
pBuffer[cch] = 0;
return cch;
}
return 0;
}
#endif
void DumpImpl()
{
using namespace wylib::stream;
using namespace wylib::container;
CFileStream fs(_T("FileLoggerStat.log"), CFileStream::faWrite, CFileStream::AlwaysOpen);
fs.setPosition(fs.getSize());
const TCHAR szSep[] = _T("-------------------------------------------------------------------------------------------\r\n");
time_t szClock;
time(&szClock);
struct tm curTime;
localtime_r(&szClock,&curTime);
TCHAR szDateTime[250] = {0};
_tcsftime(szDateTime, _tcslen(szDateTime)-1, _T("%Y-%m-%d %H:%M:%S\r\n"), &curTime);
fs.write(szSep, _tcslen(szSep)*sizeof(TCHAR));
fs.write(szDateTime, _tcslen(szDateTime)*sizeof(TCHAR));
TCHAR szDesc[256] = {0};
//_stprintf(szDesc, _T("%-40s%-25s%-25s%-25s%-25s\r\n"), _T("HandleMgrName"), _T("UsedHandleCount"), _T("MaxUsedHdlCount"), _T("AllocedBlockNum"), _T("HandlePerBlock"));
_stprintf(szDesc, _T("总分配的数据包数目 = %d\r\n"), m_MsgPackMemList.count());
fs.write(szDesc, _tcslen(szDesc)*sizeof(TCHAR));
CBufferAllocator::ALLOCATOR_MEMORY_INFO mi;
INT_PTR nFreeMsgCount = 0, nPrepareWriteMsgCount = 0;
// 获取空闲可用消息数量以及总共内存分配情况
m_FreeMsgList.lock();
nFreeMsgCount = m_FreeMsgList.count();
m_Allocator.GetMemoryInfo(&mi);
m_FreeMsgList.unlock();
_stprintf(szDesc, _T("小块内存总分配字节数 = %-20d, 空闲字节数=%d\r\n"), mi.SmallBuffer.dwAllocSize, mi.SmallBuffer.dwFreeSize);
fs.write(szDesc, _tcslen(szDesc)*sizeof(TCHAR));
_stprintf(szDesc, _T("中块内存总分配字节数 = %-20d, 空闲字节数=%d\r\n"), mi.MiddleBuffer.dwAllocSize, mi.MiddleBuffer.dwFreeSize);
fs.write(szDesc, _tcslen(szDesc)*sizeof(TCHAR));
_stprintf(szDesc, _T("大块内存总分配字节数 = %-20d, 空闲字节数=%d\r\n"), mi.LargeBuffer.dwAllocSize, mi.LargeBuffer.dwFreeSize);
fs.write(szDesc, _tcslen(szDesc)*sizeof(TCHAR));
_stprintf(szDesc, _T("超大块内存总分配字节数 = %-20d, 空闲字节数=%d\r\n"), mi.SuperBuffer.dwAllocSize, mi.SuperBuffer.dwFreeSize);
fs.write(szDesc, _tcslen(szDesc)*sizeof(TCHAR));
// 获取带写入的消息数量
m_WriteMsgList.lock();
nPrepareWriteMsgCount = m_WriteMsgList.count() + m_WriteMsgList.appendCount();
m_WriteMsgList.unlock();
_stprintf(szDesc, _T("空闲日志消息数量 = %-20d, 待写入消息数量=%d\r\n"), nFreeMsgCount, nPrepareWriteMsgCount);
fs.write(szDesc, _tcslen(szDesc)*sizeof(TCHAR));
fs.write(szSep, _tcslen(szSep)*sizeof(TCHAR));
}
private:
LONG m_nRefer; //引用计数
CBufferAllocator m_Allocator; //内存管理器
CCSLock m_WriteMsgLock; //待写入到文件的消息列表锁
CCSLock m_FreeMsgLock; //空闲消息包列表锁
CQueueList<CDataPacket*> m_WriteMsgList; //待写入到文件的消息列表
CLockList<CDataPacket*> m_FreeMsgList; //空闲消息包列表
CBaseList<CDataPacket*> m_MsgPackMemList;//消息包列表内存头指针列表
bool m_bNeedDump;
wylib::stream::CFileStream* m_fFile;
#ifdef WIN32
HANDLE m_hStdOut;
#endif
};
COPMToFile *g_pOPMToFile;
SHAREOUTPUTMSGFN lpOldFnBeforeSet;
INT_PTR STDCALL OutputMsgToFileFn(SHAREOUTPUTMSGTYPE MsgType, LPCTSTR lpMsg, INT_PTR nMsgLen)
{
g_pOPMToFile->addMsg(MsgType, lpMsg, nMsgLen);
return nMsgLen;
}
void DumpFileLogger()
{
g_pOPMToFile->Dump();
}
const TCHAR* getCurrentTimeDesc()
{
static TCHAR szDataTime[256] = {0};
//time_t szClock;
//time(&szClock);
//struct tm *curTime = localtime(&szClock);
//_tcsftime(szDataTime, sizeof(szDataTime)-1, _T("%Y-%m-%d %H-%M-%S"), curTime);
SystemTime sysTime;
GetSystemTime(sysTime);
SNPRINTFA(szDataTime, sizeof(szDataTime) - 1, "%s%d%d%d.txt", szDataTime, sysTime.year_, sysTime.mon_, sysTime.mday_);
return szDataTime;
}
CFileLogger::CFileLogger(LPCTSTR sLogFileNamePattern, ...)
{
if ( !g_pOPMToFile )
{
TCHAR* pszFileName = new TCHAR[MAX_PATH];
va_list ap;
va_start(ap, sLogFileNamePattern);
_vsntprintf(pszFileName, MAX_PATH-1, sLogFileNamePattern, ap);
va_end(ap);
g_pOPMToFile = new COPMToFile(pszFileName);
lpOldFnBeforeSet = SetOutputMsgFn(OutputMsgToFileFn);
delete []pszFileName;
}
else g_pOPMToFile->addRef();
}
CFileLogger::~CFileLogger()
{
if ( g_pOPMToFile )
{
if ( g_pOPMToFile->release() == 0 )
{
SetOutputMsgFn(lpOldFnBeforeSet);
g_pOPMToFile = NULL;
}
}
}
void CFileLogger::Dump()
{
if (g_pOPMToFile)
g_pOPMToFile->Dump();
}
void CFileLogger::DumpToFile()
{
if (g_pOPMToFile)
g_pOPMToFile->Dump();
}

24
sdk/utils/FileLogger.h Normal file
View File

@@ -0,0 +1,24 @@
#pragma once
/*********************************************************
日志文件记录器
生成的日志文件是HTML格式的
将此类型在main函数中定义一份变量即可请勿在一个程序中多次使用此类型
*********************************************************/
const TCHAR* getCurrentTimeDesc();
class CFileLogger
{
public:
CFileLogger(LPCTSTR sLogFileNamePattern, ...);
~CFileLogger();
void Dump();
static void DumpToFile();
//void SetNeedOutput(bool bFlag = true);
};

View File

@@ -0,0 +1,85 @@
#include "_osdef.h"
#include "Stream.h"
using namespace wylib::stream;
#ifdef WIN32
CHandleStream::CHandleStream(HANDLE StreamHandle)
#else
CHandleStream::CHandleStream(int StreamHandle)
#endif
:Inherited()
{
m_hHandle = StreamHandle;
}
#ifdef WIN32
void CHandleStream::setHandle(HANDLE Handle)
#else
void CHandleStream::setHandle(int Handle)
#endif
{
m_hHandle = Handle;
}
bool CHandleStream::setSize(LONGLONG tSize)
{
#ifdef WIN32
seek( tSize, soBeginning );
return SetEndOfFile( m_hHandle ) != FALSE;
#else
return ftruncate(m_hHandle, lseek(m_hHandle, tSize, SEEK_SET)) == 0;
#endif
}
LONGLONG CHandleStream::seek(const LONGLONG tOffset, const int Origin)
{
#ifdef WIN32
LARGE_INTEGER li, nNewPointer;
li.QuadPart = tOffset;
if ( SetFilePointerEx( m_hHandle, li, &nNewPointer, Origin ) )
return (LONGLONG)nNewPointer.QuadPart;
else return -1;
#else
if( Origin == soBeginning )
return ( LONGLONG )lseek( m_hHandle, tOffset, SEEK_SET ) ;
else if( Origin == soCurrent )
return ( LONGLONG )lseek( m_hHandle, tOffset, SEEK_CUR ) ;
else if( Origin == soEnd )
return ( LONGLONG )lseek( m_hHandle, tOffset, SEEK_END ) ;
else
return -1;
#endif
}
LONGLONG CHandleStream::read(LPVOID lpBuffer, const LONGLONG tSizeToRead)
{
DWORD dwBytesReaded;
#ifdef WIN32
if ( ReadFile( m_hHandle, lpBuffer, (DWORD)tSizeToRead, &dwBytesReaded, NULL ) )
return dwBytesReaded;
else return -1;
#else
dwBytesReaded = ::read( m_hHandle, lpBuffer, (int)tSizeToRead) ;
if(dwBytesReaded > 0)
return dwBytesReaded;
else return -1;
#endif
}
LONGLONG CHandleStream::write(LPCVOID lpBuffer, const LONGLONG tSizeToWrite)
{
DWORD dwBytesWriten;
#ifdef WIN32
if ( WriteFile( m_hHandle, lpBuffer, (DWORD)tSizeToWrite, &dwBytesWriten, NULL ) )
return dwBytesWriten;
else return -1;
#else
dwBytesWriten = ::write( m_hHandle, lpBuffer, (int)tSizeToWrite);
if(dwBytesWriten > 0)
return dwBytesWriten;
else return -1;
#endif
}

View File

@@ -0,0 +1,19 @@
#ifdef WIN32
#include <Windows.h>
#endif
#include "MiniDateTime.h"
const unsigned int CMiniDateTime::SecOfYear[2] = { 365 * SecOfDay, 366 * SecOfDay };
const unsigned int CMiniDateTime::SecOfMonth[2][13] =
{
{0, 31 * SecOfDay, 28 * SecOfDay, 31 * SecOfDay, 30 * SecOfDay, 31 * SecOfDay, 30 * SecOfDay, 31 * SecOfDay, 31 * SecOfDay, 30 * SecOfDay, 31 * SecOfDay, 30 * SecOfDay, 31 * SecOfDay},
{0, 31 * SecOfDay, 29 * SecOfDay, 31 * SecOfDay, 30 * SecOfDay, 31 * SecOfDay, 30 * SecOfDay, 31 * SecOfDay, 31 * SecOfDay, 30 * SecOfDay, 31 * SecOfDay, 30 * SecOfDay, 31 * SecOfDay}
};
const unsigned int CMiniDateTime::MonthDays[2][13] =
{
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

305
sdk/utils/MiniDateTime.h Normal file
View File

@@ -0,0 +1,305 @@
#pragma once
/************************************************************************
使用32位的原子数据描述日期和时间的数据类型
由于使用32位的原子数据导致数据的存储值范围有限因此时间值的最小单位是秒。对于一个
时间值本类型实际存储的就是自2010年1月1日0点到当前时间所经过的秒数
取得两个时间对象的时间差,可以直接使用减法运算。将一个日期值增加一定的时间,可以直接
增加时间的秒数。
★实际上数据存储的时间值使用0到30位第31位表示此时间是否开始计时的记录标志位
如一个装备在产生的时候肯能带有一个使用时限时间值表示的是该装备可以使用的时长例如1天
30天。而装备仅在第一次被玩家穿戴的时候才开始计时。当计时开始的时候时间值被修改为使用
时长加当前时间值,且最高位被置位来表示这个物品的时间已经开始了计时。
★短时间类型能够描述的最大日期为2079年1月1日。
************************************************************************/
#pragma pack (push, 1)
#include <string.h>
#include "_osdef.h"
struct CMiniDateTime
{
public:
//定义短时间类型开始的年份
static const int YearBase = 2010;
//定义时间是否已经开始计时的标志位
static const unsigned int RecordFlag = 0x80000000;
//定义各种单位的时间的秒数
static const unsigned int SecOfMin = 60;
static const unsigned int SecOfHour = SecOfMin * 60;
static const unsigned int SecOfDay = SecOfHour * 24;
static const unsigned int SecOfYear[2];
static const unsigned int SecOfMonth[2][13];//以月为第二数组的下标,免去月份-1的操作
static const unsigned int MonthDays[2][13];//以月为第二数组的下标,免去月份-1的操作
public:
/* 从规定的日期和时间中设置短日期时间类型值
* year 公元年份例如2012
* month 月份注意1表示1月而非0
* day 日份注意1表示1号而非0
* hour 小时0表示0点23表示晚上11点
* min 分钟0表示0分
* sec 秒钟0表示0秒
* ★★★运算函数不会改变时间的记录标志位
*/
inline CMiniDateTime& encode(const unsigned int year, const unsigned int mon, const unsigned int day,
const unsigned int hour, const unsigned int min, const unsigned int sec)
{
int i;
unsigned int v = 0;
//计算年份经过的秒数
for (i=year - 1; i>=YearBase; --i)
{
v += SecOfYear[isLeapYear(i)];
}
//计算当年1月到本月的秒数
bool boLeepYear = isLeapYear(year);
for (i=mon -1; i>=1; --i)
{
v += SecOfMonth[boLeepYear][i];
}
//计算当年1号到今天的秒数
v += (day - 1) * SecOfDay;
//计算今天0点到现在的秒数
v += hour * SecOfHour;
//计算当前小时的0分到现在的秒数
v += min * SecOfMin;
v += sec;
tv = (tv & RecordFlag) | (v & (~RecordFlag));
return *this;
}
// 从MiniDataTime转化到系统时间。暂时只精确到天。
inline void decode(SYSTEMTIME &sysTime)
{
unsigned int v = tv & (~RecordFlag);
// 年
int year = YearBase;
while (true)
{
unsigned int nSecOfCurrYear = SecOfYear[isLeapYear(year)];
if (v >= nSecOfCurrYear)
{
v -= nSecOfCurrYear;
year++;
}
else
break;
}
// 月
bool bIsLeepYear = isLeapYear(year);
int month = 1; // index based 1 <<<<
while (true)
{
unsigned int nSecOfCurrMonth = SecOfMonth[bIsLeepYear][month];
if (v >= nSecOfCurrMonth)
{
v -= nSecOfCurrMonth;
month++;
}
else
break;
}
// 日
int day = v / SecOfDay + 1; // index based 1 <<<<
memset(&sysTime, 0, sizeof sysTime);
sysTime.wYear = year;
sysTime.wMonth = month;
sysTime.wDay = day;
//小时、分、秒
UINT SecOfToday = v % (24 * 3600);
sysTime.wHour = SecOfToday / 3600;
sysTime.wMinute = (SecOfToday % 3600) / 60;
sysTime.wSecond = SecOfToday % 60;
}
inline bool isSameDay(const CMiniDateTime &rhs)
{
return ((tv & (~RecordFlag)) / SecOfDay) == ((rhs.tv & (~RecordFlag)) / SecOfDay) ? true : false;
}
//从SYSTEMTIME结构中设置日期时间值
inline CMiniDateTime& encode(const SYSTEMTIME& sysTime)
{
return encode(sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
}
//开始记录时间timeOfNow参数表示当前时间的短时间类型值
inline CMiniDateTime& startRecord(const unsigned int timeOfNow)
{
if ( !(tv & RecordFlag) )
tv = RecordFlag | ((timeOfNow & (~RecordFlag)) + tv);
return *this;
}
//获取当前日期时间的短时间值
inline static unsigned int now()
{
CMiniDateTime tv;
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
tv.encode(sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
return tv.tv;
}
//获取今天凌晨的时间
inline static unsigned int today()
{
CMiniDateTime tv;
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
tv.encode(sysTime.wYear, sysTime.wMonth, sysTime.wDay, 0, 0, 0);
return tv.tv;
}
//计算明日凌晨的值
inline static unsigned int tomorrow()
{
int dayofMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
CMiniDateTime tv;
SYSTEMTIME sysTime;
GetLocalTime(&sysTime);
sysTime.wDay++;
if (sysTime.wMonth == 2 && isLeapYear(sysTime.wYear))
{
if (sysTime.wDay > 29)
{
sysTime.wMonth++;
sysTime.wDay = 1;
}
}
else if (sysTime.wDay > dayofMonth[sysTime.wMonth-1])
{
sysTime.wMonth++;
sysTime.wDay = 1;
}
if (sysTime.wMonth > 12)
{
sysTime.wYear++;
sysTime.wMonth = 1;
}
tv.encode(sysTime.wYear, sysTime.wMonth, sysTime.wDay, 0, 0, 0);
return tv.tv;
}
// 计算相对于当前MiniDateTime所指示的时间点的明天
inline unsigned int rel_tomorrow()
{
unsigned v = tv & (~RecordFlag);
v = (v + SecOfDay) / SecOfDay * SecOfDay;
return (tv & RecordFlag) | v;
}
// // 计算相对于当前MiniDateTime所指示的时间点的当前开始时间点
inline unsigned int rel_today()
{
unsigned v = tv & (~RecordFlag);
v = v / SecOfDay * SecOfDay;
return (tv & RecordFlag) | v;
}
// // 计算相对于当前MiniDateTime所指示的时间点的当前开始时间点
inline unsigned int rel_today(unsigned int hours, unsigned int mins, unsigned int seconds)
{
unsigned v = tv & (~RecordFlag);
v = v / SecOfDay * SecOfDay;
return ((tv & RecordFlag) | v) + SecOfHour*hours + SecOfMin*mins + seconds;
}
//判断是否是闰年的函数
inline static bool isLeapYear(const unsigned int year)
{
return ((year & 3) == 0) && ((year % 100 != 0) || (year % 400 == 0));
}
public:
//转换为unsigned int的类型转换运算符
inline operator unsigned int() const
{
return tv;
}
//从unsigned int复制的运算符函数
inline CMiniDateTime& operator = (const unsigned int time)
{
tv = time;
return *this;
}
//重载相等判断的运算符
inline bool operator == (const unsigned int time)
{
return tv == time;
}
//重载不等判断的运算符
inline bool operator != (const unsigned int time)
{
return tv != time;
}
inline bool operator > (const unsigned int time)
{
return (tv & (~RecordFlag)) > (time & (~RecordFlag));
}
inline bool operator >= (const unsigned int time)
{
return (tv & (~RecordFlag)) >= (time & (~RecordFlag));
}
inline bool operator < (const unsigned int time)
{
return (tv & (~RecordFlag)) < (time & (~RecordFlag));
}
inline bool operator <= (const unsigned int time)
{
return (tv & (~RecordFlag)) <= (time & (~RecordFlag));
}
//重载+运算符,避免对是否使用的标志位进行运算
inline unsigned int operator + (const unsigned int time)
{
return ((tv & (~RecordFlag)) + (time & (~RecordFlag))) & (~RecordFlag);
}
//重载-运算符,避免对是否使用的标志位进行运算
inline unsigned int operator - (const unsigned int time)
{
return ((tv & (~RecordFlag)) - (time & (~RecordFlag))) & (~RecordFlag);
}
//重载+=运算符,避免对是否使用的标志位进行运算
inline CMiniDateTime& operator += (const unsigned int time)
{
tv = (tv & RecordFlag) | (((tv & (~RecordFlag)) + (time & (~RecordFlag))) & (~RecordFlag));
return *this;
}
//重载-=运算符,避免对是否使用的标志位进行运算
inline CMiniDateTime& operator -= (const unsigned int time)
{
tv = (tv & RecordFlag) | (((tv & (~RecordFlag)) - (time & (~RecordFlag))) & (~RecordFlag));
return *this;
}
public:
CMiniDateTime()
{
tv = 0;
}
CMiniDateTime(const CMiniDateTime &mt)
{
tv = mt.tv;
}
CMiniDateTime(const unsigned int tva)
{
tv = tva;
}
public:
unsigned int tv;
};
#pragma pack (pop)

281
sdk/utils/SQL.cpp Normal file
View File

@@ -0,0 +1,281 @@
#include <stdio.h>
#ifdef WIN32
#include <tchar.h>
#include <config-win.h>
#else
#include <stdarg.h>
#endif
#include "SQL.h"
#include <Tick.h>
#include <wyString.h>
#include "ShareUtil.h"
CSQLConenction::CSQLConenction()
{
ZeroMemory( &m_MySQL, sizeof(m_MySQL) );
m_pSqlResult = NULL;
m_uSqlRows = 0;
m_pSqlRows = NULL;
m_pSqlFields = NULL;
m_uSqlFields = NULL;
m_sServerHost[0] = 0;
m_nServerPort = 3306;
m_sUserName[0] = 0;
m_sPassWord[0] = 0;
m_sDataBase[0] = 0;
m_nConnectFlags = CLIENT_FOUND_ROWS | CLIENT_MULTI_RESULTS;
m_sQueryBuffer[0] = 0;
//InitializeCriticalSection( &m_QueryLock );
m_boConnected = FALSE;
m_boMultiThread = FALSE;
}
CSQLConenction::~CSQLConenction()
{
Disconnect();
//DeleteCriticalSection( &m_QueryLock );
}
VOID CSQLConenction::SetServerHost(const char *sServerHost)
{
ZeroMemory( m_sServerHost, sizeof(m_sServerHost) );
strncpy( m_sServerHost, sServerHost, sizeof(m_sServerHost) - 1 );
}
VOID CSQLConenction::SetServerPort(INT_PTR nServerPort)
{
m_nServerPort = nServerPort;
}
VOID CSQLConenction::SetDataBaseName(const char *sDataBaseName)
{
ZeroMemory( m_sDataBase, sizeof(m_sDataBase) );
strncpy( m_sDataBase, sDataBaseName, sizeof(m_sDataBase) - 1 );
}
VOID CSQLConenction::SetUserName(const char* sUserName)
{
ZeroMemory( m_sUserName, sizeof(m_sUserName) );
strncpy( m_sUserName, sUserName, sizeof(m_sUserName) - 1 );
}
VOID CSQLConenction::SetPassWord(const char* sPassWord)
{
ZeroMemory( m_sPassWord, sizeof(m_sPassWord) );
strncpy( m_sPassWord, sPassWord, sizeof(m_sPassWord) - 1 );
}
VOID CSQLConenction::SetConnectionFlags(const UINT_PTR nFlags)
{
m_nConnectFlags = nFlags;
}
VOID CSQLConenction::SetMultiThread(const BOOL boMultiThread)
{
m_boMultiThread = boMultiThread;
}
BOOL CSQLConenction::Connect()
{
BOOL Result = TRUE;
if ( !m_boConnected )
{
if ( mysql_init(&m_MySQL) )
{
m_MySQL.reconnect = TRUE;
if (mysql_real_connect(&m_MySQL, m_sServerHost, m_sUserName, m_sPassWord, m_sDataBase, (UINT)m_nServerPort,NULL, (UINT)m_nConnectFlags) )
{
m_boConnected = TRUE;
//ResetQuery();
}
else
{
Result = FALSE;
OutputMsg( rmError, _T("无法连接到数据库:%s"), mysql_error(&m_MySQL) );
mysql_close(&m_MySQL);
}
}
else
{
OutputMsg( rmError, _T("无法初始化数据库连接程序") );
Result = FALSE;
}
}
return Result;
}
VOID CSQLConenction::Disconnect()
{
if (m_boConnected)
{
m_boConnected = FALSE;
ResetQuery();
mysql_close(&m_MySQL);
}
}
VOID CSQLConenction::AfterQueryed(int nError)
{
if (!nError)
{
m_pSqlResult = mysql_store_result(&m_MySQL);
if (m_pSqlResult)
{
mysql_data_seek( m_pSqlResult, 0 );
mysql_field_seek( m_pSqlResult, 0 );
m_uSqlRows = mysql_num_rows(m_pSqlResult);
m_uSqlFields = mysql_num_fields(m_pSqlResult);
m_pSqlRows = mysql_fetch_row(m_pSqlResult);
}
else
{
m_uSqlFields = 0;
m_pSqlFields = NULL;
m_uSqlRows = 0;
m_pSqlRows = NULL;
m_sQueryBuffer[128] = 0;
OutputMsg(rmError, _T("%s(%s)"), mysql_error(&m_MySQL), m_sQueryBuffer );
}
}
else
{
m_uSqlFields = 0;
m_pSqlFields = NULL;
m_uSqlRows = 0;
m_pSqlRows = NULL;
m_pSqlResult = NULL;
#ifdef UNICODE
wylib::string::CAnsiString as(mysql_error(&m_MySQL));
wylib::string::CWideString *ws = as.toWStr();
OutputMsg(rmError, *ws);
delete ws;
#else
OutputMsg(rmError, mysql_error(&m_MySQL));
#endif
if ( m_boMultiThread ) m_QueryLock.Unlock();
// LeaveCriticalSection( &m_QueryLock );
}
}
VOID CSQLConenction::AfterExeced(int nError)
{
if (!nError)
{
m_pSqlResult = NULL;
m_uRowsAffected = mysql_affected_rows( &m_MySQL );
}
else
{
m_uSqlFields = 0;
m_pSqlFields = NULL;
m_uSqlRows = 0;
m_pSqlRows = NULL;
m_pSqlResult = NULL;
m_uRowsAffected = 0;
#ifdef UNICODE
wylib::string::CAnsiString as(mysql_error(&m_MySQL));
wylib::string::CWideString *ws = as.toWStr();
OutputMsg(rmError, *ws);
delete ws;
#else
OutputMsg(rmError, mysql_error(&m_MySQL));
#endif
if ( m_boMultiThread ) m_QueryLock.Unlock();
//LeaveCriticalSection( &m_QueryLock );
}
}
int CSQLConenction::Query(const char* sQueryFormat, ...)
{
int Result;
va_list args;
//OutputMsg(rmError,_T("Query :%s, CurrentThreadId[%d]"),sQueryFormat,GetCurrentThreadId());
if ( m_boMultiThread ) m_QueryLock.Lock();
// EnterCriticalSection( &m_QueryLock );
va_start(args, sQueryFormat);
Result = vsprintf(m_sQueryBuffer, sQueryFormat, args);
va_end(args);
Result = mysql_real_query(&m_MySQL, m_sQueryBuffer, Result);
AfterQueryed( Result );
return Result;
}
int CSQLConenction::RealQuery(const char* sQueryText, const size_t nTextLen)
{
int Result;
//if ( m_boMultiThread ) EnterCriticalSection( &m_QueryLock );
OutputMsg(rmError,_T("RealQuery :%s, CurrentThreadId[%d]"),sQueryText,GetCurrentThreadId());
if ( m_boMultiThread ) m_QueryLock.Lock();
Result = mysql_real_query(&m_MySQL, sQueryText, (UINT)nTextLen);
AfterQueryed( Result );
return Result;
}
int CSQLConenction::Exec(const char* sQueryFormat, ...)
{
int Result;
va_list args;
//if ( m_boMultiThread ) EnterCriticalSection( &m_QueryLock );
//OutputMsg(rmError,_T("Exec CurrentThreadId[%d]"),GetCurrentThreadId());
if ( m_boMultiThread ) m_QueryLock.Lock();
va_start(args, sQueryFormat);
Result = vsprintf(m_sQueryBuffer, sQueryFormat, args);
va_end(args);
Result = mysql_real_query(&m_MySQL, m_sQueryBuffer, Result);
AfterExeced( Result );
return Result;
}
int CSQLConenction::RealExec(const char* sExecText, const size_t nTextLen)
{
int Result;
//if ( m_boMultiThread ) EnterCriticalSection( &m_QueryLock );
//OutputMsg(rmError,_T("RealExec CurrentThreadId[%d]"),GetCurrentThreadId());
if ( m_boMultiThread ) m_QueryLock.Lock();
Result = mysql_real_query(&m_MySQL, sExecText, (UINT)nTextLen);
AfterExeced( Result );
return Result;
}
VOID CSQLConenction::ResetQuery()
{
if (m_pSqlResult)
{
mysql_free_result(m_pSqlResult);
//Commands out of sync; you can't run this command now
//get back all results
while (!mysql_next_result(&m_MySQL));
}
m_uSqlFields = 0;
m_pSqlFields = NULL;
m_uSqlRows = 0;
m_pSqlRows = NULL;
m_pSqlResult = NULL;
//if ( m_boMultiThread ) LeaveCriticalSection( &m_QueryLock );
//OutputMsg(rmError,_T("ResetQuery CurrentThreadId[%d]"),GetCurrentThreadId());
if ( m_boMultiThread ) m_QueryLock.Unlock();
}

118
sdk/utils/SQL.h Normal file
View File

@@ -0,0 +1,118 @@
#ifndef _SQL_H_
#define _SQL_H_
#undef bool //config-win.h中会把bool定义为BOOL
#include <mysql.h>
#include <_osdef.h>
#include "Lock.h"
#ifdef WIN32
#include <windows.h>
#endif
using namespace wylib::sync::lock;
class CSQLConenction
{
private:
static const int SQLQueryBufferSize = 4096 * 10;
private:
MYSQL m_MySQL;
MYSQL_RES* m_pSqlResult;
my_ulonglong m_uSqlRows;
MYSQL_ROW m_pSqlRows;
MYSQL_FIELD * m_pSqlFields;
my_ulonglong m_uSqlFields;
my_ulonglong m_uRowsAffected;
private:
char m_sServerHost[32];
INT_PTR m_nServerPort;
char m_sUserName[64];
char m_sPassWord[64];
char m_sDataBase[64];
UINT_PTR m_nConnectFlags;
char m_sQueryBuffer[SQLQueryBufferSize];
//CRITICAL_SECTION m_QueryLock; //SQL查询锁
BOOL m_boConnected; //是否连接的标志
BOOL m_boMultiThread; //是否多线程的标志如果为TRUE则进行查询是会加锁
CCSLock m_QueryLock;
private:
VOID AfterQueryed(int nError);
VOID AfterExeced(int nError);
public:
CSQLConenction();
~CSQLConenction();
inline const char* GetServerHost(){ return m_sServerHost; };
VOID SetServerHost(const char *sServerHost);
inline INT_PTR GetServerPort(){ return m_nServerPort; };
VOID SetServerPort(INT_PTR nServerPort);
inline const char* GetDataBaseName(){ return m_sDataBase; };
VOID SetDataBaseName(const char *sDataBaseName);
inline const char* GetUserName(){ return m_sUserName; };
VOID SetUserName(const char* sUserName);
inline const char* GetPassWord(){ return m_sPassWord; };
VOID SetPassWord(const char* sPassWord);
inline UINT_PTR GetConnectionFlags(){ return m_nConnectFlags; };
VOID SetConnectionFlags(const UINT_PTR nFlags);
inline BOOL GetIsMultiThread(){ return m_boMultiThread; };
VOID SetMultiThread(const BOOL boMultiThread);
BOOL Connect();
inline BOOL Connected(){ return m_boConnected; };
VOID Disconnect();
inline MYSQL* GetMySql() { return &m_MySQL;}
//Query和RealQuery用于执行带返回结果的查询操作
//查询成功则返回0并且需要在外部调用ResetQuery来释放查询结果集并解锁
//如果查询失败则会自动解锁。
int Query(const char* sQueryFormat, ...);
int RealQuery(const char* sQueryText, const size_t nTextLen);
//Exec和RealExec用于执行不带返回结果的查询操作例如delete,update,create,drop,alter等
//执行成功则返回0并且需要在外部调用ResetQuery来释放查询结果集并解锁
//如果执行失败则会自动解锁。
int Exec(const char* sQueryFormat, ...);
int RealExec(const char* sExecText, const size_t nTextLen);
VOID ResetQuery();
inline int GetFieldCount()
{
return (int)m_uSqlFields;
}
inline int GetRowCount()
{
return (int)m_uSqlRows;
}
inline int GetRowsAffected()
{
return (int)m_uRowsAffected;
}
inline MYSQL_ROW CurrentRow()
{
return m_pSqlRows;
}
inline MYSQL_ROW NextRow()
{
if ( m_pSqlResult )
{
m_pSqlRows = mysql_fetch_row( m_pSqlResult );
return m_pSqlRows;
}
return NULL;
}
inline unsigned long* GetFieldsLength()
{
return mysql_fetch_lengths(m_pSqlResult);
}
};
#endif

378
sdk/utils/ShareUtil.cpp Normal file
View File

@@ -0,0 +1,378 @@
#include <stdarg.h>
#include <stdio.h>
#ifdef WIN32
#include <Windows.h>
#include <dbghelp.h>
#include <TCHAR.h>
#include <locale.h>
#endif
#include "_osdef.h"
#include <Tick.h>
#include "Lock.h"
#include <string.h>
#include "ShareUtil.h"
//RTL_CRITICAL_SECTION g_OutputMsgLock;
wylib::sync::lock::CCSLock g_OutputMsgLock;
SHAREOUTPUTMSGFN g_lpOutputMsg;
static TCHAR sTempMsgBuf[8192 * 4];
#define TMPBUFSIZE (sizeof(sTempMsgBuf)/sizeof(sTempMsgBuf[0]))
#ifdef WIN32
static int wExceptionDumpFlag = -1 ; //这个是生成dump的标记
void SetMiniDumpFlag(int nFlag)
{
wExceptionDumpFlag =nFlag;
}
LONG WINAPI DefaultUnHandleExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
TCHAR sDumpFileName[256];
_tcscpy(sDumpFileName,szExceptionDumpFile);
INT_PTR nDotPos = _tcslen(sDumpFileName);
for(; nDotPos>=0; nDotPos--)
{
if(sDumpFileName[nDotPos] =='.')
{
break;;
}
}
if(nDotPos <0)
{
nDotPos =0;
}
SYSTEMTIME Systime;
GetLocalTime( &Systime );
_stprintf(&sDumpFileName[nDotPos], _T("-%d-%d-%d-%d-%d-%d"), Systime.wYear - 2000, Systime.wMonth, Systime.wDay, Systime.wHour, Systime.wMinute, Systime.wSecond );
_tcscat(sDumpFileName, _T(".dmp"));
HANDLE hFile = CreateFile( sDumpFileName, GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
MINIDUMP_TYPE wDumpFlag = MiniDumpWithFullMemory;
if(wExceptionDumpFlag >=0)
{
wDumpFlag = (MINIDUMP_TYPE)wExceptionDumpFlag;
}
if ( hFile != INVALID_HANDLE_VALUE )
{
MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = GetCurrentThreadId();
ExInfo.ExceptionPointers = ExceptionInfo;
ExInfo.ClientPointers = NULL;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hFile, wDumpFlag, &ExInfo, NULL, NULL );
CloseHandle(hFile);
}
ExitProcess( -1 );
return 0;
}
LPCTSTR GetSysErrorMessage(const INT_PTR ErrorCode,OUT LPTSTR sBuffer, size_t dwBufferSize, size_t *dwBufferNeeded)
{
DWORD dwLen;
TCHAR Buf[2048];
dwLen = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, (DWORD)ErrorCode, 0, Buf, sizeof(Buf), NULL );
while ( dwLen > 0 )
{
if ( (BYTE)Buf[dwLen-1] <= 0x32 )
dwLen--;
else break;
}
Buf[dwLen] = 0;
if ( sBuffer )
{
if ( dwBufferSize > dwLen )
{
memcpy( sBuffer, Buf, dwLen * sizeof(Buf[0]) );
sBuffer[dwLen] = 0;
}
else
{
memcpy( sBuffer, Buf, dwBufferSize * sizeof(Buf[0]) );
sBuffer[dwBufferSize-1] = 0;
}
}
*dwBufferNeeded = dwLen;
return sBuffer;
}
#endif
int SNPRINTFA(char* dst, int len, const char* format, ...)
{
if (NULL == dst || len <= 0 || NULL == format) return -1;
va_list va;
va_start(va, format);
int ret = vsnprintf(dst, len, format, va);
if (ret >= len) ret = -1;
va_end(va);
dst[len - 1] = '\0';
return ret;
}
int VSNPRINTFA(char* dst, int len, const char* format, va_list args)
{
if (NULL == dst || len <= 0 || NULL == format) return -1;
int ret = vsnprintf(dst, len, format, args);
if (ret >= len) ret = -1;
dst[len - 1] = '\0';
return ret;
}
// 本函数代码出自 openbsd 的 strlcpy.c 文件用于非bsd并且不提供strlcpy函数的系统
size_t
strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0) {
while (--n != 0) {
if ((*d++ = *s++) == '\0')
break;
}
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
// 本函数代码出自 openbsd 的 strlcat.c 文件用于非bsd并且不提供strlcat函数的系统
size_t
strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}
void GetSystemTime(SystemTime& sysTime)
{
#ifdef _MSC_VER
SYSTEMTIME nowSysTime; // 服务器的开启时间
GetLocalTime(&nowSysTime);
sysTime.sec_ = nowSysTime.wSecond;
sysTime.min_ = nowSysTime.wMinute;
sysTime.hour_ = nowSysTime.wHour;
sysTime.mday_ = nowSysTime.wDay;
sysTime.mon_ = nowSysTime.wMonth;
sysTime.year_ = nowSysTime.wYear;
sysTime.wday_ = nowSysTime.wDayOfWeek;
#else
time_t lcurtime;
time(&lcurtime);
struct tm curTime;
localtime_r(&lcurtime,&curTime);
sysTime.sec_ = curTime.tm_sec;
sysTime.min_ = curTime.tm_min;
sysTime.hour_ = curTime.tm_hour;
sysTime.mday_ = curTime.tm_mday;
sysTime.mon_ = curTime.tm_mon + 1;
sysTime.year_ = curTime.tm_year + 1900;
sysTime.wday_ = curTime.tm_wday;
#endif
}
//默认消息输出函数
INT_PTR STDCALL StdDefOutputMsg(SHAREOUTPUTMSGTYPE MsgType, LPCTSTR lpMsg, INT_PTR nMsgLen)
{
SYSTEMTIME Systime;
INT_PTR Result;
GetLocalTime( &Systime );
Result = _tprintf( _T("[%d-%d-%d %d:%d:%d]"), Systime.wYear - 2000, Systime.wMonth, Systime.wDay, Systime.wHour, Systime.wMinute, Systime.wSecond );
switch ( MsgType )
{
case rmWaning: Result += _tprintf( _T("[WRN]:") ); break;
case rmTip: Result += _tprintf( _T("[TIP]:") ); break;
case rmError: Result += _tprintf( _T("[ERR]:") ); break;
default: Result += _tprintf( _T(":") ); break;
}
// Result += (int)fwrite( lpMsg, 1, nMsgLen * sizeof(*lpMsg), stdout );
// Result += (int)fwrite( _T("\n"), 1, 1 * sizeof(*lpMsg), stdout );
_tprintf( _T("%s\n"), lpMsg );
return Result;
}
//全局消息输出函数
INT_PTR STDCALL OutputMsg(SHAREOUTPUTMSGTYPE MsgType, LPCTSTR sFormat, ...)
{
va_list args;
INT_PTR Result = 0;
if (g_lpOutputMsg)
{
//EnterCriticalSection( &g_OutputMsgLock );
g_OutputMsgLock.Lock();
va_start(args, sFormat);
Result = _vsntprintf(sTempMsgBuf, TMPBUFSIZE - 1, sFormat, args);
va_end(args);
Result = g_lpOutputMsg( MsgType, sTempMsgBuf, Result );
//LeaveCriticalSection( &g_OutputMsgLock );
g_OutputMsgLock.Unlock();
}
return Result;
}
INT _StrToInt(LPCTSTR sText)
{
int nResult = 0;
_stscanf(sText, _T("%d"), &nResult);
return nResult;
}
INT64 StrToInt64(LPCTSTR sText)
{
INT64 nResult = 0;
_stscanf(sText, _T("%lld"), &nResult);//Unix中的libc库使用%lld
return nResult;
}
void STDCALL UninitDefMsgOut()
{
//DeleteCriticalSection( &g_OutputMsgLock );
}
//设置全局消息输出函数,返回当前的消息输出函数
SHAREOUTPUTMSGFN STDCALL SetOutputMsgFn(SHAREOUTPUTMSGFN lpFn)
{
//EnterCriticalSection( &g_OutputMsgLock );
g_OutputMsgLock.Lock();
SHAREOUTPUTMSGFN lpCurFn = g_lpOutputMsg;
g_lpOutputMsg = lpFn;
//LeaveCriticalSection( &g_OutputMsgLock );
g_OutputMsgLock.Unlock();
return lpCurFn;
}
void STDCALL InitDefMsgOut()
{
//InitializeCriticalSection( &g_OutputMsgLock );
g_lpOutputMsg = StdDefOutputMsg;
//设置CTYPE为本地代码页防止出现无法打印UNICODE 255之后的字符的问题。
#ifdef WIN32
char sACP[16];
sprintf(sACP, ".%d", GetACP());
setlocale(LC_CTYPE, sACP);
#endif
}
INT_PTR STDCALL OutputError(const INT_PTR nErrorCode, LPCTSTR sFormat, ...)
{
INT_PTR Result = 0;
LPTSTR sptr;
size_t dwLen;
va_list args;
if (g_lpOutputMsg)
{
//EnterCriticalSection( &g_OutputMsgLock );
g_OutputMsgLock.Lock();
sptr = sTempMsgBuf;
va_start(args, sFormat);
sptr += _vsntprintf(sTempMsgBuf, TMPBUFSIZE - 1, sFormat, args);
va_end(args);
dwLen = TMPBUFSIZE - 1 - (sptr - sTempMsgBuf);
sptr += _sntprintf( sptr, dwLen, _T(" %d "), (int)nErrorCode );
Result = TMPBUFSIZE - 1 - (sptr - sTempMsgBuf);
#ifdef WIN32
GetSysErrorMessage( nErrorCode, sptr, Result, &dwLen );
#else
dwLen =0;
#endif
sptr += __min((INT_PTR)dwLen, Result);
Result = DWORD(sptr - sTempMsgBuf);
Result = g_lpOutputMsg( rmError, sTempMsgBuf, Result );
//LeaveCriticalSection( &g_OutputMsgLock );
g_OutputMsgLock.Unlock();
}
return Result;
}

196
sdk/utils/ShareUtil.h Normal file
View File

@@ -0,0 +1,196 @@
#ifndef _SHAREUTIL_H_
#define _SHAREUTIL_H_
#include "LinuxPortable.h"
//貌似vc里没有snprintf这个函数,提供了_snprintf代替,但gcc的snprintf和_snprintf返回值是有差异的这个要注意
//如果格式化的长度大于提供的字节长度_snprintf返回-1而snprintf是返回实际的长度
#ifndef _MSC_VER
#define SNPRINTF snprintf
#define STRNCASECMP strncasecmp
#else
#define SNPRINTF _snprintf
#define STRNCASECMP _strnicmp
#endif
//超出指定长度len,即返回值在[0-len]需要对snprintf返回长度做判断的统一用这个函数
int SNPRINTFA(char *dst, int len, const char *format, ...);
int VSNPRINTFA(char *dst, int len, const char *format, va_list args);
size_t strlcpy(char *dst, const char *src, size_t siz);
size_t strlcat(char *dst, const char *src, size_t siz);
//等待并关闭线程
#ifdef WIN32
#define CloseThread(ht) if ( ht ) { WaitForSingleObject( ht, 2000 ); CloseHandle( ht ); (ht) = NULL; }
#else
#define CloseThread(ht) if ( ht ) { struct timespec time; time.tv_sec = 2, time.tv_nsec = 0; pthread_timedjoin_np(ht, NULL, &time); (ht) = NULL; }
#endif
#ifndef SafeDelete
#define SafeDelete(p) if ( p ){ delete p; p = NULL; }
#endif
//获取数组长度
#ifndef ArrayCount
#define ArrayCount(a) (sizeof(a)/sizeof((a)[0]))
#endif
//拷贝字符串到字符数组支持MBCS和UCS
#ifndef _asncpy
#define _asncpy(dest, src) _tcsncpy(dest, src, sizeof(dest)/sizeof(TCHAR)-1)
#endif
//拷贝字符串到字符数组并添加终止字符支持MBCS和UCS
#ifndef _asncpyt
#define _asncpyt(dest, src) { _tcsncpy(dest, src, sizeof(dest)/sizeof(TCHAR)-1); dest[sizeof(dest)/sizeof(TCHAR)-1] = 0;}
#endif
//拷贝MBCS字符串到MBCS字符数组并添加终止字符
#ifndef _asncpytA
#define _asncpytA(dest, src) { strncpy(dest, src, sizeof(dest)/sizeof(CHAR)-1); dest[sizeof(dest)/sizeof(CHAR)-1] = 0;}
#endif
//将字符串终止于指定长度
#ifndef STRNTERM
#define STRNTERM(s, l) s[l] = 0;
#endif
//取64位整数的低32位整数
#ifndef LOLONG
#define LOLONG(S) ((DWORD)((ULONG64)(S) & 0xffffffff))
#endif
//取64位整数的高32位整数
#ifndef HILONG
#define HILONG(S) ((DWORD)((ULONG64)(S) >> 32))
#endif
#define _getTickCount wylib::time::tick64::GetTickCountEx
//#define _getTickCount Port_GetTickCount
#define _timeGetTime wylib::time::tick64::GetTickCountEx
struct SystemTime
{
int sec_; /* seconds after the minute - [0,59] */
int min_; /* minutes after the hour - [0,59] */
int hour_; /* hours since midnight - [0,23] */
int mday_; /* day of the month - [1,31] */
int mon_; /* months since January - [1,12] */
int year_; /* years */
int wday_; /* days since Sunday[0--6], Sunday:0, Monday:1 ...*/
};
void GetSystemTime(SystemTime& sysTime);
/// 输出消息类型
typedef enum tagShareOutputMsgType
{
rmNormal = 0,
rmWaning,
rmTip,
rmError,
}SHAREOUTPUTMSGTYPE;
//消息输出函数类型
typedef INT_PTR (STDCALL *SHAREOUTPUTMSGFN) (SHAREOUTPUTMSGTYPE MsgType, LPCTSTR lpMsg, INT_PTR nMsgLen);
/* 数据缓冲区结构 */
typedef struct tagDataBuffer
{
char *pBuffer;
char *pPointer;
INT_PTR nOffset;
INT_PTR nSize;
}DATABUFFER, *PDATABUFFER;
/* 性能统计结构 */
typedef struct tagPerformanceInfo
{
LONGLONG dwTickBegin;
LONGLONG dwLastTick;
LONGLONG dwMinTick;
LONGLONG dwMaxTick;
public:
//开始一次性能统计
inline void start(){ dwTickBegin = _getTickCount(); }
//结束本次性能统计
inline void end()
{
dwLastTick = _getTickCount() - dwTickBegin;
if ( dwLastTick < dwMinTick )
{
dwMinTick = dwLastTick;
}
if ( dwLastTick > dwMaxTick )
{
dwMaxTick = dwLastTick;
}
}
}PERFORMANCEINFO, *PPERFORMANCEINFO;
/* 循环统计结构 */
typedef struct tagLoopPerformance
{
INT_PTR nLastLoop;
INT_PTR nMinLoop;
INT_PTR nMaxLoop;
}LOOPPERFORMANCE, *PLOOPPERFORMANCE;
//全局消息输出函数
extern INT_PTR STDCALL OutputMsg(SHAREOUTPUTMSGTYPE MsgType, LPCTSTR sFormat, ...);
//全局错误输出函数
//删除的错误格式为sprintf(sFormat, ...) + 错误码 + 错误描述
INT_PTR STDCALL OutputError(const INT_PTR nErrorCode, LPCTSTR sFormat, ...);
//初始化全局消息输出
void STDCALL InitDefMsgOut();
//反初始化全局消息输出
void STDCALL UninitDefMsgOut();
//设置全局消息输出函数,返回当前的消息输出函数
SHAREOUTPUTMSGFN STDCALL SetOutputMsgFn(SHAREOUTPUTMSGFN lpFn);
//定义异常转出文件名称
extern const TCHAR szExceptionDumpFile[];
//static int wExceptionDumpFlag;
//默认的异常处理钩子
LONG WINAPI DefaultUnHandleExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo);
//获取系统提供的错误描述内容
LPCTSTR GetSysErrorMessage(const INT_PTR ErrorCode, OUT LPTSTR sBuffer, size_t dwBufferSize, size_t *dwBufferNeeded);
//字符串转32位整数
INT _StrToInt(LPCTSTR sText);
//设置写堆栈时候的标记,是全堆栈还是部分堆栈等
/*
typedef enum _MINIDUMP_TYPE {
MiniDumpNormal = 0x00000000,
MiniDumpWithDataSegs = 0x00000001,
MiniDumpWithFullMemory = 0x00000002,
MiniDumpWithHandleData = 0x00000004,
MiniDumpFilterMemory = 0x00000008,
MiniDumpScanMemory = 0x00000010,
MiniDumpWithUnloadedModules = 0x00000020,
MiniDumpWithIndirectlyReferencedMemory = 0x00000040,
MiniDumpFilterModulePaths = 0x00000080,
MiniDumpWithProcessThreadData = 0x00000100,
MiniDumpWithPrivateReadWriteMemory = 0x00000200,
MiniDumpWithoutOptionalData = 0x00000400,
MiniDumpWithFullMemoryInfo = 0x00000800,
MiniDumpWithThreadInfo = 0x00001000,
MiniDumpWithCodeSegs = 0x00002000,
MiniDumpWithoutAuxiliaryState = 0x00004000,
MiniDumpWithFullAuxiliaryState = 0x00008000,
MiniDumpWithPrivateWriteCopyMemory = 0x00010000,
MiniDumpIgnoreInaccessibleMemory = 0x00020000,
MiniDumpWithTokenInformation = 0x00040000,
MiniDumpValidTypeFlags = 0x0007ffff,
} MINIDUMP_TYPE;
*/
void SetMiniDumpFlag(int nFlag);
//字符串转64位整数
INT64 StrToInt64(LPCTSTR sText);
#endif

76
sdk/utils/SqlHelper.h Normal file
View File

@@ -0,0 +1,76 @@
#pragma once
/*
*
* Sql封装类避免多线程环境下执行SQL查询加锁后没有释放锁导致其他线程阻塞得不到执行。
* 使用方式:
CSqlHelper sqlHelper(&m_SQLConn)
sqlHelper.Exec(sQueryActorData, ...)
* CSqlHelper内部有个变量记录执行查询或者数据库操作命令是否成功如果成功析构函数会自动
* 调用SQL::ResetQuery()。注意因为每次执行查询成功都会修改CSqlHelper类的m_bNeedReset
* 所以如果要连续执行多个db查询命令每个命令执行完毕都需要手动调用Reset。
* 例如:
* // 执行SQL命令1
* CSqlHelper sqlHelper(&m_SQLConn)
* sqlHelper.Exec(sDBCmd1);
* // 这里需要手动重置
* sqlHelper.Reset();
* // 执行SQL命令2
* sqlHelper.Query(sDBQuery2, ...);
* // 如果这是最后一条命令,不需要手动重置,析构函数会自动重置
*/
#include "_osdef.h"
#include "SQL.h"
class CSQLConenction;
class CSqlHelper
{
public:
CSqlHelper(CSQLConenction* conn);
~CSqlHelper();
/*
* Comments: 重置本次查询结果
* @Return void:
* @Remark:
*/
void Reset();
/*
* Comments: 执行SQL查询不定长参数
* Param const char * sQueryFormat:
* Param ...:
* @Return int:
* @Remark:
*/
int Query(const char* sQueryFormat, ...);
/*
* Comments: 执行SQL查询定长参数
* Param const char * sQueryText:
* Param const size_t nTextLen:
* @Return int:
* @Remark:
*/
int RealQuery(const char* sQueryText, const size_t nTextLen);
/*
* Comments: 执行SQL命令不定长参数
* Param const char * sQueryFormat:
* Param ...:
* @Return int:
* @Remark:
*/
int Exec(const char* sQueryFormat, ...);
/*
* Comments: 执行SQL命令定长参数
* Param const char * sExecText:
* Param const size_t nTextLen:
* @Return int:
* @Remark:
*/
int RealExec(const char* sExecText, const size_t nTextLen);
private:
CSQLConenction* m_pSQLConnection;
bool m_bNeedReset;
};

180
sdk/utils/Stream.h Normal file
View File

@@ -0,0 +1,180 @@
#ifndef _WYL_FILESTREAM_H_
#define _WYL_FILESTREAM_H_
/******************************************************************
*
* wyLib库 2008 - 2010
*
* $ 数据流库 $
*
* - 主要功能 -
*
* 具有基本的数据流操作功能,写入、读取、调整流指针等基本操作和功能
* 目前具有CFileStream、CMemoryStream等常用流类
*
*****************************************************************/
#include "_osdef.h"
namespace wylib
{
namespace stream
{
#ifndef WIN32
//#define INVALID_HANDLE_VALUE ((LONG_PTR)-1)
#endif
/* 基础抽象流
流的基础类,提供流最基本的虚函数接口声明
*/
class CBaseStream
{
public:
enum StreamSeekOrigin
{
soBeginning = 0, //从流的起点开始
soCurrent = 1, //从流的当前位置开始
soEnd = 2, //从流的末尾开始
};
private:
public:
CBaseStream(){};
virtual ~CBaseStream(){};
//获取流大小
virtual LONGLONG getSize();
//设置流大小
virtual bool setSize(LONGLONG tSize){ return false; };
//获取流中当前指针位置
inline LONGLONG getPosition(){ return seek( 0, soCurrent ); };
//设置流当前指针位置
LONGLONG setPosition(const LONGLONG tPosition);
//调整流指针位置tOffset参数表示调整的长度
//Origin参数表示调整的启示位置其值应当是StreamSeekOrigin枚举类型中的值
virtual LONGLONG seek(const LONGLONG tOffset, const int Origin) = 0;
//从流中读取数据lpBuffer为读取缓冲区tSizeToRead为读取的字节数
//如果读取失败,则函数返回-1否则函数返回实际从流中读取的字节数
virtual LONGLONG read(LPVOID lpBuffer, const LONGLONG tSizeToRead) = 0;
//向流中写入数据lpBuffer为写入数据内容指针tSizeToWrite为写入的字节数
//如果写入失败,则函数返回-1否则函数返回实际写入流中的字节数
virtual LONGLONG write(LPCVOID lpBuffer, const LONGLONG tSizeToWrite) = 0;
//从另一个流中拷贝数据lpStream为另一个流对象指针tSizeToCopy表示拷贝的字节数
//从lpStream中拷贝的数据的起始位置是lpStream的当前指针位置
//若参数tSizeToCopy为0则表示拷贝lpStream整个流的数据
virtual LONGLONG copyFrom(CBaseStream& stream, LONGLONG tSizeToCopy = 0);
};
/* 句柄流,
流操作的数据是针对外部提供的句柄进行的
*/
class CHandleStream
: public CBaseStream
{
public:
typedef CBaseStream Inherited;
protected:
#ifdef WIN32
HANDLE m_hHandle;
void setHandle(HANDLE Handle);
public:
CHandleStream(HANDLE StreamHandle);
inline HANDLE getHandle(){ return m_hHandle; }
inline bool handleValid(){ return m_hHandle != INVALID_HANDLE_VALUE; }
#else
int m_hHandle;
void setHandle(int Handle);
public:
CHandleStream(int StreamHandle);
inline int getHandle(){ return m_hHandle; }
inline bool handleValid(){ return m_hHandle != INVALID_HANDLE_VALUE; }
#endif
bool setSize(LONGLONG tSize);
LONGLONG seek(const LONGLONG tOffset, const int Origin);
LONGLONG read(LPVOID lpBuffer, const LONGLONG tSizeToRead);
LONGLONG write(LPCVOID lpBuffer, const LONGLONG tSizeToWrite);
};
/* 文件流,
对文件系统中的文件读写操作的类
*/
class CFileStream
: public CHandleStream
{
public:
typedef CHandleStream Inherited;
//文件的打开方式
enum FileAccessType
{
faRead = 0x0001, //读取
faWrite = 0x0002, //写入
faCreate = 0x1000, //创建
faShareRead = 0x0100, //读共享
faShareWrite = 0x0200, //写共享
faShareDelete = 0x0400, //删除共享
};
//win32文件创建的模式
enum OpenDisposition
{
CreateIfNotExists = 1, //文件不存在则创建
AlwaysCreate, //总是创建文件如果文件存在则将文件截断为0字节
OpenExistsOnly, //仅打开存在的文件
AlwaysOpen, //总是打开文件,若文件存在则直接打开,否则尝试创建文件并打开
TruncExistsOnly, //如果文件存在则打开文件并截断为0字节
};
private:
LPTSTR m_sFileName;
protected:
void setFileName(LPCTSTR lpFileName);
void construct(LPCTSTR lpFileName, DWORD dwAccessType, DWORD dwWin32CreationDisposition);
public:
CFileStream(LPCTSTR lpFileName, DWORD dwAccessType);
CFileStream(LPCTSTR lpFileName, DWORD dwAccessType, OpenDisposition eWin32CreateionDisposition);
~CFileStream();
inline LPCTSTR getFileName(){ return m_sFileName; }
};
/* 内存流
使用内存作为数据存储区的流对象类
*/
class CMemoryStream
: public CBaseStream
{
public:
typedef CBaseStream Inherited;
private:
char *m_pMemory; //内存块指针
char *m_pPointer; //流指针
char *m_pStreamEnd; //文件尾指针
char *m_pMemoryEnd; //内存块结束地址指针
protected:
//如果需要处理内存申请和释放相关事宜,则在继承类中覆盖此函数即可
virtual char* Alloc(char* ptr, const LONGLONG size);
public:
CMemoryStream();
~CMemoryStream();
bool setSize(LONGLONG tSize);
LONGLONG seek(const LONGLONG tOffset, const int Origin);
LONGLONG read(LPVOID lpBuffer, const LONGLONG tSizeToRead);
LONGLONG write(LPCVOID lpBuffer, const LONGLONG tSizeToWrite);
//获取内存流的内存块指针
inline LPVOID getMemory(){ return m_pMemory; }
//从文件加流数据到内存
LONGLONG loadFromFile(LPCTSTR lpFileName);
//将流数据保存到文件
LONGLONG saveToFile(LPCTSTR lpFileName);
};
};
};
#endif

117
sdk/utils/Tick.cpp Normal file
View File

@@ -0,0 +1,117 @@
#include <limits.h>
#ifdef WIN32
#include <time.h>
#include <tchar.h>
#endif
#include "_osdef.h"
#include "Tick.h"
#include "Lock.h"
using namespace wylib::time::tick64;
static TICKCOUNT64 UserSetTick = 0;
#ifndef WIN32
unsigned int timeGetTime()
{
unsigned int uptime = 0;
struct timespec on;
if(clock_gettime(CLOCK_MONOTONIC, &on) == 0)
uptime = on.tv_sec*1000 + on.tv_nsec/1000000;
return uptime;
}
#endif
/***
实际测试的性能表明基于timeGetTime实现的GetTickCount64具有较高的性能
而基于QueryPerformanceCounter的实现则是timeGetTime版本时间消耗的300倍
***/
//static LONG dwAtomLock = 0;
#ifdef WIN32
static MMRESULT mmPeriod = timeBeginPeriod(1);
#endif
static TICKCOUNT64 llTickBase = 0;
static TICKCOUNT64 llStartTick = timeGetTime();
static DWORD dwLastShortTick = timeGetTime();
TICKCOUNT64 wylib::time::tick64::GetTickCount64()
{
if (UserSetTick)
return UserSetTick;
/*
此处需要将dwLastShortTick导致保存为局部变量并尝试通过保存的值以锁总线的方式改变dwLastShortTick的值。
由于在检测并修改dwLastShortTick的值的期间当前线程可能由于进程调度而使得线程被挂起。当前线程被挂
起的期间如果其他线程也执行了此函数则该线程会先于此线程修改dwLastShortTick的值。当本线程在恢复后再修改
dwLastShortTick的值将导致错误的结果并会错误的判断为进入了一个49天的循环并修改llTickBase的值从而导
致所有后续调用的返回值全部错误的问题!
为尽量降低数据同步的开销,不能使用临界区等方式来同步数据,故必须使用原子加锁操作指令代替。
*/
DWORD dwLastTick = dwLastShortTick;
DWORD dwTick = timeGetTime();
#ifdef WIN32
if (InterlockedCompareExchange((volatile long*)&dwLastShortTick, (long)dwTick, (long)dwLastTick) == dwLastTick)
#else
if (__sync_val_compare_and_swap((volatile long*)&dwLastShortTick, (long)dwLastTick, (long)dwTick) == dwLastTick)
#endif
{
if (dwTick < dwLastTick)
{
#ifdef WIN32
if (IsDebuggerPresent())
{
//请手动确认此处是否未发生BUG而是系统真正的经过了49天的循环并按继续键……
OutputDebugString(_T("请手动确认此处是否未发生BUG而是系统真正的经过了49天的循环"));
DebugBreak();
}
llTickBase += 0x1UI64 << 32;
#else
llTickBase += 0x1LL << 32;
#endif
}
}
return llTickBase + dwTick - llStartTick;
}
/*
TICKCOUNT64 wylib::time::tick64::GetTickCount64()
{
if (UserSetTick)
return UserSetTick;
static LARGE_INTEGER Frequency;
static BOOL boSuportPerformanceTick = QueryPerformanceFrequency(&Frequency);
LARGE_INTEGER tick;
TICKCOUNT64 sec, milpart;
if ( !boSuportPerformanceTick )
{
return timeGetTime();
}
QueryPerformanceCounter( &tick );
sec = tick.QuadPart / Frequency.QuadPart;
milpart = tick.QuadPart - (sec * Frequency.QuadPart);
return sec * 1000 + milpart * 1000 / Frequency.QuadPart;
}
*/
TICKCOUNT64 wylib::time::tick64::SetTickCount64(TICKCOUNT64 llValue)
{
//TICKCOUNT64 lOldTick = UserSetTick;
UserSetTick = llValue;
return UserSetTick;
}
TICKCOUNT32 wylib::time::tick64::GetTickCount32()
{
return timeGetTime();
}
TICKCOUNT32 wylib::time::tick64::SetTickCount32(TICKCOUNT32 dwTick)
{
return (TICKCOUNT32)SetTickCount64(dwTick);
}

62
sdk/utils/Tick.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef _MTICK_H_
#define _MTICK_H_
/******************************************************************
*
* wyLib库 2008 - 2010
*
* $ 增强GetTickCount函数库 $
*
* - 主要功能 -
*
* 可使用64位的TickCount。内部解决了TickCount在超过49天后重新开始的问题。
* 同时提供了一个在整个进程中使用同步的TickCount的机制即通过SetTickCountEx
* 函数来设置同步的时间值,从而避免在多处理器中不同处理器之间的频率差异带来的问题
*
*****************************************************************/
#include "_osdef.h"
namespace wylib
{
namespace time
{
namespace tick64
{
typedef LONGLONG TICKCOUNT64;
typedef DWORD TICKCOUNT32;
//取机器运行时间的函数,函数返回的是毫秒值,
//如果硬件支持查询PerformanceCounter则可避免49天的整数溢出的问题
/***
实际测试后此函数性能较差因为查询CPU中断会导致进入内核并可能挂起
r3级的线程。此外在多处理器中如果各个处理器之间频率有误差则可能
导致由不同线程的连续的两次调用,后者取得的时间值比前者要晚的问题。
***/
TICKCOUNT64 GetTickCount64();
/***
* 提供在整个进程中使用同步的TickCount的机制即通过SetTickCountEx
* 函数来设置同步的时间值,从而避免在多处理器中不同处理器之间的频率差异
* 带来的问题。因此一旦调用者调用一次SetTickCountEx则GetTickCountEx
* 也随之进入同步模式调用者必须持续更新TickCount值或设置TickCount值
* 为0从而还原默认的GetTickCountEx的取值规则。
***/
TICKCOUNT64 SetTickCount64(TICKCOUNT64);
TICKCOUNT32 GetTickCount32();
TICKCOUNT32 SetTickCount32(TICKCOUNT32);
#ifdef _MTICK64
typedef TICKCOUNT64 TICKCOUNT;
# define GetTickCountEx GetTickCount64
# define SetTickCountEx SetTickCount64
#else
typedef TICKCOUNT32 TICKCOUNT;
# define GetTickCountEx GetTickCount32
# define SetTickCountEx SetTickCount32
#endif
};
};
};
#endif

134
sdk/utils/TimeCall.cpp Normal file
View File

@@ -0,0 +1,134 @@
#include <stdlib.h>
#include <stdio.h>
#ifdef WIN32
#include <tchar.h>
#include <windows.h>
#endif
#include <_ast.h>
#include <_memchk.h>
#include <Tick.h>
#include <LinkedList.h>
#include "ShareUtil.h"
#include "TimeCall.h"
#include <string.h>
using namespace wylib::container;
CTimeCaller::CTimeCaller()
{
m_nRmCallCount = 0;
m_pRunIter.setList(m_CallList);
}
HANDLE CTimeCaller::AddTimeCall(LPVOID lpThis, TimedCallBack lpCall, LPVOID lpData, ULONGLONG lInterval, ULONGLONG lNextCall /* = 0 */)
{
TIMECALLINFO tc;
ZeroMemory(&tc, sizeof(tc));
tc.lpCallback = lpCall;
tc.lpThis = lpThis;
tc.lpData = lpData;
tc.lNextCallTick = lNextCall;
tc.lInterval = lInterval;
tc.boMarkedRemove = FALSE;
m_CallList.linkAtLast(tc);
return m_CallList.last();
}
BOOL CTimeCaller::RemoveTimeCall(HANDLE hTimedCall)
{
CLinkedNode<TIMECALLINFO>* pNode;
CLinkedListIterator<TIMECALLINFO> it(m_CallList);
for (pNode = it.first(); pNode; pNode = it.next())
{
if (hTimedCall == pNode)
{
TIMECALLINFO &tc = *pNode;
//标记为移除
tc.boMarkedRemove = TRUE;
m_nRmCallCount++;
return TRUE;
}
}
return FALSE;
}
ULONGLONG CTimeCaller::GetCallInterval(HANDLE hTimedCall, PULONGLONG lpNextCall)
{
CLinkedNode<TIMECALLINFO>* pNode;
CLinkedListIterator<TIMECALLINFO> it(m_CallList);
for (pNode = it.first(); pNode; pNode = it.next())
{
if (hTimedCall == pNode)
{
TIMECALLINFO &tc = *pNode;
if (lpNextCall) *lpNextCall = tc.lNextCallTick;
return tc.lInterval;
}
}
return 0;
}
bool CTimeCaller::SetCallInterval(HANDLE hTimedCall, ULONGLONG lInterval, ULONGLONG lNextCall)
{
CLinkedNode<TIMECALLINFO>* pNode;
CLinkedListIterator<TIMECALLINFO> it(m_CallList);
for (pNode = it.first(); pNode; pNode = it.next())
{
if (hTimedCall == pNode)
{
TIMECALLINFO &tc = *pNode;
tc.lInterval = lInterval;
if (lNextCall) tc.lNextCallTick = lNextCall;
return true;
}
}
return false;
}
INT_PTR CTimeCaller::Run(ULONGLONG lRunTickLimit /* = MAXULONGLONG */)
{
INT_PTR Result = 0;
CLinkedNode<TIMECALLINFO>* pNode =NULL;
ULONGLONG lCurTick = GetCurrentTick();
ULONGLONG lFinishTick = lRunTickLimit ? lRunTickLimit + _getTickCount() : 0;
//继续回调
while (pNode = m_pRunIter.next())
{
TIMECALLINFO &tc = *pNode;
if (lCurTick >= tc.lNextCallTick)
{
tc.nCallCount++;
tc.lNextCallTick += tc.lInterval;
tc.lpCallback(tc.lpThis, tc.lpData, tc.nCallCount);
}
Result++;
if (lFinishTick && (ULONGLONG)_getTickCount() >= lFinishTick)
break;
}
//移除标记为移除的回调
if (m_nRmCallCount > 0)
{
CLinkedNode<TIMECALLINFO>* pNode;
CLinkedListIterator<TIMECALLINFO> it(m_CallList);
for (pNode = it.first(); pNode; pNode = it.next())
{
TIMECALLINFO &tc = *pNode;
if (tc.boMarkedRemove)
it.remove(pNode);
}
m_nRmCallCount = 0;
}
return Result;
}
ULONGLONG CTimeCaller::GetCurrentTick()
{
return _getTickCount();
}

97
sdk/utils/TimeCall.h Normal file
View File

@@ -0,0 +1,97 @@
#pragma once
/************************************************************************
定时回调函数类
支持按间隔毫秒数以及指定日期时间点的周期回调。
************************************************************************/
#include "_osdef.h"
class CTimeCaller
{
public:
/*
* 定时回调函数类型定义
* lpThis 回调对象用于支持OOP存储this指针
* lpData 回调数据,数据由注册时传递
* nCount 当前是第几次被调用
*/
typedef VOID (STDCALL *TimedCallBack) (LPVOID lpThis, LPVOID lpData, INT_PTR nCount);
public:
CTimeCaller();
/*
* Comments: 注册定时回调对象
* Param LPVOID lpThis: 回调对象用于支持OOP存储this指针会在回调函数中传递
* Param TimedCallBack lpCall: 回调函数指针回调函数形如CTimeCaller::TimedCallBack
* Param LPVOID lpData: 回调数据,会在回调函数中传递
* Param ULONGLONG lInterval: 调用周期,单位是毫秒
* Param ULONGLONG lNextCall: 下次调用时间单位是TickCount如果传递0则表示从当前时间起经过一次调用周期后调用
* @Return HANDLE: 回调对象句柄
*/
HANDLE AddTimeCall(LPVOID lpThis, TimedCallBack lpCall, LPVOID lpData, ULONGLONG lInterval, ULONGLONG lNextCall = 0);
/*
* Comments: 移除回调函数
* Param HANDLE hTimedCall: 回调对象句柄
* @Return BOOL: 如果回调对象存在且成功移除则函数返回TRUE否则返回FALSE
*/
BOOL RemoveTimeCall(HANDLE hTimedCall);
/*
* Comments: 通过定时调用对象句柄获取调用周期
* Param HANDLE hTimedCall: 定时调用对象句柄
* Param PULONGLONG lpNextCall: 指向用于存储下次调用发生的TickCount值的数据缓冲参数为空则不向其中存储数据
* @Return ULONGLONG: 函数返回此回调的调用周期,单位是毫秒
*/
ULONGLONG GetCallInterval(HANDLE hTimedCall, PULONGLONG lpNextCall);
/*
* Comments: 通过定时调用对象句柄设置调用周期
* Param HANDLE hTimedCall: 定时调用对象句柄
* Param ULONGLONG lInterval: 新的调用周期,单位为毫秒
* Param ULONGLONG lNextCall: 下次调用此函数的TickCount值
* @Return bool: 更新调用周期成功则返回true
* ★注意★
* lNextCall参数表示下次调用此函数的TickCount值传递0表示不改变下次
* 调用的时间;传递比当前时间小的值将导致在下次例行监察时调用此函数,鉴于此
* 特性,调用者可以通过传递一个比当前时间小调用周期倍的值来实现立刻对此函数
* 进行N次调用的功能如果传递的值比当前时间大则会在设定的时间中回调此函数。
*/
bool SetCallInterval(HANDLE hTimedCall, ULONGLONG lInterval, ULONGLONG lNextCall = 0);
/*
* Comments: 检查并调用已经到达运行时间的回调对象
* Param ULONGLONG lRunTickLimit: 对Run函数运行的时间限制单位是毫秒0表示不限制
* @Return INT_PTR: 返回检查了多少个回调对象
*/
INT_PTR Run(ULONGLONG lRunTickLimit = 0);
protected:
/*
* Comments: 获取当前运行时间的函数默认的实现是返回当前的TickCount
* 子类可以通过覆盖此函数来实现返回基于日期时间的值
* @Return ULONGLONG:
*/
virtual ULONGLONG GetCurrentTick();
protected:
/**
* 定义回调函数注册信息
***********************/
typedef struct tagTimeCallInfo
{
TimedCallBack lpCallback; //回调函数指针
LPVOID lpThis; //回调对象用于支持OOP存储this指针
LPVOID lpData; //回调数据,数据由注册时传递
INT_PTR nCallCount; //调用次数
ULONGLONG lNextCallTick;//下次调用的时间(TickCount)
ULONGLONG lInterval; //回调周期
BOOL boMarkedRemove;//是否标记为移除
}TIMECALLINFO, *PTIMECALLINFO;
protected:
wylib::container::CBaseLinkedList<TIMECALLINFO> m_CallList; //回调对象列表
wylib::container::CLinkedListIterator<TIMECALLINFO> m_pRunIter; //下此继续检查的回调对象节点
INT_PTR m_nRmCallCount;//标记移除的数量
};

380
sdk/utils/aes.c Normal file
View File

@@ -0,0 +1,380 @@
#include <stdio.h>
#include <string.h>
#include "aes.h"
static u8 pow_tab[256];
static u8 log_tab[256];
static u8 sbx_tab[256];
static u8 isb_tab[256];
static u32 rco_tab[10];
static u32 ft_tab[4][256];
static u32 it_tab[4][256];
static u32 fl_tab[4][256];
static u32 il_tab[4][256];
static u8 byte(const u32 x ,const unsigned n)
{
return x >> (n << 3);
}
static u32 rol32(u32 word, unsigned int shift)
{
return (word << shift) | (word >> (32 - shift));
}
static u32 ror32(u32 word, unsigned int shift)
{
return (word >> shift) | (word << (32 - shift));
}
static u8 f_mult(u8 a , u8 b )
{
u8 aa = log_tab[a];
u8 cc = aa + log_tab[b];
return pow_tab[cc + (cc < aa ? 1 : 0 )];
}
#define ff_mult(a,b) (a && b ? f_mult(a,b) : 0 )
#define f_rn(bo, bi, n, k) bo[n] = ft_tab[0][byte(bi[n],0)] ^ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rn(bo, bi, n, k) bo[n] = it_tab[0][byte(bi[n],0)] ^ it_tab[1][byte(bi[(n + 3) & 3],1)] ^ it_tab[2][byte(bi[(n + 2) & 3],2)] ^ it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
#define ls_box(x) ( fl_tab[0][byte(x, 0)] ^ fl_tab[1][byte(x, 1)] ^ fl_tab[2][byte(x, 2)] ^ fl_tab[3][byte(x, 3)] )
#define f_rl(bo, bi, n, k) bo[n] = fl_tab[0][byte(bi[n],0)] ^ fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rl(bo, bi, n, k) bo[n] = il_tab[0][byte(bi[n],0)] ^ il_tab[1][byte(bi[(n + 3) & 3],1)] ^ il_tab[2][byte(bi[(n + 2) & 3],2)] ^ il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
void gen_tabs (void)
{
u32 i, t;
u8 p, q;
/* log and power tables for GF(2**8) finite field with
* 0x011b as modular polynomial - the simplest primitive
* root is 0x03, used here to generate the tables */
for (i = 0, p = 1; i < 256; ++i) {
pow_tab[i] = (u8) p;
log_tab[p] = (u8) i;
p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
}
log_tab[1] = 0;
for (i = 0, p = 1; i < 10; ++i) {
rco_tab[i] = p;
p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
}
for (i = 0; i < 256; ++i) {
p = (i ? pow_tab[255 - log_tab[i]] : 0);
q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
sbx_tab[i] = p;
isb_tab[p] = (u8) i;
}
for (i = 0; i < 256; ++i) {
p = sbx_tab[i];
t = p;
fl_tab[0][i] = t;
fl_tab[1][i] = rol32(t, 8);
fl_tab[2][i] = rol32(t, 16);
fl_tab[3][i] = rol32(t, 24);
t = ((u32) ff_mult (2, p)) |
((u32) p << 8) |
((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
ft_tab[0][i] = t;
ft_tab[1][i] = rol32(t, 8);
ft_tab[2][i] = rol32(t, 16);
ft_tab[3][i] = rol32(t, 24);
p = isb_tab[i];
t = p;
il_tab[0][i] = t;
il_tab[1][i] = rol32(t, 8);
il_tab[2][i] = rol32(t, 16);
il_tab[3][i] = rol32(t, 24);
t = ((u32) ff_mult (14, p)) |
((u32) ff_mult (9, p) << 8) |
((u32) ff_mult (13, p) << 16) |
((u32) ff_mult (11, p) << 24);
it_tab[0][i] = t;
it_tab[1][i] = rol32(t, 8);
it_tab[2][i] = rol32(t, 16);
it_tab[3][i] = rol32(t, 24);
}
}
#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
#define imix_col(y,x) u = star_x(x);v = star_x(u);w = star_x(v);t = w ^ (x); (y) = u ^ v ^ w; (y) ^= ror32(u ^ t, 8) ^ ror32(v ^ t, 16) ^ ror32(t,24)
/* initialise the key schedule from the user supplied key */
#define loop4(i) { t = ror32(t, 8); t = ls_box(t) ^ rco_tab[i];t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; }
#define loop6(i) { t = ror32(t, 8); t = ls_box(t) ^ rco_tab[i];t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; }
#define loop8(i) { t = ror32(t, 8); ; t = ls_box(t) ^ rco_tab[i];t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t;t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; t = E_KEY[8 * i + 4] ^ ls_box(t); E_KEY[8 * i + 12] = t; t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; }
int aes_set_key(struct aes_ctx * ctx, const u8 *in_key, unsigned int key_len)
{
const __le32 *key = (const __le32 *)in_key;
u32 i, t, u, v, w;
if (key_len % 8 || key_len < AES_MIN_KEY_SIZE || key_len > AES_MAX_KEY_SIZE) {
return -1;
}
ctx->key_length = key_len;
E_KEY[0] = le32_to_cpu(key[0]);
E_KEY[1] = le32_to_cpu(key[1]);
E_KEY[2] = le32_to_cpu(key[2]);
E_KEY[3] = le32_to_cpu(key[3]);
switch (key_len) {
case 16:
t = E_KEY[3];
for (i = 0; i < 10; ++i)
loop4 (i);
break;
case 24:
E_KEY[4] = le32_to_cpu(key[4]);
t = E_KEY[5] = le32_to_cpu(key[5]);
for (i = 0; i < 8; ++i)
loop6 (i);
break;
case 32:
E_KEY[4] = le32_to_cpu(key[4]);
E_KEY[5] = le32_to_cpu(key[5]);
E_KEY[6] = le32_to_cpu(key[6]);
t = E_KEY[7] = le32_to_cpu(key[7]);
for (i = 0; i < 7; ++i)
loop8 (i);
break;
}
D_KEY[0] = E_KEY[0];
D_KEY[1] = E_KEY[1];
D_KEY[2] = E_KEY[2];
D_KEY[3] = E_KEY[3];
for (i = 4; i < key_len + 24; ++i) {
imix_col (D_KEY[i], E_KEY[i]);
}
return 0;
}
/* encrypt a block of text */
#define f_nround(bo, bi, k) f_rn(bo, bi, 0, k); f_rn(bo, bi, 1, k);f_rn(bo, bi, 2, k);f_rn(bo, bi, 3, k);k += 4
#define f_lround(bo, bi, k) f_rl(bo, bi, 0, k); f_rl(bo, bi, 1, k); f_rl(bo, bi, 2, k);f_rl(bo, bi, 3, k)
void aes_encrypt(struct aes_ctx * ctx, u8 *out, const u8 *in)
{
const __le32 *src = (const __le32 *)in;
__le32 *dst = (__le32 *)out;
u32 b0[4], b1[4];
const u32 *kp = E_KEY + 4;
b0[0] = le32_to_cpu(src[0]) ^ E_KEY[0];
b0[1] = le32_to_cpu(src[1]) ^ E_KEY[1];
b0[2] = le32_to_cpu(src[2]) ^ E_KEY[2];
b0[3] = le32_to_cpu(src[3]) ^ E_KEY[3];
if (ctx->key_length > 24) {
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
}
if (ctx->key_length > 16) {
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
}
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
f_nround (b1, b0, kp);
f_nround (b0, b1, kp);
f_nround (b1, b0, kp);
f_lround (b0, b1, kp);
dst[0] = cpu_to_le32(b0[0]);
dst[1] = cpu_to_le32(b0[1]);
dst[2] = cpu_to_le32(b0[2]);
dst[3] = cpu_to_le32(b0[3]);
}
/* decrypt a block of text */
#define i_nround(bo, bi, k) i_rn(bo, bi, 0, k);i_rn(bo, bi, 1, k);i_rn(bo, bi, 2, k);i_rn(bo, bi, 3, k); k -= 4
#define i_lround(bo, bi, k) i_rl(bo, bi, 0, k);i_rl(bo, bi, 1, k);i_rl(bo, bi, 2, k);i_rl(bo, bi, 3, k)
void aes_decrypt(struct aes_ctx * ctx, u8 *out, const u8 *in)
{
const __le32 *src = (const __le32 *)in;
__le32 *dst = (__le32 *)out;
u32 b0[4], b1[4];
const int key_len = ctx->key_length;
const u32 *kp = D_KEY + key_len + 20;
b0[0] = le32_to_cpu(src[0]) ^ E_KEY[key_len + 24];
b0[1] = le32_to_cpu(src[1]) ^ E_KEY[key_len + 25];
b0[2] = le32_to_cpu(src[2]) ^ E_KEY[key_len + 26];
b0[3] = le32_to_cpu(src[3]) ^ E_KEY[key_len + 27];
if (key_len > 24) {
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
}
if (key_len > 16) {
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
}
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
i_nround (b1, b0, kp);
i_nround (b0, b1, kp);
i_nround (b1, b0, kp);
i_lround (b0, b1, kp);
dst[0] = cpu_to_le32(b0[0]);
dst[1] = cpu_to_le32(b0[1]);
dst[2] = cpu_to_le32(b0[2]);
dst[3] = cpu_to_le32(b0[3]);
}
/*
返回0表示成功1表示失败
in长度必须为16整数倍
result的空间必须足够大至少in.lenth/16+4
*/
int AesEncrypt(struct aes_ctx * ctx,unsigned char* in, unsigned char* result, int len){
int blocknum;
int reslen;
int i;
unsigned char szbuf[16],sztmp[16];
if(len%16 != 0)
{
return 1;
}
blocknum = len/16;
reslen = len;
for(i = 0;i < 4;i++){
unsigned char b = reslen%256;
reslen = reslen/256;
result[4-i-1] = b;
}
for(i = 0;i < blocknum;i++){
memcpy(szbuf,in+i*16,16);
aes_encrypt(ctx,(u8 *)sztmp,(const u8 *)szbuf);
memcpy(result+i*16+4,sztmp,16);
}
return 0;
}
/*
返回0表示成功1表示失败
in长度必须为16*n+4result长度至少为16*n
*/
int AesDecrypt(struct aes_ctx * ctx,unsigned char* in,unsigned char* result){
int inlen = 0;
long mul = 1;
int i;
int blocknum;
unsigned char szbuf[16],sztmp[16];
for(i = 0;i < 4;i++){
unsigned char b = in[4-i-1];
inlen = inlen + b * mul ;
mul = mul * 256;
}
if(inlen%16 != 0){
return 1;
}
blocknum = inlen/16;
for(i = 0;i < blocknum;i++){
memcpy(szbuf,in+i*16+4,16);
aes_decrypt(ctx,(u8 *)sztmp,(const u8 *)szbuf);
memcpy(result+i*16,sztmp,16);
}
return 0;
}
s64 _AESEncrypt(struct aes_ctx *ctx, char* out, const char* in, s64 inlen)
{
s64 ret;
s64 remand;
u32 buf[4];
ret = (inlen + 15) & (~15);
if ( out )
{
remand = inlen & 15;
inlen -= remand;
while ( inlen > 0 )
{
aes_encrypt(ctx,out,in);
inlen -= 16;
in += 16;
out += 16;
}
if ( remand )
{
buf[0] = buf[1] = buf[2] = buf[3] = 0;
memcpy( buf, in, (size_t)remand );
aes_encrypt(ctx,out,(u8*)buf);
}
}
return ret;
}
int _AESDecrypt(struct aes_ctx *ctx, char* out, const char* in, s64 inlen)
{
if ( inlen & 15 )
return 1;
while ( inlen > 0 )
{
aes_decrypt(ctx,out,in);
inlen -= 16;
in += 16;
out += 16;
}
return 0;
}

61
sdk/utils/aes.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef __AES_H__
#define __AES_H__
#ifdef __cplusplus
extern "C"
{
#endif
#define AES_MIN_KEY_SIZE 16
#define AES_MAX_KEY_SIZE 32
#define AES_BLOCK_SIZE 16
typedef unsigned char u8;
typedef signed char s8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
typedef u16 __le16;
typedef u32 __le32;
#define E_KEY (&ctx->buf[0])
#define D_KEY (&ctx->buf[60])
#define le32_to_cpu
#define cpu_to_le32
struct aes_ctx
{
int key_length;
u32 buf[120];
};
void gen_tabs (void);
int aes_set_key(struct aes_ctx * ctx, const u8 *in_key, unsigned int key_len);
void aes_encrypt(struct aes_ctx * ctx, u8 *out, const u8 *in);
void aes_decrypt(struct aes_ctx * ctx, u8 *out, const u8 *in);
int AesEncrypt(struct aes_ctx * ctx,unsigned char* in, unsigned char* result, int len);
int AesDecrypt(struct aes_ctx * ctx,unsigned char* in,unsigned char* result);
/* 如果out为null则返回加密缓冲区需要的字节长度否则返回加密后实际使用out的字节长度 */
s64 _AESEncrypt(struct aes_ctx *ctx, char* out, const char* in, s64 inlen);
/* 成功返回0否则返回非0值 */
int _AESDecrypt(struct aes_ctx *ctx, char* out, const char* in, s64 inlen);
#ifdef __cplusplus
}
#endif
#endif

144
sdk/utils/base64.c Normal file
View File

@@ -0,0 +1,144 @@
/* *****************************************************************************
* Description : BASE64 encoding and decoding
* Date : 06-08-21 21:00
* Author : aishen944
* Copryright :
********************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "base64.h"
#define BASE64_PAD64 '='
char base64_alphabet[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a',
'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
'2', '3', '4', '5', '6', '7', '8', '9', '+',
'/'};
char base64_suffix_map[256] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
/*
static char cmove_bits(unsigned char src, unsigned int lnum, unsigned int rnum) {
src <<= lnum;
src >>= rnum;
return src;
}
*/
#define cmove_bits(s, l, r) ((((s << (l)) & 0xFF) >> (r)) & 0xFF)
//#define cmove_bits(s, l, r) (unsigned char)((unsigned char)((unsigned char)(s) << (unsigned int)(l)) >> (unsigned int)(r))
int base64_encode(char *out, const char *data, int insize)
{
char *retpos;
int m, padnum = 0, retsize, dlen = insize;
if(dlen == 0) return 0;
/* Account the result buffer size and alloc the memory for it. */
if((dlen % 3) != 0)
padnum = 3 - dlen % 3;
retsize = (dlen + padnum) + ((dlen + padnum) * 1/3);
if ( !out ) return retsize;
retpos = out;
/* Starting to convert the originality characters to BASE64 chracaters.
Converting process keep to 4->6 principle. */
for(m = 0; m < (dlen + padnum); m += 3) {
/* When data is not suffice 24 bits then pad 0 and the empty place pad '='. */
*(retpos) = base64_alphabet[cmove_bits(*data, 0, 2)];
if(m == dlen + padnum - 3 && padnum != 0) { /* Whether the last bits-group suffice 24 bits. */
if(padnum == 1) { /* 16bit need pad one '='. */
*(retpos + 1) = base64_alphabet[cmove_bits(*data, 6, 2) + cmove_bits(*(data + 1), 0, 4)];
*(retpos + 2) = base64_alphabet[cmove_bits(*(data + 1), 4, 2)];
*(retpos + 3) = BASE64_PAD64;
} else if(padnum == 2) { /* 8bit need pad two'='. */
*(retpos + 1) = base64_alphabet[cmove_bits(*data, 6, 2)];
*(retpos + 2) = BASE64_PAD64;
*(retpos + 3) = BASE64_PAD64;
}
} else { /* 24bit normal. */
*(retpos + 1) = base64_alphabet[cmove_bits(*data, 6, 2) + cmove_bits(*(data + 1), 0, 4)];
*(retpos + 2) = base64_alphabet[cmove_bits(*(data + 1), 4, 2) + cmove_bits(*(data + 2), 0, 6)];
*(retpos + 3) = base64_alphabet[*(data + 2) & 0x3f];
}
retpos += 4;
data += 3;
}
return retsize;
}
int base64_decode(char *out, const char *bdata, int insize)
{
char *retpos;
int m, padnum = 0, retsize = 0;
if(insize == 0) return 0;
if(insize % 4 != 0) return 0;
/* Whether the data have invalid base-64 characters? */
for(m = 0; m < insize; ++m) {
if(bdata[m] != BASE64_PAD64 && (unsigned char)base64_suffix_map[bdata[m]] == 255)
goto LEND;
}
/* Account the output size. */
if(bdata[insize - 1] == '=') padnum = 1;
if(bdata[insize - 1] == '=' && bdata[insize - 2] == '=') padnum = 2;
retsize = (insize - 4) - (insize - 4) / 4 + (3 - padnum);
if ( !out ) return retsize;
retpos = out;
/* Begging to decode. */
for(m = 0; m < insize; m += 4) {
*retpos = cmove_bits(base64_suffix_map[*bdata], 2, 0) + cmove_bits(base64_suffix_map[*(bdata + 1)], 0, 4);
if(m == insize - 4 && padnum != 0) { /* Only deal with last four bits. */
if(padnum == 1) /* Have one pad characters, only two availability characters. */
*(retpos + 1) = cmove_bits(base64_suffix_map[*(bdata + 1)], 4, 0) + cmove_bits(base64_suffix_map[*(bdata + 2)], 0, 2);
/*
Have two pad characters, only two availability characters.
if(padnum == 2) {
}
*/
retpos += 3 - padnum;
} else {
*(retpos + 1) = cmove_bits(base64_suffix_map[*(bdata + 1)], 4, 0) + cmove_bits(base64_suffix_map[*(bdata + 2)], 0, 2);
*(retpos + 2) = cmove_bits(base64_suffix_map[*(bdata + 2)], 6, 0) + base64_suffix_map[*(bdata + 3)];
retpos += 3;
}
bdata += 4;
}
LEND: return retsize;
}

17
sdk/utils/base64.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef _BASE64_H_
#define _BASE64_H_
#ifdef __cplusplus
extern "C"
{
#endif
int base64_encode(char *out, const char *data, int insize);
int base64_decode(char *out, const char *bdata, int insize);
#ifdef __cplusplus
}
#endif
#endif

47
sdk/utils/bzhash.c Normal file
View File

@@ -0,0 +1,47 @@
#define toupper(c) (((c) >= 'a' && (c) <= 'z') ? (c) ^ 0x20 : (c))
//哈希运算种子表
static cryptTable[0x500];
//哈希种子表是否初始化
static int cryptTableInited = 0;
static void initCryptrTable()
{
unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;
for( index1 = 0; index1 < 0x100; index1++ )
{
for( index2 = index1, i = 0; i < 5; i++, index2 += 0x100 )
{
unsigned long temp1, temp2;
seed = (seed * 125 + 3) % 0x2AAAAB;
temp1 = (seed & 0xFFFF) << 0x10;
seed = (seed * 125 + 3) % 0x2AAAAB;
temp2 = (seed & 0xFFFF);
cryptTable[index2] = ( temp1 | temp2 );
}
}
}
unsigned long bzhashstr(const char *str, unsigned long seed)
{
unsigned char *key = (unsigned char *)str;
unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
int ch;
if (!cryptTableInited)
{
initCryptrTable();
cryptTableInited = 1;
}
while(*key != 0)
{
ch = *key++;
ch = toupper(ch);
seed1 = cryptTable[(seed << 8) + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
return seed1;
}

28
sdk/utils/bzhash.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef _BZ_HASH_H_
#define _BZ_HASH_H_
/******************************************************************
*
* wyLib库 2008 - 2011
*
* 基于网上流传的暴雪哈希算法实现的字符串哈希值计算函数
*
*****************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
* Comments: 计算字符串哈希值
* Param const char * str: 字符串指针必须是0终止的字符串
* Param unsigned int seed: 哈希计算种子值,不同的种子值计算出的哈希值不同
* @Return unsigned int:
*/
unsigned int bzhashstr(const char *str, unsigned int seed);
#ifdef __cplusplus
}
#endif
#endif

33
sdk/utils/crc.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef _WYLIB_CRC_H_
#define _WYLIB_CRC_H_
/**
* wylib 2006 - 2011 快速CRC运算函数库
* 通过预先计算出CRC码表并使用汇编函数书写CRC计算函数
* 将码表通过内联到函数代码中使用CPU的一级指令缓存快
* 速访问码表来提高函数效率。
*/
#ifndef STDCALL
#define STDCALL __stdcall
#endif
#ifdef __cplusplus
extern "C"
{
#endif
/**
* Comments: CRC32值计算函数对data的datalen字节计算crc值
* Param DWORD crc: 原始crc值
* Param const void * data: 数据段指针
* Param UINT_PTR datalen: 要计算数据段中crc值的字节数量
* @Return DWORD : 对数据进行crc32计算的结果
*/
unsigned int CRC32Update(unsigned int crc, const void* data, int datalen);
#ifdef __cplusplus
}
#endif
#endif

81
sdk/utils/md5.h Normal file
View File

@@ -0,0 +1,81 @@
#ifndef _MD5_H_
#define _MD5_H_
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#ifdef __cplusplus
extern "C"
{
#endif
/* copy from global.h */
/* POINTER defines a generic pointer type */
//typedef unsigned char *POINTER;
#ifndef POINTER
#define POINTER unsigned char*
#endif
/* UINT2 defines a two byte word */
//typedef unsigned short int UINT2;
#ifndef UINT2
#define UINT2 unsigned short int
#endif
/* UINT4 defines a four byte word */
//typedef unsigned long int UINT4;
#ifndef UINT4
#define UINT4 unsigned int
#endif
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
returns an empty list.
*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
void MD5Final(unsigned char [32], MD5_CTX *);
char*MD5Encode(unsigned char[32], unsigned char *, unsigned int);
#ifdef __cplusplus
}
#endif
#endif

366
sdk/utils/md5c.c Normal file
View File

@@ -0,0 +1,366 @@
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
//#include "global.h"
#include "md5.h"
/* Constants for MD5Transform routine.
*/
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
static void Encode PROTO_LIST
((unsigned char *, UINT4 *, unsigned int));
static void Decode PROTO_LIST
((UINT4 *, unsigned char *, unsigned int));
static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
//to hex char
#define TO_HEX_CHAR(v) (((unsigned char)(v) >= 10) ? (unsigned char)(v) - 10 + 'a' : (unsigned char)(v) + '0')
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void MD5Init (context)
MD5_CTX *context; /* context */
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5Update (context, input, inputLen)
MD5_CTX *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void MD5Final (text, context)
unsigned char text[32]; /* message text */
MD5_CTX *context; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
unsigned char c1, c2;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
/* Store state in digest */
Encode (text, context->state, 16);
for ( index=16-1; (signed int)index>=0; --index )
{
c1 = (text[index] & 0xF0) >> 4;
c2 = (text[index] & 0x0F);
text[index<<1] = TO_HEX_CHAR(c1);
text[(index<<1)+1] = TO_HEX_CHAR(c2);
}
//transfer to string
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
char*MD5Encode(unsigned char dest[33], unsigned char *input, unsigned int sizeinput)
{
MD5_CTX md5c;
MD5Init( &md5c );
MD5Update( &md5c, input, sizeinput );
MD5Final( dest, &md5c );
dest[32] = 0;
return dest;
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (state, block)
UINT4 state[4];
unsigned char block[64];
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (output, input, len)
unsigned char *output;
UINT4 *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (output, input, len)
UINT4 *output;
unsigned char *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8)
|(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD5_memcpy (output, input, len)
POINTER output;
POINTER input;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD5_memset (output, value, len)
POINTER output;
int value;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
}

30
sdk/utils/nonuse/AtomOP.h Normal file
View File

@@ -0,0 +1,30 @@
#pragma once
/************************************************************************/
/*
/* 具有防止运算溢出的原子数据加减法运算函数库
/*
/* 运算函数会捕获运算结果的数据类型溢出错误从而修正返回值为数据类型的最小或最大值。
/*
/************************************************************************/
namespace wylib
{
namespace arithmetic
{
namespace atomSafe
{
/* 64位原子类型加减法运算会捕获运算结果的数据类型溢出错误从而修正返回值为数据类型的最小或最大值 */
inline UINT64 uint64Add(UINT64 a, UINT64 add) { return UInt64Add(a, add); }
inline INT64 int64Add(INT64 a, INT64 add) { return Int64Add(a, add); }
/* 32位原子类型加减法运算会捕获运算结果的数据类型溢出错误从而修正返回值为数据类型的最小或最大值 */
inline UINT uintAdd(UINT_PTR a, UINT_PTR add){ return UIntAdd(a, add); }
inline INT intAdd(INT_PTR a, INT_PTR add){ return IntAdd(a, add); }
/* 16位原子类型加减法运算会捕获运算结果的数据类型溢出错误从而修正返回值为数据类型的最小或最大值 */
inline WORD ushortAdd(UINT_PTR a, UINT_PTR add){ return UShortAdd(a, add); }
inline INT shortAdd(INT_PTR a, INT_PTR add){ return ShortAdd(a, add); }
/* 8位原子类型加减法运算会捕获运算结果的数据类型溢出错误从而修正返回值为数据类型的最小或最大值 */
inline UCHAR usmallAdd(UINT_PTR a, UINT_PTR add){ return USmallAdd(a, add); }
inline CHAR smallAdd(INT_PTR a, INT_PTR add){ return SmallAdd(a, add); }
}
}
}

View File

@@ -0,0 +1,502 @@
#ifndef ___NOT_USE_MEMORY_POOL___
#include <stdlib.h>
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#include <tchar.h>
#endif
#include <_ast.h>
#include <_memchk.h>
#include <Tick.h>
#include "ShareUtil.h"
#include "BufferAllocatorEx.h"
static const DWORD dwBufferFreeTick = 30 * 1000;//标记为释放的的内存块的延时销毁时间
/*
CBufferAllocator::CBufferAllocator()
{
m_pLastSmallBuffer = NULL;
m_pLastMiddleBuffer = NULL;
m_pLastLargeBuffer = NULL;
m_pLastSuperBuffer = NULL;
#ifdef _BUFFER_TRACE
m_pLastAllocedBuffer = NULL;
#endif
m_dwAllocedSmallSize = 0;
m_dwAllocedMiddleSize = 0;
m_dwAllocedLargeSize = 0;
m_dwAllocedSuperSize = 0;
m_dwFreedSmallSize = 0;
m_dwFreedMiddleSize = 0;
m_dwFreedLargeSize = 0;
m_dwFreedSuperSize = 0;
//InitializeCriticalSection( &m_BufferLock );
}
CBufferAllocator::~CBufferAllocator()
{
PBUFFER pBuffer, pPrevBuffer;
pBuffer = m_pLastSmallBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
free( pBuffer );
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastMiddleBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
free( pBuffer );
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastLargeBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
free( pBuffer );
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastSuperBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
free( pBuffer );
pBuffer = pPrevBuffer;
}
#ifdef _BUFFER_TRACE
pBuffer = m_pLastAllocedBuffer;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
TRACE( _T("%s(%d) : 申请的内存块没有释放pointer Addr=%d\n"), pBuffer->al.lpFile, pBuffer->al.nLine,(INT_PTR)pBuffer );
free( pBuffer );
pBuffer = pPrevBuffer;
//Assert(FALSE);//有内存泄漏,提醒
}
#endif
//DeleteCriticalSection( &m_BufferLock );
m_BufferLock.Unlock();
}
#ifndef _BUFFER_TRACE
PVOID CBufferAllocator::AllocBuffer(size_t dwSize)
#else
PVOID CBufferAllocator::_AllocBuffer(size_t dwSize, const char *lpFile, int nLine)
#endif
{
PBUFFER pBuffer, pPrev, pResult = NULL;
//如果空闲内存大于100M强制释放内存避免内存膨胀
if(m_dwFreedSuperSize + m_dwFreedSmallSize + m_dwFreedMiddleSize +m_dwFreedLargeSize>= 104857600 )
{
CheckFreeBuffers(true);
}
//EnterCriticalSection( &m_BufferLock );
m_BufferLock.Lock();
if ( dwSize <= SmallBufferSize )
{
if ( m_pLastSmallBuffer )
{
pResult = m_pLastSmallBuffer;
m_pLastSmallBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
m_dwFreedSmallSize -= SmallBufferSize;
}
else
{
#ifdef _BUFFER_TRACE
pResult = (PBUFFER)malloc( SmallBufferSize + sizeof(*pResult) + sizeof(INT) );
#else
pResult = (PBUFFER)malloc( SmallBufferSize + sizeof(*pResult) );
#endif
pResult->dwSize = SmallBufferSize;
pResult->pPrevBuffer = NULL;
#ifdef _BUFFER_TRACE
pResult->boUsing = FALSE;
pResult->pNextBuffer = NULL;
#endif
}
m_dwAllocedSmallSize += SmallBufferSize;
}
else if ( dwSize <= MiddleBufferSize )
{
if ( m_pLastMiddleBuffer )
{
pResult = m_pLastMiddleBuffer;
m_pLastMiddleBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
m_dwFreedMiddleSize -= MiddleBufferSize;
}
else
{
#ifdef _BUFFER_TRACE
pResult = (PBUFFER)malloc( MiddleBufferSize + sizeof(*pResult) + sizeof(INT) );
#else
pResult = (PBUFFER)malloc( MiddleBufferSize + sizeof(*pResult) );
#endif
pResult->dwSize = MiddleBufferSize;
pResult->pPrevBuffer = NULL;
#ifdef _BUFFER_TRACE
pResult->boUsing = FALSE;
pResult->pNextBuffer = NULL;
#endif
}
m_dwAllocedMiddleSize += MiddleBufferSize;
}
else if ( dwSize <= LargeBufferSize )
{
if ( m_pLastLargeBuffer )
{
pResult = m_pLastLargeBuffer;
m_pLastLargeBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
m_dwFreedLargeSize -= LargeBufferSize;
}
else
{
#ifdef _BUFFER_TRACE
pResult = (PBUFFER)malloc( LargeBufferSize + sizeof(*pResult) + sizeof(INT) );
#else
pResult = (PBUFFER)malloc( LargeBufferSize + sizeof(*pResult) );
#endif
pResult->dwSize = LargeBufferSize;
pResult->pPrevBuffer = NULL;
#ifdef _BUFFER_TRACE
pResult->boUsing = FALSE;
pResult->pNextBuffer = NULL;
#endif
}
m_dwAllocedLargeSize += LargeBufferSize;
}
else
{
pPrev = NULL;
pBuffer = m_pLastSuperBuffer;
while ( pBuffer )
{
if ( pBuffer->dwSize >= dwSize )
{
pResult = pBuffer;
#ifdef _BUFFER_TRACE
Assert( !pResult->boUsing );
#endif
if ( pResult == m_pLastSuperBuffer )
{
m_pLastSuperBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
}
else if ( pPrev )
{
pPrev->pPrevBuffer = pResult->pPrevBuffer;
pResult->pPrevBuffer = NULL;
}
m_dwFreedSuperSize -= pResult->dwSize;
break;
}
pPrev = pBuffer;
pBuffer = pBuffer->pPrevBuffer;
}
if ( !pResult )
{
dwSize = (dwSize + 511) & (~511);
#ifdef _BUFFER_TRACE
pResult = (PBUFFER)malloc( dwSize + sizeof(*pResult) + sizeof(INT) );
#else
pResult = (PBUFFER)malloc( dwSize + sizeof(*pResult) );
#endif
pResult->dwSize = dwSize;
pResult->pPrevBuffer = NULL;
#ifdef _BUFFER_TRACE
pResult->boUsing = FALSE;
pResult->pNextBuffer = NULL;
#endif
}
m_dwAllocedSuperSize += pResult->dwSize;
}
#ifdef _BUFFER_TRACE
if ( pResult )
{
Assert( !pResult->boUsing );
pResult->boUsing = TRUE;
pResult->al.lpFile = lpFile;
pResult->al.nLine = nLine;
pResult->fl.lpFile = NULL;
pResult->fl.nLine = 0;
pResult->dwFreeTick = 0;
*((PINT)((char*)(pResult + 1) + pResult->dwSize)) = 0xCC55EE33;
if ( m_pLastAllocedBuffer ) m_pLastAllocedBuffer->pNextBuffer = pResult;
pResult->pPrevBuffer = m_pLastAllocedBuffer;
pResult->pNextBuffer = NULL;
m_pLastAllocedBuffer = pResult;
}
#endif
//LeaveCriticalSection( &m_BufferLock );
m_BufferLock.Unlock();
return pResult ? pResult + 1 : NULL;
}
#ifndef _BUFFER_TRACE
PVOID CBufferAllocator::ReallocBuffer(PVOID ptr, size_t dwNewSize)
#else
PVOID CBufferAllocator::_ReallocBuffer(PVOID ptr, size_t dwNewSize, const char* lpFile, int nLine)
#endif
{
if (dwNewSize == 0)
{
FreeBuffer(ptr);
return NULL;
}
PBUFFER pBuffer;
if (ptr)
{
pBuffer = ((PBUFFER)ptr) - 1;
if (dwNewSize <= pBuffer->dwSize)
return ptr;
}
PVOID pResult;
#ifndef _BUFFER_TRACE
pResult = AllocBuffer(dwNewSize);
if (ptr)
{
memcpy(pResult, ptr, pBuffer->dwSize);
FreeBuffer(ptr);
}
#else
pResult = _AllocBuffer(dwNewSize, lpFile, NULL);
if (ptr)
{
memcpy(pResult, ptr, pBuffer->dwSize);
_FreeBuffer(ptr, lpFile, NULL);
}
#endif
return pResult;
}
#ifndef _BUFFER_TRACE
VOID CBufferAllocator::FreeBuffer(PVOID ptr)
#else
VOID CBufferAllocator::_FreeBuffer(PVOID ptr, const char* lpFile, int nLine)
#endif
{
PBUFFER pBuffer;
if (!ptr) return;
pBuffer = ((PBUFFER)ptr) - 1;
//EnterCriticalSection( &m_BufferLock );
m_BufferLock.Lock();
#ifdef _BUFFER_TRACE
if ( !pBuffer->boUsing )
{
//TRACE( _T(__FUNCTION__)_T(" 试图释放已经被标记为释放的内存块(%X,大小:%d),申请位置:%s(%d),释放位置:%s(%d)\n"),
// pBuffer, pBuffer->dwSize, pBuffer->al.lpFile, pBuffer->al.nLine,
// pBuffer->fl.lpFile, pBuffer->fl.nLine );
OutputMsg(rmError, _T(" %s试图释放已经被标记为释放的内存块(%X,大小:%d),申请位置:%s(%d),释放位置:%s(%d)\n"),
__FUNCTION__,pBuffer, pBuffer->dwSize, pBuffer->al.lpFile, pBuffer->al.nLine,
pBuffer->fl.lpFile, pBuffer->fl.nLine );
}
Assert( pBuffer->boUsing );
pBuffer->boUsing = FALSE;
Assert(*((PINT)((char*)(pBuffer + 1) + pBuffer->dwSize)) == 0xCC55EE33);
if ( pBuffer->pPrevBuffer )
pBuffer->pPrevBuffer->pNextBuffer = pBuffer->pNextBuffer;
if ( pBuffer->pNextBuffer )
pBuffer->pNextBuffer->pPrevBuffer = pBuffer->pPrevBuffer;
if ( pBuffer == m_pLastAllocedBuffer )
m_pLastAllocedBuffer = pBuffer->pPrevBuffer;
pBuffer->pPrevBuffer = NULL;
pBuffer->pNextBuffer = NULL;
pBuffer->fl.lpFile = lpFile;
pBuffer->fl.nLine = nLine;
#endif
pBuffer->dwFreeTick = _getTickCount() + dwBufferFreeTick;
if ( pBuffer->dwSize == SmallBufferSize )
{
pBuffer->pPrevBuffer = m_pLastSmallBuffer;
m_pLastSmallBuffer = pBuffer;
m_dwAllocedSmallSize -= SmallBufferSize;
m_dwFreedSmallSize += SmallBufferSize;
}
else if ( pBuffer->dwSize == MiddleBufferSize )
{
pBuffer->pPrevBuffer = m_pLastMiddleBuffer;
m_pLastMiddleBuffer = pBuffer;
m_dwAllocedMiddleSize -= MiddleBufferSize;
m_dwFreedMiddleSize += MiddleBufferSize;
}
else if ( pBuffer->dwSize == LargeBufferSize )
{
pBuffer->pPrevBuffer = m_pLastLargeBuffer;
m_pLastLargeBuffer = pBuffer;
m_dwAllocedLargeSize -= LargeBufferSize;
m_dwFreedLargeSize += LargeBufferSize;
}
else
{
pBuffer->pPrevBuffer = m_pLastSuperBuffer;
m_pLastSuperBuffer = pBuffer;
m_dwAllocedSuperSize -= pBuffer->dwSize;
m_dwFreedSuperSize += pBuffer->dwSize;
}
//LeaveCriticalSection( &m_BufferLock );
m_BufferLock.Lock();
}
VOID CBufferAllocator::GetMemoryInfo(CBufferAllocator::PALLOCATPR_MEMORY_INFOR pMemoryInfo)
{
pMemoryInfo->SmallBuffer.dwAllocSize = m_dwAllocedSmallSize;
pMemoryInfo->SmallBuffer.dwFreeSize = m_dwFreedSmallSize;
pMemoryInfo->MiddleBuffer.dwAllocSize = m_dwAllocedMiddleSize;
pMemoryInfo->MiddleBuffer.dwFreeSize = m_dwFreedMiddleSize;
pMemoryInfo->LargeBuffer.dwAllocSize = m_dwAllocedLargeSize;
pMemoryInfo->LargeBuffer.dwFreeSize = m_dwFreedLargeSize;
pMemoryInfo->SuperBuffer.dwAllocSize = m_dwAllocedSuperSize;
pMemoryInfo->SuperBuffer.dwFreeSize = m_dwFreedSuperSize;
}
VOID CBufferAllocator::CheckFreeBuffers(bool bIgnoreInterval)
{
PBUFFER pBuffer, pPrevBuffer, pLastBuffer;
LONGLONG dwTick = _getTickCount();
//EnterCriticalSection( &m_BufferLock );
m_BufferLock.Lock();
pBuffer = m_pLastSmallBuffer;
pLastBuffer = NULL;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
if (bIgnoreInterval || dwTick >= pBuffer->dwFreeTick)
{
if ( pBuffer == m_pLastSmallBuffer )
m_pLastSmallBuffer = pPrevBuffer;
if ( pLastBuffer )
pLastBuffer->pPrevBuffer = pPrevBuffer;
m_dwFreedSmallSize -= pBuffer->dwSize;
free( pBuffer );
}
else pLastBuffer = pBuffer;
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastMiddleBuffer;
pLastBuffer = NULL;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
if (bIgnoreInterval || dwTick >= pBuffer->dwFreeTick)
{
if ( pBuffer == m_pLastMiddleBuffer )
m_pLastMiddleBuffer = pPrevBuffer;
if ( pLastBuffer )
pLastBuffer->pPrevBuffer = pPrevBuffer;
m_dwFreedMiddleSize -= pBuffer->dwSize;
free( pBuffer );
}
else pLastBuffer = pBuffer;
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastLargeBuffer;
pLastBuffer = NULL;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
if (bIgnoreInterval || dwTick >= pBuffer->dwFreeTick)
{
if ( pBuffer == m_pLastLargeBuffer )
m_pLastLargeBuffer = pPrevBuffer;
if ( pLastBuffer )
pLastBuffer->pPrevBuffer = pPrevBuffer;
m_dwFreedLargeSize -= pBuffer->dwSize;
free( pBuffer );
}
else pLastBuffer = pBuffer;
pBuffer = pPrevBuffer;
}
pBuffer = m_pLastSuperBuffer;
pLastBuffer = NULL;
while ( pBuffer )
{
pPrevBuffer = pBuffer->pPrevBuffer;
if (bIgnoreInterval || dwTick >= pBuffer->dwFreeTick)
{
if ( pBuffer == m_pLastSuperBuffer )
m_pLastSuperBuffer = pPrevBuffer;
if ( pLastBuffer )
pLastBuffer->pPrevBuffer = pPrevBuffer;
m_dwFreedSuperSize -= pBuffer->dwSize;
free( pBuffer );
}
else pLastBuffer = pBuffer;
pBuffer = pPrevBuffer;
}
//LeaveCriticalSection( &m_BufferLock );
m_BufferLock.Unlock();
}
#ifdef _BUFFER_TRACE
DataBuffer::DataBuffer(CBufferAllocator *pAllocator, size_t dwSize, const char *_FILE, const int _LINE)
#else
DataBuffer::DataBuffer(CBufferAllocator *pAllocator, size_t dwSize)
#endif
{
m_pAllocator = pAllocator;
m_dwSize = dwSize;
#ifdef _BUFFER_TRACE
pData = (char*)pAllocator->_AllocBuffer(dwSize, _FILE, _LINE);
#else
pData = (char*)pAllocator->AllocBuffer(dwSize);
#endif
ptr = pReadPtr = pData;
pEnd = pData + dwSize;
}
DataBuffer::~DataBuffer()
{
m_pAllocator->FreeBuffer( pData );
}
*/
#endif

View File

@@ -0,0 +1,126 @@
#ifndef _MSG_ALLOCATOR_H_
#define _MSG_ALLOCATOR_H_
/*
#include <_osdef.h>
#include <Tick.h>
#include <string.h>
#include "Lock.h"
#include "Lock.h"
#ifdef _DEBUG
#define _BUFFER_TRACE
#endif
using namespace wylib::time::tick64;
class CBufferAllocator
{
public:
static const DWORD SmallBufferSize = 64; //小块内存块大小
static const DWORD MiddleBufferSize = 256; //中等内存块大小
static const DWORD LargeBufferSize = 1024; //大块内存块大小
#pragma pack(push, 1)
typedef struct tagBuffer
{
size_t dwSize; //内存数据段大小
tagBuffer* pPrevBuffer;//指向上一个内存块的指针
TICKCOUNT dwFreeTick; //即将被销毁的时间
#ifdef _BUFFER_TRACE
tagBuffer* pNextBuffer;//指向上下个内存块的指针,用于调试
struct
{
const char* lpFile; //申请内存块的代码位置,用于调试
int nLine;
}al, fl;
BOOL boUsing; //是否使用的标记
#endif
}BUFFER, *PBUFFER;
#pragma pack(pop)
struct BufferStatic
{
size_t dwAllocSize;
size_t dwFreeSize;
};
typedef struct tagAllocatorMemoryInfo
{
BufferStatic SmallBuffer;
BufferStatic MiddleBuffer;
BufferStatic LargeBuffer;
BufferStatic SuperBuffer;
}ALLOCATOR_MEMORY_INFO, *PALLOCATPR_MEMORY_INFOR;
private:
//CRITICAL_SECTION m_BufferLock; //内存块申请锁
wylib::sync::lock::CCSLock m_BufferLock; //加锁
PBUFFER m_pLastSmallBuffer; //指向最后一个空闲的小型内存块的指针
PBUFFER m_pLastMiddleBuffer; //指向最后一个空闲的中型内存块的指针
PBUFFER m_pLastLargeBuffer; //指向最后一个空闲的大型内存块的指针
PBUFFER m_pLastSuperBuffer; //指向最后一个空闲的超级内存块的指针
#ifdef _BUFFER_TRACE
PBUFFER m_pLastAllocedBuffer; //指向最后一个被申请的内存块
#endif
size_t m_dwAllocedSmallSize; //已被申请的小型内存块大小
size_t m_dwAllocedMiddleSize; //已被申请的中型内存块大小
size_t m_dwAllocedLargeSize; //已被申请的大型内存块大小
size_t m_dwAllocedSuperSize; //已被申请的超级内存块大小
size_t m_dwFreedSmallSize; //已被释放的小型内存块大小
size_t m_dwFreedMiddleSize; //已被释放的中型内存块大小
size_t m_dwFreedLargeSize; //已被释放的大型内存块大小
size_t m_dwFreedSuperSize; //已被释放的超级内存块大小
public:
CBufferAllocator();
~CBufferAllocator();
#ifndef _BUFFER_TRACE
PVOID AllocBuffer(size_t dwSize);
PVOID ReallocBuffer(LPVOID ptr, size_t dwNewSize);
VOID FreeBuffer(PVOID ptr);
#else
PVOID _AllocBuffer(size_t dwSize, const char* lpFile, int nLine);
PVOID _ReallocBuffer(LPVOID ptr, size_t dwNewSize, const char* lpFile, int nLine);
VOID _FreeBuffer(PVOID ptr, const char* lpFile, int nLine);
#define AllocBuffer(dwSize) _AllocBuffer(dwSize, __FILE__, __LINE__)
#define ReallocBuffer(ptr, dwNewSize) _ReallocBuffer(ptr, dwNewSize, __FILE__, __LINE__)
#define FreeBuffer(ptr) _FreeBuffer(ptr, __FILE__, __LINE__)
#endif
VOID GetMemoryInfo(CBufferAllocator::PALLOCATPR_MEMORY_INFOR pMemoryInfo);
// bIgnoreInterval:是否忽略间隔。如果忽略时间间隔,不管是否时间间隔到,都强制删除
VOID CheckFreeBuffers(bool bIgnoreInterval = false);
};
class DataBuffer
{
public:
CBufferAllocator *m_pAllocator;
size_t m_dwSize;
char *pData;//内存块指针
char *ptr;//写内存指针
char *pEnd;//内存块结束指针
char *pReadPtr;//读内存指针
#ifdef _BUFFER_TRACE
DataBuffer(CBufferAllocator *pAllocator, size_t dwSize, const char *_FILE, const int _LINE);
#else
DataBuffer(CBufferAllocator *pAllocator, size_t dwSize);
#endif
~DataBuffer();
};
#ifdef _BUFFER_TRACE
#define DATA_BUFFER_VAR(_allocator, _name, _size) DataBuffer _name((_allocator), (_size), __FILE__, __LINE__)
#else
#define DATA_BUFFER_VAR(_allocator, _name, _size) DataBuffer _name((_allocator), (_size))
#endif
*/
#endif

View File

@@ -0,0 +1,909 @@
#ifdef WIN32
#include <stdio.h>
#include <stdlib.h>
#include <crtdbg.h>
#include <tchar.h>
#include <Windows.h>
#include <_ast.h>
#include <_memchk.h>
#include <QueueList.h>
#include <Tick.h>
#include <wyString.h>
#include "ShareUtil.h"
#include "../include/FDOP.h"
#include "../include/ObjectAllocator.hpp"
#include "../include/CustomSortList.h"
#include "CustomFileDB.h"
#include <new>
const TCHAR CCustomFileDB::DataFileExt[] = _T(".fdb");
const TCHAR CCustomFileDB::IndexFileExt[] = _T(".fdi");
using namespace wylib::sync::lock;
CCustomFileDB::CCustomFileDB()
{
m_hIndexFile = m_hDataFile = INVALID_HANDLE_VALUE;
m_nNextIndexOffset = sizeof(m_Header);
ZeroMemory(&m_Header, sizeof(m_Header));
m_boFlushFileDataImmediately = FALSE;
}
CCustomFileDB::~CCustomFileDB()
{
close();
}
class CFDBOpenHelper
{
public:
HANDLE hIndex;
HANDLE hData;
CCustomFileDB::ChunkIndex::ChunkDesc *pChunkDescBuffer;
CFDBOpenHelper()
{
hIndex = hData = INVALID_HANDLE_VALUE;
pChunkDescBuffer = NULL;
}
~CFDBOpenHelper()
{
if (hIndex != INVALID_HANDLE_VALUE)
CloseHandle(hIndex);
if (hData != INVALID_HANDLE_VALUE)
CloseHandle(hData);
if (pChunkDescBuffer)
free(pChunkDescBuffer);
}
};
bool CCustomFileDB::open(LPCTSTR sDBName)
{
CFDBOpenHelper openHelper;
//以共享读方式打开数据文件
String sPath = sDBName;
String sFilePath = sPath + DataFileExt;
openHelper.hData = CreateFile(sFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
if (openHelper.hData == INVALID_HANDLE_VALUE)
{
OutputError(GetLastError(), _T("Can not open DataFile \"%s\""), sFilePath.rawStr());
return false;
}
//以共享读方式打开索引文件
sFilePath = sPath + IndexFileExt;
openHelper.hIndex = CreateFile(sFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
if (openHelper.hIndex == INVALID_HANDLE_VALUE)
{
OutputError(GetLastError(), _T("Can not open IndexFile \"%s\""), sFilePath.rawStr());
return false;
}
//读取文件头
SetFilePointer(openHelper.hIndex, 0, NULL, 0);
FDBHeader hdr;
DWORD dwBytesReaded;
if (!ReadFile(openHelper.hIndex, &hdr, sizeof(hdr), &dwBytesReaded, NULL) || dwBytesReaded != sizeof(hdr))
{
OutputError(GetLastError(), _T("Can not read IndexHeader"));
return false;
}
//检查文件头标志
if (hdr.dwIdent != FDBHeader::IDENT)
{
OutputMsg(rmError, _T("Invalid IndexHeader %08X"), hdr.dwIdent);
return false;
}
//检查文件版本
if (hdr.dwVersion != FDBHeader::VERSION)
{
OutputMsg(rmError, _T("Invalid IndexVersion %08X"), hdr.dwVersion);
return false;
}
//申请索引数据临时内容缓冲区
DWORD dwDataIndexSize = sizeof(openHelper.pChunkDescBuffer[0]) * hdr.nRecordCount;
openHelper.pChunkDescBuffer = (ChunkIndex::ChunkDesc*)malloc(dwDataIndexSize);
if (!openHelper.pChunkDescBuffer)
{
OutputMsg(rmError, _T("Out of memory to alloc indexbuffer %08X"), hdr.dwVersion);
return false;
}
//读取索引数据内容
if (!ReadFile(openHelper.hIndex, openHelper.pChunkDescBuffer, dwDataIndexSize, &dwBytesReaded, NULL) || dwBytesReaded != dwDataIndexSize)
{
OutputMsg(rmError, _T("Invalid IndexVersion %08X"), hdr.dwVersion);
return false;
}
//关闭当前文件
close();
//将文件句柄以及文件头保存到类中
m_hIndexFile = openHelper.hIndex;
m_hDataFile = openHelper.hData;
m_nNextIndexOffset = sizeof(m_Header) + dwDataIndexSize;
openHelper.hIndex = openHelper.hData = INVALID_HANDLE_VALUE;
m_Header = hdr;
//保留读取内存空间
m_IndexRecordList.reserve(hdr.nRecordCount);
m_DataList.setSorted(FALSE);
m_DataList.reserve(hdr.nRecordCount);
m_FreeDataSizeList.setSorted(FALSE);
m_FreeDataSizeList.reserve(hdr.nRecordCount);
m_FreeDataOffsetList.setSorted(FALSE);
m_FreeDataOffsetList.reserve(hdr.nRecordCount);
m_NullIndexList.reserve(hdr.nRecordCount);
//开始读取索引数据到内存
ChunkIndex::ChunkDesc *pChunkDesc = openHelper.pChunkDescBuffer;
ChunkIndex *pIndex = m_IndexAllocator.allocObjects(hdr.nRecordCount);
AvaliableDataIndex avalIndex;
FreeDataSizeIndex sizeIndex;
FreeDataOffsetIndex offsetIndex;
INT64 nOffset = sizeof(hdr);
for (INT_PTR i=hdr.nRecordCount-1; i>-1; --i)
{
pIndex->chunk = *pChunkDesc;
pIndex->nIndexOffset = nOffset;
m_IndexRecordList.add(pIndex);
//如果记录块大小值为0则表示该记录为没有任何意义需将记录存储在空闲块列表中。
if (pChunkDesc->nChunkSize == 0)
{
m_NullIndexList.add(pIndex);
}
//如果记录ID值为零则表示该记录为一个空闲的数据块需将记录存储在空闲块列表中。
else if (pChunkDesc->nId == 0)
{
sizeIndex.pIndex = pIndex;
m_FreeDataSizeList.add(sizeIndex);
offsetIndex.pIndex = pIndex;
m_FreeDataOffsetList.add(offsetIndex);
}
else
{
//数据有效,添加到有效数据列表中
avalIndex.pIndex = pIndex;
m_DataList.add(avalIndex);
}
nOffset += sizeof(*pChunkDesc);
pChunkDesc++;
pIndex++;
}
m_DataList.setSorted(TRUE);
m_FreeDataSizeList.setSorted(TRUE);
m_FreeDataOffsetList.setSorted(TRUE);
return true;
}
void CCustomFileDB::close()
{
CSafeLock sl1(&m_IndexFileLock);
CSafeLock sl2(&m_DataFileLock);
if (m_hIndexFile != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hIndexFile);
m_hIndexFile = INVALID_HANDLE_VALUE;
}
if (m_hDataFile != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hDataFile);
m_hDataFile = INVALID_HANDLE_VALUE;
}
m_IndexRecordList.trunc(0);
m_DataList.trunc(0);
m_FreeDataSizeList.trunc(0);
m_FreeDataOffsetList.trunc(0);
m_NullIndexList.trunc(0);
//释放索引块内存管理器中的内存并重新初始化内存管理器
m_IndexAllocator.~CObjectAllocator<ChunkIndex>();
new (&m_IndexAllocator) IndexAllocator();
}
bool CCustomFileDB::create(LPCTSTR sDBName)
{
CFDBOpenHelper helper;
String sPath = sDBName;
String sDataFile = sPath + DataFileExt;
String sIndexFile = sPath + IndexFileExt;
//数据文件已经存在则不能再创建
if (FDOP::IsArchive(sDataFile))
{
OutputMsg(rmError, _T("Can not create new database, data file \"%s\" already exists"), sDataFile.rawStr());
return false;
}
//索引文件已经存在则不能再创建
if (FDOP::IsArchive(sIndexFile))
{
OutputMsg(rmError, _T("Can not create new database, index file \"%s\" already exists"), sIndexFile.rawStr());
return false;
}
//逐层创建数据库目录,例如指定数据库./FDB/db1/char则需要创建目录./FDB以及./FDB/db1。
FDOP::ExtractFileDirectory(sDBName, sPath, MAXINT);
if (!FDOP::DeepCreateDirectory(sPath))
{
OutputMsg(rmError, _T("Can not create new database, index file \"%s\" already exists"), sIndexFile.rawStr());
return false;
}
//创建数据库索引文件
helper.hIndex = CreateFile(sIndexFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, 0, NULL);
if (helper.hIndex == INVALID_HANDLE_VALUE)
{
OutputMsg(rmError, _T("Can not create new index file \"%s\")"), sIndexFile.rawStr());
return false;
}
//向索引文件中写入文件头
FDBHeader hdr;
DWORD dwSizeWritten;
ZeroMemory(&hdr, sizeof(hdr));
hdr.dwIdent = FDBHeader::IDENT;
hdr.dwVersion = FDBHeader::VERSION;
if (!WriteFile(helper.hIndex, &hdr, sizeof(hdr), &dwSizeWritten, NULL) || sizeof(hdr) != dwSizeWritten)
{
OutputMsg(rmError, _T("Can not write new index file \"%s\""), sIndexFile.rawStr());
return false;
}
//创建数据文件
helper.hData = CreateFile(sDataFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, 0, NULL);
if (helper.hData == INVALID_HANDLE_VALUE)
{
OutputMsg(rmError, _T("Can not create new data file \"%s\""), sDataFile.rawStr());
return false;
}
//关闭当前数据库
close();
//保存当前的数据库文件句柄为新打开的句柄
m_Header = hdr;
m_hIndexFile = helper.hIndex;
m_hDataFile = helper.hData;
//
helper.hIndex = helper.hData = INVALID_HANDLE_VALUE;
return true;
}
bool CCustomFileDB::put(INT64 nDataId, LPCVOID lpData, INT64 dwSize)
{
//不允许数据ID值为0因为在索引中记录ID值为零用于表示索引记录包含一个空闲的数据块
if (nDataId == 0)
{
DbgAssert(FALSE);
return false;
}
ChunkIndex *pIndex, *pNewIndex;
DataHeader dh;
dh.dwIdent = DataHeader::VALID_IDENT;
dh.nId = nDataId;
dh.nDataSize = dwSize;
dwSize += sizeof(dh);
INT_PTR nIdx = m_DataList.search(nDataId);
if (nIdx > -1)
{
pIndex = m_DataList[nIdx];
/*如果当前块空间足够容纳新数据,则检查是否因当前块的数据减少了从而需要将一
个大的块拆解为两个独立的记录块。如果当前快空间不足容纳新数据,则必须申请一
个新的块来存放数据并且将当前块添加为空闲块。*/
if (pIndex->chunk.nChunkSize >= dwSize)
{
INT64 nOldDataSize = pIndex->chunk.nDataSize;
pIndex->chunk.nDataSize = dwSize;
if (!writeData(pIndex, &dh, lpData))
return false;
//计算可以从这个大的数据块中分出多大的新的数据快
INT64 dwSplitOutSize = getChunkSplitOutSize(pIndex->chunk.nChunkSize, dwSize);
//如果可以分出新的数据块则拆分数据块
if (dwSplitOutSize > 0)
{
if (!splitLargeChunk(pIndex, dwSplitOutSize))
return false;
}
else
{
//如果数据块没有进行拆分则检查是否需要更新改块的索引数据
if (nOldDataSize != dwSize)
{
if (!flushIndex(pIndex))
return false;
}
}
}
else
{
//重新申请新记录块,并向新的块中写入数据
pNewIndex = reallocChunk(pIndex, dwSize);
if (!pNewIndex)
return false;
//向数据文件中更新数据
if (!writeData(pNewIndex, &dh, lpData))
return false;
//将新记录块索引写入到索引文件中。
//必须在writeData发生后才能写因为当pNewIndex是全新的索引时chunk.nDataOffset为-1
//用于表示在writeData发生时再确定数据块索引
if (!flushIndex(pNewIndex))
return NULL;
//将新的记录索引替换到数据索引列表中
m_DataList[nIdx].pIndex = pNewIndex;
}
}
else
{
//申请新的记录块,并向新的块中写入数据
pNewIndex = allocChunk(nDataId, dwSize);
if (!writeData(pNewIndex, &dh, lpData))
return false;
//将新记录块索引写入到索引文件中
if (!flushIndex(pNewIndex))
return false;
//将新索引添加到有效数据列表中
AvaliableDataIndex ChunkIndex;
ChunkIndex.pIndex = pNewIndex;
m_DataList.add(ChunkIndex);
}
return true;
}
INT64 CCustomFileDB::get(INT64 nDataId, LPVOID lpBuffer, INT64 dwBufferSize) const
{
static const DWORD DataHeaderSize = sizeof(DataHeader);
INT_PTR nIdx = m_DataList.search(nDataId);
if (nIdx < 0)
return 0;
ChunkIndex *pIndex = m_DataList[nIdx].pIndex;
DbgAssert(pIndex->chunk.nDataSize >= DataHeaderSize);
//dwBufferSize为0则仅表示获取数据长度
if (dwBufferSize == 0)
{
if (pIndex->chunk.nDataSize > DataHeaderSize)
return pIndex->chunk.nDataSize - DataHeaderSize;
else return 0;
}
else
{
INT64 nOffset = pIndex->chunk.nDataOffset + DataHeaderSize;
INT64 nSize = pIndex->chunk.nDataSize - DataHeaderSize;
if (dwBufferSize > nSize)
dwBufferSize = nSize;
if (!readDataFile(nOffset, lpBuffer, dwBufferSize))
return 0;
return dwBufferSize;
}
}
bool CCustomFileDB::remove(INT64 nDataId)
{
INT_PTR nIdx = m_DataList.search(nDataId);
if (nIdx > -1)
{
ChunkIndex *pIndex = m_DataList[nIdx];
//将索引记录从数据列表移除
m_DataList.remove(nIdx);
//将旧的索引记录添加到空闲记录列表中
pIndex->chunk.nId = 0;
addFreeChunk(pIndex);
//新索引写入到索引文件中
if (!flushIndex(pIndex))
return false;
return true;
}
return false;
}
INT64 CCustomFileDB::getTotalDataSize() const
{
INT_PTR i;
INT64 nSize = 0;
AvaliableDataIndex *pIndexList = m_DataList;
AvaliableDataIndex *pIndex = pIndexList;
for (i=m_DataList.count()-1; i>-1; --i)
{
nSize += pIndex->pIndex->chunk.nDataSize;
pIndex++;
}
return nSize;
}
INT64 CCustomFileDB::getTotalFreeChunkSize() const
{
INT_PTR i;
INT64 nSize = 0;
FreeDataSizeIndex *pIndexList = m_FreeDataSizeList;
FreeDataSizeIndex *pIndex = pIndexList;
for (i=m_FreeDataSizeList.count()-1; i>-1; --i)
{
nSize += pIndex->pIndex->chunk.nChunkSize;
pIndex++;
}
return nSize;
}
INT64 CCustomFileDB::getDataFileSize() const
{
LARGE_INTEGER lSize;
if (m_hDataFile == INVALID_HANDLE_VALUE)
return 0;
if (GetFileSizeEx(m_hDataFile, &lSize))
return lSize.QuadPart;
else return 0;
}
INT64 CCustomFileDB::getIdList(INT64 nIndex, PINT64 pIdList, INT64 nMaxCount)
{
PINT64 pIdPtr = pIdList;
INT_PTR nListCount = m_DataList.count();
for (INT_PTR i=(INT_PTR)nIndex; i<nListCount && nMaxCount>0; ++i)
{
*pIdPtr = m_DataList[i].pIndex->chunk.nId;
pIdPtr++;
nMaxCount--;
}
return pIdPtr - pIdPtr;
}
CCustomFileDB::ChunkIndex* CCustomFileDB::allocChunk(INT64 nId, INT64 dwDataSize)
{
ChunkIndex *pResult = NULL;
INT64 nChunkSize = 0;
//当dwDataSize为0时表示仅申请一个索引对象不预留空间。
if (dwDataSize != 0)
{
//根据数据块单元大小调整nChunkSize
if (m_Header.dwChunkSize > 0)
nChunkSize = dwDataSize + (m_Header.dwChunkSize - (dwDataSize % m_Header.dwChunkSize));
else nChunkSize = dwDataSize;
//在空闲列表中找一个大小最接近的数据块索引
INT_PTR nIdx = m_FreeDataSizeList.searchMiniGreater(nChunkSize);
if (nIdx > -1)
{
FreeDataOffsetIndex offsetIndex;
pResult = m_FreeDataSizeList[nIdx].pIndex;
DbgAssert(pResult->chunk.nChunkSize >= nChunkSize);
offsetIndex.pIndex = pResult;
INT_PTR nOffsetIndex = m_FreeDataOffsetList.search(pResult->chunk.nDataOffset);
if (nOffsetIndex > -1)
{
DbgAssert(m_FreeDataOffsetList[nOffsetIndex].pIndex == pResult);
//分别从空闲偏移以及空闲大小列表中删除索引记录
m_FreeDataSizeList.remove(nIdx);
m_FreeDataOffsetList.remove(nOffsetIndex);
}
else
{
OutputMsg(rmError, _T("Missing SizeRecord of Free ChunkIndex at %08X"), pResult);
DbgAssert(FALSE);
pResult = NULL;
}
}
}
//空闲数据块列表中没有合适的记录,则在数据文件末尾写入
if (!pResult)
{
if (m_NullIndexList.count() > 0)
{
pResult = m_NullIndexList.pop();
}
else
{
pResult = m_IndexAllocator.allocObjects(1);
m_IndexRecordList.add(pResult);
//将nIndexOffset置为-1以便在写索引的时候再确定记录偏移位置
pResult->nIndexOffset = -1;
}
//将nDataOffset置为-1以便在写数据的时候再确定偏移位置
//无论是在m_NullIndexList列表中的索引记录或新创建的索引记录都是没有数据块的
pResult->chunk.nDataOffset = -1;
}
//填充新索引记录的所有有效字段
pResult->chunk.nId = nId;
pResult->chunk.nDataSize = dwDataSize;
pResult->chunk.nChunkSize = nChunkSize;
return pResult;
}
bool CCustomFileDB::flushIndex(ChunkIndex *pIndex)
{
bool isNewIndex = pIndex->nIndexOffset == -1;
//如果是新索引,则计算并确定索引偏移
if (isNewIndex)
{
pIndex->nIndexOffset = m_nNextIndexOffset;
//TRACE(_T("New IndexOffset is : %08X\r\n"), pIndex->nIndexOffset);
m_nNextIndexOffset += sizeof(pIndex->chunk);
}
//向索引文件中写入索引记录
if (!writeIndexFile(pIndex->nIndexOffset, &pIndex->chunk, sizeof(pIndex->chunk)))
return false;
//如果是新索引,则更新索引文件头
if (isNewIndex)
{
m_Header.nRecordCount++;
if (!writeIndexFile(0, &m_Header, sizeof(m_Header)))
return false;
}
return true;
}
void CCustomFileDB::addFreeChunk(ChunkIndex *pIndex)
{
ChunkIndex *pExistsRecord;
FreeDataOffsetIndex offsetIndex;
FreeDataSizeIndex sizeIndex;
INT_PTR nIdx, nListIndex, nMergeFrom, nMergedCount, nListCount;
DataHeader dh;
Assert(pIndex->chunk.nId == 0);
Assert(pIndex->chunk.nDataOffset != -1);
//将原有的数据头标记为无效数据,以防在通过数据文件重建索引时将无用的数据块再挖掘出来!
dh.dwIdent = DataHeader::INVALID_IDENT;//标记数据无效
writeDataFile(pIndex->chunk.nDataOffset, &dh.dwIdent, sizeof(dh.dwIdent));
//将索引记录添加到数据块偏移以及大小排序列表中
offsetIndex.pIndex = pIndex;
sizeIndex.pIndex = pIndex;
nIdx = m_FreeDataOffsetList.add(offsetIndex);
m_FreeDataSizeList.add(sizeIndex);
//尝试合并与改数据块前后相邻的空闲数据块
nMergeFrom = -1;
nMergedCount = 0;
nListIndex = nIdx - 1;
//向前合并连续的数据块为一个大块
while (nListIndex >= 0)
{
pExistsRecord = m_FreeDataOffsetList[nListIndex].pIndex;
if (pExistsRecord->chunk.nDataOffset + pExistsRecord->chunk.nChunkSize == pIndex->chunk.nDataOffset)
{
pExistsRecord->chunk.nChunkSize += pIndex->chunk.nChunkSize;
pIndex->chunk.nChunkSize = 0;
pIndex->chunk.nId = 0;
pIndex = pExistsRecord;
nMergeFrom = nListIndex;
nMergedCount++;
nListIndex--;
}
else break;
}
//向后合并连续的数据块为一个大块
nListCount = m_FreeDataOffsetList.count();
nListIndex = nIdx + 1;
while (nListIndex < nListCount)
{
pExistsRecord = m_FreeDataOffsetList[nListIndex].pIndex;
if (pIndex->chunk.nDataOffset + pIndex->chunk.nChunkSize == pExistsRecord->chunk.nDataOffset)
{
pIndex->chunk.nChunkSize += pExistsRecord->chunk.nChunkSize;
pExistsRecord->chunk.nChunkSize = 0;
pExistsRecord->chunk.nId = 0;
if (nMergeFrom == -1)
nMergeFrom = nIdx;
nMergedCount++;
nListIndex++;
}
else break;
}
if (nMergedCount > 0)
{
INT_PTR i;
//将被合并的数据块的索引从块偏移以及块大小列表中移除
for (i=nMergeFrom + nMergedCount; i> nMergeFrom; --i)
{
pIndex = m_FreeDataOffsetList[i].pIndex;
//目前查找pIndex在m_FreeDataSizeList中索引的操作采取的是完全遍历的方式
//由于m_FreeDataSizeList使用数据块大小成员进行排序而列表中可能存在多个大
//小相同的块的索引记录,因而如果使用基于对比的快速查找有可能返回其他的指针的问题。
nListIndex = getFreeSizeListIndex(pIndex);
if (nListIndex > -1)
{
m_FreeDataSizeList.remove(nListIndex);
m_NullIndexList.add(pIndex);
flushIndex(pIndex);
}
else Assert(FALSE);
}
m_FreeDataOffsetList.remove(nMergeFrom + 1, nMergedCount);
//向索引文件中写入被合并后的最终块索引
pIndex = m_FreeDataOffsetList[nMergeFrom].pIndex;
flushIndex(pIndex);
}
validateListCount();
}
bool CCustomFileDB::splitLargeChunk(ChunkIndex *pIndex, INT64 dwSplitOutSize)
{
//减少当前数据块的大小并写入索引文件中
Assert(pIndex->chunk.nChunkSize >= dwSplitOutSize);
pIndex->chunk.nChunkSize -= dwSplitOutSize;
if (!flushIndex(pIndex))
return false;
//申请新的记录块,并向将剩余空间保留给新记录块
ChunkIndex *pNewIndex = allocChunk(0, 0);
pNewIndex->chunk.nChunkSize = dwSplitOutSize;
pNewIndex->chunk.nDataOffset= pIndex->chunk.nDataOffset + pIndex->chunk.nChunkSize;
//将新的索引记录添加到空闲记录列表中
addFreeChunk(pNewIndex);
//新索引写入到索引文件中
if (!flushIndex(pNewIndex))
return false;
return true;
}
CCustomFileDB::ChunkIndex* CCustomFileDB::reallocChunk(ChunkIndex *pIndex, INT64 dwNewDataSize)
{
INT64 nMergedChunkSize;
ChunkIndex *pNewIndex;
//首先在尝试与该数据块后面相邻的空闲数据块进行合并
INT_PTR nIdx = m_FreeDataOffsetList.search(pIndex->chunk.nDataOffset + pIndex->chunk.nChunkSize);
pNewIndex = ((nIdx > -1) ? m_FreeDataOffsetList[nIdx].pIndex : NULL);
//如果改数据块与下一个块的总大小可以容纳新的数据长度,则进行合并
if (pNewIndex && (nMergedChunkSize = pIndex->chunk.nChunkSize + pNewIndex->chunk.nChunkSize) >= dwNewDataSize)
{
//如果完全合并后的块太大,将从空闲块中拆分一部分空间与当前块合并,剩余的空间继续作为一个独立的块
//例如我们需要存储10K的数据而空闲块中有1GB的数据如果将1G与当前快合并将造成过度的浪费
INT64 nSplitOutSize = getChunkSplitOutSize(nMergedChunkSize, dwNewDataSize);
if (nSplitOutSize > 0)
{
Assert(nSplitOutSize <= pNewIndex->chunk.nChunkSize);
//减少空闲块的长度
pNewIndex->chunk.nDataOffset += pNewIndex->chunk.nChunkSize - nSplitOutSize;
pNewIndex->chunk.nChunkSize = nSplitOutSize;
if (!flushIndex(pNewIndex))
return NULL;
//增加当前块的长度
pIndex->chunk.nChunkSize = nMergedChunkSize - nSplitOutSize;
pIndex->chunk.nDataSize = dwNewDataSize;
if (!flushIndex(pIndex))
return NULL;
}
else
{
//将空闲数据块调整为无效数据块
pNewIndex->chunk.nChunkSize = 0;
if (!flushIndex(pNewIndex))
return NULL;
//扩展当前块的长度
pIndex->chunk.nChunkSize = nMergedChunkSize;
pIndex->chunk.nDataSize = dwNewDataSize;
if (!flushIndex(pIndex))
return NULL;
//将空闲块索引记录从空闲偏移以及大小列表中移除
INT_PTR nSizeListIdx = getFreeSizeListIndex(pNewIndex);
Assert(nSizeListIdx > -1);
m_FreeDataSizeList.remove(nSizeListIdx);
m_FreeDataOffsetList.remove(nIdx);
//将空闲块索引记录添加到无效块列表
m_NullIndexList.add(pNewIndex);
}
return pIndex;
}
else
{
//申请新的记录块,并向新的块中写入数据
pNewIndex = allocChunk(pIndex->chunk.nId, dwNewDataSize);
//向索引文件中更新旧索引
pIndex->chunk.nId = 0;
if (!flushIndex(pIndex))
return NULL;
//将旧的索引记录添加到空闲记录列表中
addFreeChunk(pIndex);
return pNewIndex;
}
return NULL;
}
bool CCustomFileDB::writeData(ChunkIndex *pIndex, const DataHeader *pDataHeader, LPCVOID lpDataBuffer)
{
INT64 nOffset = pIndex->chunk.nDataOffset;
LARGE_INTEGER lFileSize, lNewSize;
INT64 nBlockDataSize = pDataHeader->nDataSize + sizeof(*pDataHeader);
bool boIsNewData = nOffset == -1;
DbgAssert(pIndex->chunk.nId == pDataHeader->nId);
DbgAssert(pIndex->chunk.nChunkSize >= nBlockDataSize);
DbgAssert(pIndex->chunk.nChunkSize >= pIndex->chunk.nDataSize);
CSafeLock sl(&m_DataFileLock);
//偏移为-1表示这是一个新的数据块需要写入数据文件末尾
if (boIsNewData)
{
if (!GetFileSizeEx(m_hDataFile, &lFileSize))
{
OutputError(GetLastError(), _T("Can not query data file size"));
return false;
}
pIndex->chunk.nDataOffset = nOffset = lFileSize.QuadPart;
}
if (!writeDataFile(nOffset, pDataHeader, sizeof(*pDataHeader)))
return false;
nOffset += sizeof(*pDataHeader);
if (!writeDataFile(nOffset, lpDataBuffer, pDataHeader->nDataSize))
return false;
//如果是新数据块且数据库头中指定了数据块单元大小,则调整数据文件以进行数据块大小对齐
if (boIsNewData && m_Header.dwChunkSize > 0 && pIndex->chunk.nChunkSize != nBlockDataSize)
{
lFileSize.QuadPart = pIndex->chunk.nDataOffset + pIndex->chunk.nChunkSize;
//调整文件指针到数据块大小单元处
if (!SetFilePointerEx(m_hDataFile, lFileSize, &lNewSize, FILE_BEGIN) || lFileSize.QuadPart != lNewSize.QuadPart)
{
OutputError(GetLastError(), _T("Can not query data file size"));
return false;
}
//设置文件结束位置
if (!SetEndOfFile(m_hDataFile))
{
OutputError(GetLastError(), _T("Can not set end of data file"));
return false;
}
}
return true;
}
bool CCustomFileDB::writeDataFile(INT64 nOffset, LPCVOID lpBuffer, INT64 dwSize)
{
static const DWORD OnceWriteBytes = 0x10000;//每次写文件的字节数
CSafeLock sl(&m_DataFileLock);
LONG nHighInt = HILONG(nOffset);
if (SetFilePointer(m_hDataFile, (LONG)nOffset, &nHighInt, FILE_BEGIN) != nOffset)
{
OutputError(GetLastError(), _T("Fatal error can not set data file pointer"));
return false;
}
DWORD dwBytesToWrite, dwBytesWriten;
const char* ptr = (const char*)lpBuffer;
while (dwSize > 0)
{
if (dwSize > OnceWriteBytes)
dwBytesToWrite = OnceWriteBytes;
else dwBytesToWrite = (LONG)dwSize;
if (!WriteFile(m_hDataFile, ptr, dwBytesToWrite, &dwBytesWriten, NULL))
{
OutputError(GetLastError(), _T("Fatal error can not write data file"));
return false;
}
ptr += dwBytesWriten;
dwSize -= dwBytesWriten;
}
if (m_boFlushFileDataImmediately)
{
FlushFileBuffers(m_hDataFile);
}
return true;
}
bool CCustomFileDB::readDataFile(INT64 nOffset, LPVOID lpBuffer, INT64 dwSize) const
{
static const DWORD OnceReadBytes = 0x10000;//每次读文件的字节数
CSafeLock sl((CBaseLock *)&m_DataFileLock);
LONG nHighInt = HILONG(nOffset);
if (SetFilePointer(m_hDataFile, (LONG)nOffset, &nHighInt, FILE_BEGIN) != nOffset)
{
OutputError(GetLastError(), _T("Fatal error can not set data file pointer"));
return false;
}
DWORD dwBytesToRead, dwBytesReaded;
INT64 dwTotalRead = 0;
char* ptr = (char*)lpBuffer;
while (dwSize > dwTotalRead)
{
if (dwSize > OnceReadBytes)
dwBytesToRead = OnceReadBytes;
else dwBytesToRead = (LONG)dwSize;
if (!ReadFile(m_hDataFile, ptr, dwBytesToRead, &dwBytesReaded, NULL) || dwBytesReaded == 0)
{
OutputError(GetLastError(), _T("Fatal error can not read data file"));
return false;
}
ptr += dwBytesReaded;
dwTotalRead += dwBytesReaded;
}
return true;
}
bool CCustomFileDB::writeIndexFile(INT64 nOffset, LPCVOID lpBuffer, INT64 dwSize)
{
static const DWORD OnceWriteBytes = 8192;//每次写文件的字节数
CSafeLock sl(&m_IndexFileLock);
LONG nHighInt = HILONG(nOffset);
if (SetFilePointer(m_hIndexFile, (LONG)nOffset, &nHighInt, FILE_BEGIN) != nOffset)
{
OutputError(GetLastError(), _T("Fatal error can not set index file pointer"));
return false;
}
DWORD dwBytesToWrite, dwBytesWriten;
const char* ptr = (const char*)lpBuffer;
while (dwSize > 0)
{
if (dwSize > OnceWriteBytes)
dwBytesToWrite = OnceWriteBytes;
else dwBytesToWrite = (LONG)dwSize;
if (!WriteFile(m_hIndexFile, ptr, dwBytesToWrite, &dwBytesWriten, NULL))
{
OutputError(GetLastError(), _T("Fatal error can not write index file"));
return false;
}
ptr += dwBytesWriten;
dwSize -= dwBytesWriten;
}
if (m_boFlushFileDataImmediately)
{
FlushFileBuffers(m_hIndexFile);
}
return true;
}
void CCustomFileDB::validateListCount() const
{
Assert(m_FreeDataOffsetList.count() == m_FreeDataSizeList.count());
Assert(m_FreeDataOffsetList.count() + m_NullIndexList.count() + m_DataList.count() == m_IndexRecordList.count());
}
INT64 CCustomFileDB::getChunkSplitOutSize(INT64 nChunkSize, INT64 dwDataSize) const
{
INT64 nRemainSize = nChunkSize - dwDataSize;
/*将大的数据块拆分为小数据块的条件为:
1、数据库头中规定的数据块大小不低于128字节
2、数据块写入新数据后剩余空间大于数据库头中的数据块单位大小
3、新数据长度是数据块长度的一半以内
*/
if (nRemainSize >= 128 && (nRemainSize > m_Header.dwChunkSize) && (dwDataSize <= nChunkSize / 2) )
{
//将新数据块的大小调整为头中规定的数据库单位大小的倍数
return nRemainSize / m_Header.dwChunkSize * m_Header.dwChunkSize;
}
//返回0表示无法分割
return 0;
}
INT_PTR CCustomFileDB::getFreeSizeListIndex(ChunkIndex *pIndex) const
{
INT_PTR i;
FreeDataSizeIndex *pSizeIndexList = m_FreeDataSizeList;
for (i=m_FreeDataSizeList.count()-1; i>-1; --i)
{
if (pSizeIndexList[i] == pIndex)
{
return i;
}
}
return -1;
}
#endif

View File

@@ -0,0 +1,273 @@
#pragma once
/************************************************************************
简易二进制K-V数据库系统
FileDB是一个简易的面向二进制的KV数据存储系统。设计目的在于以最高效和简单的方式提供
一种可变长度二进制数据的存储方式。数据的存储介质是磁盘而不是内存,实时的将数据写入到磁
盘可以在系统宕机时将损失降到最小,这满足最大化降低系统故障影响的设计需求。
每个数据库由两个文件组成,一个是数据文件另一个是索引文件。数据文件中存储在该数据库中
数据存储的所有数据。我们将数据文件划分为一系列的“块”Chunk块是存储数据的基本单元。
如果一个FileDB数据库中存储了100份数据那么这个数据库的数据文件中至少会有100个块
个块负责存储一份数据,每添加一份新数据,就有一个新的块产生,块在产生的时候,其大小由需要
存储的数据的大小决定,但每个块的大小都会进行“块单元大小对齐”。块单元大小对齐值是在创建数
据库后指定的,其意义在于使每个块的长度对齐到一个值的整倍数,视不同的应用需求指定将合理的
块单元大小将有利于优化已存储的数据内容增长和减少时的存储效率以及整个数据文件的空间利用率。
每个块的起始24字节为一个DataHeader结构结构中描述了块的数据ID以及块存储的数据长度
这被称之为块描述头。块描述头的设计目的在于当丢失索引文件时可以通过数据文件中的块描述头来
重建索引文件。
在索引文件中存储了数据文件中的所有块的描述信息。每个描述信息包括块存储的数据的ID、块
在数据文件中的偏移位置,块存储的数据长度以及块的大小。这些信息用于在读写数据库的时候快速的
定位要在数据文件中读和写的位置等一切针对块进行操作的功能。
向FileDB中存储数据以及获取数据的一句是64位的整数ID。对于不同的数据内容ID必须是唯一
的。如果以1为ID向数据库存储了100字节的数据然后再存储50字节的数据那么最终通过ID值1获
取的数据是最后存储的50字节的内容。值为0的ID是不允许使用的他在FileDB的实现中有着特殊的
意义。
★★★该数据库只能在本机系统运行,目前没有提供基于网络的支持,但这依然是可以扩展实现的。
★★★该数据库没有提供权限管理功能,对存储数据的安全管理是使用本数据库系统的软件的责任。
************************************************************************/
#ifdef WIN32
class CCustomFileDB
{
public:
CCustomFileDB();
~CCustomFileDB();
//打开数据库
bool open(LPCTSTR sDBName);
//关闭索引文件
void close();
//创建数据库
bool create(LPCTSTR sDBName);
//向数据库更新数据,如果数据不存在则添加为新数据
bool put(INT64 nDataId, LPCVOID lpData, INT64 dwSize);
//从数据库中读取数据
//如果dwBufferSize为0则进行指定ID数据的长度查询操作此时函数返回此ID的数据长度。
//如果dwBufferSize为正数值则函数向lpBuffer中拷贝数据库中存储的数据拷贝的长度
//受dwBufferSize限制。如果dwBufferSize大于数据的实际长度则仅向lpBuffer中拷贝
//数据的实际长度字节数。函数返回值表示最终向lpBuffer拷贝了多少字节。
INT64 get(INT64 nDataId, LPVOID lpBuffer, INT64 dwBufferSize) const;
//从数据库移除数据
//如果数据存在且删除成功则返回true。
//改操作可能引发索引列表的内存大量拷贝。
bool remove(INT64 nDataId);
//获取存储在数据库中的第nIndex个数据的ID
inline INT64 getId(INT_PTR nIndex){ return m_DataList[nIndex].pIndex->chunk.nId; }
//获取数据块单位长度
inline DWORD getChunkSize() const{ return m_Header.dwChunkSize; }
//设置数据块单位长度
inline void setChunkSize(DWORD dwNewSize){ m_Header.dwChunkSize = dwNewSize; };
//是否在向文件写入数据后立即提交数据,如果开启则每当发生一次完整的数据和索引文件的写操作时,
//都会等待文件被写入到硬盘后才返回。这个可以有效的提高数据存储的安全性。但由于同步文件写操作
//比较耗时,因此可能因为存储效率被降低而造成性能瓶颈。
inline bool getFlushFileDataImmediately() const{ return m_boFlushFileDataImmediately != 0; }
inline void setFlushFileDataImmediately(bool boImmediately){ m_boFlushFileDataImmediately = (boImmediately ? TRUE : FALSE); }
//获取数据记录数量
inline INT_PTR getDataCount() const{ return m_DataList.count(); }
//获取空闲数据块数量
inline INT_PTR getFreeChunkCount() const{ return m_FreeDataOffsetList.count(); }
//获取空索引数量
inline INT_PTR getNullIndexCount() const{ return m_NullIndexList.count(); }
//计算总存储数据大小
//通过计算总存储数据大小与数据文件大小,可以进行数据文件利用率的计算:利用率 = 总存储数据大小 / 数据文件大小
INT64 getTotalDataSize() const;
//计算总空闲数据块大小
//通过计算总空闲数据块大小与数据文件大小,可以进行数据空闲率的计算:空闲率 = 总空闲数据块大小 / 数据文件大小
INT64 getTotalFreeChunkSize() const;
//获取数据文件大小
INT64 getDataFileSize() const;
//获取数据ID列表
//函数从第nIndex个ID开始填充pIdList列表并且最多填充nMaxCount个。
//函数返回值表示实际向pIdList中填充的ID数量返回值可能比nMaxCount小。
INT64 getIdList(INT64 nIndex, PINT64 pIdList, INT64 nMaxCount);
public:
static const TCHAR DataFileExt[];//数据文件后缀
static const TCHAR IndexFileExt[];//索引文件后缀
/** 数据库文件头 **/
struct FDBHeader
{
static const DWORD IDENT = MAKEFOURCC('F', 'D', 'I', 0);
static const DWORD VERSION = 0x010B0A0D;
//文件标识固定为MAKEFOURCC('F', 'D', 'B', 0)
DWORD dwIdent;
//数据库文件格式版本号目前为0x010B0A0D
DWORD dwVersion;
//数据库中存储的记录数量
INT nRecordCount;
/*数据记录块单位大小
记录块大小用于预保留数据记录的空间,以便优化在记录内数据长度变大
时的存储效率。数据库存储记录数据时,会保证用于对一个记录的字节长
度是dwChunkSize的倍数。例如在创建数据库时指定记录块大小为1024
那么向数据库存储一个长度为800字节的记录时仍然会给此记录分配长度
为1024字节的空间存储1025字节的记录时则会分配2048字节的空间。
这将有利于在记录的数据长度会不断变化的场合,预先为下次变化保留存储
空间,而合理的提供数据记录块大小值,则能充分的体现这一优化效果。
dwChunkSize在数据库创建的时候既被指定并且此后不得再改变。
*/
DWORD dwChunkSize;
//保留字节
char btReseves[48];
};
#pragma pack(push, 1)
//数据记录头。每个数据块均以一个数据记录头开始。
struct DataHeader
{
static const INT64 VALID_IDENT = 0xFFAADD8800DDAAFF;
static const INT64 INVALID_IDENT = 0xCCAADD8800DDAACC;
INT64 dwIdent; //数据记录头标志固定为0xFFAADD8800DDAAFF
INT64 nId; //数据ID
INT64 nDataSize; //数据长度(不含本记录头)
public:
DataHeader(){ dwIdent = VALID_IDENT; }
};
#pragma pack(pop)
// 数据块索引
struct ChunkIndex
{
#pragma pack(push, 1)
struct ChunkDesc
{
INT64 nId; //数据记录唯一ID值。如果值为零则表示该记录为一个空闲的数据块可以被回收利用。
INT64 nDataOffset;//记录在数据库文件中的绝对偏移值
INT64 nDataSize; //数据记录字节数包含数据块开头的DataHeader的大小
INT64 nChunkSize; //数据记录块大小。如果值为0则表示该记录为没有任何意义该索引在文件中的位置空间可以被回收利用。
}chunk;
#pragma pack(pop)
INT64 nIndexOffset; //本索引记录在索引文件中的偏移位置
};
//有效数据记录项
struct AvaliableDataIndex
{
ChunkIndex *pIndex;
public:
inline operator ChunkIndex* (){ return pIndex; }
inline INT_PTR compare (const AvaliableDataIndex & another) const
{
if (pIndex == another.pIndex) return 0;
if (this->pIndex->chunk.nId < another.pIndex->chunk.nId) return -1;
else if (this->pIndex->chunk.nId > another.pIndex->chunk.nId) return 1;
//如果出现相同ID索引的情况那么就是发生错误了
else { Assert(pIndex == another.pIndex); return 0; };
}
inline INT_PTR compareKey(const INT64 nID) const
{
if (this->pIndex->chunk.nId < nID) return -1;
else if (this->pIndex->chunk.nId > nID) return 1;
else return 0;
}
};
//空闲记录块大小排序项
struct FreeDataSizeIndex
{
ChunkIndex *pIndex;
public:
inline operator ChunkIndex* (){ return pIndex; }
inline bool operator == (const FreeDataSizeIndex & another) const { return pIndex == another.pIndex; }
inline INT_PTR compare (const FreeDataSizeIndex & another) const
{
//if (pRecord == another.pRecord) return 0;
if (this->pIndex->chunk.nChunkSize < another.pIndex->chunk.nChunkSize) return -1;
else if (this->pIndex->chunk.nChunkSize > another.pIndex->chunk.nChunkSize) return 1;
else return 0;
}
inline INT_PTR compareKey(const INT64 nSize) const
{
if (this->pIndex->chunk.nChunkSize < nSize) return -1;
else if (this->pIndex->chunk.nChunkSize > nSize) return 1;
else return 0;
}
};
// 空闲记录块偏移排序项
struct FreeDataOffsetIndex
{
ChunkIndex *pIndex;
public:
inline operator ChunkIndex* (){ return pIndex; }
inline bool operator == (const FreeDataOffsetIndex & another) const { return pIndex == another.pIndex; }
inline INT_PTR compare (const FreeDataOffsetIndex & another) const
{
if (this->pIndex->chunk.nDataOffset < another.pIndex->chunk.nDataOffset) return -1;
else if (this->pIndex->chunk.nDataOffset > another.pIndex->chunk.nDataOffset) return 1;
//对于存储数据块索引的列表,如果出现相同偏移位置的索引的情况,那么就是发生错误了!
else { Assert(pIndex == another.pIndex); return 0; };
}
inline INT_PTR compareKey(const INT64 nOffset) const
{
if (this->pIndex->chunk.nDataOffset < nOffset) return -1;
else if (this->pIndex->chunk.nDataOffset > nOffset) return 1;
else return 0;
}
};
typedef CObjectAllocator<ChunkIndex> IndexAllocator;
typedef wylib::container::CBaseList<ChunkIndex*> IndexRecordList;
typedef CCustomSortList<AvaliableDataIndex, INT64> DataList;
typedef CCustomSortList<FreeDataSizeIndex, INT64> FreeDataSizeList;
typedef CCustomSortList<FreeDataOffsetIndex, INT64> FreeDataOffsetList;
typedef wylib::container::CBaseList<ChunkIndex*> NullIndexList;
typedef wylib::sync::lock::CCSLock FileLock;
protected:
HANDLE m_hIndexFile; //索引文件句柄
HANDLE m_hDataFile; //数据文件句柄
FileLock m_IndexFileLock;//索引文件锁
FileLock m_DataFileLock; //数据文件锁
FDBHeader m_Header; //文件头
IndexAllocator m_IndexAllocator; //索引记录申请器
IndexRecordList m_IndexRecordList; //索引记录列表
DataList m_DataList; //有效数据索引列表
FreeDataSizeList m_FreeDataSizeList; //空闲数据大小排序表,用于快速找到一个合适的空数据位置
FreeDataOffsetList m_FreeDataOffsetList; //空闲数据偏移排序表,用于合并连续的空数据位置
NullIndexList m_NullIndexList; //无效索引记录列表
INT64 m_nNextIndexOffset; //下一个索引记录的偏移位置
BOOL m_boFlushFileDataImmediately;//是否在向文件写入数据后立即提交数据
protected:
//申请一个索引记录。返回的索引中会正确填充所以记录的所有成员。
//当dwDataSize为0时表示仅申请一个索引对象不预留空间。
ChunkIndex* allocChunk(INT64 nId, INT64 dwDataSize);
//将索引记录写入到索引文件中
bool flushIndex(ChunkIndex *pIndex);
//将索引记录添加为空数据索引
void addFreeChunk(ChunkIndex *pIndex);
//将一个大的数据块拆分成两个小块参数dwSplitOutSize为从大数据块中拆分出来的新数据块的大小
bool splitLargeChunk(ChunkIndex *pIndex, INT64 dwSplitOutSize);
//重新申请一个更大的数据库块
ChunkIndex* reallocChunk(ChunkIndex *pIndex, INT64 dwNewDataSize);
//向数据文件写数据块
bool writeData(ChunkIndex *pIndex, const DataHeader *pDataHeader, LPCVOID lpDataBuffer);
//向数据文件中写数据(任意数据)
bool writeDataFile(INT64 nOffset, LPCVOID lpBuffer, INT64 dwSize);
//从数据文件中读数据
bool readDataFile(INT64 nOffset, LPVOID lpBuffer, INT64 dwSize) const;
//向索引文件中写数据(任意数据)
bool writeIndexFile(INT64 nOffset, LPCVOID lpBuffer, INT64 dwSize);
protected:
//验证各个列表的数据数量
void validateListCount() const;
//计算一个nChunkSize大小的数据块能够分割出的新数据块的大小如果返回0则表示不能分割
//参数dwDataSize为在nChunkSize大小的数据块中存储的数据大小包含DataHeader的大小非块大小
//将大的数据块拆分为小数据块的条件为:
// 1、数据库头中规定的数据块大小不低于128字节
// 2、数据块写入新数据后剩余空间大于数据库头中的数据块单位大小
// 3、新数据长度是数据块长度的一半以内
INT64 getChunkSplitOutSize(INT64 nChunkSize, INT64 dwDataSize) const;
//获取索引记录在空闲大小列表中的索引
INT_PTR getFreeSizeListIndex(ChunkIndex *pIndex) const;
};
#endif

View File

@@ -0,0 +1,71 @@
#include "aes.h"
#include <stdlib.h>
#include <string.h>
#include "base64.h"
static int boInited = 0;
static const int Bits128 = 16;
const char* EncryptPassword(char* sDest, int nDestSize, const char* sPassWord, const char* sKey128Bit)
{
struct aes_ctx ctx;
int nInSize;
char* sBuffer;
char* sBase64Buffer;
int nSize;
if ( !boInited )
{
boInited = 1;
gen_tabs();
}
aes_set_key( &ctx, (const u8 *)sKey128Bit, Bits128 );
nInSize = (int)strlen(sPassWord) * sizeof(sPassWord[0]);
sBuffer = (char*)malloc(nInSize * 8 + 4);
sBase64Buffer = sBuffer + nInSize * 2;
nSize = (int)_AESEncrypt( &ctx, sBuffer, sPassWord, nInSize );
nSize = base64_encode(sBase64Buffer, sBuffer, nSize);
sBase64Buffer[nSize] = 0;
strncpy(sDest, sBase64Buffer, nDestSize-1);
sDest[nDestSize-1] = 0;
free(sBuffer);
return sDest;
}
const char* DecryptPassword(char* sPassword, int nPasswordLen, const char* sEncrypted, const char* sKey128Bit)
{
struct aes_ctx ctx;
int nInSize;
char* sAESBuffer;
char* sBuffer;
int nSize;
if ( !boInited )
{
boInited = 1;
gen_tabs();
}
aes_set_key( &ctx, (const u8 *)sKey128Bit, Bits128 );
nInSize = (int)strlen(sEncrypted) * sizeof(sEncrypted[0]);
sAESBuffer = (char*)malloc(nInSize * 8 + 4);
sBuffer = sAESBuffer + nInSize * 2;
nSize = base64_decode(sAESBuffer, sEncrypted, nInSize);
_AESDecrypt( &ctx, sBuffer, sAESBuffer, nSize );
sBuffer[nSize] = 0;
strncpy(sPassword, sBuffer, nPasswordLen-1);
sPassword[nPasswordLen-1] = 0;
free(sAESBuffer);
return sPassword;
}

22
sdk/utils/nonuse/EDPass.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef _ED_PASS_H_
#define _ED_PASS_H_
/**
* 加密密码字符串
* sDest 加密输出缓冲区
* nDestSize 输出缓冲区长度(如果空间足够则会在sDest末尾添加终止字符)
* sPassWord 密码字符串
* sKey128Bit 16字节的密钥字符串
**/
const char* EncryptPassword(char* sDest, int nDestSize, const char* sPassWord, const char* sKey128Bit);
/**
* 解密密码字符串
* sDest 解密输出缓冲区
* nDestSize 输出缓冲区长度(如果空间足够则会在sDest末尾添加终止字符)
* sPassWord 加密过的密码字符串
* sKey128Bit 16字节的密钥字符串
**/
const char* DecryptPassword(char* sPassword, int nPasswordLen, const char* sEncrypted, const char* sKey128Bit);
#endif

View File

@@ -0,0 +1,137 @@
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//// STL A* Search implementation
//// (C)2001 Justin Heyes-Jones
////
//// Finding a path on a simple grid maze
//// This shows how to do shortest path finding using A*
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//
//#include "MapSearchNode.h" // See header for copyright and usage information
//#include <iostream>
//#include <math.h>
//VirturalMap * CMapSearchNode::m_pMap =NULL;
//
//bool CMapSearchNode::IsSameState( CMapSearchNode &rhs )
//{
//
// // same state in a maze search is simply when (x,y) are the same
// if( (x == rhs.x) &&
// (y == rhs.y) )
// {
// return true;
// }
// else
// {
// return false;
// }
//
//}
//
//void CMapSearchNode::PrintNodeInfo()
//{
// cout << "Node position : (" << x << ", " << y << ")" << endl;
//}
//
//// Here's the heuristic function that estimates the distance from a Node
//// to the Goal.
//
//int CMapSearchNode::GoalDistanceEstimate( CMapSearchNode &nodeGoal )
//{
// return abs(x - nodeGoal.x) + abs(y - nodeGoal.y);
//}
//
//bool CMapSearchNode::IsGoal( CMapSearchNode &nodeGoal )
//{
//
// if( (x == nodeGoal.x) &&
// (y == nodeGoal.y) )
// {
// return true;
// }
//
// return false;
//}
//
//// This generates the successors to the given Node. It uses a helper function called
//// AddSuccessor to give the successors to the AStar class. The A* specific initialisation
//// is done for each node internally, so here you just set the state information that
//// is specific to the application
//bool CMapSearchNode::GetSuccessors( AStarSearch<CMapSearchNode> *astarsearch, CMapSearchNode *parent_node )
//{
//
// int parent_x = -1;
// int parent_y = -1;
//
// if( parent_node )
// {
// parent_x = parent_node->x;
// parent_y = parent_node->y;
// }
//
//
// CMapSearchNode NewNode;
//
// // push each possible move except allowing the search to go backwards
// int nCurrentX,nCurrentY;
// if(parent_x <0 || parent_y <0)
// {
// for(int i=-1;i <=1; i++)
// {
// for(int j=-1; j<=1; j++ )
// {
// if(i==0 && j==0) continue;
//
// nCurrentX = x +i;
// nCurrentY = y+j;
// if( GetMap( nCurrentX, nCurrentY,0,0 ) >= 0 )
// {
// NewNode = CMapSearchNode( nCurrentX, nCurrentY );
// astarsearch->AddSuccessor( NewNode );
// }
// }
// }
// }
// else
// {
// for(int i=-1;i <=1; i++)
// {
// for(int j=-1; j<=1; j++ )
// {
// if(i==0 && j==0) continue;
// nCurrentX = x +i;
// nCurrentY = y+j;
//
// if((parent_x == nCurrentX) && (parent_y == nCurrentY) )continue;
//
// if( GetMap( nCurrentX, nCurrentY,0 ,0) >= 0 )
// {
// NewNode = CMapSearchNode( nCurrentX, nCurrentY );
// astarsearch->AddSuccessor( NewNode );
// }
// }
// }
// }
//
// return true;
//}
//
//// given this node, what does it cost to move to successor. In the case
//// of our map the answer is the map terrain value at this node since that is
//// conceptually where we're moving
//
//int CMapSearchNode::GetCost( CMapSearchNode &successor )
//{
// if(x == -1 || y ==-1 || successor.x ==-1 || successor.y ==-1 )
// {
// return 1000000;
// }
// else
// {
// return abs(x - successor.x) + abs(y - successor.y);
// }
//}
//
//

View File

@@ -0,0 +1,67 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// STL A* Search implementation
// (C)2001 Justin Heyes-Jones
//
// Finding a path on a simple grid maze
// This shows how to do shortest path finding using A*
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef WIN32
#pragma once
#include "VirturalMap.h"
#include "stlastar.h" // See header for copyright and usage information
#define DEBUG_LISTS 0
#define DEBUG_LIST_LENGTHS_ONLY 0
using namespace std;
// Definitions
class CMapSearchNode
{
public:
int x; // the (x,y) positions of the node
int y;
static VirturalMap * m_pMap; //µØÍ¼µÄÖ¸Õë
CMapSearchNode() { x = y = -1; }
CMapSearchNode( int px, int py ) { x=px; y=py;}
static void SetMapPtr(VirturalMap * pMap)
{
m_pMap = pMap;
}
int GoalDistanceEstimate( CMapSearchNode &nodeGoal );
bool IsGoal( CMapSearchNode &nodeGoal );
bool GetSuccessors( AStarSearch<CMapSearchNode> *astarsearch, CMapSearchNode *parent_node );
int GetCost( CMapSearchNode &successor );
bool IsSameState( CMapSearchNode &rhs );
void PrintNodeInfo();
inline int GetMap(int x,int y,int nParam,int nParam2,int nParam3,int nParam4)
{
if(m_pMap==NULL)
{
return -1;
}
else
{
return m_pMap->canEntityMove(x,y,nParam,nParam2,nParam3,nParam4) ?1:0;
}
}
};
#endif

View File

@@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdarg.h>
#ifdef WIN32
#include <tchar.h>
#else
#include <stdlib.h>
#include <wchar.h>
#endif
#include "_osdef.h"
#include <_ast.h>
#include <_memchk.h>
#include "PrintMsg.h"
using namespace wylib::printmsg;
MSGHANDLEPROC g_lpMsgHandleProc;
MSGHANDLEPROC wylib::printmsg::SetMsgHandler(MSGHANDLEPROC lpProc)
{
MSGHANDLEPROC lpOldProc = g_lpMsgHandleProc;
g_lpMsgHandleProc = lpProc;
return lpOldProc;
}
MSGHANDLEPROC wylib::printmsg::GetMsgHandler()
{
return g_lpMsgHandleProc;
}
int wylib::printmsg::PrintMsg(ePrintMsgType msgType, eMsgLevel msgLevel, LPCTSTR format, ...)
{
TCHAR sBuffer[4096/sizeof(TCHAR) + 1];
va_list args;
int Result = 0;
if (g_lpMsgHandleProc)
{
sBuffer[0] = 0;
va_start(args, format);
Result = _vsntprintf(sBuffer, ArrayCount(sBuffer), format, args);
va_end(args);
Result = g_lpMsgHandleProc( msgType, msgLevel, sBuffer, Result );
}
return Result;
}

View File

@@ -0,0 +1,64 @@
#ifndef _WYLIB_PRINT_MSG_H_
#define _WYLIB_PRINT_MSG_H_
/******************************************************************
*
* wyLib库 2008 - 2010
*
* $ 通用输出消息重定向函数库 $
*
* - 主要功能 -
*
* 实现常用的消息输出重定向,在不同项目中设置新的消息输出处
* 理函数即可默认的消息输出处理函数是libc的printf函数。
* 输出消息函数的临时数据是基于栈的,所以是多线程安全的。
*
*****************************************************************/
#include "TypeDef.h"
namespace wylib
{
namespace printmsg
{
/* 输出消息的类型定义 */
typedef enum ePrintMsgType
{
pmNormal = 0, //普通消息
pmTip, //提示信息
pmAlert, //警告信息
pmError, //错误信息
}PRINTMSGTYPE;
/* 输出消息的重要程度定义 */
typedef enum eMsgLevel
{
mlLowest = 0, //无关紧要的信息
mlNormal = 5, //正常等级的信息
mlHighest = 10, //非常重要的信息
}MSGLEVEL;
#ifndef EXTEN_CALL
#define EXTEN_CALL __stdcall
#endif
/* 输出消息处理函数的函数类型 */
#ifdef WIN32
typedef int (EXTEN_CALL *MSGHANDLEPROC) (ePrintMsgType, eMsgLevel, LPCTSTR sMsg, int nMsgLen);
#else
typedef int ( * MSGHANDLEPROC) (ePrintMsgType, eMsgLevel, LPCTSTR sMsg, int nMsgLen);
#endif
//设定消息处理函数,函数返回之前的消息处理函数
MSGHANDLEPROC SetMsgHandler(MSGHANDLEPROC lpProc);
//获取当前的消息处理函数
MSGHANDLEPROC GetMsgHandler();
//输出消息的函数,内部会对传递的相关参数进行格式化。
//注意格式化后输出的内容的长度必须小于4K
int PrintMsg(ePrintMsgType msgType, eMsgLevel msgLevel, LPCTSTR format, ...);
};
};
#endif

View File

@@ -0,0 +1,83 @@
#include <stdlib.h>
#include <stdio.h>
#ifdef WIN32
#include <Windows.h>
#include <tchar.h>
#include <_ast.h>
#include <_memchk.h>
#include "sqlite3.h"
#include "../include/SQLiteDB.h"
CSQLiteDB::CSQLiteDB()
{
m_pDB = NULL;
}
CSQLiteDB::~CSQLiteDB()
{
close();
}
int CSQLiteDB::copen(const char * sDBFile)
{
sqlite3 *pDB;
//打开数据库
int nErr = sqlite3_open(sDBFile, &pDB);
return checkOpenResult(nErr, pDB);
}
int CSQLiteDB::wopen(const wchar_t * wsDBFile)
{
sqlite3 *pDB;
//打开数据库
int nErr = sqlite3_open16(wsDBFile, &pDB);
return checkOpenResult(nErr, pDB);
}
void CSQLiteDB::close()
{
if (m_pDB)
{
sqlite3_close(m_pDB);
m_pDB = NULL;
}
}
unsigned short CSQLiteDB::getPageSize()
{
if (!opened())
return 0;
CSQLiteStatement stmt(this, "PRAGMA page_size;");
if (stmt.step())
return stmt.val_int(0);
else return 0;
}
int CSQLiteDB::getErrorCode()
{
if (!opened())
return 0;
return sqlite3_errcode(m_pDB);
}
const wchar_t * CSQLiteDB::getErrorMessage()
{
if (!opened())
return NULL;
return (const wchar_t *)sqlite3_errmsg16(m_pDB);
}
int CSQLiteDB::checkOpenResult(int nErr, sqlite3 *pdb)
{
if (nErr == SQLITE_OK)
{
//打开数据成功则关闭现有数据库并保持新的数据库连接对象
close();
m_pDB = pdb;
}
return nErr;
}
#endif

164
sdk/utils/nonuse/SQLiteDB.h Normal file
View File

@@ -0,0 +1,164 @@
#pragma once
/******************************************************************
SQLite数据库的基本操作类
实现了基本的数据库查询和更新操作。
对数据库的操作并不是多线程安全的,调用者必须负责维护好多线程的调用问
题,或者对类打开的数据库的操作只由一个固定的线程操作。
******************************************************************/
#ifdef WIN32
class CSQLiteDB
{
public:
CSQLiteDB();
~CSQLiteDB();
public:
/*打开一个数据文件。
* 如果当前已经有打开的数据库,则会在成功打开新的数据库后关闭原有数据库文件,
* 如果无法打开新的数据库,则原有打开的数据库不会被关闭。
* 函数返回SQLITE3_OK(0)表示打开成功。
*/
int copen(const char *sDBFile);
int wopen(const wchar_t *wsDBFile);
//关闭当前打开的数据库
void close();
//判断数据库是否已经打开
inline bool opened(){ return m_pDB != NULL; }
public:
//获取sqlite3指针
inline sqlite3* getSqlite3Ptr(){ return m_pDB; }
//获取数据库的分页大小
unsigned short getPageSize();
//获取上次操作的错误码
int getErrorCode();
//获取上次操作的错误描述字串
const wchar_t * getErrorMessage();
protected:
//检查打开数据库的结果,并进行后续的操作
int checkOpenResult(int nErr, sqlite3 *pdb);
protected:
sqlite3 *m_pDB; //数据库连接对象
};
class CSQLiteStatement
{
public:
CSQLiteStatement(){ zd(); }
CSQLiteStatement(CSQLiteDB *lpDB, const wchar_t *wsSQL){ zd(); m_pDB = lpDB; if (wsSQL) wprepare(wsSQL); }
CSQLiteStatement(CSQLiteDB *lpDB, const char *sSQL){ zd(); m_pDB = lpDB; if (sSQL) cprepare(sSQL); }
~CSQLiteStatement(){ if (m_pStmt) finalize(); }
/***************** 操作函数集 *****************/
inline sqlite3_stmt* stmt(){ return m_pStmt; }
/*设置目标数据库对象
*如果当前有为销毁的stmt则函数调用失败并返回false
*否则函数返回true并将lpDB设置为新的数据库操作对象
*/
inline bool setDB(CSQLiteDB *lpDB){ if (m_pStmt) return false; m_pDB = lpDB; return true; }
/*从ansi字符编码初始化stmt
*如果操作成功则会销毁之前初始化的stmt对象否则先前的对象不会被改变。
*/
inline int cprepare(const char* sSQL)
{
sqlite3_stmt *pStmt;
int result = sqlite3_prepare(m_pDB->getSqlite3Ptr(), sSQL, -1, &pStmt, NULL);
if (result == SQLITE_OK)
{
finalize();
m_pStmt = pStmt;
}
return result;
}
/*从utf16字符编码初始化stmt
*如果操作成功则会销毁之前初始化的stmt对象否则先前的对象不会被改变。
*/
inline int wprepare(const wchar_t* wsSQL)
{
sqlite3_stmt *pStmt;
int result = sqlite3_prepare16(m_pDB->getSqlite3Ptr(), wsSQL, -1, &pStmt, NULL);
if (result == SQLITE_OK)
{
finalize();
m_pStmt = pStmt;
}
return result;
}
//清空stmt中已经绑定的数据
inline int reset(){ return sqlite3_reset(m_pStmt); }
//对于执行成功的select语句将游标调整至下一行
inline int step(){ return sqlite3_step(m_pStmt); }
//销毁stmt
inline int finalize()
{
int result = 0;
if (m_pStmt)
{
result = sqlite3_finalize(m_pStmt);
m_pStmt = NULL;
}
return result;
}
/***************** 参数绑定函数集如果涉及到参数的索引则索引从1开始 *****************/
//获取stmt中的参数数量
inline int param_count(){ return sqlite3_bind_parameter_count(m_pStmt); }
//获取参数绑定时的数据析构函数
inline sqlite3_destructor_type param_destruct_type(){ return m_pDstrFunc; }
/*设置参数绑定时的数据析构函数
*绑定text、text16、blob参数时需要提供一个数据的析构函数
*并且会在对数据绑定完成后调用此析构函数从而适当的处理提供的数据,
*例如有机会调用free释放数据。
*可以使用预定义的析构函数SQLITE_STATIC和SQLITE_TRANSIENT前者不对数据进行释放
*而后者会在替换参数前使得SQLite在内部使用一份似有的内存来拷贝数据并且自动管理新内存且不会对数据本身进行释放
*/
inline void set_param_destruct_type(sqlite3_destructor_type lpFn){ m_pDstrFunc = lpFn; }
inline int bind_int(int nIdx, int nVal){ return sqlite3_bind_int(m_pStmt, nIdx, nVal); }
inline int bind_int64(int nIdx, sqlite3_int64 nVal){ return sqlite3_bind_int64(m_pStmt, nIdx, nVal); }
inline int bind_double(int nIdx, double dVal){ return sqlite3_bind_double(m_pStmt, nIdx, dVal); }
inline int bind_ctext(int nIdx, const char* sVal){ return sqlite3_bind_text(m_pStmt, nIdx, sVal, -1, m_pDstrFunc); }
inline int bind_wtext(int nIdx, const wchar_t* wsVal){ return sqlite3_bind_text16(m_pStmt, nIdx, wsVal, -1, m_pDstrFunc); }
inline int bind_blob(int nIdx, const void* pVal, const int bytes){ return sqlite3_bind_blob(m_pStmt, nIdx, pVal, bytes, m_pDstrFunc); }
/***************** 结果集状态函数集合 *****************/
inline int col_count(){ return sqlite3_column_count(m_pStmt); }
//获取select返回的数据数量非常遗憾sqlite3没有直接支持
//inline int row_count(){ return sqlite3_data_count(m_pStmt); }
//获取最后一个插入的行的自增ID值
inline sqlite3_int64 last_row_id(){ return sqlite3_last_insert_rowid(m_pDB->getSqlite3Ptr()); }
/***************** 取结果函数集 *****************/
inline int val_int(int nCol){ return sqlite3_column_int(m_pStmt, nCol); }
inline sqlite3_int64 val_int64(int nCol){ return sqlite3_column_int64(m_pStmt, nCol); }
inline double val_double(int nCol){ return sqlite3_column_double(m_pStmt, nCol); }
inline const char* val_ctext(int nCol){ return (const char*)sqlite3_column_text(m_pStmt, nCol); }
inline const wchar_t* val_wtext(int nCol){ return (const wchar_t*)sqlite3_column_text16(m_pStmt, nCol); }
inline const unsigned char* val_binary(int nCol){ return (const unsigned char*)sqlite3_column_blob(m_pStmt, nCol); }
/*获取某列数据的字节大小
*对于字符串型数据,其返回值表示字符串的内存字节长度,并且终止字符不算在内。
*/
inline int val_size(int nCol){ return sqlite3_column_bytes(m_pStmt, nCol); }
/*获取某列数据的类型
*由于SQLite具有类型亲和性所以大可不必明确数据的类型。
*/
inline int val_type(int nCol){ return sqlite3_column_type(m_pStmt, nCol); }
private:
//用于在构造函数中初始化成员的函数
inline void zd()
{
m_pDB = NULL;
m_pDstrFunc = SQLITE_STATIC;
m_pStmt = NULL;
}
private:
sqlite3_stmt *m_pStmt; //stmt指针
CSQLiteDB *m_pDB; //stmt作用的目标数据库对象
sqlite3_destructor_type m_pDstrFunc;//text、text16、blob参数数据析构函数默认为SQLITE_STATIC表示不会对内容做任何析构
};
#endif

View File

@@ -0,0 +1,63 @@
//#include "StdAfx.h"
//
//CSqlHelper::CSqlHelper(CSQLConenction* conn) : m_pSQLConnection(conn), m_bNeedReset(false)
//{
//}
//
//CSqlHelper::~CSqlHelper()
//{
// Reset();
//}
//
//void CSqlHelper::Reset()
//{
// if (m_bNeedReset)
// {
// m_pSQLConnection->ResetQuery();
// m_bNeedReset = false;
// }
//}
//
//int CSqlHelper::Query(const char* sQueryFormat, ...)
//{
// int Result;
// va_list args;
// va_start(args, sQueryFormat);
// char szBuff[40960] = {0};
// Result = vsprintf(szBuff, sQueryFormat, args);
// va_end(args);
// int nResult = RealQuery(szBuff, Result);
// if (nResult == 0)
// m_bNeedReset = true;
// return nResult;
//}
//
//int CSqlHelper::RealQuery(const char* sQueryText, const size_t nTextLen)
//{
// int nResult = m_pSQLConnection->RealQuery(sQueryText, nTextLen);
// if (nResult == 0)
// m_bNeedReset = true;
// return nResult;
//}
//
//int CSqlHelper::Exec(const char* sQueryFormat, ...)
//{
// int Result;
// va_list args;
// va_start(args, sQueryFormat);
// char szBuff[40960] = {0};
// Result = vsprintf(szBuff, sQueryFormat, args);
// va_end(args);
// int nResult = RealExec(szBuff, Result);
// if (nResult == 0)
// m_bNeedReset = true;
// return nResult;
//}
//
//int CSqlHelper::RealExec(const char* sExecText, const size_t nTextLen)
//{
// int nResult = m_pSQLConnection->RealExec(sExecText, nTextLen);
// if (nResult == 0)
// m_bNeedReset = true;
// return nResult;
//}

View File

@@ -0,0 +1,324 @@
/*/////////////////////////////////////////////////////////////////////////
文件名: WinService.cpp
功能描述: Windows 服务程序基本框架类实现文件. 从此类继承并实现指定的自定义
功能函数就可以将程序作为服务程序运行.
创建人: 谭建冲
创建时间: 2010年06月04日
/////////////////////////////////////////////////////////////////////////*/
#ifdef WIN32
#include "WinService.h"
#include <string.h>
#include <TCHAR.h>
// 全局服务对象地址,用于静态成员函数访问内部成员
static CWinService *g_pWinService = NULL;
CWinService::CWinService(LPCTSTR pServiceName, DWORD dwServiceType)
{
g_pWinService = this; //保存此对象地址(注:全局只能存在一个此对象)
_tcscpy(m_szServiceName, pServiceName);
m_dwServiceType = dwServiceType;
m_boServiceExit = FALSE;
memset(&m_ServiceStatus, 0, sizeof(m_ServiceStatus));
m_ServiceStatus.dwServiceType = dwServiceType;
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
// 设置 "当前目录" 为程序文件的目录(负责系统会默认为system32目录)
TCHAR AppPath[MAX_PATH + 1] = {0};
GetModuleFileName(NULL, AppPath, sizeof(AppPath));
signed __int64 len = _tcslen(AppPath)-1;
while (len > 0 && AppPath[len] != '\\')
{
len--;
}
AppPath[len] = 0;
SetCurrentDirectory(AppPath);
}
CWinService::~CWinService(void)
{
}
int CWinService::SetStatus( DWORD dwState, DWORD dwExitCode, DWORD dwProgress)
{
m_dwServiceStatus = dwState;
m_ServiceStatus.dwCurrentState = m_dwServiceStatus;
m_ServiceStatus.dwWin32ExitCode = dwExitCode;
m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_ServiceStatus.dwCheckPoint = dwProgress;
m_ServiceStatus.dwWaitHint = 0;
return SetServiceStatus(m_hServiceStatus, &m_ServiceStatus);
}
BOOL CWinService::ServiceInstalled()
{
BOOL bResult = FALSE;
SERVICE_STATUS svcState;
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM != NULL)
{
SC_HANDLE hService = OpenService(hSCM, m_szServiceName, SERVICE_ALL_ACCESS );
if (hService != NULL)
{
if ( QueryServiceStatus(hService, &svcState) )
{
if ( svcState.dwCurrentState == SERVICE_RUNNING )
{
bResult = TRUE;
}
else if ( svcState.dwCurrentState == SERVICE_STOPPED )
{
bResult = ::StartService(hService, 0, NULL);
if ( !bResult )
{
if (!DeleteService(hService))
bResult = FALSE;
}
}
}
CloseServiceHandle(hService);
}
CloseServiceHandle(hSCM);
}
return bResult;
}
BOOL CWinService::InstallService()
{
if (ServiceInstalled())
return TRUE;
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL)
{
return FALSE;
}
TCHAR sPath[MAX_PATH];
GetModuleFileName(NULL, sPath, sizeof(sPath));
SC_HANDLE hService = CreateService( hSCM,
m_szServiceName,
m_szServiceName,
SERVICE_ALL_ACCESS,
m_dwServiceType,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
sPath,
NULL,
NULL,
_T(""),
NULL,
NULL);
if (hService == NULL)
{
CloseServiceHandle(hSCM);
return FALSE;
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
return TRUE;
}
BOOL CWinService::StartService()
{
BOOL bRet = FALSE;
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM != NULL)
{
SC_HANDLE hService = OpenService(hSCM, m_szServiceName, SERVICE_ALL_ACCESS );
if (hService != NULL)
{
SERVICE_STATUS svcState;
if ( QueryServiceStatus(hService, &svcState) )
{
if (svcState.dwCurrentState == SERVICE_RUNNING )
{
bRet = TRUE;
}
else
{
if (::StartService(hService, 0, NULL))
{
bRet = TRUE;
}
}
}
}
CloseServiceHandle(hService);
}
CloseServiceHandle(hSCM);
return bRet;
}
BOOL CWinService::StopService()
{
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM != NULL)
{
SC_HANDLE hService = OpenService(hSCM, m_szServiceName, SERVICE_ALL_ACCESS );
if (hService != NULL)
{
SERVICE_STATUS svcState;
if ( QueryServiceStatus(hService, &svcState) )
{
if ( svcState.dwCurrentState == SERVICE_RUNNING )
{
if (!ControlService(hService, SERVICE_CONTROL_STOP, &svcState))
{
return FALSE;
}
}
}
}
CloseServiceHandle(hService);
}
CloseServiceHandle(hSCM);
return TRUE;
}
BOOL CWinService::UninstallService()
{
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM != NULL)
{
SC_HANDLE hService = OpenService(hSCM, m_szServiceName, SERVICE_ALL_ACCESS );
if (hService != NULL)
{
SERVICE_STATUS svcState;
if ( QueryServiceStatus(hService, &svcState) )
{
if ( svcState.dwCurrentState == SERVICE_RUNNING )
{
if (!ControlService(hService, SERVICE_CONTROL_STOP, &svcState))
{
return FALSE;
}
}
}
if (!DeleteService(hService))
{
return FALSE;
}
}
CloseServiceHandle(hService);
}
CloseServiceHandle(hSCM);
return TRUE;
}
VOID WINAPI CWinService::ServiceControl(DWORD dwOption)
{
switch (dwOption)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
g_pWinService->SetStatus( SERVICE_STOP_PENDING, 0, 1);
g_pWinService->m_boServiceExit = TRUE;
return;
case SERVICE_CONTROL_PAUSE:
return;
case SERVICE_CONTROL_CONTINUE:
return;
case SERVICE_CONTROL_INTERROGATE:
return;
default:
break;
}
SetServiceStatus(g_pWinService->m_hServiceStatus, &g_pWinService->m_ServiceStatus);
}
VOID WINAPI CWinService::ServiceMain(DWORD dwArgc, LPSTR *lpszArgv)
{
HANDLE hThread = NULL;
//注册服务控制
g_pWinService->m_hServiceStatus = RegisterServiceCtrlHandler(g_pWinService->m_szServiceName, &CWinService::ServiceControl);
if (g_pWinService->m_hServiceStatus == NULL)
{
g_pWinService->SetStatus(SERVICE_STOPPED, -1, 0);
return;
}
g_pWinService->SetStatus(SERVICE_START_PENDING, 0, 1);
g_pWinService->SetStatus(SERVICE_RUNNING, 0, 0);
//=======================================================================
// 服务程序功能开始运作
//=======================================================================
g_pWinService->AppMain();
//=======================================================================
// 服务程序功能运作结束
//=======================================================================
// 服务停止
g_pWinService->SetStatus(SERVICE_STOPPED, 0, 0);
}
VOID CWinService::Run(LPTSTR lpCmdLine)
{
// 防止strstr函数引起的程序崩溃
if ( NULL == lpCmdLine )
{
lpCmdLine = _T("");
}
if (_tcsstr(lpCmdLine, _T("/install")) != NULL )
{
InstallService();
}
else if (_tcsstr(lpCmdLine, _T("/start")) != NULL)
{
StartService();
}
else if (_tcsstr(lpCmdLine, _T("/stop")) != NULL)
{
StopService();
}
else if (_tcsstr(lpCmdLine, _T("/uninstall")) != NULL)
{
UninstallService();
}
else
{
SERVICE_TABLE_ENTRY ste[2];
ste[0].lpServiceName = m_szServiceName;
ste[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
memset(&ste[1], 0, sizeof(ste[1]));
if (!StartServiceCtrlDispatcher(ste))
{
while ( !m_boServiceExit )
{
Sleep( 10000 );
}
}
}
}
#endif

View File

@@ -0,0 +1,88 @@
/*/////////////////////////////////////////////////////////////////////////
文件名: WinService.h
功能描述: Windows 服务程序基本框架类定义头文件. 从此类继承并实现指定的自定义
功能函数就可以将程序作为服务程序运行.
创建人: 谭建冲
创建时间: 2010年06月04日
// 用法示例:
#include "WinService.h"
// 首先继承并实现功能主函数
class CMyAppService : public CWinService
{
public:
CMyAppService(LPCSTR pServiceName, DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS):CWinService(pServiceName, dwServiceType){};
int AppMain()
{
// TODO: 在这里添加自定义代码
// 示例:
while ( !m_boServiceExit )
{
Sleep(1000);
}
return 0;
}
};
// 其次是创建对象后运行即可.
void main(int argc, char *argv[])
{
CMyAppService MyAppService("testServiceName");
MyAppService.Run(argv[1]);
}
// 或者
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
CMyAppService MyAppService("testServiceName");
MyAppService.Run(lpCmdLine);
return 0;
}
/////////////////////////////////////////////////////////////////////////*/
#pragma once
#ifdef WIN32
#include <Windows.h>
class CWinService
{
public:
CWinService(LPCTSTR pServiceName, DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS);
virtual ~CWinService(void);
public:
BOOL InstallService(); // 安装服务程序到系统中
BOOL StartService(); // 启动服务程序
BOOL StopService(); // 停止服务程序
BOOL UninstallService(); // 卸载服务程序
VOID Run(LPTSTR lpCmdLine); // 执行服务程序 参数 lpCmdLine 表示系统传入的参数(用于安装,卸载服务等操作)
virtual int AppMain() = 0; // 程序的主要功能函数, 子类必须实现此函数.
static VOID WINAPI ServiceControl(DWORD dwOption);
static VOID WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
protected:
int SetStatus( DWORD dwState, DWORD dwExitCode, DWORD dwProgress);
BOOL ServiceInstalled();
public:
TCHAR m_szServiceName[128];
BOOL m_boServiceExit; //服务程序是否退出的开关
DWORD m_dwServiceType;
SERVICE_STATUS m_ServiceStatus;
DWORD m_dwServiceStatus;
SERVICE_STATUS_HANDLE m_hServiceStatus;
};
#endif

42
sdk/utils/nonuse/cp.c Normal file
View File

@@ -0,0 +1,42 @@
#ifdef WIN32
#include <Windows.h>
/**
* 跳转指令结构
*************************/
#pragma pack(push, 1)
struct jmpInstruct
{
unsigned char code;
unsigned int offset;
};
#pragma pack(pop)
//计算跳转偏移地址
#define CalcJmpOffset(s, d) ((SIZE_T)(d) - ((SIZE_T)(s) + 5))
int patchFunction(void *dest, void *src)
{
struct jmpInstruct* fn = (struct jmpInstruct*)src;
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION mbi;
if ( VirtualQuery(fn, &mbi, sizeof(mbi)) != sizeof(mbi) )
return GetLastError();
//修改_output_l函数的内存保护模式增加可读写保护
if ( !VirtualProtect(fn, sizeof(*fn), PAGE_EXECUTE_READWRITE, &dwOldProtect) )
return GetLastError();
fn->code = 0xE9;
fn->offset = (UINT)CalcJmpOffset(fn, dest);
//还原_output_l函数的内存保护模式
if ( !VirtualProtect(fn, sizeof(*fn), dwOldProtect, &dwOldProtect) )
return GetLastError();
return 0;
}
#endif

29
sdk/utils/nonuse/cp.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef _CODE_PATCH_SETUP_H_
#define _CODE_PATCH_SETUP_H_
/************************************************************************/
/*
/* 运行时函数代码补丁安装库
/*
/*
/* 函数代码补丁的实现原理为在原始代码位置写入跳转指令跳转到新的函数位置。期间用到内存
/* 页属性更改函数VirtualProtect。
/*
/************************************************************************/
#ifdef __cplusplus
extern "C"{
#endif
/*
* Comments: 应用代码补丁
* Param void * dest: 补丁后代码的执行位置
* Param void * src: 要打补丁的代码位置
* @Return int: 返回0表示应用代码补丁成功否则返回值表示系统错误码
*/
int patchFunction(void *dest, void *src);
#ifdef __cplusplus
};
#endif
#endif _CODE_PATCH_SETUP_H_

View File

@@ -0,0 +1,25 @@
#ifndef _EDCODE_H_
#define _EDCODE_H_
/*
extern "C"
{
#ifndef STDCALL
#define STDCALL __stdcall
#endif
unsigned int STDCALL Encode6BitBuf(const char *pSrc, char *pDest, unsigned int dwSrcSize, unsigned int dwMaxSize);
unsigned int STDCALL Decode6BitBuf(const char *pSrc, char *pDest, unsigned int dwSrcSize, unsigned int dwMaxSize);
unsigned int STDCALL GetEncryptedSize(unsigned int dwSize);
unsigned int STDCALL GetDecryptedSize(unsigned int dwSize);
#define EncodeBuffer( i, o, si, so ) (Encode6BitBuf( (char*)(i), (char*)(o), (DWORD)(si), (DWORD)(so) ))
#define DecodeBuffer( i, o, si, so ) (Decode6BitBuf( (char*)(i), (char*)(o), (DWORD)(si), (DWORD)(so)))
//#define EncodeBuffer( i, o, si, so )
//#define DecodeBuffer( i, o, si, so )
}
*/
#endif

783
sdk/utils/nonuse/stlastar.h Normal file
View File

@@ -0,0 +1,783 @@
/*
A* Algorithm Implementation using STL is
Copyright (C)2001-2005 Justin Heyes-Jones
Permission is given by the author to freely redistribute and
include this code in any program as long as this credit is
given where due.
COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE
IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED
CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL
DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE
OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
THIS DISCLAIMER.
Use at your own risk!
*/
#ifdef WIN32
#pragma once
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <tchar.h>
#include <Windows.h>
#endif
#include <_ast.h>
#include <Stream.h>
//#include <iostream>
//#include <conio.h>
#include <assert.h>
#include "SingleObjectAllocator.hpp"
// stl includes
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
// fast fixed size memory allocator, used for fast node memory management
//#include "fsa.h"
// Fixed size memory allocator can be disabled to compare performance
// Uses std new and delete instead if you turn it off
#define USE_FSA_MEMORY 1
// disable warning that debugging information has lines that are truncated
// occurs in stl headers
#pragma warning( disable : 4786 )
// The AStar search class. UserState is the users state space type
template <class UserState> class AStarSearch
{
public: // data
enum
{
SEARCH_STATE_NOT_INITIALISED,
SEARCH_STATE_SEARCHING,
SEARCH_STATE_SUCCEEDED,
SEARCH_STATE_FAILED,
SEARCH_STATE_OUT_OF_MEMORY,
SEARCH_STATE_INVALID
};
// A node represents a possible state in the search
// The user provided state type is included inside this type
public:
class Node
{
public:
Node *parent; // used during the search to record the parent of successor nodes
Node *child; // used after the search for the application to view the search in reverse
int g; // cost of this node + it's predecessors
int h; // heuristic estimate of distance to goal
int f; // sum of cumulative cost of predecessors and self and heuristic
Node() :
parent( 0 ),
child( 0 ),
g(0 ),
h( 0),
f( 0 )
{
}
UserState m_UserState;
};
// For sorting the heap the STL needs compare function that lets us compare
// the f value of two nodes
class HeapCompare_f
{
public:
bool operator() ( const Node *x, const Node *y ) const
{
return x->f > y->f;
}
};
public: // methods
// constructor just initialises private data
AStarSearch( int MaxNodes = 1000 ) :
m_AllocateNodeCount(0),
#if USE_FSA_MEMORY
m_FixedSizeAllocator( "Astar" ),
#endif
m_State( SEARCH_STATE_NOT_INITIALISED ),
m_CurrentSolutionNode( NULL ),
m_CancelRequest( false )
{
}
// call at any time to cancel the search and free up all the memory
void CancelSearch()
{
m_CancelRequest = true;
}
// Set Start and goal states
void SetStartAndGoalStates( UserState &Start, UserState &Goal )
{
m_CancelRequest = false;
m_Start = AllocateNode();
m_Goal = AllocateNode();
assert((m_Start != NULL && m_Goal != NULL));
m_Start->m_UserState = Start;
m_Goal->m_UserState = Goal;
m_State = SEARCH_STATE_SEARCHING;
// Initialise the AStar specific parts of the Start Node
// The user only needs fill out the state information
m_Start->g = 0;
m_Start->h = m_Start->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState );
m_Start->f = m_Start->g + m_Start->h;
m_Start->parent = 0;
// Push the start node on the Open list
m_OpenList.push_back( m_Start ); // heap now unsorted
// Sort back element into heap
push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
// Initialise counter for search steps
m_Steps = 0;
}
// Advances search one step
unsigned int SearchStep()
{
// Firstly break if the user has not initialised the search
assert( (m_State > SEARCH_STATE_NOT_INITIALISED) &&
(m_State < SEARCH_STATE_INVALID) );
// Next I want it to be safe to do a searchstep once the search has succeeded...
if( (m_State == SEARCH_STATE_SUCCEEDED) ||
(m_State == SEARCH_STATE_FAILED)
)
{
return m_State;
}
// Failure is defined as emptying the open list as there is nothing left to
// search...
// New: Allow user abort
if( m_OpenList.empty() || m_CancelRequest )
{
FreeAllNodes();
m_State = SEARCH_STATE_FAILED;
return m_State;
}
// Incremement step count
m_Steps ++;
// Pop the best node (the one with the lowest f)
Node *n = m_OpenList.front(); // get pointer to the node
pop_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
m_OpenList.pop_back();
// Check for the goal, once we pop that we're done
if( n->m_UserState.IsGoal( m_Goal->m_UserState ) )
{
// The user is going to use the Goal Node he passed in
// so copy the parent pointer of n
m_Goal->parent = n->parent;
// A special case is that the goal was passed in as the start state
// so handle that here
if( false == n->m_UserState.IsSameState( m_Start->m_UserState ) )
{
FreeNode( n );
// set the child pointers in each node (except Goal which has no child)
Node *nodeChild = m_Goal;
Node *nodeParent = m_Goal->parent;
do
{
//ÕâÀï³öÏÖÁËÎÊÌâ,xiaoÐÞ¸Ä
if(nodeChild == nodeParent)
{
FreeUnusedNodes();
m_State = SEARCH_STATE_FAILED;
return m_State;
}
if(nodeParent->child ==NULL)
{
nodeParent->child = nodeChild;
}
nodeChild = nodeParent;
nodeParent = nodeParent->parent;
}
while( nodeChild != m_Start ); // Start is always the first node by definition
}
// delete nodes that aren't needed for the solution
FreeUnusedNodes();
m_State = SEARCH_STATE_SUCCEEDED;
return m_State;
}
else // not goal
{
// We now need to generate the successors of this node
// The user helps us to do this, and we keep the new nodes in
// m_Successors ...
m_Successors.clear(); // empty vector of successor nodes to n
// User provides this functions and uses AddSuccessor to add each successor of
// node 'n' to m_Successors
bool ret = n->m_UserState.GetSuccessors( this, n->parent ? &n->parent->m_UserState : NULL );
if( !ret )
{
typename vector< Node * >::iterator successor;
// free the nodes that may previously have been added
for( successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ )
{
FreeNode( (*successor) );
}
m_Successors.clear(); // empty vector of successor nodes to n
// free up everything else we allocated
FreeAllNodes();
m_State = SEARCH_STATE_OUT_OF_MEMORY;
return m_State;
}
// Now handle each successor to the current node ...
for( typename vector< Node * >::iterator successor = m_Successors.begin(); successor != m_Successors.end(); successor ++ )
{
// The g value for this successor ...
int newg = n->g + n->m_UserState.GetCost( (*successor)->m_UserState );
// Now we need to find whether the node is on the open or closed lists
// If it is but the node that is already on them is better (lower g)
// then we can forget about this successor
// First linear search of open list to find node
typename vector< Node * >::iterator openlist_result;
for( openlist_result = m_OpenList.begin(); openlist_result != m_OpenList.end(); openlist_result ++ )
{
if( (*openlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) )
{
break;
}
}
if( openlist_result != m_OpenList.end() )
{
// we found this state on open
if( (*openlist_result)->g <= newg )
{
FreeNode( (*successor) );
// the one on Open is cheaper than this one
continue;
}
}
typename vector< Node * >::iterator closedlist_result;
for( closedlist_result = m_ClosedList.begin(); closedlist_result != m_ClosedList.end(); closedlist_result ++ )
{
if( (*closedlist_result)->m_UserState.IsSameState( (*successor)->m_UserState ) )
{
break;
}
}
if( closedlist_result != m_ClosedList.end() )
{
// we found this state on closed
if( (*closedlist_result)->g <= newg )
{
// the one on Closed is cheaper than this one
FreeNode( (*successor) );
continue;
}
}
// This node is the best node so far with this particular state
// so lets keep it and set up its AStar specific data ...
(*successor)->parent = n;
(*successor)->g = newg;
(*successor)->h = (*successor)->m_UserState.GoalDistanceEstimate( m_Goal->m_UserState );
(*successor)->f = (*successor)->g + (*successor)->h;
// Remove successor from closed if it was on it
if( closedlist_result != m_ClosedList.end() )
{
// remove it from Closed
FreeNode( (*closedlist_result) );
m_ClosedList.erase( closedlist_result );
// Fix thanks to ...
// Greg Douglas <gregdouglasmail@gmail.com>
// who noticed that this code path was incorrect
// Here we have found a new state which is already CLOSED
// anus
}
// Update old version of this node
if( openlist_result != m_OpenList.end() )
{
FreeNode( (*openlist_result) );
m_OpenList.erase( openlist_result );
// re-make the heap
// make_heap rather than sort_heap is an essential bug fix
// thanks to Mike Ryynanen for pointing this out and then explaining
// it in detail. sort_heap called on an invalid heap does not work
make_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
}
// heap now unsorted
m_OpenList.push_back( (*successor) );
// sort back element into heap
push_heap( m_OpenList.begin(), m_OpenList.end(), HeapCompare_f() );
}
// push n onto Closed, as we have expanded it now
m_ClosedList.push_back( n );
} // end else (not goal so expand)
return m_State; // Succeeded bool is false at this point.
}
// User calls this to add a successor to a list of successors
// when expanding the search frontier
bool AddSuccessor( UserState &State )
{
Node *node = AllocateNode();
if( node )
{
node->m_UserState = State;
m_Successors.push_back( node );
return true;
}
return false;
}
// Free the solution nodes
// This is done to clean up all used Node memory when you are done with the
// search
void FreeSolutionNodes()
{
Node *n = m_Start;
if( m_Start->child )
{
do
{
Node *del = n;
n = n->child;
FreeNode( del );
del = NULL;
} while( n != m_Goal );
FreeNode( n ); // Delete the goal
}
else
{
// if the start node is the solution we need to just delete the start and goal
// nodes
FreeNode( m_Start );
FreeNode( m_Goal );
}
}
// Functions for traversing the solution
// Get start node
UserState *GetSolutionStart()
{
m_CurrentSolutionNode = m_Start;
if( m_Start )
{
return &m_Start->m_UserState;
}
else
{
return NULL;
}
}
// Get next node
UserState *GetSolutionNext()
{
if( m_CurrentSolutionNode )
{
if( m_CurrentSolutionNode->child )
{
Node *child = m_CurrentSolutionNode->child;
m_CurrentSolutionNode = m_CurrentSolutionNode->child;
return &child->m_UserState;
}
}
return NULL;
}
// Get end node
UserState *GetSolutionEnd()
{
m_CurrentSolutionNode = m_Goal;
if( m_Goal )
{
return &m_Goal->m_UserState;
}
else
{
return NULL;
}
}
// Step solution iterator backwards
UserState *GetSolutionPrev()
{
if( m_CurrentSolutionNode )
{
if( m_CurrentSolutionNode->parent )
{
Node *parent = m_CurrentSolutionNode->parent;
m_CurrentSolutionNode = m_CurrentSolutionNode->parent;
return &parent->m_UserState;
}
}
return NULL;
}
// For educational use and debugging it is useful to be able to view
// the open and closed list at each step, here are two functions to allow that.
UserState *GetOpenListStart()
{
int f,g,h;
return GetOpenListStart( f,g,h );
}
UserState *GetOpenListStart( int &f, int &g, int &h )
{
iterDbgOpen = m_OpenList.begin();
if( iterDbgOpen != m_OpenList.end() )
{
f = (*iterDbgOpen)->f;
g = (*iterDbgOpen)->g;
h = (*iterDbgOpen)->h;
return &(*iterDbgOpen)->m_UserState;
}
return NULL;
}
UserState *GetOpenListNext()
{
int f,g,h;
return GetOpenListNext( f,g,h );
}
UserState *GetOpenListNext( int &f, int &g, int &h )
{
iterDbgOpen++;
if( iterDbgOpen != m_OpenList.end() )
{
f = (*iterDbgOpen)->f;
g = (*iterDbgOpen)->g;
h = (*iterDbgOpen)->h;
return &(*iterDbgOpen)->m_UserState;
}
return NULL;
}
UserState *GetClosedListStart()
{
int f,g,h;
return GetClosedListStart( f,g,h );
}
UserState *GetClosedListStart( int &f, int &g, int &h )
{
iterDbgClosed = m_ClosedList.begin();
if( iterDbgClosed != m_ClosedList.end() )
{
f = (*iterDbgClosed)->f;
g = (*iterDbgClosed)->g;
h = (*iterDbgClosed)->h;
return &(*iterDbgClosed)->m_UserState;
}
return NULL;
}
UserState *GetClosedListNext()
{
int f,g,h;
return GetClosedListNext( f,g,h );
}
UserState *GetClosedListNext( int &f, int &g, int &h )
{
iterDbgClosed++;
if( iterDbgClosed != m_ClosedList.end() )
{
f = (*iterDbgClosed)->f;
g = (*iterDbgClosed)->g;
h = (*iterDbgClosed)->h;
return &(*iterDbgClosed)->m_UserState;
}
return NULL;
}
// Get the number of steps
int GetStepCount() { return m_Steps; }
void EnsureMemoryFreed()
{
#if USE_FSA_MEMORY
assert(m_AllocateNodeCount == 0);
#endif
}
private: // methods
// This is called when a search fails or is cancelled to free all used
// memory
void FreeAllNodes()
{
// iterate open list and delete all nodes
typename vector< Node * >::iterator iterOpen = m_OpenList.begin();
while( iterOpen != m_OpenList.end() )
{
Node *n = (*iterOpen);
FreeNode( n );
iterOpen ++;
}
m_OpenList.clear();
// iterate closed list and delete unused nodes
typename vector< Node * >::iterator iterClosed;
for( iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed ++ )
{
Node *n = (*iterClosed);
FreeNode( n );
}
m_ClosedList.clear();
// delete the goal
FreeNode(m_Goal);
}
// This call is made by the search class when the search ends. A lot of nodes may be
// created that are still present when the search ends. They will be deleted by this
// routine once the search ends
void FreeUnusedNodes()
{
// iterate open list and delete unused nodes
typename vector< Node * >::iterator iterOpen = m_OpenList.begin();
while( iterOpen != m_OpenList.end() )
{
Node *n = (*iterOpen);
if( !n->child )
{
FreeNode( n );
n = NULL;
}
iterOpen ++;
}
m_OpenList.clear();
// iterate closed list and delete unused nodes
typename vector< Node * >::iterator iterClosed;
for( iterClosed = m_ClosedList.begin(); iterClosed != m_ClosedList.end(); iterClosed ++ )
{
Node *n = (*iterClosed);
if( !n->child )
{
FreeNode( n );
n = NULL;
}
}
m_ClosedList.clear();
}
// Node memory management
Node *AllocateNode()
{
#if !USE_FSA_MEMORY
Node *p = new Node;
return p;
#else
Node *address = m_FixedSizeAllocator.allocObject();
if( !address )
{
return NULL;
}
m_AllocateNodeCount ++;
Node *p = new (address) Node;
return p;
#endif
}
void FreeNode( Node *node )
{
m_AllocateNodeCount --;
#if !USE_FSA_MEMORY
delete node;
#else
m_FixedSizeAllocator.freeObject( node );
#endif
}
private: // data
// Heap (simple vector but used as a heap, cf. Steve Rabin's game gems article)
vector< Node *> m_OpenList;
// Closed list is a vector.
vector< Node * > m_ClosedList;
// Successors is a vector filled out by the user each type successors to a node
// are generated
vector< Node * > m_Successors;
// State
unsigned int m_State;
// Counts steps
int m_Steps;
// Start and goal state pointers
Node *m_Start;
Node *m_Goal;
Node *m_CurrentSolutionNode;
#if USE_FSA_MEMORY
// Memory
CSingleObjectAllocator<Node>m_FixedSizeAllocator;
//FixedSizeAllocator<Node> m_FixedSizeAllocator;
#endif
//Debug : need to keep these two iterators around
// for the user Dbg functions
typename vector< Node * >::iterator iterDbgOpen;
typename vector< Node * >::iterator iterDbgClosed;
// debugging : count memory allocation and free's
int m_AllocateNodeCount;
bool m_CancelRequest;
};
#endif

View File

@@ -0,0 +1,221 @@
//--------------------------------------------------------------------
// 文件名: util_func_extend.h
// 内 容: 工具函数
// 说 明:
// 创建日期: 2017年07月24日
// 创建人: chenwl
// 版权所有: XX公司
//--------------------------------------------------------------------
#ifndef __GAME_UTIL_FUNC_EXTEND_H__
#define __GAME_UTIL_FUNC_EXTEND_H__
#include <sstream>
#include <string>
namespace utility
{
template<typename T>
inline std::string toString (T p)
{
std::ostringstream stream;
stream << p;
return stream.str();
}
template<typename T1, typename T2>
inline std::string toString (T1 p1, T2 p2)
{
std::ostringstream stream;
stream << p1 << p2;
return stream.str();
}
template<typename T1, typename T2, typename T3>
inline std::string toString (T1 p1, T2 p2, T3 p3)
{
std::ostringstream stream;
stream << p1 << p2 << p3;
return stream.str();
}
template<typename T1, typename T2, typename T3, typename T4>
inline std::string toString (T1 p1, T2 p2, T3 p3, T4 p4)
{
std::ostringstream stream;
stream << p1 << p2 << p3 << p4;
return stream.str();
}
template<typename T1, typename T2, typename T3, typename T4, typename T5>
inline std::string toString (T1 p1, T2 p2, T3 p3, T4 p4, T5 p5)
{
std::ostringstream stream;
stream << p1 << p2 << p3 << p4 << p5;
return stream.str();
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
inline std::string toString (T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6)
{
std::ostringstream stream;
stream << p1 << p2 << p3 << p4 << p5 << p6;
return stream.str();
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
inline std::string toString (T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7)
{
std::ostringstream stream;
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7;
return stream.str();
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
inline std::string toString (T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8)
{
std::ostringstream stream;
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8;
return stream.str();
}
template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
inline std::string toString (T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, T8 p8, T9 p9)
{
std::ostringstream stream;
stream << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8 << p9;
return stream.str();
}
namespace templates
{
template<typename T>
inline void split(std::vector<std::string>& _ret, const std::string& _source, const std::string& _delims)
{
if (_source == "")
{
return;
}
size_t start = 0;
size_t end = _source.find(_delims);
while (start != _source.npos)
{
if (end != _source.npos)
_ret.push_back(_source.substr(start, end - start));
else
{
_ret.push_back(_source.substr(start));
break;
}
start = end;
if (start != _source.npos)
{
start+=_delims.size();
}
end = _source.find(_delims, start);
}
}
} // namespace templates
inline std::vector<std::string> split(const std::string& _source, const std::string& _delims = "\t\n ")
{
std::vector<std::string> result;
templates::split<void>(result, _source, _delims);
return result;
}
template<typename T>
inline T parseValue( const std::string& _value )
{
std::istringstream stream(_value);
T result;
stream >> result;
if (stream.fail())
return T();
else
{
int item = stream.get();
while (item != -1)
{
if (item != ' ' && item != '\t')
return T();
item = stream.get();
}
}
return result;
}
// отдельная имплементация под bool
template<>
inline bool parseValue(const std::string& _value)
{
if (_value == "True" || _value == "true" || _value == "1")
return true;
return false;
}
// отдельная имплементация под char
template<>
inline char parseValue(const std::string& _value)
{
return (char)parseValue<short>(_value);
}
// отдельная имплементация под unsigned char
template<>
inline unsigned char parseValue(const std::string& _value)
{
return (unsigned char)parseValue<unsigned short>(_value);
}
inline short parseShort(const std::string& _value)
{
return parseValue<short>(_value);
}
inline unsigned short parseUShort(const std::string& _value)
{
return parseValue<unsigned short>(_value);
}
inline int parseInt(const std::string& _value)
{
return parseValue<int>(_value);
}
inline unsigned int parseUInt(const std::string& _value)
{
return parseValue<unsigned int>(_value);
}
inline size_t parseSizeT(const std::string& _value)
{
return parseValue<size_t>(_value);
}
inline float parseFloat(const std::string& _value)
{
return parseValue<float>(_value);
}
inline double parseDouble(const std::string& _value)
{
return parseValue<double>(_value);
}
inline bool parseBool(const std::string& _value)
{
return parseValue<bool>(_value);
}
inline char parseChar(const std::string& _value)
{
return parseValue<char>(_value);
}
inline unsigned char parseUChar(const std::string& _value)
{
return parseValue<unsigned char>(_value);
}
}
#endif

52
sdk/utils/wrand.c Normal file
View File

@@ -0,0 +1,52 @@
#include <time.h>
static unsigned long state[16] = {
0x8C12D566, 0x00C2793E, 0x5016EECF, 0x234869FA,
0x6E4C8852, 0x32574386, 0x3573DC34, 0x7E4C00F0,
0xC830516B, 0x085437E9, 0x32478EAC, 0xDEFCDCD0,
0xFE09BBC2, 0x34EA087D, 0x112F367C, 0x0324EFAA
};
static unsigned long index = 0;
void winitseed(unsigned long seed)
{
int i;
if ( !seed ) seed = (unsigned long)time(NULL);
for (i=0; i<16; ++i)
{
state[i] ^= seed;
}
}
static unsigned long WELLRNG512()
{
unsigned long a, b, c, d;
a = state[index];
c = state[(index+13) & 15];
b = a ^ c ^(a << 16) ^ (c << 15);
c = state[(index+9) & 15];
c ^= (c >> 11);
a = state[index] = b ^ c;
d = a ^ ((a << 5) & 0xDA442D20UL);
index = (index + 15) & 15;
a = state[index];
state[index] = a ^ b ^ d ^ (a << 2) ^ (b << 18) ^ (c << 28);
return state[index];
}
unsigned long wrand(unsigned long max)
{
if(max == 0)
return 0;
return WELLRNG512() % max + 1;
}
//返回一个随机数
unsigned long wrandvalue()
{
return WELLRNG512();
}

41
sdk/utils/wrand.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef _WELL_RNG_H_
#define _WELL_RNG_H_
/******************************************************************
*
* wyLib库 2008 - 2011
*
* $ 基于WELL算法实现的快速随机函数库 $
*
* - 主要功能 -
*
* 实现快速的波动更无规律的随机数算法
*
*****************************************************************/
/*
* Comments: 使用WELL算法产生一个随机数产生的随机数在0到max以内。
* Param unsigned long max: 随机数上限
* @Return unsigned long:
*/
#ifdef __cplusplus
extern "C" {
#endif
//范围一个[0,max)之间的随机数
unsigned long wrand(unsigned long max);
/*
* Comments: 初始化随机种子表
* Param unsigned int seed: 种子值如果值为0则自动使用time()值作为种子
* 该函数在整个程序中调用一次即可。也可以不调用只是每次运行第N次随机产生的值都一样。
*/
void winitseed(unsigned int seed);
//返回一个随机数
unsigned long wrandvalue();
#ifdef __cplusplus
}
#endif
#endif