Commit 4df124bc by 许梦竹

add dev-code

parents
File added
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/Common/include
LOCAL_SRC_FILES := \
Common/src/WNObject.cpp \
Common/src/WNCStringList.cpp \
Common/src/IniFileManager.cpp \
Common/src/WNSocketObserverManager.cpp \
Common/src/WNSocketSelectObserver.cpp \
Common/src/WNSocketObserver.cpp \
Common/src/WNCommonSocket.cpp \
Common/src/WNNotificationCenter.cpp \
Common/src/WNByteBufferManager.cpp \
Common/src/WNByteBuffer.cpp \
Common/src/WNReadWriteLocker.cpp \
Common/src/MD5Checksum.cpp \
Common/src/WNCreticalSection.cpp \
Common/src/WNBitIndex.cpp \
Common/src/WNWorkThread.cpp \
BaseSerialPort.cpp \
PcmPlayer.cpp \
WNMemoryPool.cpp \
TTSManager.cpp \
JNIInterface.cpp
LOCAL_SHARED_LIBRARIES := \
libmedia \
libutils \
libcutils
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= libgtsdev
LOCAL_SHARED_LIBRARIES += libstlport
include external/stlport/libstlport.mk
include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
#include "BaseSerialPort.h"
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
#define MOD_LOG_TAG "libgtsdev.so"
#define _WANIN_LOG_
#ifdef _WANIN_LOG_
#include <android/log.h>
#define LOG(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MOD_LOG_TAG, fmt, ##args)
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, MOD_LOG_TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR,MOD_LOG_TAG, fmt, ##args)
#else
#define LOG (...)
#define LOGI(...)
#define LOGE(...)
#endif
BaseSerialPort::BaseSerialPort()
:m_bRunning(false)
,m_type(SP_Default)
,m_iFd(-1)
,m_thread_recver(0)
{
}
BaseSerialPort::~BaseSerialPort()
{
}
bool BaseSerialPort::Start(int iPort, int iBaudRate, SerialPortType type)
{
m_type = type;
//LOGE("BaseSerialPort::Start Port%d, type: %d", iPort, type);
if(!OpenPort(iPort))
{
return false;
}
if(!SetParams(iBaudRate, 8, 'N', 1))
{
close(m_iFd);
return false;
}
m_bRunning = true;
StartRecver();
return true;
}
void BaseSerialPort::Stop()
{
m_bRunning = false;
if(m_thread_recver != 0)
{
void *dummy;
pthread_join(m_thread_recver, &dummy);
m_thread_recver = 0;
}
if(m_iFd > 0)
{
close(m_iFd);
m_iFd = -1;
}
}
bool BaseSerialPort::OpenPort(int port)
{
std::string strDev = "/dev/ttyS";
std::string strPort;
std::stringstream ss;
ss << port;
ss >> strPort;
strDev += strPort;
long vdisable;
m_iFd = open(strDev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if (-1 == m_iFd)
{
LOGE("Can't Open Serial Port%d", port);
return false;
}
if(fcntl(m_iFd, F_SETFL, 0) < 0)
{
LOGE("fcntl failed!");
}
//else
//{
// LOGE("fcntl=%d",fcntl(fd, F_SETFL,0));
//}
if(isatty(STDIN_FILENO)==0)
{
LOGE("standard input is not a terminal device");
}
return true;
}
bool BaseSerialPort::SetParams(int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio,oldtio;
if(tcgetattr(m_iFd, &oldtio) != 0)
{
LOGE("SetupSerial failed");
return false;
}
bzero( &newtio, sizeof( newtio ) );
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch( nEvent )
{
case 'O': //奇校验
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E': //偶校验
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N': //无校验
newtio.c_cflag &= ~PARENB;
break;
}
switch( nSpeed )
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
if( nStop == 1 )
{
newtio.c_cflag &= ~CSTOPB;
}
else if ( nStop == 2 )
{
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
tcflush(m_iFd, TCIFLUSH);
if((tcsetattr(m_iFd, TCSANOW, &newtio)) != 0)
{
LOGE("com set error");
return false;
}
return true;
}
void BaseSerialPort::StartRecver()
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&m_thread_recver, &attr, RecverWrapper, this);
pthread_attr_destroy(&attr);
}
void * BaseSerialPort::RecverWrapper(void * p)
{
BaseSerialPort * pThis = static_cast<BaseSerialPort *>(p);
if(pThis->m_type == FarReader)
{
return (void *)pThis->FarRecverProcess();
}
else if(pThis->m_type == NearReader)
{
return (void *)pThis->NearRecverProcess();
}
else if(pThis->m_type == RelayVoltage)
{
return (void *)pThis->RelayVoltageRecverProcess();
}
return 0;
}
/*
数据格式: (近程)
STX(0X02) DATA(8HEX) CR LF ETX(0X03)
注:
STX 为开始字符 (十六进制)
DATA 为8位十六进制字符卡号
CR 为0D(表示空格)
LF 为0A(表示换行)
ETX 为结束字符03(十六进制)
实例:读卡器输出到计算机十六进制卡号类型:
02 30 31 38 31 30 31 44 34 0D 0A 03
其中:30 31 38 31 30 31 44 34 为卡号的四个字节的ASCII码
*/
int BaseSerialPort::NearRecverProcess()
{
LOGE("enter NearRecverProcess");
char szBuf[256] = {0};
fd_set readset;
struct timeval tv;
int ret = -1;
int size = 0;
char szTmp[4] = {0};
int iBase = 0, iCardNum = 0;
while(m_bRunning)
{
FD_ZERO(&readset);
FD_SET(m_iFd, &readset);
tv.tv_sec = 0;
tv.tv_usec = 1000 * 1000;
ret = select(m_iFd + 1, &readset, NULL, NULL, &tv);
if(ret < 0)
{
LOGE("read port error");
break;
}
if(ret == 0)
{
continue;
}
if(FD_ISSET(m_iFd, &readset))
{
size = read(m_iFd, szBuf, 14);
//LOGE("szBuf[0]=%02x, szBuf[1]=%02x, szBuf[2]=%02x, szBuf[3]=%02x, szBuf[4]=%02x", szBuf[0], szBuf[1], szBuf[2], szBuf[3], szBuf[4]);
//LOGE("szBuf[5]=%02x, szBuf[6]=%02x, szBuf[7]=%02x, szBuf[8]=%02x, szBuf[9]=%02x, szBuf[10]=%02x, iCardNum = %d", szBuf[5], szBuf[6], szBuf[7], szBuf[8], szBuf[9], szBuf[10], iCardNum);
//size = read(m_iFd, szBuf, 14);
if(size > 0)
{
memset(szTmp, 0, 4);
/*
szTmp[0] = szBuf[5];
szTmp[1] = szBuf[6];
sscanf(szTmp, "%02x", &iBase);
szTmp[0] = szBuf[7];
szTmp[1] = szBuf[8];
szTmp[2] = szBuf[9];
szTmp[3] = szBuf[10];
sscanf(szTmp, "%04x", &iCardNum);
LOGE("base = %d, num = %d", iBase, iCardNum);
iCardNum = iBase * 100000 + iCardNum;
*/
szTmp[0] = szBuf[3];
szTmp[1] = szBuf[4];
sscanf(szTmp, "%02x", &iBase);
szTmp[0] = szBuf[5];
szTmp[1] = szBuf[6];
szTmp[2] = szBuf[7];
szTmp[3] = szBuf[8];
sscanf(szTmp, "%04x", &iCardNum);
//LOGE("base = %d, num = %d", iBase, iCardNum);
iCardNum = iBase * 100000 + iCardNum;
SendCardNumber(iCardNum, NearReader);
//LOGE("szBuf[5]=%02x, szBuf[6]=%02x, szBuf[7]=%02x, szBuf[8]=%02x, szBuf[9]=%02x, szBuf[10]=%02x, iCardNum = %d", szBuf[5], szBuf[6], szBuf[7], szBuf[8], szBuf[9], szBuf[10], iCardNum);
}
}
}
return 1;
}
/*
数据格式: (远程)
起始码 0x30 0x32
读卡器id 1-255, 2字节发送,ASCII码
数据 5个字节的卡号,分10字节ASCII码发送
校验crc 取5个字节卡号之和的最低字节,分2字节ASCII码发送
结束码 0x0D 0X0A
*/
int BaseSerialPort::FarRecverProcess()
{
LOGE("enter FarRecverProcess");
char szBuf[256] = {0};
char szTmp[4] = {0};
fd_set readset;
struct timeval tv;
int ret = -1;
int size = 0;
int pos = 0;
int idx = 0;
int iState = 0;
int iBaseNum = 0;
int iCardNum = 0;
bool bFind = false;
while(m_bRunning)
{
FD_ZERO(&readset);
FD_SET(m_iFd, &readset);
tv.tv_sec = 0;
tv.tv_usec = 1000 * 100;
ret = select(m_iFd + 1, &readset, NULL, NULL, &tv);
if(ret < 0)
{
LOGE("read port error");
break;
}
if(ret == 0)
{
continue;
}
if(FD_ISSET(m_iFd, &readset))
{
size = read(m_iFd, szBuf + pos, 1);
if(size > 0)
{
if(iState == 0)
{
if(szBuf[pos] == 0x30)
{
pos++;
iState = 1;
}
}
else if(iState == 1)
{
if(szBuf[pos] == 0x32)
{
pos++;
iState = 2;
}
else
{
pos = 0;
iState = 0;
}
}
else if(iState == 2)
{
if(szBuf[pos] == 0x0D)
{
iState = 3;
}
pos++;
}
else if(iState == 3)
{
if(szBuf[pos] == 0x0A)
{
pos++;
iState = 4;
}
else
{
pos = 0;
iState = 0;
}
}
else if(iState == 4)
{
//LOGE("CardNo%03d, pos=%d, %s", idx++, pos, szBuf + pos -18);
/*char szTmp[2];
int c = 0;
for(int i = 0; i < 12; i += 2)
{
szTmp[0] = szBuf[pos -16 + i];
szTmp[1] = szBuf[pos -16 + i + 1];
sscanf(szTmp, "%02x", &c);
printf("%d ", c);
}
*/
szTmp[0] = szBuf[pos -10];
szTmp[1] = szBuf[pos -9];
sscanf(szTmp, "%02x", &iBaseNum);
//iCardNum = iBaseNum * 100000;
szTmp[0] = szBuf[pos -8];
szTmp[1] = szBuf[pos -7];
szTmp[2] = szBuf[pos -6];
szTmp[3] = szBuf[pos -5];
sscanf(szTmp, "%04x", &iCardNum);
iCardNum = iBaseNum * 100000 + iCardNum;
SendCardNumber(iCardNum, FarReader);
//LOGE("get card num is %d", iCardNum);
pos = 0;
iState = 0;
}
}
}
}
return 1;
}
// + is 43, . is 46
int BaseSerialPort::RelayVoltageRecverProcess()
{
LOGE("enter RelayVoltageRecverProcess");
char szBuf[32] = {0};
fd_set readset;
struct timeval tv;
int ret = -1;
int size = 0;
int pos = 0;
int iState = 0;
while(m_bRunning)
{
FD_ZERO(&readset);
FD_SET(m_iFd, &readset);
tv.tv_sec = 0;
tv.tv_usec = 1000 * 1000;
ret = select(m_iFd + 1, &readset, NULL, NULL, &tv);
if(ret < 0)
{
LOGE("read port error");
break;
}
if(ret == 0)
{
continue;
}
if(FD_ISSET(m_iFd, &readset))
{
size = read(m_iFd, szBuf + pos, 1);
if(size > 0)
{
//LOGE("szBuf[%d] = %d, szBuf is %s", pos, szBuf[pos], szBuf);
if(iState == 0)
{
if(szBuf[pos] == '+')
{
pos = -1;
iState = 1;
}
}
else if(iState == 1)
{
if(szBuf[pos] == '+')
{
//此时的buf如12.03+,注意前边不带+,后边带+号
szBuf[pos] = '\0';
//LOGE("pos = %d, szBuf = %s, szBuf[3] = %d, szBuf[4] = %d", pos, szBuf, szBuf[3], szBuf[4]);
double v = atof(szBuf);
WNNotification notification;
notification.mParams[0] = (int)v;//电压值整数部分
notification.mParams[1] = szBuf[3] - 48;//电压值小数部分第一位
notification.mParams[2] = szBuf[4] - 48;//电压值小数部分第二位
notification.muNotificationId = WNNotificationCenter::DefaultCenter()->GetNotificationIdByName("GTS_RelayVoltage");
WNNotificationCenter::DefaultCenter()->PostNotification(&notification);
iState = 0;
pos = 0;
}
}
pos++;
}
}
}
return 1;
}
void BaseSerialPort::SendCardNumber(int number, SerialPortType type)
{
WNNotification notification;
if(type == NearReader)
{
notification.mParams[0] = 0;
}
else if(type == FarReader)
{
notification.mParams[0] = 1;
}
else
{
return;
}
notification.mParams[1] = number;
notification.muNotificationId = WNNotificationCenter::DefaultCenter()->GetNotificationIdByName("GTS_CardNumber");
WNNotificationCenter::DefaultCenter()->PostNotification(&notification);
}
\ No newline at end of file
#ifndef _BaseSerialPort_H
#define _BaseSerialPort_H
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#include <pthread.h>
#include "Common/include/WNNotificationCenter.h"
enum SerialPortType
{
SP_Default = -1,
NearReader,
FarReader,
RelayVoltage
};
class BaseSerialPort
{
public:
BaseSerialPort();
~BaseSerialPort();
bool Start(int iPort, int iBaudRate, SerialPortType type);
void Stop();
private:
void StartRecver();
static void * RecverWrapper(void * p);
int FarRecverProcess();
int NearRecverProcess();
int RelayVoltageRecverProcess();
bool OpenPort(int port);
bool SetParams(int nSpeed, int nBits, char nEvent, int nStop);
void SendCardNumber(int number, SerialPortType type);
bool m_bRunning;
SerialPortType m_type;
int m_iFd;
pthread_t m_thread_recver;
};
#endif //#ifndef _BaseSerialPort_H
\ No newline at end of file
#ifndef _DTCOMMON_H_
#define _DTCOMMON_H_
#define MOD_LOG_TAG "libtts.so"
#define _WANIN_LOG_
#ifdef _WANIN_LOG_
#include <android/log.h>
#define LOG(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MOD_LOG_TAG, fmt, ##args)
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, MOD_LOG_TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR,MOD_LOG_TAG, fmt, ##args)
#else
#define LOG (...)
#define LOGI(...)
#define LOGE(...)
#endif
#endif //_DTCOMMON_H_
\ No newline at end of file
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef ACCALLBACK_H
#define ACCALLBACK_H
#include<new>
#include "stdlib.h"
template<class ret_type, class arg_type>
class function_base
{
public:
function_base() {}
virtual ~function_base(){}
virtual ret_type operator() (arg_type) = 0;
};
template<class ret_type, class arg_type>
class function_impl_normal: public function_base<ret_type, arg_type>
{
public:
typedef ret_type (* NORM_PROC) (arg_type);
explicit function_impl_normal(NORM_PROC proc): norm_proc_(proc) {}
ret_type operator() (arg_type arg) { return norm_proc_(arg); }
private:
NORM_PROC norm_proc_;
};
template<class ret_type, class arg_type>
class function
{
public:
typedef ret_type (* NORM_PROC) (arg_type);
explicit function(function_base<ret_type, arg_type>* fun): fun_(fun), ref_(new int(1)) {}
function(NORM_PROC proc = 0): fun_(new function_impl_normal<ret_type, arg_type>(proc)), ref_(new int(1)) {}
ret_type operator() (arg_type arg) { fun_->operator()(arg); }
~function()
{
Release();
}
void Release()
{
*ref_ -= 1;
if (*ref_ == 0)
{
delete ref_;
delete fun_;
}
}
function(const function& fun)
{
fun_ = fun.fun_;
ref_ = fun.ref_;
*ref_ += 1;
}
void operator=(const function& fun)
{
Release();
fun_ = fun.fun_;
ref_ = fun.ref_;
*ref_ += 1;
}
private:
int* ref_;
function_base<ret_type, arg_type>* fun_;
};
template<class CS, class ret_type, class arg_type>
class function_impl: public function_base<ret_type, arg_type>
{
public:
typedef ret_type (CS::* PROC)(arg_type);
function_impl(CS* obj, PROC proc): obj_(obj), proc_(proc) {}
ret_type operator() (arg_type arg) { return (obj_->*proc_)(arg); }
private:
CS* obj_;
PROC proc_;
};
template<class CS, class ret_type, class arg_type>
function<ret_type, arg_type> bind(ret_type (CS::* proc)(arg_type), CS* pc)
{
function_base<ret_type, arg_type>* pf = new function_impl<CS, ret_type, arg_type>(pc, proc);
return function<ret_type, arg_type>(pf);
}
template<class CS, class ret_type>
function<ret_type, void> bind(ret_type (CS::* proc)(), CS* pc)
{
function_base<ret_type, void>* pf = new function_impl<CS, ret_type, void>(pc, proc);
return function<ret_type, void>(pf);
}
struct _ACCallbackOpCodes
{
unsigned char tag; // CALL e8
long* offset; // offset (dest - src - 5, 5=sizeof(tag + offset))
long* _this; // a this pointer
long* _func; // pointer to real member function address
};
static void STDACJMPProc()
{
asm
(
"POP R7\n"
"mov R6 , [R7 + 4]\n" // func
"MOV R7 , [R7]\n" // this
"BL R6\n"
);
}
static long* CalcJmpOffset(long* Src, long* Dest)
{
return (long*)(Dest - (Src + 5));
}
template<typename _TPStdFunc, class _TClass, typename _TPMemberFunc>
class ACCallback
{
public:
_TClass *m_pThis;
_TPMemberFunc m_pFunc;
private:
_TPStdFunc m_pStdFunc;
void MakeCode()
{
if (m_pStdFunc) free(m_pStdFunc);
m_pStdFunc = (_TPStdFunc)malloc(sizeof(_ACCallbackOpCodes));
_ACCallbackOpCodes *p = (_ACCallbackOpCodes *)m_pStdFunc;
p->_func = *(int* *)&m_pFunc;
p->_this = (int*)m_pThis;
p->tag = 0xE8;
p->offset = CalcJmpOffset((int*)p, (int*)STDACJMPProc);
}
public:
ACCallback<_TPStdFunc, _TClass, _TPMemberFunc>()
{
}
ACCallback<_TPStdFunc, _TClass, _TPMemberFunc>(_TClass* pThis,
_TPMemberFunc pFunc
)
{
m_pFunc = pFunc;
m_pThis = pThis;
m_pStdFunc = 0;
// MakeCode();
}
void Assign(_TClass* pThis,
_TPMemberFunc pFunc
)
{
m_pFunc = pFunc;
m_pThis = pThis;
m_pStdFunc = 0;
//MakeCode();
}
~ACCallback<_TPStdFunc, _TClass, _TPMemberFunc>()
{
//::VirtualFree(m_pStdFunc, 0, MEM_RELEASE);
}
operator _TPStdFunc()
{
return m_pStdFunc;
}
};
template <typename _TPStdFunc>
class ACCallbackEx
{
template <typename _TClass, typename _TPMemberFunc>
void MakeCode(_TClass* pThis, _TPMemberFunc pMenberFunc)
{
/*FreeCode();
mpStdFunc = (_TPStdFunc)::VirtualAlloc(0, sizeof(_ACCallbackOpCodes), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
_ACCallbackOpCodes *p = (_ACCallbackOpCodes *)mpStdFunc;
p->_func = *(int* *)&pMenberFunc;
p->_this = (int*)pThis;
p->tag = 0xE8;
p->offset = CalcJmpOffset((int*)p, (int*)STDACJMPProc);*/
}
public:
ACCallbackEx()
{
mpStdFunc = 0;
}
~ACCallbackEx()
{
// FreeCode();
}
operator _TPStdFunc()
{
return mpStdFunc;
}
_TPStdFunc StdFnPtr()
{
return mpStdFunc;
}
template <typename _TClass, typename _TPMemberFunc>
void SetCallBackMemberFunc(_TClass* pThis, _TPMemberFunc pMenberFunc)
{
//MakeCode(pThis, pMenberFunc);
//mpStdFunc = std::bind(pMenberFunc , pThis, _1 );
//bind_base0<void>* tobj0 = bindfun(pThis,pMenberFunc);
f = bind(pMenberFunc,pThis);
}
void operator()(int i=0){
}
void FreeCode()
{
if (mpStdFunc)
{
//::VirtualFree(mpStdFunc, 0, MEM_RELEASE);
mpStdFunc = 0;
}
}
public:
_TPStdFunc mpStdFunc;
function<void ,int> f;
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef __BIND_H_INCLUDED__
#define __BIND_H_INCLUDED__
#include <stdexcept>
# if defined(_MSC_VER)
// MS compatible compilers support #pragma once
# if (_MSC_VER >= 1020)
# pragma once
# endif
# pragma warning(push)
# pragma warning(disable: 4512) // assignment operator could not be generated
# endif
namespace std
{
template<class T> class shared_ptr;
template<class T, class D> class unique_ptr;
}
namespace bi
{
template<int I> struct Argc{};
template<typename T> struct type{ typedef T value; };
template<typename R, typename F, typename L> struct bind_t;
template<typename T> struct untie_ref
{
typedef T type;
};
template<typename T> struct untie_ref<T&> : untie_ref<T>{};
template<typename T> struct param_traits
{
typedef typename untie_ref<T>::type &type;
};
template<typename R> struct result_traits
{
typedef R type;
};
template<typename F> struct result_traits<type<F> > : result_traits<typename F::result_type> {};
template<typename T> struct reference_wrapper
{
public:
typedef T type;
explicit reference_wrapper(T &t): t_(&t) {}
operator T& () const { return *t_; }
T& get() const { return *t_; }
T* get_pointer() const { return t_; }
private:
T* t_;
};
template<typename F> struct result_traits<type<reference_wrapper<F> > > : result_traits<typename F::result_type> {};
template<typename T>
inline reference_wrapper<T> ref(T &t)
{
return reference_wrapper<T>(t);
}
template<typename T>
inline reference_wrapper<T const> cref(const T &t)
{
return reference_wrapper<const T>(t);
}
template<typename T>
inline T* get_pointer(T *o){return o;}
template<typename T>
inline T* get_pointer(T &o){return &o;}
template<typename T>
inline T* get_pointer(const std::shared_ptr<T> &o){return o.get();}
template<typename T, typename D>
inline T* get_pointer(const std::unique_ptr<T, D> &o){return o.get();}
}
namespace
{
static inline bi::Argc<1> _1() { return bi::Argc<1>(); }
static inline bi::Argc<2> _2() { return bi::Argc<2>(); }
static inline bi::Argc<3> _3() { return bi::Argc<3>(); }
static inline bi::Argc<4> _4() { return bi::Argc<4>(); }
static inline bi::Argc<5> _5() { return bi::Argc<5>(); }
static inline bi::Argc<6> _6() { return bi::Argc<6>(); }
static inline bi::Argc<7> _7() { return bi::Argc<7>(); }
static inline bi::Argc<8> _8() { return bi::Argc<8>(); }
static inline bi::Argc<9> _9() { return bi::Argc<9>(); }
} // unnamed namespace
namespace bi
{
template<typename R, typename F> struct f_i
{
typedef typename result_traits<R>::type result_type;
template<typename R, typename F>
bool operator==(const f_i<R, F> &o) const
{
return get_pointer(o.f_) == get_pointer(f_);
}
protected:
explicit f_i(const F &f) : f_(f) {}
F f_;
};
template<typename R, typename C, typename F>
struct f_cplus_0 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_0(const F &f) : base(f) {}
template<typename U>
inline typename base::result_type operator()(U &u) const
{
return (get_pointer(u)->*base::f_)();
}
inline typename base::result_type operator()(C &c) const
{
return (c.*base::f_)();
}
};
template<typename R, typename C, typename F>
struct f_cplus_1 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_1(const F &f) : base(f) {}
template<typename U, typename A1>
inline typename base::result_type operator()(U &u, A1 a1) const
{
return (get_pointer(u)->*base::f_)(a1);
}
template<typename A1>
inline typename base::result_type operator()(C &c, A1 a1) const
{
return (c.*base::f_)(a1);
}
};
template<typename R, typename C, typename F>
struct f_cplus_2 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_2(const F &f) : base(f) {}
template<typename U, typename A1, typename A2>
inline typename base::result_type operator()(U &u, A1 a1, A2 a2) const
{
return (get_pointer(u)->*base::f_)(a1, a2);
}
template<typename A1, typename A2>
inline typename base::result_type operator()(C &c, A1 a1, A2 a2) const
{
return (c.*base::f_)(a1, a2);
}
};
template<typename R, typename C, typename F>
struct f_cplus_3 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_3(const F &f) : base(f) {}
template<typename U, typename A1, typename A2, typename A3>
inline typename base::result_type operator()(U &u, A1 &a1, A2 &a2, A3 &a3) const
{
return (get_pointer(u)->*base::f_)(a1, a2, a3);
}
template<typename A1, typename A2, typename A3>
inline typename base::result_type operator()(C &c, A1 &a1, A2 &a2, A3 &a3) const
{
return (c.*base::f_)(a1, a2, a3);
}
};
template<typename R, typename C, typename F>
struct f_cplus_4 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_4(const F &f) : base(f) {}
template<typename U, typename A1, typename A2, typename A3, typename A4>
inline typename base::result_type operator()(U &u, A1 &a1, A2 &a2, A3 &a3, A4 &a4) const
{
return (get_pointer(u)->*base::f_)(a1, a2, a3, a4);
}
template<typename A1, typename A2, typename A3, typename A4>
inline typename base::result_type operator()(C &c, A1 &a1, A2 &a2, A3 &a3, A4 &a4) const
{
return (c.*base::f_)(a1, a2, a3, a4);
}
};
template<typename R, typename C, typename F>
struct f_cplus_5 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_5(const F &f) : base(f) {}
template<typename U, typename A1, typename A2, typename A3, typename A4, typename A5>
inline typename base::result_type operator()(U &u, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5) const
{
return (get_pointer(u)->*base::f_)(a1, a2, a3, a4, a5);
}
template<typename A1, typename A2, typename A3, typename A4, typename A5>
inline typename base::result_type operator()(C &c, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5) const
{
return (c.*base::f_)(a1, a2, a3, a4, a5);
}
};
template<typename R, typename C, typename F>
struct f_cplus_6 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_6(const F &f) : base(f) {}
template<typename U, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
inline typename base::result_type operator()(U &u, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6) const
{
return (get_pointer(u)->*base::f_)(a1, a2, a3, a4, a5, a6);
}
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
inline typename base::result_type operator()(C &c, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6) const
{
return (c.*base::f_)(a1, a2, a3, a4, a5, a6);
}
};
template<typename R, typename C, typename F>
struct f_cplus_7 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_7(const F &f) : base(f) {}
template<typename U, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
inline typename base::result_type operator()(U &u, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6, A7 &a7) const
{
return (get_pointer(u)->*base::f_)(a1, a2, a3, a4, a5, a6, a7);
}
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
inline typename base::result_type operator()(C &c, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6, A7 &a7) const
{
return (c.*base::f_)(a1, a2, a3, a4, a5, a6, a7);
}
};
template<typename R, typename C, typename F>
struct f_cplus_8 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_8(const F &f) : base(f) {}
template<typename U, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
inline typename base::result_type operator()(U &u, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6, A7 &a7, A8 &a8) const
{
return (get_pointer(u)->*base::f_)(a1, a2, a3, a4, a5, a6, a7, a8);
}
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
inline typename base::result_type operator()(C &c, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6, A7 &a7, A8 &a8) const
{
return (c.*base::f_)(a1, a2, a3, a4, a5, a6, a7, a8);
}
};
template<typename R, typename C, typename F>
struct f_cplus_9 : f_i<R, F>
{
typedef f_i<R, F> base;
explicit f_cplus_9(const F &f) : base(f) {}
template<typename U, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
inline typename base::result_type operator()(U &u, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6, A7 &a7, A8 &a8, A9 &a9) const
{
return (get_pointer(u)->*base::f_)(a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
inline typename base::result_type operator()(C &c, A1 &a1, A2 &a2, A3 &a3, A4 &a4, A5 &a5, A6 &a6, A7 &a7, A8 &a8, A9 &a9) const
{
return (c.*base::f_)(a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
};
struct list_b
{
template<typename T>
inline T& operator[](T &v) const {return v;}
template<typename T>
inline const T& operator[](const T &v) const{return v;}
template<typename T>
inline T& operator[](reference_wrapper<T> &v) const {return v.get();}
template<typename T>
inline T& operator[](const reference_wrapper<T> &v) const {return v.get();}
};
struct list0 : list_b
{
typedef list_b base;
using base::operator[];
inline void operator[](Argc<0>(*)()) const{};
inline void operator[](Argc<0>) const{};
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L&)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f]();
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L&) const
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f]();
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
return b.eval(*this);
}
};
template<typename D>
struct list1b : list0
{
typedef list0 base;
using base::operator[];
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f](l[d.a1_]);
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return d[f](l[d.a1_]);
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return b.eval(d);
}
};
template<typename A1>
struct list1 : list1b<list1<A1> >
{
typedef list1b<list1<A1> > base;
typedef typename param_traits<A1>::type P1;
typedef typename result_traits<A1>::type result_type;
explicit list1(P1 p1) : a1_(p1) {}
using base::operator[];
inline result_type operator[](Argc<1>(*)()) const { return a1_;}
inline result_type operator[](Argc<1>) const { return a1_;}
A1 a1_;
};
template<int I>
struct list1<Argc<I>(*)()> : list1b<list1<Argc<I>(*)()> >
{
typedef list1b<list1<Argc<I>(*)()> > base;
typedef typename param_traits<Argc<I>(*)()>::type P1;
using base::operator[];
explicit list1(P1){}
static Argc<I> a1_() {return Argc<I>();}
};
template<typename D, typename A1>
struct list2b : list1<A1>
{
typedef list1<A1> base;
using base::operator[];
list2b(typename base::P1 p1) : base(p1){}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_]);
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_]);
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return b.eval(d);
}
};
template<typename A1, typename A2>
struct list2 : list2b<list2<A1, A2>, A1>
{
typedef list2b<list2<A1, A2>, A1> base;
typedef typename param_traits<A2>::type P2;
typedef typename result_traits<A2>::type result_type;
list2(typename base::P1 p1, P2 p2) : base(p1), a2_(p2) {}
using base::operator[];
inline result_type operator[](Argc<2> (*)()) const { return a2_; }
inline result_type operator[](Argc<2>) const { return a2_;}
A2 a2_;
};
template<typename A1, int I>
struct list2<A1, Argc<I>(*)()> : list2b<list2<A1, Argc<I>(*)()>, A1>
{
typedef list2b<list2<A1, Argc<I>(*)()>, A1> base;
typedef typename param_traits<Argc<I>(*)()>::type P2;
using base::operator[];
list2(typename base::P1 p1, P2) : base(p1){}
static Argc<I> a2_() { return Argc<I>(); }
};
template<typename D, typename A1, typename A2>
struct list3b : list2<A1, A2>
{
typedef list2<A1, A2> base;
using base::operator[];
list3b(typename base::P1 p1, typename base::P2 p2) : base(p1, p2) {}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_]);
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_]);
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return b.eval(d);
}
};
template<typename A1, typename A2, typename A3>
struct list3 : list3b<list3<A1, A2, A3>, A1, A2>
{
typedef list3b<list3<A1, A2, A3>, A1, A2> base;
typedef typename param_traits<A3>::type P3;
typedef typename result_traits<A3>::type result_type;
list3(typename base::P1 p1, typename base::P2 p2, P3 p3) : base(p1, p2), a3_(p3) {}
using base::operator[];
inline result_type operator[](Argc<3> (*)()) const { return a3_; }
inline result_type operator[](Argc<3>) const { return a3_;}
A3 a3_;
};
template<typename A1, typename A2, int I>
struct list3<A1, A2, Argc<I>(*)()> : list3b<list3<A1, A2, Argc<I>(*)()>, A1, A2>
{
typedef list3b<list3<A1, A2, Argc<I>(*)()>, A1, A2> base;
typedef typename param_traits<Argc<I>(*)()>::type P3;
using base::operator[];
list3(typename base::P1 p1, typename base::P2 p2, P3) : base(p1, p2) {}
static Argc<I> a3_() { return Argc<I>(); }
};
template<typename D, typename A1, typename A2, typename A3>
struct list4b : list3<A1, A2, A3>
{
typedef list3<A1, A2, A3> base;
using base::operator[];
list4b(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3) : base(p1, p2, p3){}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_]);
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_]);
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return b.eval(d);
}
};
template<typename A1, typename A2, typename A3, typename A4>
struct list4 : list4b<list4<A1, A2, A3, A4>, A1, A2, A3>
{
typedef list4b<list4<A1, A2, A3, A4>, A1, A2, A3> base;
typedef typename param_traits<A4>::type P4;
typedef typename result_traits<A4>::type result_type;
using base::operator[];
list4(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, P4 p4) : base(p1, p2, p3), a4_(p4) {}
inline result_type operator[](Argc<4>(*)()) const { return a4_; }
inline result_type operator[](Argc<4>) const { return a4_;}
A4 a4_;
};
template<typename A1, typename A2, typename A3, int I>
struct list4<A1, A2, A3, Argc<I>(*)()> : list4b<list4<A1, A2, A3, Argc<I>(*)()>, A1, A2, A3>
{
typedef list4b<list4<A1, A2, A3, Argc<I>(*)()>, A1, A2, A3> base;
typedef typename param_traits<Argc<I>(*)()>::type P4;
using base::operator[];
list4(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, P4) : base(p1, p2, p3) {}
static Argc<I> a4_() { return Argc<I>(); }
};
template<typename D, typename A1, typename A2, typename A3, typename A4>
struct list5b : list4<A1, A2, A3, A4>
{
typedef list4<A1, A2, A3, A4> base;
using base::operator[];
list5b(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4) : base(p1, p2, p3, p4) { }
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_], l[d.a5_]);
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4], l[d.a5_]);
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return b.eval(d);
}
};
template<typename A1, typename A2, typename A3, typename A4, typename A5>
struct list5 : list5b<list5<A1, A2, A3, A4, A5>, A1, A2, A3, A4>
{
typedef list5b<list5<A1, A2, A3, A4, A5>, A1, A2, A3, A4> base;
typedef typename param_traits<A5>::type P5;
typedef typename result_traits<A5>::type result_type;
using base::operator[];
list5(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, P5 p5) : base(p1, p2, p3, p4), a5_(p5) { }
inline result_type operator[](Argc<5> (*)()) const { return a5_; }
inline result_type operator[](Argc<5>) const { return a5_;}
A5 a5_;
};
template<typename A1, typename A2, typename A3, typename A4, int I>
struct list5<A1, A2, A3, A4, Argc<I>(*)()> : list5b<list5<A1, A2, A3, A4, Argc<I>(*)()>, A1, A2, A3, A4>
{
typedef list5b<list5<A1, A2, A3, A4, Argc<I>(*)()>, A1, A2, A3, A4> base;
typedef typename param_traits<Argc<I>(*)()>::type P5;
using base::operator[];
list5(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, P5) : base(p1, p2, p3, p4) {}
static Argc<I> a5_() { return Argc<I>(); }
};
template<typename D, typename A1, typename A2, typename A3, typename A4, typename A5>
struct list6b : list5<A1, A2, A3, A4, A5>
{
typedef list5<A1, A2, A3, A4, A5> base;
using base::operator[];
list6b(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5) : base(p1, p2, p3, p4, p5) {}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_], l[d.a5_], l[d.a6_]);
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_], l[d.a5_], l[d.a6_]);
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return b.eval(d);
}
};
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
struct list6 : list6b<list6<A1, A2, A3, A4, A5, A6>, A1, A2, A3, A4, A5>
{
typedef list6b<list6<A1, A2, A3, A4, A5, A6>, A1, A2, A3, A4, A5> base;
typedef typename param_traits<A6>::type P6;
typedef typename result_traits<A6>::type result_type;
using base::operator[];
list6(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, P6 p6) : base(p1, p2, p3, p4, p5), a6_(p6) {}
inline result_type operator[](Argc<6> (*)()) const { return a6_; }
inline result_type operator[](Argc<6>) const { return a6_;}
A6 a6_;
};
template<typename A1, typename A2, typename A3, typename A4, typename A5, int I>
struct list6<A1, A2, A3, A4, A5, Argc<I>(*)()> : list6b<list6<A1, A2, A3, A4, A5, Argc<I>(*)()>, A1, A2, A3, A4, A5>
{
typedef list6b<list6<A1, A2, A3, A4, A5, Argc<I>(*)()>, A1, A2, A3, A4, A5> base;
typedef typename param_traits<Argc<I>(*)()>::type P6;
using base::operator[];
list6(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, P6) : base(p1, p2, p3, p4, p5) {}
static Argc<I> a6_() { return Argc<I>(); }
};
template<typename D, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
struct list7b : list6<A1, A2, A3, A4, A5, A6>
{
typedef list6<A1, A2, A3, A4, A5, A6> base;
using base::operator[];
list7b(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, typename base::P6 p6) : base(p1, p2, p3, p4, p5, p6) {}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_], l[d.a5_], l[d.a6_], l[d.a7_]);
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_], l[d.a5_], l[d.a6_], l[d.a7_]);
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return b.eval(d);
}
};
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
struct list7 : list7b<list7<A1, A2, A3, A4, A5, A6, A7>, A1, A2, A3, A4, A5, A6>
{
typedef list7b<list7<A1, A2, A3, A4, A5, A6, A7>, A1, A2, A3, A4, A5, A6> base;
typedef typename param_traits<A7>::type P7;
typedef typename result_traits<A7>::type result_type;
using base::operator[];
list7(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, typename base::P6 p6, P7 p7) : base(p1, p2, p3, p4, p5, p6), a7_(p7) {}
inline result_type operator[](Argc<7> (*)()) const { return a7_; }
inline result_type operator[](Argc<7>) const { return a7_;}
A7 a7_;
};
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, int I>
struct list7<A1, A2, A3, A4, A5, A6, Argc<I>(*)()> : list7b<list7<A1, A2, A3, A4, A5, A6, Argc<I>(*)()>, A1, A2, A3, A4, A5, A6>
{
typedef list7b<list7<A1, A2, A3, A4, A5, A6, Argc<I>(*)()>, A1, A2, A3, A4, A5, A6> base;
typedef typename param_traits<Argc<I>(*)()>::type P7;
using base::operator[];
list7(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, typename base::P6 p6, P7) : base(p1, p2, p3, p4, p5, p6) {}
static Argc<I> a7_() { return Argc<I>(); }
};
template<typename D, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
struct list8b : list7<A1, A2, A3, A4, A5, A6, A7>
{
typedef list7<A1, A2, A3, A4, A5, A6, A7> base;
using base::operator[];
list8b(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, typename base::P6 p6, typename base::P7 p7) : base(p1, p2, p3, p4, p5, p6, p7) {}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_], l[d.a5_], l[d.a6_], l[d.a7_], l[d.a8_]);
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_], l[d.a5_], l[d.a6_], l[d.a7_], l[d.a8_]);
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return b.eval(d);
}
};
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
struct list8 : list8b<list8<A1, A2, A3, A4, A5, A6, A7, A8>, A1, A2, A3, A4, A5, A6, A7>
{
typedef list8b<list8<A1, A2, A3, A4, A5, A6, A7, A8>, A1, A2, A3, A4, A5, A6, A7> base;
typedef typename param_traits<A8>::type P8;
typedef typename result_traits<A8>::type result_type;
using base::operator[];
list8(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, typename base::P6 p6, typename base::P7 p7, P8 p8) : base(p1, p2, p3, p4, p5, p6, p7), a8_(p8) {}
inline result_type operator[](Argc<8> (*)()) const { return a8_; }
inline result_type operator[](Argc<8>) const { return a8_;}
A8 a8_;
};
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, int I>
struct list8<A1, A2, A3, A4, A5, A6, A7, Argc<I>(*)()> : list8b<list8<A1, A2, A3, A4, A5, A6, A7, Argc<I>(*)()>, A1, A2, A3, A4, A5, A6, A7>
{
typedef list8b<list8<A1, A2, A3, A4, A5, A6, A7, Argc<I>(*)()>, A1, A2, A3, A4, A5, A6, A7> base;
typedef typename param_traits<Argc<I>(*)()>::type P8;
using base::operator[];
list8(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, typename base::P6 p6, typename base::P7 p7, P8) : base(p1, p2, p3, p4, p5, p6, p7) {}
static Argc<I> a8_() { return Argc<I>(); }
};
template<typename D, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
struct list9b : list8<A1, A2, A3, A4, A5, A6, A7, A8>
{
typedef list8<A1, A2, A3, A4, A5, A6, A7, A8> base;
using base::operator[];
list9b(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, typename base::P6 p6, typename base::P7 p7, typename base::P8 p8) : base(p1, p2, p3, p4, p5, p6, p7, p8) {}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l)
{
D &d = static_cast<D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_], l[d.a5_], l[d.a6_], l[d.a7_], l[d.a8_], l[d.a9_]);
}
template<typename R, typename F, typename L>
inline R operator()(type<R>, F &f, const L &l) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return d[f](l[d.a1_], l[d.a2_], l[d.a3_], l[d.a4_], l[d.a5_], l[d.a6_], l[d.a7_], l[d.a8_], l[d.a9_]);
}
template<typename R, typename F, typename L>
inline R operator[](bind_t<R, F, L> &b) const
{
const D &d = static_cast<const D&>(*this); d; //used C4189
return b.eval(d);
}
};
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
struct list9 : list9b<list9<A1, A2, A3, A4, A5, A6, A7, A8, A9>, A1, A2, A3, A4, A5, A6, A7, A8>
{
typedef list9b<list9<A1, A2, A3, A4, A5, A6, A7, A8, A9>, A1, A2, A3, A4, A5, A6, A7, A8> base;
typedef typename param_traits<A9>::type P9;
typedef typename result_traits<A9>::type result_type;
using base::operator[];
list9(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, typename base::P6 p6, typename base::P7 p7, typename base::P8 p8, P9 p9) : base(p1, p2, p3, p4, p5, p6, p7, p8), a9_(p9) {}
inline result_type operator[](Argc<9> (*)()) const { return a9_; }
inline result_type operator[](Argc<9>) const { return a9_;}
A9 a9_;
};
template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, int I>
struct list9<A1, A2, A3, A4, A5, A6, A7, A8, Argc<I>(*)()> : list9b<list9<A1, A2, A3, A4, A5, A6, A7, A8, Argc<I>(*)()>, A1, A2, A3, A4, A5, A6, A7, A8>
{
typedef list9b<list9<A1, A2, A3, A4, A5, A6, A7, A8, Argc<I>(*)()>, A1, A2, A3, A4, A5, A6, A7, A8> base;
typedef typename param_traits<Argc<I>(*)()>::type P9;
using base::operator[];
list9(typename base::P1 p1, typename base::P2 p2, typename base::P3 p3, typename base::P4 p4, typename base::P5 p5, typename base::P6 p6, typename base::P7 p7, typename base::P8 p8, P9) : base(p1, p2, p3, p4, p5, p6, p7, p8) {}
static Argc<I> a9_() { return Argc<I>(); }
};
#ifndef BI_BIND
#define BI_BIND bind
#endif
template<typename R>
bind_t<R, R (*)(), list0> BI_BIND(R (*f)())
{
typedef R (*F)();
typedef list0 L;
return bind_t<R, F, L>(f, L());
}
template<typename R, typename P1, typename A1>
bind_t<R, R (*)(P1), list1<A1> > BI_BIND(R (*f)(P1), A1 a1)
{
typedef R (*F)(P1);
typedef list1<A1> L;
return bind_t<R, F, L>(f, L(a1));
}
template<typename R, typename P1, typename P2, typename A1, typename A2>
bind_t<R, R (*)(P1, P2), list2<A1, A2> > BI_BIND(R (*f)(P1, P2), A1 a1, A2 a2)
{
typedef R (*F)(P1, P2);
typedef list2<A1, A2> L;
return bind_t<R, F, L>(f, L(a1, a2));
}
template<typename R, typename P1, typename P2, typename P3, typename A1, typename A2, typename A3>
bind_t<R, R (*)(P1, P2, P3), list3<A1, A2, A3> > BI_BIND(R (*f)(P1, P2, P3), A1 a1, A2 a2, A3 a3)
{
typedef R (*F)(P1, P2, P3);
typedef list3<A1, A2, A3> L;
return bind_t<R, F, L>(f, L(a1, a2, a3));
}
template<typename R, typename P1, typename P2, typename P3, typename P4, typename A1, typename A2, typename A3, typename A4>
bind_t<R, R (*)(P1, P2, P3, P4), list4<A1, A2, P3, A4> > BI_BIND(R (*f)(P1, P2, P3, P4), A1 a1, A2 a2, A3 a3, A4 a4)
{
typedef R (*F)(P1, P2, P3, P4);
typedef list4<A1, A2, A3, A4> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4));
}
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename A1, typename A2, typename A3, typename A4, typename A5>
bind_t<R, R (*)(P1, P2, P3, P4, P5), list5<A1, A2, A3, A4, A5> > BI_BIND(R (*f)(P1, P2, P3, P4, P5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
{
typedef R (*F)(P1, P2, P3, P4, P5);
typedef list5<A1, A2, A3, A4, A5> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5));
}
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
bind_t<R, R (*)(P1, P2, P3, P4, P5, P6), list6<A1, A2, A3, A4, A5, A6> > BI_BIND(R (*f)(P1, P2, P3, P4, P5, P6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
{
typedef R (*F)(P1, P2, P3, P4, P5, P6);
typedef list6<A1, A2, A3, A4, A5, A6> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5, a6));
}
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
bind_t<R, R (*)(P1, P2, P3, P4, P5, P6, P7), list7<A1, A2, A3, A4, A5, A6, A7> > BI_BIND(R (*f)(P1, P2, P3, P4, P5, P6, P7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
{
typedef R (*F)(P1, P2, P3, P4, P5, P6, P7);
typedef list7<A1, A2, A3, A4, A5, A6, A7> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5, a6, a7));
}
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
bind_t<R, R (*)(P1, P2, P3, P4, P5, P6, P7, P8), list8<A1, A2, A3, A4, A5, A6, A7, A8> > BI_BIND(R (*f)(P1, P2, P3, P4, P5, P6, P7, P8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
{
typedef R (*F)(P1, P2, P3, P4, P5, P6, P7, P8);
typedef list8<A1, A2, A3, A4, A5, A6, A7, A8> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5, a6, a7, a8));
}
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
bind_t<R, R (*)(P1, P2, P3, P4, P5, P6, P7, P8, P9), list9<A1, A2, A3, A4, A5, A6, A7, A8, A9> > BI_BIND(R (*f)(P1, P2, P3, P4, P5, P6, P7, P8, P9), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
{
typedef R (*F)(P1, P2, P3, P4, P5, P6, P7, P8, P9);
typedef list9<A1, A2, A3, A4, A5, A6, A7, A8, A9> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5, a6, a7, a8, a9));
}
template<typename F>
bind_t<type<F>, F, list0> BI_BIND(F f)
{
typedef list0 L;
return bind_t<type<F>, F, L>(f, L());
}
template<typename R, typename F>
bind_t<R, F, list0> BI_BIND(const type<R>&, F f)
{
typedef list0 L;
return bind_t<R, F, L>(f, L());
}
template<typename F, typename A1>
bind_t<type<F>, F, list1<A1> > BI_BIND(F f, A1 a1)
{
typedef list1<A1> L;
return bind_t<type<F>, F, L>(f, L(a1));
}
template<typename R, typename F, typename A1>
bind_t<R, F, list1<A1> > BI_BIND(const type<R>&, F f, A1 a1)
{
typedef list1<A1> L;
return bind_t<R, F, L>(f, L(a1));
}
template<typename F, typename A1, typename A2>
bind_t<type<F>, F, list2<A1, A2> > BI_BIND(F f, A1 a1, A2 a2)
{
typedef list2<A1, A2> L;
return bind_t<type<F>, F, L>(f, L(a1, a2));
}
template<typename R, typename F, typename A1, typename A2>
bind_t<R, F, list2<A1, A2> > BI_BIND(const type<R>&, F f, A1 a1, A2 a2)
{
typedef list2<A1, A2> L;
return bind_t<R, F, L>(f, L(a1, a2));
}
template<typename F, typename A1, typename A2, typename A3>
bind_t<type<F>, F, list3<A1, A2, A3> > BI_BIND(F f, A1 a1, A2 a2, A3 a3)
{
typedef list3<A1, A2, A3> L;
return bind_t<type<F>, F, L>(f, L(a1, a2, a3));
}
template<typename R, typename F, typename A1, typename A2, typename A3>
bind_t<R, F, list3<A1, A2, A3> > BI_BIND(const type<R>&, F f, A1 a1, A2 a2, A3 a3)
{
typedef list3<A1, A2, A3> L;
return bind_t<R, F, L>(f, L(a1, a2, a3));
}
template<typename F, typename A1, typename A2, typename A3, typename A4>
bind_t<type<F>, F, list4<A1, A2, A3, A4> > BI_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4)
{
typedef list4<A1, A2, A3, A4> L;
return bind_t<type<F>, F, L>(f, L(a1, a2, a3, a4));
}
template<typename R, typename F, typename A1, typename A2, typename A3, typename A4>
bind_t<R, F, list4<A1, A2, A3, A4> > BI_BIND(const type<R>&, F f, A1 a1, A2 a2, A3 a3, A4 a4)
{
typedef list4<A1, A2, A3, A4> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4));
}
template<typename F, typename A1, typename A2, typename A3, typename A4, typename A5>
bind_t<type<F>, F, list5<A1, A2, A3, A4, A5> > BI_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
{
typedef list5<A1, A2, A3, A4, A5> L;
return bind_t<type<F>, F, L>(f, L(a1, a2, a3, a4, a5));
}
template<typename R, typename F, typename A1, typename A2, typename A3, typename A4, typename A5>
bind_t<R, F, list5<A1, A2, A3, A4, A5> > BI_BIND(const type<R>&, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
{
typedef list5<A1, A2, A3, A4, A5> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5));
}
template<typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
bind_t<type<F>, F, list6<A1, A2, A3, A4, A5, A6> > BI_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
{
typedef list6<A1, A2, A3, A4, A5, A6> L;
return bind_t<type<F>, F, L>(f, L(a1, a2, a3, a4, a5, a6));
}
template<typename R, typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
bind_t<R, F, list6<A1, A2, A3, A4, A5, A6> > BI_BIND(const type<R>&, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
{
typedef list6<A1, A2, A3, A4, A5, A6> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5, a6));
}
template<typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
bind_t<type<F>, F, list7<A1, A2, A3, A4, A5, A6, A7> > BI_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
{
typedef list7<A1, A2, A3, A4, A5, A6, A7> L;
return bind_t<type<F>, F, L>(f, L(a1, a2, a3, a4, a5, a6, a7));
}
template<typename R, typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
bind_t<R, F, list7<A1, A2, A3, A4, A5, A6, A7> > BI_BIND(const type<R>&, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
{
typedef list7<A1, A2, A3, A4, A5, A6, A7> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5, a6, a7));
}
template<typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
bind_t<type<F>, F, list8<A1, A2, A3, A4, A5, A6, A7, A8> > BI_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
{
typedef list8<A1, A2, A3, A4, A5, A6, A7, A8> L;
return bind_t<type<F>, F, L>(f, L(a1, a2, a3, a4, a5, a6, a7, a8));
}
template<typename R, typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
bind_t<R, F, list8<A1, A2, A3, A4, A5, A6, A7, A8> > BI_BIND(const type<R>&, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
{
typedef list8<A1, A2, A3, A4, A5, A6, A7, A8> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5, a6, a7, a8));
}
template<typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
bind_t<type<F>, F, list9<A1, A2, A3, A4, A5, A6, A7, A8, A9> > BI_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
{
typedef list9<A1, A2, A3, A4, A5, A6, A7, A8, A9> L;
return bind_t<type<F>, F, L>(f, L(a1, a2, a3, a4, a5, a6, a7, a8, a9));
}
template<typename R, typename F, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
bind_t<R, F, list9<A1, A2, A3, A4, A5, A6, A7, A8, A9> > BI_BIND(const type<R>&, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
{
typedef list9<A1, A2, A3, A4, A5, A6, A7, A8, A9> L;
return bind_t<R, F, L>(f, L(a1, a2, a3, a4, a5, a6, a7, a8, a9));
}
template<typename R, typename C, typename C1>
bind_t<R, f_cplus_0<R, C, R (C::*)()>, list1<C1> > BI_BIND(R (C::*f)(), C1 c1)
{
typedef f_cplus_0<R, C, R (C::*)()> F;
typedef list1<C1> L;
return bind_t<R, F, L>(F(f), L(c1));
}
template<typename R, typename C, typename C1>
bind_t<R, f_cplus_0<R, C, R (C::*)() const>, list1<C1> > BI_BIND(R (C::*f)() const, C1 c1)
{
typedef f_cplus_0<R, C, R (C::*)() const> F;
typedef list1<C1> L;
return bind_t<R, F, L>(F(f), L(c1));
}
template<typename R, typename C, typename A1, typename C1, typename P1>
bind_t<R, f_cplus_1<R, C, R (C::*)(A1)>, list2<C1, P1> > BI_BIND(R (C::*f)(A1), C1 c1, P1 p2)
{
typedef f_cplus_1<R, C, R (C::*)(A1)> F;
typedef list2<C1, P1> L;
return bind_t<R, F, L>(F(f), L(c1, p2));
}
template<typename R, typename C, typename A1, typename C1, typename P1>
bind_t<R, f_cplus_1<R, C, R (C::*)(A1) const>, list2<C1, P1> > BI_BIND(R (C::*f)(A1) const, C1 c1, P1 p1)
{
typedef f_cplus_1<R, C, R (C::*)(A1) const> F;
typedef list2<C1, P1> L;
return bind_t<R, F, L>(F(f), L(c1, p1));
}
template<typename R, typename C, typename A1, typename A2, typename C1, typename P1, typename P2>
bind_t<R, f_cplus_2<R, C, R (C::*)(A1,A2)>, list3<C1, P1, P2> > BI_BIND(R (C::*f)(A1,A2), C1 c1, P1 p1, P2 p2)
{
typedef f_cplus_2<R, C, R (C::*)(A1,A2)> F;
typedef list3<C1, P1, P2> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2));
}
template<typename R, typename C, typename A1, typename A2, typename C1, typename P1, typename P2>
bind_t<R, f_cplus_2<R, C, R (C::*)(A1,A2) const>, list3<C1, P1, P2> > BI_BIND(R (C::*f)(A1,A2) const, C1 c1, P1 p1, P2 p2)
{
typedef f_cplus_2<R, C, R (C::*)(A1,A2) const> F;
typedef list3<C1, P1, P2> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename C1, typename P1, typename P2, typename P3>
bind_t<R, f_cplus_3<R, C, R (C::*)(A1,A2,A3)>, list4<C1, P1, P2, P3> > BI_BIND(R (C::*f)(A1,A2,A3), C1 c1, P1 p1, P2 p2, P3 p3)
{
typedef f_cplus_3<R, C, R (C::*)(A1,A2,A3)> F;
typedef list4<C1, P1, P2, P3> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename C1, typename P1, typename P2, typename P3>
bind_t<R, f_cplus_3<R, C, R (C::*)(A1,A2,A3) const>, list4<C1, P1, P2, P3> > BI_BIND(R (C::*f)(A1,A2,A3) const, C1 c1, P1 p1, P2 p2, P3 p3)
{
typedef f_cplus_3<R, C, R (C::*)(A1,A2,A3) const> F;
typedef list4<C1, P1, P2, P3> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename C1, typename P1, typename P2, typename P3, typename P4>
bind_t<R, f_cplus_4<R, C, R (C::*)(A1,A2,A3,A4)>, list5<C1, P1, P2, P3, P4> > BI_BIND(R (C::*f)(A1,A2,A3,A4), C1 c1, P1 p1, P2 p2, P3 p3, P4 p4)
{
typedef f_cplus_4<R, C, R (C::*)(A1,A2,A3,A4)> F;
typedef list5<C1, P1, P2, P3, P4> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename C1, typename P1, typename P2, typename P3, typename P4>
bind_t<R, f_cplus_4<R, C, R (C::*)(A1,A2,A3,A4) const>, list5<C1, P1, P2, P3, P4> > BI_BIND(R (C::*f)(A1,A2,A3,A4) const, C1 c1, P1 p1, P2 p2, P3 p3, P4 p4)
{
typedef f_cplus_4<R, C, R (C::*)(A1,A2,A3,A4) const> F;
typedef list5<C1, P1, P2, P3, P4> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename A5, typename C1, typename P1, typename P2, typename P3, typename P4, typename P5>
bind_t<R, f_cplus_5<R, C, R (C::*)(A1,A2,A3,A4,A5)>, list6<C1, P1, P2, P3, P4, P5> > BI_BIND(R (C::*f)(A1,A2,A3,A4,A5), C1 c1, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
{
typedef f_cplus_5<R, C, R (C::*)(A1,A2,A3,A4,A5)> F;
typedef list6<C1, P1, P2, P3, P4, P5> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4, p5));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename A5, typename C1, typename P1, typename P2, typename P3, typename P4, typename P5>
bind_t<R, f_cplus_5<R, C, R (C::*)(A1,A2,A3,A4,A5) const>, list6<C1, P1, P2, P3, P4, P5> > BI_BIND(R (C::*f)(A1,A2,A3,A4,A5) const, C1 c1, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
{
typedef f_cplus_5<R, C, R (C::*)(A1,A2,A3,A4,A5) const> F;
typedef list6<C1, P1, P2, P3, P4, P5> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4, p5));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename C1, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
bind_t<R, f_cplus_6<R, C, R (C::*)(A1,A2,A3,A4,A5,A6)>, list7<C1, P1, P2, P3, P4, P5, P6> > BI_BIND(R (C::*f)(A1,A2,A3,A4,A5,A6), C1 c1, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
{
typedef f_cplus_6<R, C, R (C::*)(A1,A2,A3,A4,A5,A6)> F;
typedef list7<C1, P1, P2, P3, P4, P5, P6> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4, p5, p6));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename C1, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
bind_t<R, f_cplus_6<R, C, R (C::*)(A1,A2,A3,A4,A5,A6) const>, list7<C1, P1, P2, P3, P4, P5, P6> > BI_BIND(R (C::*f)(A1,A2,A3,A4,A5,A6) const, C1 c1, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
{
typedef f_cplus_6<R, C, R (C::*)(A1,A2,A3,A4,A5,A6) const> F;
typedef list7<C1, P1, P2, P3, P4, P5, P6> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4, p5, p6));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename C1, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
bind_t<R, f_cplus_7<R, C, R (C::*)(A1,A2,A3,A4,A5,A6,A7)>, list8<C1, P1, P2, P3, P4, P5, P6, P7> > BI_BIND(R (C::*f)(A1,A2,A3,A4,A5,A6,A7), C1 c1, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
{
typedef f_cplus_7<R, C, R (C::*)(A1,A2,A3,A4,A5,A6,A7)> F;
typedef list8<C1, P1, P2, P3, P4, P5, P6, P7> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4, p5, p6, p7));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename C1, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
bind_t<R, f_cplus_7<R, C, R (C::*)(A1,A2,A3,A4,A5,A6,A7) const>, list8<C1, P1, P2, P3, P4, P5, P6, P7> > BI_BIND(R (C::*f)(A1,A2,A3,A4,A5,A6,A7) const, C1 c1, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
{
typedef f_cplus_7<R, C, R (C::*)(A1,A2,A3,A4,A5,A6,A7) const> F;
typedef list8<C1, P1, P2, P3, P4, P5, P6, P7> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4, p5, p6, p7));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename C1, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
bind_t<R, f_cplus_8<R, C, R (C::*)(A1,A2,A3,A4,A5,A6,A7,A8)>, list9<C1, P1, P2, P3, P4, P5, P6, P7, P8> > BI_BIND(R (C::*f)(A1,A2,A3,A4,A5,A6,A7,A8), C1 c1, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
{
typedef f_cplus_8<R, C, R (C::*)(A1,A2,A3,A4,A5,A6,A7,A8)> F;
typedef list9<C1, P1, P2, P3, P4, P5, P6, P7, P8> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4, p5, p6, p7, p8));
}
template<typename R, typename C, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename C1, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
bind_t<R, f_cplus_8<R, C, R (C::*)(A1,A2,A3,A4,A5,A6,A7,A8) const>, list9<C1, P1, P2, P3, P4, P5, P6, P7, P8> > BI_BIND(R (C::*f)(A1,A2,A3,A4,A5,A6,A7,A8) const, C1 c1, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
{
typedef f_cplus_8<R, C, R (C::*)(A1,A2,A3,A4,A5,A6,A7,A8) const> F;
typedef list9<C1, P1, P2, P3, P4, P5, P6, P7, P8> L;
return bind_t<R, F, L>(F(f), L(c1, p1, p2, p3, p4, p5, p6, p7, p8));
}
template<typename R, typename F, typename L> struct bind_t
{
public:
typedef typename result_traits<R>::type result_type;
public:
bind_t(const F &f, const L &l) : f_(f), l_(l) {}
template<typename A>
inline result_type eval(A &a)
{
return l_(type<result_type>(), f_, a);
}
template<typename A>
inline result_type eval(A &a) const
{
return l_(type<result_type>(), f_, a);
}
inline result_type operator()()
{
typedef list0 ll;
return l_(type<result_type>(), f_, ll());
}
inline result_type operator()() const
{
typedef list0 ll;
return l_(type<result_type>(), f_, ll());
}
template<typename P1>
inline result_type operator()(P1 &p1)
{
typedef list1<P1&> ll;
return l_(type<result_type>(), f_, ll(p1));
}
template<typename P1>
inline result_type operator()(P1 &p1) const
{
typedef list1<P1&> ll;
return l_(type<result_type>(), f_, ll(p1));
}
template<typename P1>
inline result_type operator()(const P1 &p1)
{
typedef list1<const P1&> ll;
return l_(type<result_type>(), f_, ll(p1));
}
template<typename P1>
inline result_type operator()(const P1 &p1) const
{
typedef list1<const P1&> ll;
return l_(type<result_type>(), f_, ll(p1));
}
template<typename P1, typename P2>
inline result_type operator()(P1 &p1, P2 &p2)
{
typedef list2<P1&, P2&> ll;
return l_(type<result_type>(), f_, ll(p1, p2));
}
template<typename P1, typename P2>
inline result_type operator()(P1 &p1, P2 &p2) const
{
typedef list2<P1&, P2&> ll;
return l_(type<result_type>(), f_, ll(p1, p2));
}
template<typename P1, typename P2>
inline result_type operator()(const P1 &p1, P2 &p2)
{
typedef list2<const P1&, P2&> ll;
return l_(type<result_type>(), f_, ll(p1, p2));
}
template<typename P1, typename P2>
inline result_type operator()(const P1 &p1, P2 &p2) const
{
typedef list2<const P1&, P2&> ll;
return l_(type<result_type>(), f_, ll(p1, p2));
}
template<typename P1, typename P2>
inline result_type operator()(P1 &p1, const P2 &p2)
{
typedef list2<P1&, const P2&> ll;
return l_(type<result_type>(), f_, ll(p1, p2));
}
template<typename P1, typename P2>
inline result_type operator()(P1 &p1, const P2 &p2) const
{
typedef list2<P1&, const P2&> ll;
return l_(type<result_type>(), f_, ll(p1, p2));
}
template<typename P1, typename P2>
inline result_type operator()(const P1 &p1, const P2 &p2)
{
typedef list2<const P1&, const P2&> ll;
return l_(type<result_type>(), f_, ll(p1, p2));
}
template<typename P1, typename P2>
inline result_type operator()(const P1 &p1, const P2 &p2) const
{
typedef list2<const P1&, const P2&> ll;
return l_(type<result_type>(), f_, ll(p1, p2));
}
template<typename P1, typename P2, typename P3>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3)
{
typedef list3<P1&, P2&, P3&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3));
}
template<typename P1, typename P2, typename P3>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3) const
{
typedef list3<P1&, P2&, P3&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3));
}
template<typename P1, typename P2, typename P3>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3)
{
typedef list3<const P1&, const P2&, const P3&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3));
}
template<typename P1, typename P2, typename P3>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3) const
{
typedef list3<const P1&, const P2&, const P3&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3));
}
template<typename P1, typename P2, typename P3, typename P4>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4)
{
typedef list4<P1&, P2&, P3&, P4&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4));
}
template<typename P1, typename P2, typename P3, typename P4>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4) const
{
typedef list4<P1&, P2&, P3&, P4&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4));
}
template<typename P1, typename P2, typename P3, typename P4>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4)
{
typedef list4<const P1&, const P2&, const P3&, const P4&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4));
}
template<typename P1, typename P2, typename P3, typename P4>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4) const
{
typedef list4<const P1&, const P2&, const P3&, const P4&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5)
{
typedef list5<P1&, P2&, P3&, P4&, P5&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5) const
{
typedef list5<P1&, P2&, P3&, P4&, P5&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5)
{
typedef list5<const P1&, const P2&, const P3&, const P4&, const P5&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5) const
{
typedef list5<const P1&, const P2&, const P3&, const P4&, const P5&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6)
{
typedef list6<P1&, P2&, P3&, P4&, P5&, P6&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6) const
{
typedef list6<P1&, P2&, P3&, P4&, P5&, P6&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6)
{
typedef list6<const P1&, const P2&, const P3&, const P4&, const P5&, const P6&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6) const
{
typedef list6<const P1&, const P2&, const P3&, const P4&, const P5&, const P6&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6, P7 &p7)
{
typedef list7<P1&, P2&, P3&, P4&, P5&, P6&, P7&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6, P7 &p7) const
{
typedef list7<P1&, P2&, P3&, P4&, P5&, P6&, P7&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7)
{
typedef list7<const P1&, const P2&, const P3&, const P4&, const P5&, const P6&, const P7&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7) const
{
typedef list7<const P1&, const P2&, const P3&, const P4&, const P5&, const P6&, const P7&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6, P7 &p7, P8 &p8)
{
typedef list8<P1&, P2&, P3&, P4&, P5&, P6&, P7&, P8&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7, p8));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6, P7 &p7, P8 &p8) const
{
typedef list8<P1&, P2&, P3&, P4&, P5&, P6&, P7&, P8&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7, p8));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8)
{
typedef list8<const P1&, const P2&, const P3&, const P4&, const P5&, const P6&, const P7&, const P8&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7, p8));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8) const
{
typedef list8<const P1&, const P2&, const P3&, const P4&, const P5&, const P6&, const P7&, const P8&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7, p8));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6, P7 &p7, P8 &p8, P9 &p9)
{
typedef list9<P1&, P2&, P3&, P4&, P5&, P6&, P7&, P8&, P9&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7, p8, p9));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
inline result_type operator()(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6, P7 &p7, P8 &p8, P9 &p9) const
{
typedef list9<P1&, P2&, P3&, P4&, P5&, P6&, P7&, P8&, P9&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7, p8, p9));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8, const P9 &p9)
{
typedef list9<const P1&, const P2&, const P3&, const P4&, const P5&, const P6&, const P7&, const P8&, const P9&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7, p8, p9));
}
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
inline result_type operator()(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8, const P9 &p9) const
{
typedef list9<const P1&, const P2&, const P3&, const P4&, const P5&, const P6&, const P7&, const P8&, const P9&> ll;
return l_(type<result_type>(), f_, ll(p1, p2, p3, p4, p5, p6, p7, p8, p9));
}
private:
F f_;
L l_;
};
struct bundling
{
typedef void (bundling::*BFn)(...) const;
mutable BFn invoke;
virtual ~bundling(){}
virtual bundling* clone() const = 0;
};
template<typename B, typename LP>
struct bind_bundling : bundling
{
const B b_;
explicit bind_bundling(const B &b) : b_(b) {bundling::invoke = reinterpret_cast<BFn>(&bind_bundling::invoke);}
virtual bundling* clone() const { return new bind_bundling(*this); }
typename B::result_type invoke(LP &p) { return b_.eval(p); }
};
struct bad_function_call : std::runtime_error
{
bad_function_call() : std::runtime_error("call to empty function") {}
};
struct callback_base
{
callback_base() { b_ = 0; }
~callback_base() { delete b_;}
callback_base(const callback_base &other) { if (other.b_) b_ = other.b_->clone(); }
callback_base& operator=(const callback_base &other) { delete b_; b_ = other.b_ ? other.b_->clone() : other.b_; return *this; }
void clear() { b_ = 0; }
bool empty() const { return !b_; }
void swap(callback_base &other) {const bundling *t = b_; b_ = other.b_; other.b_ = t; }
const bundling *b_;
};
inline bool operator==(const callback_base &r, const callback_base &l)
{
return !(r.b_ && l.b_) ? r.b_ == l.b_ : r.b_->invoke == l.b_->invoke;
}
template<typename R, typename L>
struct callback_sign : callback_base
{
typedef L LP;
typedef R (bundling::*Fn)(LP&) const;
};
template<typename S> struct callback{};
template<typename R>
struct callback<R()> : callback_sign<R, list0>
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()() const { return b_ ? (b_->*(reinterpret_cast<Fn>(b_->invoke)))((LP())) : throw bad_function_call(); }
};
template<typename R, typename P1>
struct callback<R(P1)> : callback_sign<R, list1<P1> >
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()(P1 p1) const { return b_ ? (b_->*(reinterpret_cast<Fn>(b_->invoke)))(LP(p1)) : throw bad_function_call(); }
};
template<typename R, typename P1, typename P2>
struct callback<R(P1, P2)> : callback_sign<R, list2<P1, P2> >
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()(P1 p1, P2 p2) const { return b_ ? (b_->*(reinterpret_cast<Fn>(b_->invoke)))(LP(p1, p2)) : throw bad_function_call(); }
};
template<typename R, typename P1, typename P2, typename P3>
struct callback<R(P1, P2, P3)> : callback_sign<R, list3<P1, P2, P3> >
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()(P1 p1, P2 p2, P3 p3) const { return b_ ? (b_->*(reinterpret_cast<Fn>(b_->invoke)))(LP(p1, p2, p3)) : throw bad_function_call(); }
};
template<typename R, typename P1, typename P2, typename P3, typename P4>
struct callback<R(P1, P2, P3, P4)> : callback_sign<R, list4<P1, P2, P3, P4> >
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { return b_ ? (b_->*(reinterpret_cast<Fn>(b_->invoke)))(LP(p1, p2, p3, p4)) : throw bad_function_call(); }
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5>
struct callback<R(P1, P2, P3, P4, P5)> : callback_sign<R, list5<P1, P2, P3, P4, P5> >
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const { return b_ ? (b_->*(reinterpret_cast<Fn>(b_->invoke)))(LP(p1, p2, p3, p4, p5)) : throw bad_function_call(); }
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
struct callback<R(P1, P2, P3, P4, P5, P6)> : callback_sign<R, list6<P1, P2, P3, P4, P5, P6> >
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const { return b_ ? (b_->*(reinterpret_cast<Fn>(b_->invoke)))(LP(p1, p2, p3, p4, p5, p6)) : throw bad_function_call(); }
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
struct callback<R(P1, P2, P3, P4, P5, P6, P7)> : callback_sign<R, list7<P1, P2, P3, P4, P5, P6, P7> >
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const { return b_ ? (b_->*(reinterpret_cast<Fn>(b_->invoke)))(LP(p1, p2, p3, p4, p5, p6, p7)) : throw bad_function_call(); }
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
struct callback<R(P1, P2, P3, P4, P5, P6, P7, P8)> : callback_sign<R, list8<P1, P2, P3, P4, P5, P6, P7, P8> >
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const { return b_ ? (b_->*(reinterpret_cast<Fn>(b_->invoke)))(LP(p1, p2, p3, p4, p5, p6, p7, p8)) : throw bad_function_call(); }
};
template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
struct callback<R(P1, P2, P3, P4, P5, P6, P7, P8, P9)> : callback_sign<R, list9<P1, P2, P3, P4, P5, P6, P7, P8, P9> >
{
callback() {}
template<typename B>
callback(const B &b) { b_ = new bind_bundling<B, LP>(b); }
template<typename B>
callback& operator=(const B &b) { delete b_; b_ = new bind_bundling<B, LP>(b); return *this; }
R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) const { b_ ? return (b_->*(reinterpret_cast<Fn>(b_->invoke)))(LP(p1, p2, p3, p4, p5, p6, p7, p8, p9)) : throw bad_function_call(); }
};
} // namespace bi
# ifdef _MSC_VER
# pragma warning(default: 4512) // assignment operator could not be generated
# pragma warning(pop)
# endif
#endif // bind_h__
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef INIFILEMANAGER_H
#define INIFILEMANAGER_H
#include "WNCLoopList.h"
//#include "EBaseFunctions.h"
#include <string>
#include <sstream>
#include <ctype.h>
using namespace std;
class IniSectionInfo;
class IniFileManager;
typedef unsigned char u_char;
#ifndef INI_CRLF
#define INI_CRLF "\r\n"
#endif
/*
* This array is designed for mapping upper and lower case letter
* together for a case independent comparison. The mappings are
* based upon ascii character sequences.
*/
int strcasecmp(const char *s1, const char* s2);
class NoCase
{
public:
static bool compare(const string& x, const string& y);
};
class IniKeyInfo
{
public:
IniKeyInfo();
inline void SetSection(IniSectionInfo* pSection) { m_pSection = pSection; }
inline IniSectionInfo* GetSection() const { return m_pSection; }
inline string& KeyName() { return m_strKeyName; }
inline string& KeyValue() { return m_strKeyValue; }
inline string KeyNameEx() { return m_strKeyTrimLeft + m_strKeyName + m_strKeyTrimRight; }
inline string KeyValueEx() { return m_strValueTrimLeft + m_strKeyValue + m_strValueTrimRight; }
inline void SetLong(long lKeyValue) {ostringstream tempstream;tempstream << lKeyValue;m_strKeyValue=tempstream.str();/*ww m_strKeyValue.Format(("%d"), lKeyValue);*/ }
inline void SetULong(unsigned long ulKeyValue) { ostringstream tempstream;tempstream << ulKeyValue;m_strKeyValue=tempstream.str();/*m_strKeyValue.Format(("%u"), ulKeyValue);*/}
inline void SetHex(long lKeyValue) { ostringstream tempstream;tempstream << hex << lKeyValue;m_strKeyValue=tempstream.str();/*m_strKeyValue.Format(("%X"), lKeyValue);*/ }
inline void SetUHex(unsigned long ulKeyValue) {ostringstream tempstream;tempstream << hex << ulKeyValue;m_strKeyValue=tempstream.str();/* m_strKeyValue.Format(("%X"), ulKeyValue); */}
inline void SetDouble(double dblKeyValue) {ostringstream tempstream;tempstream << dblKeyValue;m_strKeyValue=tempstream.str();}
inline void SetString(const char* lpKeyValue) {ostringstream tempstream;tempstream << lpKeyValue;m_strKeyValue=tempstream.str(); /*m_strKeyValue = lpKeyValue; */}
void SetKeyName(const char* lpKeyName, bool bDoTrim = true);
void SetKeyValue(const char* lpKeyValue, bool bDoTrim = true);
void SetMultiLineString(const char* lpKeyValue);
long ToLong(long lDefault = 0);
unsigned long ToULong(unsigned long ulDefault = 0);
long ToHex(long lDefault = 0);
unsigned long ToUHex(unsigned long ulDefault = 0);
double ToDouble(double dblDefault = 0.0);
string ToString(const char* lpDefault = (""));
string ToMultiLineString(const char* lpDefault = (""));
inline string GetText(); //{ return m_strKeyName == ("")?m_strKeyValue:(m_strKeyName + ('=') + m_strKeyValue); }
inline string GetTextEx(); //{ return (m_strKeyName == (""))?((m_strKeyValue == (""))?(""):(("\r\n") + m_strKeyValue)):(("\r\n") + m_strKeyName + ('=') + m_strKeyValue); }
protected:
void TrimAndGetTrimValue(string& strSrc, string& strTrimLeft, string& strTrimRight);
const char* SplitStrP();
string& SplitStrR();
protected:
string m_strKeyName;
string m_strKeyValue;
string m_strKeyTrimLeft;
string m_strKeyTrimRight;
string m_strValueTrimLeft;
string m_strValueTrimRight;
//unsigned int m_uKeyNameLeftSpaceCount;
//unsigned int m_uKeyNameRightSpaceCount;
//unsigned int m_uKeyValueLeftSpaceCount;
//unsigned int m_uKeyValueRightSpaceCount;
IniSectionInfo* m_pSection;
};
typedef IniKeyInfo* PIniKeyInfo;
class IniSectionInfo : public WNCLoopList<IniKeyInfo>
{
public:
IniSectionInfo();
inline string& SectionName() { return m_strSectionName; }
inline void SetManager(IniFileManager* pManager) { m_pManager = pManager; }
inline IniFileManager* GetManager() { return m_pManager; }
inline PIniKeyInfo AddKey(const char* lpKeyName) { return GetKey(lpKeyName, true); }
PIniKeyInfo AddKey(const char* lpKeyName, const char* lpKeyValue, bool bReplace = true);
PIniKeyInfo AddKeyEx(const char* lpKeyName);
PIniKeyInfo AddKeyEx(const char* lpKeyName, const char* lpKeyValue);
PIniKeyInfo ParseData(const char* lpData, bool bReplace = true);
PIniKeyInfo ParseDataEx(const char* lpData);
PIniKeyInfo GetKey(const char* lpKeyName, bool bAdd = false);
long ToLong(const char* lpKeyName, long lDefault = 0);
unsigned long ToULong(const char* lpKeyName, unsigned long ulDefault = 0);
long ToHex(const char* lpKeyName, long lDefault = 0);
unsigned long ToUHex(const char* lpKeyName, unsigned long ulDefault = 0);
double ToDouble(const char* lpKeyName, double dblDefault = 0.0);
string ToString(const char* lpKeyName, const char* lpDefault = (""));
string ToMultiLineString(const char* lpKeyName, const char* lpDefault = (""));
inline void SetLong(const char* lpKeyName, long lKeyValue) { AddKey(lpKeyName)->SetLong(lKeyValue); }
inline void SetULong(const char* lpKeyName, unsigned long ulKeyValue) { AddKey(lpKeyName)->SetULong(ulKeyValue); }
inline void SetHex(const char* lpKeyName, long lKeyValue) { AddKey(lpKeyName)->SetHex(lKeyValue); }
inline void SetUHex(const char* lpKeyName, unsigned long ulKeyValue) { AddKey(lpKeyName)->SetUHex(ulKeyValue); }
inline void SetDouble(const char* lpKeyName, double dblKeyValue) { AddKey(lpKeyName)->SetDouble(dblKeyValue); }
inline void SetString(const char* lpKeyName, const char* lpKeyValue) { AddKey(lpKeyName)->SetString(lpKeyValue); }
inline void SetMultiLineString(const char* lpKeyName, const char* lpKeyValue) { AddKey(lpKeyName)->SetMultiLineString(lpKeyValue); }
string GetText();
string GetTextEx();
void JoinTo(IniSectionInfo& tarSection);
inline const char* SplitStrP();
inline string& SplitStrR();
protected:
string m_strSectionName;
IniFileManager* m_pManager;
};
typedef IniSectionInfo* PIniSectionInfo;
class IniFileManager : public WNCLoopList<IniSectionInfo>
{
public:
IniFileManager(bool bAutoSave = false);
virtual ~IniFileManager();
virtual inline PIniSectionInfo AddSection(const char* lpSectionName, bool bAdd = true) { return GetSection(lpSectionName, bAdd); }
virtual PIniSectionInfo AddSectionEx(const char* lpSectionName);
virtual PIniSectionInfo GetSection(const char* lpSectionName, bool bAdd = false);
virtual bool ParseSectionName(const char* lpData, string& strSectionName);
virtual PIniSectionInfo ParseLine(const char* lpData, bool* pbReplace = NULL);
virtual bool ParseData(const char* lpData, bool* pbReplace = NULL);
virtual bool ParseFile(const char* lpFileName, bool* pbReplace = NULL);
virtual bool SaveFile(const char* lpFileName = NULL, bool* pbUnicode = NULL);
virtual bool SaveFileEx(const char* lpFileName = NULL, bool* pbUnicode = NULL);
virtual long ToLong(const char* lpSectionName, const char* lpKeyName, long lDefault = 0);
virtual unsigned long ToULong(const char* lpSectionName, const char* lpKeyName, unsigned long ulDefault = 0);
virtual long ToHex(const char* lpSectionName, const char* lpKeyName, long lDefault = 0);
virtual unsigned long ToUHex(const char* lpSectionName, const char* lpKeyName, unsigned long ulDefault = 0);
virtual double ToDouble(const char* lpSectionName, const char* lpKeyName, double dblDefault = 0.0);
virtual string ToString(const char* lpSectionName, const char* lpKeyName, const char* lpDefault = (""));
virtual string ToMultiLineString(const char* lpSectionName, const char* lpKeyName, const char* lpDefault = (""));
virtual inline void SetLong(const char* lpSectionName, const char* lpKeyName, long lKeyValue) { AddSection(lpSectionName)->SetLong(lpKeyName, lKeyValue); }
virtual inline void SetULong(const char* lpSectionName, const char* lpKeyName, unsigned long ulKeyValue) { AddSection(lpSectionName)->SetULong(lpKeyName, ulKeyValue); }
virtual inline void SetHex(const char* lpSectionName, const char* lpKeyName, long lKeyValue) { AddSection(lpSectionName)->SetHex(lpKeyName, lKeyValue); }
virtual inline void SetUHex(const char* lpSectionName, const char* lpKeyName, unsigned long ulKeyValue) { AddSection(lpSectionName)->SetUHex(lpKeyName, ulKeyValue); }
virtual inline void SetDouble(const char* lpSectionName, const char* lpKeyName, double dblKeyValue) { AddSection(lpSectionName)->SetDouble(lpKeyName, dblKeyValue); }
virtual inline void SetString(const char* lpSectionName, const char* lpKeyName, const char* lpKeyValue) { AddSection(lpSectionName)->SetString(lpKeyName, lpKeyValue); }
virtual inline void SetMultiLineString(const char* lpSectionName, const char* lpKeyName, const char* lpKeyValue) { AddSection(lpSectionName)->SetMultiLineString(lpKeyName, lpKeyValue); }
virtual string GetText();
virtual string GetTextEx();
virtual void JoinTo(IniFileManager& tarIniManager);
virtual void SetAutoSave(bool bAutoSave);
virtual inline bool GetAutoSave() { return m_bAutoSave; }
//保存GetTextEx的结果
virtual void SaveState();
//判断文件内容是否改变
//带Ex的函数只检查mstrContentSaved与GetTextEx的内容是否相同
virtual bool DidStateChanged();
virtual bool DidStateChangedEx();
inline const char* SplitStrP();
inline string& SplitStrR();
protected:
string mstrIniFileName;
string mstrLineSplit; //行分割符,用于保存文件,解析数据时自动记录
bool m_bUnicode;
bool m_bAutoSave;
string mstrContentSaved;
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
// MD5Checksum.h: interface for the MD5Checksum class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_)
#define AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/****************************************************************************************
This software is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
Incorporation of this statement is a condition of use; please see the RSA
Data Security Inc copyright notice below:-
Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
rights reserved.
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.
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.
*****************************************************************************************/
/****************************************************************************************
This implementation of the RSA MD5 Algorithm was written by Langfine Ltd.
Langfine Ltd 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.
In addition to the above, Langfine make no warrant or assurances regarding the
accuracy of this implementation of the MD5 checksum algorithm nor any assurances regarding
its suitability for any purposes.
This implementation may be used freely provided that Langfine is credited
in a copyright or similar notices (eg, RSA MD5 Algorithm implemented by Langfine
Ltd.) and provided that the RSA Data Security notices are complied with.
Langfine may be contacted at mail@langfine.com
*/
/*****************************************************************************************
CLASS: CMD5Checksum
DESCRIPTION: Implements the "RSA Data Security, Inc. MD5 Message-Digest Algorithm".
NOTES: Calculates the RSA MD5 checksum for a file or congiguous array of data.
Below are extracts from a memo on The MD5 Message-Digest Algorithm by R. Rivest of MIT
Laboratory for Computer Science and RSA Data Security, Inc., April 1992.
1. Executive Summary
This document describes the MD5 message-digest algorithm. The
algorithm takes as input a message of arbitrary length and produces
as output a 128-bit "fingerprint" or "message digest" of the input.
It is conjectured that it is computationally infeasible to produce
two messages having the same message digest, or to produce any
message having a given prespecified target message digest. The MD5
algorithm is intended for digital signature applications, where a
large file must be "compressed" in a secure manner before being
encrypted with a private (secret) key under a public-key cryptosystem
such as RSA.
The MD5 algorithm is designed to be quite fast on 32-bit machines. In
addition, the MD5 algorithm does not require any large substitution
tables; the algorithm can be coded quite compactly.
The MD5 algorithm is an extension of the MD4 message-digest algorithm
1,2]. MD5 is slightly slower than MD4, but is more "conservative" in
design. MD5 was designed because it was felt that MD4 was perhaps
being adopted for use more quickly than justified by the existing
critical review; because MD4 was designed to be exceptionally fast,
it is "at the edge" in terms of risking successful cryptanalytic
attack. MD5 backs off a bit, giving up a little in speed for a much
greater likelihood of ultimate security. It incorporates some
suggestions made by various reviewers, and contains additional
optimizations. The MD5 algorithm is being placed in the public domain
for review and possible adoption as a standard.
2. Terminology and Notation
In this document a "word" is a 32-bit quantity and a "byte" is an
eight-bit quantity. A sequence of bits can be interpreted in a
natural manner as a sequence of bytes, where each consecutive group
of eight bits is interpreted as a byte with the high-order (most
significant) bit of each byte listed first. Similarly, a sequence of
bytes can be interpreted as a sequence of 32-bit words, where each
consecutive group of four bytes is interpreted as a word with the
low-order (least significant) byte given first.
Let x_i denote "x sub i". If the subscript is an expression, we
surround it in braces, as in x_{i+1}. Similarly, we use ^ for
superscripts (exponentiation), so that x^i denotes x to the i-th power.
Let the symbol "+" denote addition of words (i.e., modulo-2^32
addition). Let X <<< s denote the 32-bit value obtained by circularly
shifting (rotating) X left by s bit positions. Let not(X) denote the
bit-wise complement of X, and let X v Y denote the bit-wise OR of X
and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY
denote the bit-wise AND of X and Y.
3. MD5 Algorithm Description
We begin by supposing that we have a b-bit message as input, and that
we wish to find its message digest. Here b is an arbitrary
nonnegative integer; b may be zero, it need not be a multiple of
eight, and it may be arbitrarily large. We imagine the bits of the
message written down as follows: m_0 m_1 ... m_{b-1}
The following five steps are performed to compute the message digest
of the message.
3.1 Step 1. Append Padding Bits
The message is "padded" (extended) so that its length (in bits) is
congruent to 448, modulo 512. That is, the message is extended so
that it is just 64 bits shy of being a multiple of 512 bits long.
Padding is always performed, even if the length of the message is
already congruent to 448, modulo 512.
Padding is performed as follows: a single "1" bit is appended to the
message, and then "0" bits are appended so that the length in bits of
the padded message becomes congruent to 448, modulo 512. In all, at
least one bit and at most 512 bits are appended.
3.2 Step 2. Append Length
A 64-bit representation of b (the length of the message before the
padding bits were added) is appended to the result of the previous
step. In the unlikely event that b is greater than 2^64, then only
the low-order 64 bits of b are used. (These bits are appended as two
32-bit words and appended low-order word first in accordance with the
previous conventions.)
At this point the resulting message (after padding with bits and with
b) has a length that is an exact multiple of 512 bits. Equivalently,
this message has a length that is an exact multiple of 16 (32-bit)
words. Let M[0 ... N-1] denote the words of the resulting message,
where N is a multiple of 16.
3.3 Step 3. Initialize MD Buffer
A four-word buffer (A,B,C,D) is used to compute the message digest.
Here each of A, B, C, D is a 32-bit register. These registers are
initialized to the following values in hexadecimal, low-order bytes first):
word A: 01 23 45 67 word B: 89 ab cd ef
word C: fe dc ba 98 word D: 76 54 32 10
3.4 Step 4. Process Message in 16-Word Blocks
We first define four auxiliary functions that each take as input
three 32-bit words and produce as output one 32-bit word.
F(X,Y,Z) = XY v not(X) Z G(X,Y,Z) = XZ v Y not(Z)
H(X,Y,Z) = X xor Y xor Z I(X,Y,Z) = Y xor (X v not(Z))
In each bit position F acts as a conditional: if X then Y else Z.
The function F could have been defined using + instead of v since XY
and not(X)Z will never have 1's in the same bit position.) It is
interesting to note that if the bits of X, Y, and Z are independent
and unbiased, the each bit of F(X,Y,Z) will be independent and unbiased.
The functions G, H, and I are similar to the function F, in that they
act in "bitwise parallel" to produce their output from the bits of X,
Y, and Z, in such a manner that if the corresponding bits of X, Y,
and Z are independent and unbiased, then each bit of G(X,Y,Z),
H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that
the function H is the bit-wise "xor" or "parity" function of its inputs.
This step uses a 64-element table T[1 ... 64] constructed from the
sine function. Let T[i] denote the i-th element of the table, which
is equal to the integer part of 4294967296 times abs(sin(i)), where i
is in radians. The elements of the table are given in the appendix.
Do the following:
//Process each 16-word block.
For i = 0 to N/16-1 do // Copy block i into X.
For j = 0 to 15 do
Set X[j] to M[i*16+j].
end //of loop on j
// Save A as AA, B as BB, C as CC, and D as DD.
AA = A BB = B
CC = C DD = D
// Round 1.
// Let [abcd k s i] denote the operation
// a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s).
// Do the following 16 operations.
[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4]
[ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8]
[ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12]
[ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]
// Round 2.
// Let [abcd k s i] denote the operation
// a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s).
// Do the following 16 operations.
[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20]
[ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]
[ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28]
[ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]
// Round 3.
// Let [abcd k s t] denote the operation
// a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s).
// Do the following 16 operations.
[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]
[ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40]
[ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]
[ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]
// Round 4.
// Let [abcd k s t] denote the operation
// a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s).
// Do the following 16 operations.
[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]
[ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]
[ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]
[ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]
// Then perform the following additions. (That is increment each
// of the four registers by the value it had before this block
// was started.)
A = A + AA B = B + BB C = C + CC D = D + DD
end // of loop on i
3.5 Step 5. Output
The message digest produced as output is A, B, C, D. That is, we
begin with the low-order byte of A, and end with the high-order byte of D.
This completes the description of MD5.
Summary
The MD5 message-digest algorithm is simple to implement, and provides
a "fingerprint" or message digest of a message of arbitrary length.
It is conjectured that the difficulty of coming up with two messages
having the same message digest is on the order of 2^64 operations,
and that the difficulty of coming up with any message having a given
message digest is on the order of 2^128 operations. The MD5 algorithm
has been carefully scrutinized for weaknesses. It is, however, a
relatively new algorithm and further security analysis is of course
justified, as is the case with any new proposal of this sort.
5. Differences Between MD4 and MD5
The following are the differences between MD4 and MD5:
1. A fourth round has been added.
2. Each step now has a unique additive constant.
3. The function g in round 2 was changed from (XY v XZ v YZ) to
(XZ v Y not(Z)) to make g less symmetric.
4. Each step now adds in the result of the previous step. This
promotes a faster "avalanche effect".
5. The order in which input words are accessed in rounds 2 and
3 is changed, to make these patterns less like each other.
6. The shift amounts in each round have been approximately
optimized, to yield a faster "avalanche effect." The shifts in
different rounds are distinct.
References
[1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and
RSA Data Security, Inc., April 1992.
[2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes
and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90
Proceedings, pages 303-311, Springer-Verlag, 1991.
[3] CCITT Recommendation X.509 (1988), "The Directory -
Authentication Framework."APPENDIX A - Reference Implementation
The level of security discussed in this memo is considered to be
sufficient for implementing very high security hybrid digital-
signature schemes based on MD5 and a public-key cryptosystem.
Author's Address
Ronald L. Rivest Massachusetts Institute of Technology
Laboratory for Computer Science NE43-324 545 Technology Square
Cambridge, MA 02139-1986 Phone: (617) 253-5880
EMail: rivest@theory.lcs.mit.edu
*****************************************************************************************/
#include <string>
#include<fstream>
using namespace std;
class CMD5Checksum
{
public:
string test;
//interface functions for the RSA MD5 calculation
static string GetMD5(unsigned char* pBuf, unsigned int nLength);
static string GetMD5(fstream& File);
static string GetMD5(const string& strFilePath);
protected:
//constructor/destructor
CMD5Checksum();
virtual ~CMD5Checksum() {};
//RSA MD5 implementation
void Transform(unsigned char Block[64]);
void Update(unsigned char* Input, unsigned long nInputLen);
string Final();
inline unsigned long RotateLeft(unsigned long x, int n);
inline void FF( unsigned long& A, unsigned long B, unsigned long C, unsigned long D, unsigned long X, unsigned long S, unsigned long T);
inline void GG( unsigned long& A, unsigned long B, unsigned long C, unsigned long D, unsigned long X, unsigned long S, unsigned long T);
inline void HH( unsigned long& A, unsigned long B, unsigned long C, unsigned long D, unsigned long X, unsigned long S, unsigned long T);
inline void II( unsigned long& A, unsigned long B, unsigned long C, unsigned long D, unsigned long X, unsigned long S, unsigned long T);
//utility functions
void DWordToByte(unsigned char* Output, unsigned long* Input, unsigned int nLength);
void ByteToDWord(unsigned long* Output, unsigned char* Input, unsigned int nLength);
private:
unsigned char m_lpszBuffer[64]; //input buffer
unsigned long m_nCount[2]; //number of bits, modulo 2^64 (lsb first)
unsigned long m_lMD5[4]; //MD5 checksum
};
#endif // !defined(AFX_MD5CHECKSUM_H__2BC7928E_4C15_11D3_B2EE_A4A60E20D2C3__INCLUDED_)
/*utf8解析行 Don't remove or modify this first line!*/
//MD5ChecksumDefines.h : MD5 Checksum constants
//Magic initialization constants
#define MD5_INIT_STATE_0 0x67452301
#define MD5_INIT_STATE_1 0xefcdab89
#define MD5_INIT_STATE_2 0x98badcfe
#define MD5_INIT_STATE_3 0x10325476
//Constants for Transform routine.
#define MD5_S11 7
#define MD5_S12 12
#define MD5_S13 17
#define MD5_S14 22
#define MD5_S21 5
#define MD5_S22 9
#define MD5_S23 14
#define MD5_S24 20
#define MD5_S31 4
#define MD5_S32 11
#define MD5_S33 16
#define MD5_S34 23
#define MD5_S41 6
#define MD5_S42 10
#define MD5_S43 15
#define MD5_S44 21
//Transformation Constants - Round 1
#define MD5_T01 0xd76aa478 //Transformation Constant 1
#define MD5_T02 0xe8c7b756 //Transformation Constant 2
#define MD5_T03 0x242070db //Transformation Constant 3
#define MD5_T04 0xc1bdceee //Transformation Constant 4
#define MD5_T05 0xf57c0faf //Transformation Constant 5
#define MD5_T06 0x4787c62a //Transformation Constant 6
#define MD5_T07 0xa8304613 //Transformation Constant 7
#define MD5_T08 0xfd469501 //Transformation Constant 8
#define MD5_T09 0x698098d8 //Transformation Constant 9
#define MD5_T10 0x8b44f7af //Transformation Constant 10
#define MD5_T11 0xffff5bb1 //Transformation Constant 11
#define MD5_T12 0x895cd7be //Transformation Constant 12
#define MD5_T13 0x6b901122 //Transformation Constant 13
#define MD5_T14 0xfd987193 //Transformation Constant 14
#define MD5_T15 0xa679438e //Transformation Constant 15
#define MD5_T16 0x49b40821 //Transformation Constant 16
//Transformation Constants - Round 2
#define MD5_T17 0xf61e2562 //Transformation Constant 17
#define MD5_T18 0xc040b340 //Transformation Constant 18
#define MD5_T19 0x265e5a51 //Transformation Constant 19
#define MD5_T20 0xe9b6c7aa //Transformation Constant 20
#define MD5_T21 0xd62f105d //Transformation Constant 21
#define MD5_T22 0x02441453 //Transformation Constant 22
#define MD5_T23 0xd8a1e681 //Transformation Constant 23
#define MD5_T24 0xe7d3fbc8 //Transformation Constant 24
#define MD5_T25 0x21e1cde6 //Transformation Constant 25
#define MD5_T26 0xc33707d6 //Transformation Constant 26
#define MD5_T27 0xf4d50d87 //Transformation Constant 27
#define MD5_T28 0x455a14ed //Transformation Constant 28
#define MD5_T29 0xa9e3e905 //Transformation Constant 29
#define MD5_T30 0xfcefa3f8 //Transformation Constant 30
#define MD5_T31 0x676f02d9 //Transformation Constant 31
#define MD5_T32 0x8d2a4c8a //Transformation Constant 32
//Transformation Constants - Round 3
#define MD5_T33 0xfffa3942 //Transformation Constant 33
#define MD5_T34 0x8771f681 //Transformation Constant 34
#define MD5_T35 0x6d9d6122 //Transformation Constant 35
#define MD5_T36 0xfde5380c //Transformation Constant 36
#define MD5_T37 0xa4beea44 //Transformation Constant 37
#define MD5_T38 0x4bdecfa9 //Transformation Constant 38
#define MD5_T39 0xf6bb4b60 //Transformation Constant 39
#define MD5_T40 0xbebfbc70 //Transformation Constant 40
#define MD5_T41 0x289b7ec6 //Transformation Constant 41
#define MD5_T42 0xeaa127fa //Transformation Constant 42
#define MD5_T43 0xd4ef3085 //Transformation Constant 43
#define MD5_T44 0x04881d05 //Transformation Constant 44
#define MD5_T45 0xd9d4d039 //Transformation Constant 45
#define MD5_T46 0xe6db99e5 //Transformation Constant 46
#define MD5_T47 0x1fa27cf8 //Transformation Constant 47
#define MD5_T48 0xc4ac5665 //Transformation Constant 48
//Transformation Constants - Round 4
#define MD5_T49 0xf4292244 //Transformation Constant 49
#define MD5_T50 0x432aff97 //Transformation Constant 50
#define MD5_T51 0xab9423a7 //Transformation Constant 51
#define MD5_T52 0xfc93a039 //Transformation Constant 52
#define MD5_T53 0x655b59c3 //Transformation Constant 53
#define MD5_T54 0x8f0ccc92 //Transformation Constant 54
#define MD5_T55 0xffeff47d //Transformation Constant 55
#define MD5_T56 0x85845dd1 //Transformation Constant 56
#define MD5_T57 0x6fa87e4f //Transformation Constant 57
#define MD5_T58 0xfe2ce6e0 //Transformation Constant 58
#define MD5_T59 0xa3014314 //Transformation Constant 59
#define MD5_T60 0x4e0811a1 //Transformation Constant 60
#define MD5_T61 0xf7537e82 //Transformation Constant 61
#define MD5_T62 0xbd3af235 //Transformation Constant 62
#define MD5_T63 0x2ad7d2bb //Transformation Constant 63
#define MD5_T64 0xeb86d391 //Transformation Constant 64
//Null data (except for first BYTE) used to finalise the checksum calculation
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
};
/*utf8解析行 Don't remove or modify this first line!*/
// Markup.h: interface for the CMarkup class.
//
// Markup Release 11.5
// Copyright (C) 2011 First Objective Software, Inc. All rights reserved
// Go to www.firstobject.com for the latest CMarkup and EDOM documentation
// Use in commercial applications requires written permission
// This software is provided "as is", with no warranty.
#if !defined(_MARKUP_H_INCLUDED_)
#define _MARKUP_H_INCLUDED_
#include <stdlib.h>
#include <string.h> // memcpy, memset, strcmp...
// Major build options
// MARKUP_WCHAR wide char (2-byte UTF-16 on Windows, 4-byte UTF-32 on Linux and OS X)
// MARKUP_MBCS ANSI/double-byte strings on Windows
// MARKUP_STL (default except VC++) use STL strings instead of MFC strings
// MARKUP_SAFESTR to use string _s functions in VC++ 2005 (_MSC_VER >= 1400)
// MARKUP_WINCONV (default for VC++) for Windows API character conversion
// MARKUP_ICONV (default for GNU) for character conversion on Linux and OS X and other platforms
// MARKUP_STDCONV to use neither WINCONV or ICONV, falls back to setlocale based conversion for ANSI
//
#if ! defined(MARKUP_WINDOWS)
#if defined(_WIN32) || defined(WIN32)
#define MARKUP_WINDOWS
#endif // WIN32 or _WIN32
#endif // not MARKUP_WINDOWS
#if _MSC_VER > 1000 // VC++
#pragma once
#if ! defined(MARKUP_SAFESTR) // not VC++ safe strings
#pragma warning(disable:4996) // VC++ 2005 deprecated function warnings
#endif // not VC++ safe strings
#if defined(MARKUP_STL) && _MSC_VER < 1400 // STL pre VC++ 2005
#pragma warning(disable:4786) // std::string long names
#endif // VC++ 2005 STL
#else // not VC++
#if ! defined(MARKUP_STL)
#define MARKUP_STL
#endif // not STL
#if defined(__GNUC__) && ! defined(MARKUP_ICONV) && ! defined(MARKUP_STDCONV) && ! defined(MARKUP_WINCONV)
#if ! defined(MARKUP_WINDOWS)
#define MARKUP_ICONV
#endif // not Windows
#endif // GNUC and not ICONV not STDCONV not WINCONV
#endif // not VC++
#if (defined(_UNICODE) || defined(UNICODE)) && ! defined(MARKUP_WCHAR)
#define MARKUP_WCHAR
#endif // _UNICODE or UNICODE
#if (defined(_MBCS) || defined(MBCS)) && ! defined(MARKUP_MBCS)
#define MARKUP_MBCS
#endif // _MBCS and not MBCS
#if ! defined(MARKUP_SIZEOFWCHAR)
#if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000
#define MARKUP_SIZEOFWCHAR 4
#else // sizeof(wchar_t) != 4
#define MARKUP_SIZEOFWCHAR 2
#endif // sizeof(wchar_t) != 4
#endif // not MARKUP_SIZEOFWCHAR
#if ! defined(MARKUP_WINCONV) && ! defined(MARKUP_STDCONV) && ! defined(MARKUP_ICONV)
#define MARKUP_WINCONV
#endif // not WINCONV not STDCONV not ICONV
#if ! defined(MARKUP_FILEBLOCKSIZE)
#define MARKUP_FILEBLOCKSIZE 16384
#endif
// Text type and function defines (compiler and build-option dependent)
//
#define MCD_ACP 0
#define MCD_UTF8 65001
#define MCD_UTF16 1200
#define MCD_UTF32 65005
#if defined(MARKUP_WCHAR)
#define MCD_CHAR wchar_t
#define MCD_PCSZ const wchar_t*
#define MCD_PSZLEN (int)wcslen
#define MCD_PSZCHR wcschr
#define MCD_PSZSTR wcsstr
#define MCD_PSZTOL wcstol
#if defined(MARKUP_SAFESTR) // VC++ safe strings
#define MCD_SSZ(sz) sz,(sizeof(sz)/sizeof(MCD_CHAR))
#define MCD_PSZCPY(sz,p) wcscpy_s(MCD_SSZ(sz),p)
#define MCD_PSZNCPY(sz,p,n) wcsncpy_s(MCD_SSZ(sz),p,n)
#define MCD_SPRINTF swprintf_s
#define MCD_FOPEN(f,n,m) {if(_wfopen_s(&f,n,m)!=0)f=NULL;}
#else // not VC++ safe strings
#if defined(__GNUC__) && ! defined(MARKUP_WINDOWS) // non-Windows GNUC
#define MCD_SSZ(sz) sz,(sizeof(sz)/sizeof(MCD_CHAR))
#else // not non-Windows GNUC
#define MCD_SSZ(sz) sz
#endif // not non-Windows GNUC
#define MCD_PSZCPY wcscpy
#define MCD_PSZNCPY wcsncpy
#define MCD_SPRINTF swprintf
#define MCD_FOPEN(f,n,m) f=_wfopen(n,m)
#endif // not VC++ safe strings
#define MCD_T(s) L ## s
#if MARKUP_SIZEOFWCHAR == 4 // sizeof(wchar_t) == 4
#define MCD_ENC MCD_T("UTF-32")
#else // sizeof(wchar_t) == 2
#define MCD_ENC MCD_T("UTF-16")
#endif
#define MCD_CLEN(p) 1
#else // not MARKUP_WCHAR
#define MCD_CHAR char
#define MCD_PCSZ const char*
#define MCD_PSZLEN (int)strlen
#define MCD_PSZCHR strchr
#define MCD_PSZSTR strstr
#define MCD_PSZTOL strtol
#if defined(MARKUP_SAFESTR) // VC++ safe strings
#define MCD_SSZ(sz) sz,(sizeof(sz)/sizeof(MCD_CHAR))
#define MCD_PSZCPY(sz,p) strcpy_s(MCD_SSZ(sz),p)
#define MCD_PSZNCPY(sz,p,n) strncpy_s(MCD_SSZ(sz),p,n)
#define MCD_SPRINTF sprintf_s
#define MCD_FOPEN(f,n,m) {if(fopen_s(&f,n,m)!=0)f=NULL;}
#else // not VC++ safe strings
#define MCD_SSZ(sz) sz
#define MCD_PSZCPY strcpy
#define MCD_PSZNCPY strncpy
#define MCD_SPRINTF sprintf
#define MCD_FOPEN(f,n,m) f=fopen(n,m)
#endif // not VC++ safe strings
#define MCD_T(s) s
#if defined(MARKUP_MBCS) // MBCS/double byte
#define MCD_ENC MCD_T("")
#if defined(MARKUP_WINCONV)
#define MCD_CLEN(p) (int)_mbclen((const unsigned char*)p)
#else // not WINCONV
#define MCD_CLEN(p) (int)mblen(p,MB_CUR_MAX)
#endif // not WINCONV
#else // not MBCS/double byte
#define MCD_ENC MCD_T("UTF-8")
#define MCD_CLEN(p) 1
#endif // not MBCS/double byte
#endif // not MARKUP_WCHAR
#if _MSC_VER < 1000 // not VC++
#define MCD_STRERROR strerror(errno)
#endif // not VC++
// String type and function defines (compiler and build-option dependent)
// Define MARKUP_STL to use STL strings
//
#if defined(MARKUP_STL) // STL
#include <string>
#if defined(MARKUP_WCHAR)
#define MCD_STR std::wstring
#else // not MARKUP_WCHAR
#define MCD_STR std::string
#endif // not MARKUP_WCHAR
#define MCD_2PCSZ(s) s.c_str()
#define MCD_STRLENGTH(s) (int)s.size()
#define MCD_STRCLEAR(s) s.erase()
#define MCD_STRCLEARSIZE(s) MCD_STR t; s.swap(t)
#define MCD_STRISEMPTY(s) s.empty()
#define MCD_STRMID(s,n,l) s.substr(n,l)
#define MCD_STRASSIGN(s,p,n) s.assign(p,n)
#define MCD_STRCAPACITY(s) (int)s.capacity()
#define MCD_STRINSERTREPLACE(d,i,r,s) d.replace(i,r,s)
#define MCD_GETBUFFER(s,n) new MCD_CHAR[n+1]; if ((int)s.capacity()<(int)n) s.reserve(n)
#define MCD_RELEASEBUFFER(s,p,n) s.replace(0,s.size(),p,n); delete[]p
#define MCD_BLDRESERVE(s,n) s.reserve(n)
#define MCD_BLDCHECK(s,n,d) ;
#define MCD_BLDRELEASE(s) ;
#define MCD_BLDAPPENDN(s,p,n) s.append(p,n)
#define MCD_BLDAPPEND(s,p) s.append(p)
#define MCD_BLDAPPEND1(s,c) s+=(MCD_CHAR)(c)
#define MCD_BLDLEN(s) (int)s.size()
#define MCD_BLDTRUNC(s,n) s.resize(n)
#else // not STL, i.e. MFC
// afx.h provides CString, to avoid "WINVER not defined" #include stdafh.x in Markup.cpp
#include <afx.h>
#define MCD_STR CString
#define MCD_2PCSZ(s) ((MCD_PCSZ)s)
#define MCD_STRLENGTH(s) s.GetLength()
#define MCD_STRCLEAR(s) s.Empty()
#define MCD_STRCLEARSIZE(s) s=MCD_STR()
#define MCD_STRISEMPTY(s) s.IsEmpty()
#define MCD_STRMID(s,n,l) s.Mid(n,l)
#define MCD_STRASSIGN(s,p,n) memcpy(s.GetBuffer(n),p,(n)*sizeof(MCD_CHAR));s.ReleaseBuffer(n);
#define MCD_STRCAPACITY(s) (((CStringData*)((MCD_PCSZ)s)-1)->nAllocLength)
#define MCD_GETBUFFER(s,n) s.GetBuffer(n)
#define MCD_RELEASEBUFFER(s,p,n) s.ReleaseBuffer(n)
#define MCD_BLDRESERVE(s,n) MCD_CHAR*pD=s.GetBuffer(n); int nL=0
#define MCD_BLDCHECK(s,n,d) if(nL+(int)(d)>n){s.ReleaseBuffer(nL);n<<=2;pD=s.GetBuffer(n);}
#define MCD_BLDRELEASE(s) s.ReleaseBuffer(nL)
#define MCD_BLDAPPENDN(s,p,n) MCD_PSZNCPY(&pD[nL],p,n);nL+=n
#define MCD_BLDAPPEND(s,p) MCD_PSZCPY(&pD[nL],p);nL+=MCD_PSZLEN(p)
#define MCD_BLDAPPEND1(s,c) pD[nL++]=(MCD_CHAR)(c)
#define MCD_BLDLEN(s) nL
#define MCD_BLDTRUNC(s,n) nL=n
#endif // not STL
#define MCD_STRTOINT(s) MCD_PSZTOL(MCD_2PCSZ(s),NULL,10)
// Allow function args to accept string objects as constant string pointers
struct MCD_CSTR
{
MCD_CSTR() { pcsz=NULL; };
MCD_CSTR( MCD_PCSZ p ) { pcsz=p; };
MCD_CSTR( const MCD_STR& s ) { pcsz = MCD_2PCSZ(s); };
operator MCD_PCSZ() const { return pcsz; };
MCD_PCSZ pcsz;
};
// On Linux and OS X, filenames are not specified in wchar_t
#if defined(MARKUP_WCHAR) && defined(__GNUC__)
#undef MCD_FOPEN
#define MCD_FOPEN(f,n,m) f=fopen(n,m)
#define MCD_T_FILENAME(s) s
#define MCD_PCSZ_FILENAME const char*
struct MCD_CSTR_FILENAME
{
MCD_CSTR_FILENAME() { pcsz=NULL; };
MCD_CSTR_FILENAME( MCD_PCSZ_FILENAME p ) { pcsz=p; };
MCD_CSTR_FILENAME( const std::string& s ) { pcsz = s.c_str(); };
operator MCD_PCSZ_FILENAME() const { return pcsz; };
MCD_PCSZ_FILENAME pcsz;
};
#else // not WCHAR GNUC
#define MCD_CSTR_FILENAME MCD_CSTR
#define MCD_T_FILENAME MCD_T
#define MCD_PCSZ_FILENAME MCD_PCSZ
#endif // not WCHAR GNUC
// File fseek, ftell and offset type
#if defined(__GNUC__) && ! defined(MARKUP_WINDOWS) // non-Windows GNUC
#define MCD_FSEEK fseeko
#define MCD_FTELL ftello
#define MCD_INTFILEOFFSET off_t
#elif _MSC_VER >= 1000 && defined(MARKUP_HUGEFILE) // VC++ HUGEFILE
#if _MSC_VER < 1400 // before VC++ 2005
extern "C" int __cdecl _fseeki64(FILE *, __int64, int);
extern "C" __int64 __cdecl _ftelli64(FILE *);
#endif // before VC++ 2005
#define MCD_FSEEK _fseeki64
#define MCD_FTELL _ftelli64
#define MCD_INTFILEOFFSET __int64
#else // not non-Windows GNUC or VC++ HUGEFILE
#define MCD_FSEEK fseek
#define MCD_FTELL ftell
#define MCD_INTFILEOFFSET long
#endif // not non-Windows GNUC or VC++ HUGEFILE
// End of line choices: none, return, newline, or CRLF
#if defined(MARKUP_EOL_NONE)
#define MCD_EOL MCD_T("")
#elif defined(MARKUP_EOL_RETURN) // rare; only used on some old operating systems
#define MCD_EOL MCD_T("\r")
#elif defined(MARKUP_EOL_NEWLINE) // Unix standard
#define MCD_EOL MCD_T("\n")
#elif defined(MARKUP_EOL_CRLF) || defined(MARKUP_WINDOWS) // Windows standard
#define MCD_EOL MCD_T("\r\n")
#else // not Windows and not otherwise specified
#define MCD_EOL MCD_T("\n")
#endif // not Windows and not otherwise specified
#define MCD_EOLLEN (sizeof(MCD_EOL)/sizeof(MCD_CHAR)-1) // string length of MCD_EOL
struct FilePos;
struct TokenPos;
struct NodePos;
struct PathPos;
struct SavedPosMapArray;
struct ElemPosTree;
class CMarkup
{
public:
CMarkup() { x_InitMarkup(); SetDoc( NULL ); };
CMarkup( MCD_CSTR szDoc ) { x_InitMarkup(); SetDoc( szDoc ); };
CMarkup( int nFlags ) { x_InitMarkup(); SetDoc( NULL ); m_nDocFlags = nFlags; };
CMarkup( const CMarkup& markup ) { x_InitMarkup(); *this = markup; };
void operator=( const CMarkup& markup );
~CMarkup();
// Navigate
bool Load( MCD_CSTR_FILENAME szFileName );
bool SetDoc( MCD_PCSZ pDoc );
bool SetDoc( const MCD_STR& strDoc );
bool IsWellFormed();
bool FindElem( MCD_CSTR szName=NULL );
bool FindChildElem( MCD_CSTR szName=NULL );
bool IntoElem();
bool OutOfElem();
void ResetChildPos() { x_SetPos(m_iPosParent,m_iPos,0); };
void ResetMainPos() { x_SetPos(m_iPosParent,0,0); };
void ResetPos() { x_SetPos(0,0,0); };
MCD_STR GetTagName() const;
MCD_STR GetChildTagName() const { return x_GetTagName(m_iPosChild); };
MCD_STR GetData() { return x_GetData(m_iPos); };
MCD_STR GetChildData() { return x_GetData(m_iPosChild); };
MCD_STR GetElemContent() const { return x_GetElemContent(m_iPos); };
MCD_STR GetAttrib( MCD_CSTR szAttrib ) const { return x_GetAttrib(m_iPos,szAttrib); };
MCD_STR GetChildAttrib( MCD_CSTR szAttrib ) const { return x_GetAttrib(m_iPosChild,szAttrib); };
bool GetNthAttrib( int n, MCD_STR& strAttrib, MCD_STR& strValue ) const;
MCD_STR GetAttribName( int n ) const;
int FindNode( int nType=0 );
int GetNodeType() { return m_nNodeType; };
bool SavePos( MCD_CSTR szPosName=MCD_T(""), int nMap = 0 );
bool RestorePos( MCD_CSTR szPosName=MCD_T(""), int nMap = 0 );
bool SetMapSize( int nSize, int nMap = 0 );
MCD_STR GetError() const;
const MCD_STR& GetResult() const { return m_strResult; };
int GetDocFlags() const { return m_nDocFlags; };
void SetDocFlags( int nFlags ) { m_nDocFlags = (nFlags & ~(MDF_READFILE|MDF_WRITEFILE|MDF_APPENDFILE)); };
enum MarkupDocFlags
{
MDF_UTF16LEFILE = 1,
MDF_UTF8PREAMBLE = 4,
MDF_IGNORECASE = 8,
MDF_READFILE = 16,
MDF_WRITEFILE = 32,
MDF_APPENDFILE = 64,
MDF_UTF16BEFILE = 128,
MDF_TRIMWHITESPACE = 256,
MDF_COLLAPSEWHITESPACE = 512
};
enum MarkupNodeFlags
{
MNF_WITHCDATA = 0x01,
MNF_WITHNOLINES = 0x02,
MNF_WITHXHTMLSPACE = 0x04,
MNF_WITHREFS = 0x08,
MNF_WITHNOEND = 0x10,
MNF_ESCAPEQUOTES = 0x100,
MNF_NONENDED = 0x100000,
MNF_ILLDATA = 0x200000
};
enum MarkupNodeType
{
MNT_ELEMENT = 1, // 0x0001
MNT_TEXT = 2, // 0x0002
MNT_WHITESPACE = 4, // 0x0004
MNT_TEXT_AND_WHITESPACE = 6, // 0x0006
MNT_CDATA_SECTION = 8, // 0x0008
MNT_PROCESSING_INSTRUCTION = 16, // 0x0010
MNT_COMMENT = 32, // 0x0020
MNT_DOCUMENT_TYPE = 64, // 0x0040
MNT_EXCLUDE_WHITESPACE = 123, // 0x007b
MNT_LONE_END_TAG = 128, // 0x0080
MNT_NODE_ERROR = 32768 // 0x8000
};
// Create
bool Save( MCD_CSTR_FILENAME szFileName );
const MCD_STR& GetDoc() const { return m_strDoc; };
bool AddElem( MCD_CSTR szName, MCD_CSTR szData=NULL, int nFlags=0 ) { return x_AddElem(szName,szData,nFlags); };
bool InsertElem( MCD_CSTR szName, MCD_CSTR szData=NULL, int nFlags=0 ) { return x_AddElem(szName,szData,nFlags|MNF_INSERT); };
bool AddChildElem( MCD_CSTR szName, MCD_CSTR szData=NULL, int nFlags=0 ) { return x_AddElem(szName,szData,nFlags|MNF_CHILD); };
bool InsertChildElem( MCD_CSTR szName, MCD_CSTR szData=NULL, int nFlags=0 ) { return x_AddElem(szName,szData,nFlags|MNF_INSERT|MNF_CHILD); };
bool AddElem( MCD_CSTR szName, int nValue, int nFlags=0 ) { return x_AddElem(szName,nValue,nFlags); };
bool InsertElem( MCD_CSTR szName, int nValue, int nFlags=0 ) { return x_AddElem(szName,nValue,nFlags|MNF_INSERT); };
bool AddChildElem( MCD_CSTR szName, int nValue, int nFlags=0 ) { return x_AddElem(szName,nValue,nFlags|MNF_CHILD); };
bool InsertChildElem( MCD_CSTR szName, int nValue, int nFlags=0 ) { return x_AddElem(szName,nValue,nFlags|MNF_INSERT|MNF_CHILD); };
bool AddAttrib( MCD_CSTR szAttrib, MCD_CSTR szValue ) { return x_SetAttrib(m_iPos,szAttrib,szValue); };
bool AddChildAttrib( MCD_CSTR szAttrib, MCD_CSTR szValue ) { return x_SetAttrib(m_iPosChild,szAttrib,szValue); };
bool AddAttrib( MCD_CSTR szAttrib, int nValue ) { return x_SetAttrib(m_iPos,szAttrib,nValue); };
bool AddChildAttrib( MCD_CSTR szAttrib, int nValue ) { return x_SetAttrib(m_iPosChild,szAttrib,nValue); };
bool AddSubDoc( MCD_CSTR szSubDoc ) { return x_AddSubDoc(szSubDoc,0); };
bool InsertSubDoc( MCD_CSTR szSubDoc ) { return x_AddSubDoc(szSubDoc,MNF_INSERT); };
MCD_STR GetSubDoc() { return x_GetSubDoc(m_iPos); };
bool AddChildSubDoc( MCD_CSTR szSubDoc ) { return x_AddSubDoc(szSubDoc,MNF_CHILD); };
bool InsertChildSubDoc( MCD_CSTR szSubDoc ) { return x_AddSubDoc(szSubDoc,MNF_CHILD|MNF_INSERT); };
MCD_STR GetChildSubDoc() { return x_GetSubDoc(m_iPosChild); };
bool AddNode( int nType, MCD_CSTR szText ) { return x_AddNode(nType,szText,0); };
bool InsertNode( int nType, MCD_CSTR szText ) { return x_AddNode(nType,szText,MNF_INSERT); };
// Modify
bool RemoveElem();
bool RemoveChildElem();
bool RemoveNode();
bool SetAttrib( MCD_CSTR szAttrib, MCD_CSTR szValue, int nFlags=0 ) { return x_SetAttrib(m_iPos,szAttrib,szValue,nFlags); };
bool SetChildAttrib( MCD_CSTR szAttrib, MCD_CSTR szValue, int nFlags=0 ) { return x_SetAttrib(m_iPosChild,szAttrib,szValue,nFlags); };
bool SetAttrib( MCD_CSTR szAttrib, int nValue, int nFlags=0 ) { return x_SetAttrib(m_iPos,szAttrib,nValue,nFlags); };
bool SetChildAttrib( MCD_CSTR szAttrib, int nValue, int nFlags=0 ) { return x_SetAttrib(m_iPosChild,szAttrib,nValue,nFlags); };
bool SetData( MCD_CSTR szData, int nFlags=0 ) { return x_SetData(m_iPos,szData,nFlags); };
bool SetChildData( MCD_CSTR szData, int nFlags=0 ) { return x_SetData(m_iPosChild,szData,nFlags); };
bool SetData( int nValue ) { return x_SetData(m_iPos,nValue); };
bool SetChildData( int nValue ) { return x_SetData(m_iPosChild,nValue); };
bool SetElemContent( MCD_CSTR szContent ) { return x_SetElemContent(szContent); };
// Utility
static bool ReadTextFile( MCD_CSTR_FILENAME szFileName, MCD_STR& strDoc, MCD_STR* pstrResult=NULL, int* pnDocFlags=NULL, MCD_STR* pstrEncoding=NULL );
static bool WriteTextFile( MCD_CSTR_FILENAME szFileName, const MCD_STR& strDoc, MCD_STR* pstrResult=NULL, int* pnDocFlags=NULL, MCD_STR* pstrEncoding=NULL );
static MCD_STR EscapeText( MCD_CSTR szText, int nFlags = 0 );
static MCD_STR UnescapeText( MCD_CSTR szText, int nTextLength = -1, int nFlags = 0 );
static int UTF16To8( char *pszUTF8, const unsigned short* pwszUTF16, int nUTF8Count );
static int UTF8To16( unsigned short* pwszUTF16, const char* pszUTF8, int nUTF8Count );
static MCD_STR UTF8ToA( MCD_CSTR pszUTF8, int* pnFailed = NULL );
static MCD_STR AToUTF8( MCD_CSTR pszANSI );
static void EncodeCharUTF8( int nUChar, char* pszUTF8, int& nUTF8Len );
static int DecodeCharUTF8( const char*& pszUTF8, const char* pszUTF8End = NULL );
static void EncodeCharUTF16( int nUChar, unsigned short* pwszUTF16, int& nUTF16Len );
static int DecodeCharUTF16( const unsigned short*& pwszUTF16, const unsigned short* pszUTF16End = NULL );
static bool DetectUTF8( const char* pText, int nTextLen, int* pnNonASCII = NULL, bool* bErrorAtEnd = NULL );
static MCD_STR GetDeclaredEncoding( MCD_CSTR szDoc );
static int GetEncodingCodePage( MCD_CSTR pszEncoding );
protected:
#if defined(_DEBUG)
MCD_PCSZ m_pDebugCur;
MCD_PCSZ m_pDebugPos;
#endif // DEBUG
MCD_STR m_strDoc;
MCD_STR m_strResult;
int m_iPosParent;
int m_iPos;
int m_iPosChild;
int m_iPosFree;
int m_iPosDeleted;
int m_nNodeType;
int m_nNodeOffset;
int m_nNodeLength;
int m_nDocFlags;
FilePos* m_pFilePos;
SavedPosMapArray* m_pSavedPosMaps;
ElemPosTree* m_pElemPosTree;
enum MarkupNodeFlagsInternal
{
MNF_INSERT = 0x002000,
MNF_CHILD = 0x004000
};
#if defined(_DEBUG) // DEBUG
void x_SetDebugState();
#define MARKUP_SETDEBUGSTATE x_SetDebugState()
#else // not DEBUG
#define MARKUP_SETDEBUGSTATE
#endif // not DEBUG
void x_InitMarkup();
void x_SetPos( int iPosParent, int iPos, int iPosChild );
int x_GetFreePos();
bool x_AllocElemPos( int nNewSize = 0 );
int x_GetParent( int i );
bool x_ParseDoc();
int x_ParseElem( int iPos, TokenPos& token );
int x_FindElem( int iPosParent, int iPos, PathPos& path ) const;
MCD_STR x_GetPath( int iPos ) const;
MCD_STR x_GetTagName( int iPos ) const;
MCD_STR x_GetData( int iPos );
MCD_STR x_GetAttrib( int iPos, MCD_PCSZ pAttrib ) const;
static MCD_STR x_EncodeCDATASection( MCD_PCSZ szData );
bool x_AddElem( MCD_PCSZ pName, MCD_PCSZ pValue, int nFlags );
bool x_AddElem( MCD_PCSZ pName, int nValue, int nFlags );
MCD_STR x_GetSubDoc( int iPos );
bool x_AddSubDoc( MCD_PCSZ pSubDoc, int nFlags );
bool x_SetAttrib( int iPos, MCD_PCSZ pAttrib, MCD_PCSZ pValue, int nFlags=0 );
bool x_SetAttrib( int iPos, MCD_PCSZ pAttrib, int nValue, int nFlags=0 );
bool x_AddNode( int nNodeType, MCD_PCSZ pText, int nNodeFlags );
void x_RemoveNode( int iPosParent, int& iPos, int& nNodeType, int& nNodeOffset, int& nNodeLength );
static bool x_CreateNode( MCD_STR& strNode, int nNodeType, MCD_PCSZ pText );
int x_InsertNew( int iPosParent, int& iPosRel, NodePos& node );
void x_AdjustForNode( int iPosParent, int iPos, int nShift );
void x_Adjust( int iPos, int nShift, bool bAfterPos = false );
void x_LinkElem( int iPosParent, int iPosBefore, int iPos );
int x_UnlinkElem( int iPos );
int x_UnlinkPrevElem( int iPosParent, int iPosBefore, int iPos );
int x_ReleaseSubDoc( int iPos );
int x_ReleasePos( int iPos );
void x_CheckSavedPos();
bool x_SetData( int iPos, MCD_PCSZ szData, int nFlags );
bool x_SetData( int iPos, int nValue );
int x_RemoveElem( int iPos );
MCD_STR x_GetElemContent( int iPos ) const;
bool x_SetElemContent( MCD_PCSZ szContent );
void x_DocChange( int nLeft, int nReplace, const MCD_STR& strInsert );
};
#endif // !defined(_MARKUP_H_INCLUDED_)
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNBITINDEX_H
#define WNBITINDEX_H
#include "WNMemoryObjectManger.h"
class WNBitNode
{
public:
WNBitNode();
virtual ~WNBitNode();
//初始化
void ReInit();
//得到指定节点值(0-15)的子节点
WNBitNode* ChildNode(unsigned int uChildValue);
//得到指定节点值(0-15)的子节点的引用
WNBitNode*& ChildNodeRef(unsigned int uChildValue);
//添加子节点pNewNode
//如果pNewNode对应位置(pNewNode->muBitValue)的子节点已存在且bRemoveOldNode为false,则返回已有节点
//如果bRemoveOldNode为true则delete已有节点,同时返回NULL
//如果pNewNode与已存在的子节点相同则返回NULL
WNBitNode* AttatchChildNode(WNBitNode* pNewNode, bool bRemoveOldNode = true);
//分离指定节点值(0-15)的子节点
//返回已存在的节点,如指定节点不存在则返回NULL
WNBitNode* DetatchChildNode(unsigned int uChildValue);
//增加指定节点值(0-15)的子节点
//返回新增的节点
//如果节点已存在,则返回已有节点
WNBitNode* AddChildNode(unsigned int uChildValue);
//移除指定节点值(0-15)的子节点
void RemoveChildNode(unsigned int uChildValue);
//得到当前的节点的子节点数目
unsigned int LeafsCount();
//得到当前节点的子节点数目(包含数据)
unsigned int LeafsAndValueCount();
//获得当前节点所对应的数据
void* Data();
//获得当前节点所对应的数据的引用
void*& DataRef();
//设置当前节点所对应的数据为pNewData
//如果pNewData为NULL则删除当前节点所对应的数据的指针,此时如果mbIsWNObjectPtr为true则会旧数据进行Release操作
//如果bIsWNObject为true则会对新数据进行Retain操作
//返回旧数据,当旧数据(当前mbIsWNObjectPtr)为true时返回NULL
void* SetData(void* pNewData, bool bIsWNObject = false);
public:
static WNBitNode* NullPtr; //用于返回空引用
public:
unsigned long muLeafsInfo : 16; //叶子节点列表信息
unsigned int muNodeValue : 12; //当前节点所代表的值
bool mbHasData : 1; //当前节点是否有数值
bool mbIsWNObjectPtr : 1; //表示当前节点的数据是否是WNObject*类型的数据
//如果为true则析构或者调用SetData时会进行相关引用操作
bool mbIsEndBit : 1; //是否是一个字节的结束
bool mbDoNotFreeLeafs : 1; //是否在析构时delete所有的子节点,为true表示不delete
WNBitNode** mppLeafs; //叶子节点以及数据指针
};
class WNBitIndex
{
public:
typedef WNMemoryObjectManager<WNBitNode> NodeHeapManager;
public:
WNBitIndex();
virtual ~WNBitIndex();
//设置指定关键字的映射
//pKey是要设置的关键字,不能为NULL
//uKeyLen是关键字的长度,不能为0,单位是字节
//pData是与pKey关联的数据
//如果关键字已存在,则使用pData替换已存在的数据
//如果pData为NULL表示删除与pKey相关联的数据
//当pData以及pKey均不为NULL时返回与pKey相关联的旧数据(旧数据不存在返回NULL)
//如果旧数据是WNObject类型,返回NULL(参见WNBitNode类的SetData函数)
virtual void* SetItem(const void* pKey, unsigned int uKeyLen, void* pData, bool mbIsWNObject = false);
//获得与指定关键字相关联的数据
//pKey是指定的关键字,不能为NULL
//uKeyLen是关键字长度,不能为0,单位是字节
//返回值是与pKey相关联的数据,为NULL则表示数据不存在
virtual void* GetItem(const void* pKey, unsigned int uKeyLen);
//移除与指定关键字相关联的数据
//pKey是指定的关键字,不能为NULL
//uKeyLen是关键字长度,单位是字节
//返回值是与pKey相关联的数据,为NULL则表示数据不存在
virtual void* RemoveItem(const void* pKey, unsigned int uKeyLen);
//清空所有节点
virtual void ClearAll();
protected:
//查找与指定关键字相同的节点
//pKey是指定的关键字,不能为NULL
//uKeyLen是关键字长度,单位是字节
//返回值是与pKey相关联的节点
virtual WNBitNode* FindNode(const void* pKey, unsigned int uKeyLen);
//添加与指定关键字相同的节点(指定关键字的最后半个字节的节点)
//pKey是指定的关键字,不能为NULL
//uKeyLen是关键字长度,单位是字节
//返回值是与pKey相关联的节点,如果关键字节点不存在则添加
virtual WNBitNode* AddNode(const void* pKey, unsigned int uKeyLen);
protected:
WNBitNode* mpRoot[256]; //所有根节点,数组,下标从0-255
NodeHeapManager* mpNodeHeapManager; //所有中间节点的内存管理
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNBYTEBUFFER_H
#define WNBYTEBUFFER_H
#ifndef DEFAULT_BUFFER_SIZE
#define DEFAULT_BUFFER_SIZE 512
#endif
#include "WNCLoopList.h"
#include "WNObject.h"
class ByteBuffer
{
public:
ByteBuffer(unsigned long dwBufferSize = DEFAULT_BUFFER_SIZE);
ByteBuffer(void* pData, unsigned long dwSize);
ByteBuffer(ByteBuffer& srcByteBuffer);
virtual ~ByteBuffer();
bool InitBuffer(unsigned long dwBufferSize = DEFAULT_BUFFER_SIZE, bool bReserveData = false, bool bReservePos = false);
bool ReleaseBuffer();
unsigned long SetValidString(unsigned long dwStrLen);
unsigned long SetValidSize(unsigned long dwSize);
//bool ReadFile(FILE* pFile, unsigned long dwReadSize = 0);
bool ReadMemory(const void* pSrcData, unsigned long dwReadSize = 0);
unsigned long OutputWithPos(void* pTarData, unsigned long dwOutputSize = 0, const unsigned long* pdwPos = NULL);
unsigned long InputWithPos(const void* pSrcData, unsigned long dwInputSize = 0, const unsigned long* pdwPos = NULL );
bool operator == (const ByteBuffer& srcData);
bool operator == (const char* strSrc);
inline bool operator != (const char* strSrc) { return (*this == strSrc)?false:true; }
inline operator char* () { return (char*)m_pBuffer; }
inline operator unsigned char* () { return (unsigned char*)m_pBuffer; }
inline operator void* () { return (void*)m_pBuffer; }
ByteBuffer& operator = (const ByteBuffer& SrcByteBuffer);
inline ByteBuffer& operator = (const char* strData);
inline unsigned char& operator [] (unsigned long dwIndex) { return m_pBuffer[dwIndex]; }
inline unsigned long BufferSize() { return m_dwBufferSize; } //返回实际使用的缓冲区大小,真实缓冲区要比实际缓冲区多2个字节。
inline unsigned char* GetBuffer() { return m_pBuffer; }
inline unsigned char* GetPosBuffer() { return m_pPos; }
inline unsigned long GetPos() { return m_pPos - m_pBuffer; }
inline bool SetPos(unsigned long dwIndex) { return (dwIndex && (dwIndex < m_dwBufferSize))?((m_pPos = m_pBuffer+ dwIndex)?true:false):false; }
inline bool MovePos(long lOffset) { return SetPos(m_pPos + lOffset - m_pBuffer); }
inline void MovePosBegin() { m_pPos = m_pBuffer; }
inline char* GetString() { return (char*)m_pBuffer; }
inline char* GetPosString() { return (char*)m_pPos; }
inline unsigned long GetValidSize() { return m_dwValidSize; }
//bool SaveFile(const char* strFilename, bool bUseValidSize = true);
public:
unsigned long m_dwFlag;
protected:
unsigned char* m_pBuffer;
unsigned long m_dwBufferSize;
unsigned long m_dwValidSize;
unsigned char* m_pPos;
};
class WNByteBufferManager;
class WNByteBuffer : public ByteBuffer, public WNObject
{
public:
WNByteBuffer(unsigned long dwBufferSize = DEFAULT_BUFFER_SIZE);
public:
WNByteBufferManager* mpBufferManager;
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNBYTEBUFFERMANAGER_H
#define WNBYTEBUFFERMANAGER_H
#include "WNCreticalSection.h"
#include "WNCLoopList.h"
#include "WNByteBuffer.h"
#include "WNObject.h"
typedef WNCLoopList<WNByteBuffer> _WNByteBufferList;
class WNByteBufferList : public _WNByteBufferList
{
public:
WNByteBufferList();
public:
unsigned int muBufferSize;
};
#define DefMaxAllBufferSize 0x7FFFFFFF
#define DefMaxBufferCount 0x7FFFFFFF
#define DefMinBufferSize 1024
#define DefSetpBufferSize 1024
#define DefMaxBufferSize 1024*1024*10
class WNByteBufferManager : public WNCreticalSection, public WNObjectDelegate
{
public:
//构造函数
//uMinBufferSize表示缓冲区的最小大小
//uStepBufferSize表示每级缓冲区增加的大小
//uMaxBufferSize表示最大缓冲区大小
WNByteBufferManager(unsigned uMinBufferSize = DefMinBufferSize,
unsigned int uSetpBufferSize = DefSetpBufferSize,
unsigned int uMaxBufferSize = DefMaxBufferSize);
virtual ~WNByteBufferManager(void);
//初始化缓冲区管理器
void InitManager(unsigned int uMinBufferSize, unsigned int uStepBufferSize, unsigned int uMaxBufferSize);
//释放缓冲区管理器
void FreeManager();
//初始化指定大小以及数量的未使用的缓冲区
void InitBuffers(unsigned int uBufferSize, unsigned int uCount = 1);
//获得指定大小的未使用的自由缓冲区
//如果指定大小的缓冲区不存在则创建后返回
WNByteBuffer* GetBuffer(unsigned int uBufferSize, bool mbThreadSafeBuffer = false);
//释放缓冲区
void FreeBuffer(WNByteBuffer* pBuffer);
//设置自由缓冲区大小上限
void SetMaxAllBufferSize(unsigned int uSize);
//设置自由缓冲区数目上限
void SetMaxBufferCount(unsigned int uCount);
virtual bool OnWNObjectRetainCountIsZero(WNObject* pObject);
protected:
//根据指定的大小获得适合的缓冲区列表
WNByteBufferList* GetListByBufferSize(unsigned int uBufferSize);
public:
WNByteBufferList* mpBufferList; //自由缓冲区列表数组,下标0-muListCount,元素0保存不在[muMinBufferSize, muMaxBufferSize]范围内的缓冲区
unsigned int muListCount; //自由缓冲区列表数目
unsigned int muMinBufferSize; //最小缓冲区大小
unsigned int muStepBufferSize; //每一级增加的缓冲区大小
unsigned int muMaxBufferSize; //最大缓冲区大小
unsigned int muAllBufferSize; //所有缓冲区的大小
unsigned int muMaxAllBufferSize; //所有缓冲区的最大大小
unsigned int muAllBufferCount; //所有缓冲区的数目
unsigned int muMaxAllBufferCount; //所有缓冲区的最大数目
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef VNETMATELIST_H
#define VNETMATELIST_H
#include <unistd.h>
template <class T>
class WNCLoopListNode
{
public:
WNCLoopListNode() { prevNode = 0; nextNode = 0; };
WNCLoopListNode(const T& tValue) { prevNode = 0; nextNode = 0; data = tValue; }
T data;
WNCLoopListNode* prevNode;
WNCLoopListNode* nextNode;
};
template <class T>
class WNCLoopList
{
public:
typedef WNCLoopListNode<T> Node;
typedef Node* PNode;
WNCLoopList()
{
m_head = new Node;
m_head->prevNode = m_head;
m_head->nextNode = m_head;
m_begin = m_head;
m_end = m_head;
m_current = m_head;
m_dwCount = 0;
}
WNCLoopList(const WNCLoopList<T>& list)
{
m_head = new Node;
m_head->prevNode = m_head;
m_head->nextNode = m_head;
m_begin = m_head;
m_end = m_head;
m_current = m_head;
m_dwCount = 0;
*this = list;
}
WNCLoopList<T>& operator = (const WNCLoopList<T>& list)
{
ClearList();
for (WNCLoopList<T>::PNode pNode = list.Begin(); pNode != list.Head(); pNode = pNode->nextNode)
{
AppendNode(pNode->data);
}
return *this;
}
virtual ~WNCLoopList()
{
ClearList();
if (m_head)
{
delete m_head;
m_head = 0;
}
m_begin = 0;
m_end = 0;
m_current = 0;
m_dwCount = 0;
}
inline PNode Head() const { return m_head; }
inline PNode Begin() const { return m_begin; }
inline PNode End() const { return m_end; }
inline PNode Current() const { return m_current; }
inline PNode MoveBegin() { return m_current = m_begin; }
inline PNode MoveEnd() { return m_current = m_end; }
inline PNode MovePrev() { return m_current = m_current->prevNode; }
inline PNode MoveNext() { return m_current = m_current->nextNode; }
inline unsigned long ListCount() const { return m_dwCount; }
inline T& HeadData() const { return m_head->data; }
inline T& BeginData() const { return m_begin->data; }
inline T& EndData() const { return m_end->data; }
inline T& CurrentData() const { return m_current->data; }
inline bool NotHead() const { return m_current != m_head; }
PNode Item(unsigned long dwIndex) const
{
PNode pNode = m_head;
while (dwIndex)
{
pNode = pNode->nextNode;
dwIndex--;
}
return pNode;
}
inline T& operator [] (unsigned long dwIndex) const
{
return Item(dwIndex)->data;
}
bool FindNode(PNode pFindNode) const
{
for (PNode pNode = m_begin; pNode != m_head; pNode = pNode.nextNode)
{
if (pNode == pFindNode)
{
return true;
}
}
return false;
}
PNode FindData(T& data) const
{
for (PNode pNode = m_begin; pNode != m_head; pNode = pNode->nextNode)
{
if (pNode->data == data)
{
return pNode;
}
}
return 0;
}
PNode AppendNode(const Node& node, PNode pPrevNode = 0)
{
PNode pNode = (PNode)&node;
if (!pNode)
{
return 0;
}
if (!pPrevNode)
{
pPrevNode = m_end;
}
PNode pNewNode = new Node(*pNode);
pNewNode->nextNode = pPrevNode->nextNode;
pPrevNode->nextNode->prevNode = pNewNode;
pPrevNode->nextNode = pNewNode;
pNewNode->prevNode = pPrevNode;
if (pNewNode->prevNode == m_head)
{
m_begin = pNewNode;
}
if (pNewNode->nextNode == m_head)
{
m_end = pNewNode;
}
m_dwCount++;
return pNewNode;
}
PNode AppendNode(PNode pNode, PNode pPrevNode = 0)
{
if (!pNode)
{
return 0;
}
if (!pPrevNode)
{
pPrevNode = m_end;
}
PNode pNewNode = pNode;
pNewNode->nextNode = pPrevNode->nextNode;
pPrevNode->nextNode->prevNode = pNewNode;
pPrevNode->nextNode = pNewNode;
pNewNode->prevNode = pPrevNode;
if (pNewNode->prevNode == m_head)
{
m_begin = pNewNode;
}
if (pNewNode->nextNode == m_head)
{
m_end = pNewNode;
}
m_dwCount++;
return pNewNode;
}
PNode AppendNode(T& data, PNode pPreNode = 0)
{
PNode pNode = new Node;
pNode->data = data;
return AppendNode(pNode, pPreNode);
}
PNode PreAppendNode(const Node& node, PNode pNextNode = 0)
{
PNode pNode = (PNode)&node;
if (!pNode)
{
return NULL;
}
if (!pNextNode)
{
pNextNode = m_begin;
}
PNode pNewNode = new Node(*pNode);
pNewNode->prevNode = pNextNode->prevNode;
pNextNode->prevNode->nextNode = pNewNode;
pNewNode->nextNode = pNextNode;
pNextNode->prevNode = pNewNode;
if (pNewNode->prevNode == m_head)
{
m_begin = pNewNode;
}
if (pNewNode->nextNode == m_head)
{
m_end = pNewNode;
}
m_dwCount++;
return pNewNode;
}
PNode PreAppendNode(PNode pNode, PNode pNextNode = 0)
{
if (!pNode)
{
return NULL;
}
if (!pNextNode)
{
pNextNode = m_begin;
}
PNode pNewNode = pNode;
pNewNode->prevNode = pNextNode->prevNode;
pNextNode->prevNode->nextNode = pNewNode;
pNewNode->nextNode = pNextNode;
pNextNode->prevNode = pNewNode;
if (pNewNode->prevNode == m_head)
{
m_begin = pNewNode;
}
if (pNewNode->nextNode == m_head)
{
m_end = pNewNode;
}
m_dwCount++;
return pNewNode;
}
PNode PreAppendNode(T& data, PNode pNextNode = 0)
{
PNode pNode = new Node;
pNode->data = data;
return PreAppendNode(pNode, pNextNode);
}
PNode DetachNode(PNode pNode = 0)
{
if (!pNode)
{
pNode = m_current;
}
if (pNode == m_head)
{
return 0;
}
if (m_current == pNode)
{
if (m_current == m_end)
{
m_current = pNode->prevNode;
}
else
{
m_current = pNode->nextNode;
}
}
pNode->prevNode->nextNode = pNode->nextNode;
if (m_end == pNode)
{
m_end = pNode->prevNode;
}
pNode->nextNode->prevNode = pNode->prevNode;
if (m_begin == pNode)
{
m_begin = pNode->nextNode;
}
pNode->prevNode= NULL;
pNode->nextNode = NULL;
m_dwCount--;
return pNode;
}
PNode RemoveNode(PNode pNode = 0)
{
if (!pNode)
{
pNode = m_current;
}
if (pNode == m_head)
{
return m_head;
}
PNode retNode = 0;
if (m_current == pNode)
{
if (m_current == m_end)
{
m_current = pNode->prevNode;
}
else
{
m_current = pNode->nextNode;
}
retNode = m_current;
}
else
{
if (pNode == m_end)
{
retNode = pNode->prevNode;
}
else
{
retNode = pNode->nextNode;
}
}
pNode->prevNode->nextNode = pNode->nextNode;
if (m_end == pNode)
{
m_end = pNode->prevNode;
}
pNode->nextNode->prevNode = pNode->prevNode;
if (m_begin == pNode)
{
m_begin = pNode->nextNode;
}
delete pNode;
m_dwCount--;
return retNode;
}
virtual void ClearList()
{
for (MoveBegin(); Current() != Head(); )
{
RemoveNode();
}
m_begin = m_head;
m_end = m_head;
m_current = m_head;
m_dwCount = 0;
}
protected:
PNode m_head;
PNode m_begin;
PNode m_end;
PNode m_current;
unsigned long m_dwCount;
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef STRINGLIST_H
#define STRINGLIST_H
#include "WNCLoopList.h"
#include <string>
using namespace std;
class WNCStringList:public WNCLoopList<string>
{
public:
WNCStringList() { };
~WNCStringList() { };
WNCStringList(const char* lpStringList, const char* lpSplit = "|");
WNCStringList(const string& strStringList, const string& strSplit = "|");
virtual void CreateList(const char* lpStringList = "", const char* lpSplit = "|");
virtual void CreateList(const string& strStringList = string(""), const string& strSplit = string("|"));
string Join(const char* lpSplit = "|");
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNCOMMONSOCKET_H
#define WNCOMMONSOCKET_H
//#include "ACCallback.h"
#include "WNCommonSocketDelegate.h"
#include "WNSocketObserver.h"
#include "WNWorkThread.h"
#include <sys/socket.h>
#include <string>
using namespace std;
#ifndef WIN32
# ifndef WINTYPEDEF
# define WINTYPEDEF
typedef bool BOOL;
#define TRUE true
#define FALSE false
typedef unsigned short USHORT;
typedef const char* LPCTSTR;
typedef unsigned int UINT;
typedef int INT;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
typedef unsigned int DWORD;
typedef string CString;
typedef void* HWND;
#define LRESULT long
#define CALLBACK
#define WINAPI
#define _tcstoul strtoul
#define _T(str) str
typedef long LONG;
typedef LONG WPARAM;
typedef LONG LPARAM;
typedef void* LPVOID;
typedef void* HANDLE;
typedef void* ACWinProc;
typedef int SOCKET;
# endif
#endif
class WNCommonSocket
: public WNSocketObserverTarget
, public WNSocketObserverTargetDelegate
, public WNWorkThreadDelegate
{
#ifdef WIN32
typedef LRESULT (WNCommonSocket::*ACWindowHookProc)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
typedef ACCallback<WNDPROC, WNCommonSocket, WNCommonSocket::ACWindowHookProc> ACWinProc;
#endif
public:
WNCommonSocket(void);
virtual ~WNCommonSocket(void);
virtual BOOL CreateSocket();
virtual BOOL SetSocketAddress(LPCTSTR lpAddress);
virtual BOOL SetSocketAddress(LPCTSTR lpAddress, UINT uPort);
virtual BOOL SetSocketAddress(SOCKADDR* pSockAddr);
virtual BOOL EnterObserverLoop(BOOL bInNewThread);
virtual BOOL ExitObserverLoop();
virtual void CloseSocket();
virtual BOOL AcceptSocket(WNCommonSocket* pNewSocket, SOCKADDR* pSockAddr = NULL, int* pSockAddrLen = NULL);
virtual BOOL AcceptSocket(WNCommonSocket& newSocket, CString* pstrSockAddr = NULL, int* pSockAddrLen = NULL);
virtual BOOL ConnectSocket(LPCTSTR lpszHostAddress);
virtual BOOL ConnectSocket(SOCKADDR* pHostAddress);
virtual BOOL IOCtl(long lCommand, DWORD* lpArgument);
virtual BOOL SetSockOpt(int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel = SOL_SOCKET);
virtual BOOL GetSockOpt(int nOptionName, void* lpOptionValue,int* lpOptionLen, int nLevel = SOL_SOCKET);
virtual BOOL Listen(int nConnectionBacklog);
virtual BOOL GetPeerName(CString& strIp, UINT& uPort);
virtual BOOL GetPeerName(SOCKADDR* lpSockAddr, int* lpSockAddrLen);
virtual BOOL GetSockName(CString& strIp, UINT& uPort);
virtual BOOL GetSockName(SOCKADDR* lpSockAddr, int* lpSockAddrLen);
virtual void SetReceiveBuffer(void* pBuffer, UINT uBufferLen);
virtual DWORD ReceivedDataLen();
virtual int Receive(void* lpBuf, int nBufLen, int nFlags = 0);
virtual int ReceiveFrom(void* lpBuf, int nBufLen, CString& rSocketAddress, int nFlags = 0);
virtual int ReceiveFrom(void* lpBuf, int nBufLen, SOCKADDR* pSocketAddress, int* pSockAddrLen, int nFlags = 0);
virtual int Send(const void* lpBuf, int nBufLen, int nFlags = 0);
virtual int SendTo(const void* lpBuf, int nBufLen, LPCTSTR lpSocketAddress, int nFlags = 0);
virtual int SendTo(const void* lpBuf, int nBufLen, SOCKADDR* pSocketAddress, int nFlags = 0);
static SOCKADDR Ipv4StringToData(LPCTSTR lpAddress);
static BOOL Ipv4StringToData(LPCTSTR lpAddress, SOCKADDR& addrData);
static CString Ipv4DataToString(SOCKADDR& addrIn, BOOL bWithPort);
static BOOL Ipv4DataToString(SOCKADDR& addrIn, CString& strAddr, BOOL bWithPort);
static int GetLastError();
virtual bool OnWorkThreadProc(WNWorkThread* objThread, unsigned int& uStep);
virtual unsigned int OnWorkThreadNeedSleep(WNWorkThread* objThread);
protected:
virtual BOOL CreateSocketWindow();
virtual BOOL DestroySocketWindow();
virtual LRESULT InternalWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT ACWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static DWORD WINAPI RunLoopThreadProc(LPVOID lpParameter);
DWORD InternalRunLoopThreadProc();
//当前socket可读(或可以进行accept操作)
virtual void OnObserverRead(IWNSocketObserver* observer);
//当前socket错误
virtual void OnObserverError(IWNSocketObserver* observer);
virtual BOOL DoPorcessTcpDataRead();
virtual BOOL DoProcessUdpDataRead();
virtual BOOL DoProcessObserverRead(IWNSocketObserver* observer);
virtual BOOL DoProcessObserverError(IWNSocketObserver* observer);
#ifndef WIN32
friend LRESULT CALLBACK WNCommonSocketWindowProcedure (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif
public:
HWND mhwnd; //socket相关窗口,在非当前线程中创建socket时有效
DWORD mdwWindowThreadId; //窗口线程id
//BOOL mbHasWindowMessage; //表示是否有窗口消息未处理/
HANDLE mThreadHandle; //线程句柄
DWORD mdwThreadId; //线程id
WNWorkThread* mpRunLoopThread; //工作线程
UINT muRunLoopThreadSleepTime; //工作线程睡眠时间,毫秒
INT miSocketInitProtocalFamily; //初始化用的socket协议族,默认为AF_INET
INT miSocketInitType; //初始化用的socket类型,默认为SOCK_STREAM
INT miSocketInitProtocal; //初始化用的协议,默认为0
BOOL mbExitThread; //退出线程标志位
BOOL mbIsThreadRunning; //表示线程是否正在运行
WNCommonSocketDelegate* mpCommonSocketDelegate; //托管对象
CString mstrSocketIdentity; //socket标识符
void* mUserInfo; //用户信息
ACWinProc* mpACWinProc; //窗口处理函数回调
#ifdef WIN32
UINT muMsgOnWNObserverRead; //检测到socket可读
UINT muMsgOnWNObserverError; //检测到socket错误
UINT muMsgNeedDestroyWindow; //需要销毁窗口消消息
#endif
char* mpReceiveBuffer; //接收缓冲区
char* mpReceiveBufferPos; //当前接收位置
UINT muAvailableReceiveLen; //接收缓冲区可用大小
volatile BOOL mbOnRead;
volatile BOOL mbOnError;
volatile IWNSocketObserver* mpReadObserver;
volatile IWNSocketObserver* mpErrorObserver;
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNCOMMONSOCKETDELEGATE_H
#define WNCOMMONSOCKETDELEGATE_H
class WNCommonSocket;
class WNCommonSocketDelegate
{
public:
//可以进行Accept连接
virtual void OnCommonSocketAccept(WNCommonSocket* sock) { }
//远程socket已关闭
virtual void OnCommonSocketClose(WNCommonSocket* sock) { }
//有错误发生
virtual void OnCommonSocketError(WNCommonSocket* sock, int iErrorCode) { }
//有数据可以接收
virtual void OnCommonSocketReceive(WNCommonSocket* sock, unsigned int uUnreadDataLen) { }
//提示接收缓冲区已满
//仅仅在socket的类型为SOCK_STREAM(tcp)时有效
virtual void OnCommonSocketRecvBufferFulled(WNCommonSocket* sock, void* pBuffer, unsigned int uBufferLen, unsigned int uUnreadDataLen) { }
virtual bool OnCommonSocketThreadProc(unsigned int* uSleepTime) { return true; }
virtual ~WNCommonSocketDelegate(){}
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNCRETICALSECTION_H
#define WNCRETICALSECTION_H
#include <pthread.h>
class WNCreticalSection
{
public:
WNCreticalSection(void);
virtual ~WNCreticalSection(void);
virtual void CreateLocker();
virtual void DestroyLocker();
virtual bool TryLock();
virtual bool Lock();
virtual bool Unlock();
protected:
//wlf CRITICAL_SECTION* mpLocker;
pthread_mutex_t* mpLocker;
};
//自动解锁,仅在同一函数中定义以及使用
class WNCreticalSectionAutoLocker
{
public:
WNCreticalSectionAutoLocker();
WNCreticalSectionAutoLocker(WNCreticalSection* pCreiticalSection, bool bLocker = true);
virtual ~WNCreticalSectionAutoLocker();
virtual bool TryLock();
virtual void Lock();
virtual void Unlock();
public:
WNCreticalSection* mpLocker;
WNCreticalSection* mpLocking;
};
#endif
\ No newline at end of file
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNDECOD_H
#define WNDECOD_H
class WNByteBuffer;
typedef struct _WNFrameInfo
{
unsigned int uUserInfo[2]; //包类型
unsigned int uHeader; //头标记
unsigned int uVersion; //版本号
unsigned int uSize; //数据长度
unsigned int uType; //数据包类型
unsigned int uStreamID; //数据流ID,
unsigned int uTimeStamp; //时间戳
} WNFrameInfo, *PWNFrameInfo;
typedef struct _WNDecodedFrameInfo
{
unsigned int uUserInfo[2];
unsigned int uDataFormat; //数据格式
unsigned int uWidth; //宽度
unsigned int uHeight; //高度
unsigned int uSize; //数据大小
unsigned int uStreamID; //数据流ID
unsigned int uTimeStamp; //时间戳
} WNDecodedFrameInfo, *PWNDecodedFrameInfo;
typedef const char* WNDecoderName;
class WNDecoder;
class WNDecoderDelegate
{
public:
virtual ~WNDecoderDelegate() { }
virtual void OnNetworkVideoDeviceDecoded(WNDecoder* pDevice) { }
};
class WNDecoder
{
public:
//托管对象,非空时通过此对象回调WNDecoderDelegate的接口
WNDecoderDelegate* mpDecoderDelegate;
public:
WNDecoder() { mpDecoderDelegate = 0; }
virtual ~WNDecoder() { mpDecoderDelegate = 0; }
//返回解码器名称
virtual WNDecoderName DecoderName() = 0;
//初始化解码器
//成功返回true,识别返回false
virtual bool InitDecoder() = 0;
//解码器开始工作
//成功返回true,识别返回false
virtual bool StartWork() =0;
//解码器停止工作
//成功返回true,识别返回false
virtual bool EndWork() = 0;
//解码pFrameBuffer
//pInfo是pFrameBuffer的相关信息
//成功返回true,失败返回false
virtual bool DoDecode(WNByteBuffer* pFrameBuffer, WNFrameInfo* pInfo = 0) = 0;
//获得最后一次解码成功的帧(解码后的数据)
//返回的帧在调用FreeDecodedFrame之前当前解码器不允许使用
//[输出] pInfo是解码后帧的信息指针。
//[输入] bSafeCall表示是否是安全调用。
//安全调用是指在托管对象的OnNetworkVideoDeviceDecoded被调用的时候在同一线程中调用本函数
//安全调用时无需加锁
//注意,对同一WNDecoder对象只能选择一种方式调用本函数,或者安全调用,或者非安装调用
virtual void* GetNextDecodedFrame(WNDecodedFrameInfo* pInfo = 0, bool bSafeCall = true) = 0;
//释放通过GetNextDecodedFrame获得的解码后的数据
//释放后的数据可以被当前解码器使用
virtual void FreeDecodedFrame(void* pDecodedFrame) = 0;
};
//通过默认的消息中心创建解码器
//发送:
// 参数1设置为要创建的解码器名称指针(WNDecoderName类型)
// 参数2设置为0
//返回(调用完毕后):
// 参数1不变
// 参数2设置为创建的解码器指针,继承WNDecoder
#define NT_CreateDecoder "NT_CreateDecoder"
//通过默认的消息中心销毁解码器
//发送:
// 参数1设置为要销毁的解码器名称指针(WNDecoderName类型)
// 参数2设置为要销毁的解码器指针
//返回(调用完毕后):
// 参数1不变
// 参数2设置为0,表示销毁成功,继承WNDecoder
#define NT_DestroyDecoder "NT_DestroyDecoder"
#endif
\ No newline at end of file
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNINVOKER_H
#define WNINVOKER_H
#include "ACCallback.h"
#include "WNObject.h"
#include "WNReadWriteLocker.h"
#include "WNCLoopList.h"
#include <sys/time.h>
extern long getCurrentTime();
class WNInvokeInfo : public WNObject
{
public:
WNInvokeInfo();
~WNInvokeInfo();
virtual void InvokeMemberFunc() { return; }
virtual void Reset();
public:
BOOL mbInvoked;
UINT muInvokeTime;
void* mpReturnValue;
};
typedef void (*StdInvokeMemberFuncVoid)();
template <typename _TClass, typename _TPMemberFunc>
class InvokeMemberFuncVoidInfo : public WNInvokeInfo
{
public:
virtual void InvokeMemberFunc()
{
mCallBack.mpStdFunc();
mbInvoked = TRUE;
}
virtual void Reset()
{
mCallBack.FreeCode();
WNInvokeInfo::Reset();
}
public:
ACCallbackEx<StdInvokeMemberFuncVoid> mCallBack;
};
typedef void (*StdInvokeMemberFuncVoidWNObject)(WNObject*);
template <typename _TClass, typename _TPMemberFunc>
class InvokeMemberFuncVoidWNObjectInfo : public WNInvokeInfo
{
public:
InvokeMemberFuncVoidWNObjectInfo()
{
mpParam = NULL;
}
virtual void InvokeMemberFunc()
{
mCallBack.mpStdFunc(mpParam);
mbInvoked = TRUE;
}
virtual void Reset()
{
doRelease(mpParam);
WNInvokeInfo::Reset();
}
public:
ACCallbackEx<StdInvokeMemberFuncVoidWNObject> mCallBack;
WNObject* mpParam;
};
class WNInvoker
{
public:
virtual ~WNInvoker();
//执行类对象的成员函数
//支持的成员函数形式为void Class::MemberFunc();
//pObject是要执行成员函数的对象
// 请注意保证在函数被执行前pObject不要被销毁
//pMemberFunc是成员函数指针
//pParam是要执行的成员函数参数
//uAfterDelay表示执行的延迟,为0表示在执行线程的下一个循环中执行
//返回值为执行信息
template <typename _TClass, typename _TPMemberFunc>
WNInvokeInfo* InvokeMemberFuncVoid(_TClass* pObject, _TPMemberFunc pMemberFunc, UINT uAfterDelay = 0)
{
InvokeMemberFuncVoidInfo<_TClass, _TPMemberFunc>* pInvokeInfo = _WNSafeAlloc<InvokeMemberFuncVoidInfo<_TClass, _TPMemberFunc> >();
pInvokeInfo->Retain();
pInvokeInfo->mCallBack.SetCallBackMemberFunc(pObject, pMemberFunc);
pInvokeInfo->muInvokeTime = getCurrentTime() + uAfterDelay;
AddInvokeInfo(pInvokeInfo);
return pInvokeInfo;
}
//执行类对象的成员函数
//支持的成员函数形式为void Class::MemberFunc(WNObject*);
//pObject是要执行成员函数的对象
// 请注意保证在函数被执行前pObject不要被销毁
//pMemberFunc是成员函数指针
//pParam是要执行的成员函数参数
//uAfterDelay表示执行的延迟,为0表示在执行线程的下一个循环中执行
////返回值为执行信息
template <typename _TClass, typename _TPMemberFunc>
WNInvokeInfo* InvokeMemberFuncVoidWNObject(_TClass* pObject, _TPMemberFunc pMemberFunc, WNObject* pParam = NULL, UINT uAfterDelay = 0)
{
InvokeMemberFuncVoidWNObjectInfo<_TClass, _TPMemberFunc>* pInvokeInfo = _WNSafeAlloc<InvokeMemberFuncVoidWNObjectInfo<_TClass, _TPMemberFunc> >();
pInvokeInfo->Retain();
pInvokeInfo->mCallBack.SetCallBackMemberFunc(pObject, pMemberFunc);
if (pParam)
{
pInvokeInfo->mpParam = pParam->Retain();
}
pInvokeInfo->muInvokeTime = getCurrentTime() + uAfterDelay;
AddInvokeInfo(pInvokeInfo);
return pInvokeInfo;
}
virtual void AddInvokeInfo(WNInvokeInfo* pInvokeInfo);
//检查执行队列中是否有需要执行的函数
//如果有则执行所有的函数
//返回是否有执行函数
virtual BOOL DoCheckAndInvoke();
//检查执行队列中是否有需要执行的函数
//如果队列中有需要执行的函数则返回TRUE,否则返回FALSE
virtual BOOL DoCheckInvoke();
//调用执行队列中的函数
//只做一次调用
//如果执行了函数返回TRUE,否则返回FALSE
virtual BOOL DoInvoke();
public:
WNCLoopList<WNInvokeInfo*> mInvokeList;
WNReadWriteLocker mInvokeLocker;
};
#endif
\ No newline at end of file
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef MEMORYOBJECTMANAGER_H
#define MEMORYOBJECTMANAGER_H
#include "WNCLoopList.h"
template <class T>
class WNMemoryObject
{
public:
WNMemoryObject() { m_pPrevObject = NULL; m_pNextObject = NULL; }
public:
T m_Object;
WNMemoryObject* m_pPrevObject;
WNMemoryObject* m_pNextObject;
};
template <class T>
class WNMemoryObjectManager
{
public:
typedef WNMemoryObject<T> Node;
typedef Node* PNode;
typedef WNCLoopList<PNode> MemoryBlocks;
public:
WNMemoryObjectManager(unsigned long dwBlockSize = 1024)
{
m_dwBlockSize = dwBlockSize;
m_FreeObjectHead.m_pNextObject = &m_FreeObjectHead;
m_FreeObjectHead.m_pPrevObject = &m_FreeObjectHead;
m_dwFreeCount = 0;
m_UsedObjectHead.m_pNextObject = &m_UsedObjectHead;
m_UsedObjectHead.m_pPrevObject = &m_UsedObjectHead;
m_dwUsedCount = 0;
AllocMemoryBlock();
}
virtual ~WNMemoryObjectManager()
{
for (m_MemoryBlocks.MoveBegin(); m_MemoryBlocks.NotHead(); m_MemoryBlocks.MoveNext())
{
delete[] m_MemoryBlocks.CurrentData();
}
}
//从自由区分配对象指针,返回的对象指针未经过初始化
virtual T* AllocObject()
{
if (!m_dwFreeCount)
{
AllocMemoryBlock();
}
if (!m_dwFreeCount)
{
return NULL;
}
PNode pNode = m_FreeObjectHead.m_pNextObject;
//将节点从自由区移入已使用区
m_FreeObjectHead.m_pNextObject = pNode->m_pNextObject;
pNode->m_pNextObject->m_pPrevObject = &m_FreeObjectHead;
m_dwFreeCount--;
m_UsedObjectHead.m_pPrevObject->m_pNextObject = pNode;
pNode->m_pPrevObject = m_UsedObjectHead.m_pPrevObject;
m_UsedObjectHead.m_pPrevObject = pNode;
pNode->m_pNextObject = &m_UsedObjectHead;
m_dwUsedCount--;
return (T*)pNode;
}
//将对象指针从使用区放入自由区,pObject必须为从AllocObject函数分配的对象指针
virtual void FreeObject(T* pObject)
{
PNode pNode = (PNode)pObject;
//将节点从使用区移入自由区
pNode->m_pPrevObject->m_pNextObject = pNode->m_pNextObject;
pNode->m_pNextObject->m_pPrevObject = pNode->m_pPrevObject;
m_dwUsedCount--;
m_FreeObjectHead.m_pPrevObject->m_pNextObject = pNode;
pNode->m_pPrevObject = m_FreeObjectHead.m_pPrevObject;
m_FreeObjectHead.m_pPrevObject = pNode;
pNode->m_pNextObject = &m_FreeObjectHead;
m_dwFreeCount++;
}
protected:
virtual bool AllocMemoryBlock()
{
if (!m_dwBlockSize)
{
return false;
}
PNode pBlock = new Node[m_dwBlockSize];
if (!pBlock)
{
return false;
}
//将内存块放入内存块列表
m_MemoryBlocks.AppendNode(pBlock);
//将所有区块相连
for (unsigned long i = 0; i < m_dwBlockSize; i++ )
{
pBlock[i].m_pPrevObject = pBlock + i - 1;
pBlock[i].m_pNextObject = pBlock + i + 1;
}
//将区块加入自由区
m_FreeObjectHead.m_pPrevObject->m_pNextObject = pBlock;
pBlock->m_pPrevObject = m_FreeObjectHead.m_pPrevObject->m_pNextObject;
m_FreeObjectHead.m_pPrevObject = &pBlock[m_dwBlockSize - 1];
pBlock[m_dwBlockSize -1 ].m_pNextObject = &m_FreeObjectHead;
m_dwFreeCount += m_dwBlockSize;
return true;
}
protected:
MemoryBlocks m_MemoryBlocks;
Node m_FreeObjectHead;
Node m_UsedObjectHead;
unsigned long m_dwBlockSize;
unsigned long m_dwFreeCount;
unsigned long m_dwUsedCount;
};
#endif
\ No newline at end of file
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef SYSTEMIDNUMBER_H
#define SYSTEMIDNUMBER_H
#pragma once
#pragma comment(lib, "Iphlpapi")
#include "Iphlpapi.h"
#include "EBaseFunctions.h"
//#include "CSWbemServices.h"
//#include "CSWbemObject.h"
//#include "CSWbemObjectSet.h"
//#include "CSWbemLocator.h"
#define MAC_LENGTH 20
#define ADAPTER_COUNT_MAX 20
class WNAddrData
{
public:
WNAddrData();
WNAddrData(const WNAddrData& data);
CString GetMacAddress();
inline BOOL IsVirtual() { return m_bIsVirtual; }
WNAddrData& operator=(const WNAddrData& data);
public:
DWORD m_dwAdapterIndex;
CString m_strAdapterName;
CString m_strAdapterInfo;
CString m_strIp;
CString m_strSubnetMask;
CString m_strBroadCastIp;
UINT m_uMacLen;
BYTE m_MacAddr[MAC_LENGTH];
CString m_strVirtualMac;
BOOL m_bIsVirtual;
UINT m_uType;
CString m_strIPList[256];
UINT m_nIPCount;
DWORD m_dwStartIp;
DWORD m_dwEndIp;
};
class WNNetworkInfo
{
public:
WNNetworkInfo();
//get mac address,return the number of mac address
LONG GetCount() { return m_lCount; }
WNAddrData* GetAdapterInfo(LONG lIndex);
VOID ReInit();
VOID SetVirtualMac(CString& strMac);
void OutputAdapterInfo();
static BOOL IsConnectedAdapter(DWORD dwAdapterIndex);
protected:
LONG GetSystemMacInfo(WNAddrData* pMacData);
private:
WNAddrData m_AddrData[100];
LONG m_lCount;
};
#endif
\ No newline at end of file
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNNOTIFICATIONCENTER_H
#define WNNOTIFICATIONCENTER_H
#include "WNObject.h"
#include "WNCLoopList.h"
#include <string>
using namespace std;
class WNNotificationCenter;
class WNReadWriteLocker;
class WNCreticalSection;
//默认2个参数,可以重定义此宏,但是此宏不能为0
//重定义此宏时,在包含WNNotificationCenter.h之前定义
#ifndef DEF_NT_PARAMS_COUNT
#define DEF_NT_PARAMS_COUNT 3
#endif
//通知消息类
class WNNotification : public WNObject
{
public:
WNNotification(unsigned int muParamsCount = DEF_NT_PARAMS_COUNT);
virtual ~WNNotification();
//通知名称
virtual const char* NotificationName();
//判断通知名称是否为指定名称
virtual bool IsNotification(const char* lpNotificationName);
//获得整个通知的大小
virtual unsigned int GetSize();
//获得整个通知的拷贝
//返回值需要通过Release释放
//未实现
virtual WNNotification* GetCopy();
//拷贝内容至pNotification
//未实现
virtual void CopyTo(WNNotification* pNotification);
public:
unsigned int muNotificationId; //通知Id
void* mpNotificationSender; //通知发送者
WNObject* mpNotificationData; //通知数据
WNNotificationCenter* mpNotificationCenter; //投递消息的消息中心
unsigned int muParamsCount; //参数个数
unsigned int mParams[DEF_NT_PARAMS_COUNT]; //参数列表
};
//通知接受者类
class WNNotificationReceiver
{
public:
//通知回调
virtual void OnReceiveNotification(WNNotification* pNotification) { }
virtual void OnReceiveNotification(WNNotification *pNotification, void* pThread) { }
virtual ~WNNotificationReceiver(){}
};
class WNWorkThread;
//通知观察者类
class WNNotificationObserver : public WNNotificationReceiver
{
public:
virtual ~WNNotificationObserver(){}
//开始观察指定发送者以及消息中心的通知(字符串)
//lpNotificationName是要观察的通知名称
//pSender是发送者,为NULL时表示观察所有发送者发送的lpNotificationName
//pNotification是指定的消息中心,为默认值NULL是表示使用WNNotificationCenter::DefaultCenter()
//返回值为通知Id,返回值为非0表示成功,否则表示失败
virtual unsigned int StartObserveNotification(const char* lpNotificationName, void* pSender = NULL, WNNotificationCenter* pNotificationCenter = NULL);
//停止观察指定发送者以及消息中心的通知(字符串)
//lpNotificationName是要停止观察的消息名称
//pSender是发送者,为NULL时表示停止观察所有发送者发送的lpNotificationName所对应的消息
//当lpNotificationName为NULL时表示停止观察所有的消息
//pNotification是指定的消息中心,为默认值NULL是表示使用WNNotificationCenter::DefaultCenter()
virtual void StopObserveNotification(const char* lpNotificationName = NULL, void* pSender = NULL, WNNotificationCenter* pNotificationCenter = NULL);
//开始在指定线程观察指定发送者以及消息中心的通知(字符串)
//lpNotificationName是要停止观察的消息名称
//pThread是指定的线程,为NULL时表示在当前线程观察
//pSender是发送者,为NULL时表示停止观察所有发送者发送的lpNotificationName所对应的消息
//当lpNotificationName为NULL时表示停止观察所有的消息
//pNotification是指定的消息中心,为默认值NULL是表示使用WNNotificationCenter::DefaultCenter()
//返回值为通知Id,返回值为非0表示成功,否则表示失败
virtual unsigned int StartObserveNotificationOnThread(const char *lpNotificationName, WNWorkThread* pThread = NULL, void *pSender = NULL, WNNotificationCenter *pNotificationCenter = NULL);
//停止在指定的线程观察指定发送者以及消息中心的通知(字符串)
//lpNotificationName是要停止观察的消息名称
//pThread是指定的线程,为NULL时表示在当前线程观察
//pSender是发送者,为NULL时表示停止观察所有发送者发送的lpNotificationName所对应的消息
//当lpNotificationName为NULL时表示停止观察所有的消息
//pNotification是指定的消息中心,为默认值NULL是表示使用WNNotificationCenter::DefaultCenter()
virtual void StopObserveNotificationOnThread(const char* lpNotificationName = NULL, WNWorkThread* pThread = NULL, void* pSender = NULL, WNNotificationCenter* pNotificationCenter = NULL);
};
//WNObserverInfo用于保存观察者的信息
class WNObserverInfo
{
public:
WNObserverInfo();
virtual ~WNObserverInfo(){}
public:
WNNotificationReceiver* mpNotificationReceiver; //通知接受者
void* mpNotificationSender; //通知发送者
bool mbIsValid; //是否有效
};
//WNNotificationObserverList用于保存指定通知的观察者信息列表
class WNNotificationObserverList : public WNCLoopList<WNObserverInfo>
{
public:
WNNotificationObserverList();
virtual ~WNNotificationObserverList();
//添加观察者
void AddObserver(WNNotificationObserver* pObserver, void* pSender);
//移除观察者
void RemoveObserver(WNNotificationObserver* pObserver, void* pSender);
//投递通知
void PostNotification(WNNotification* pNotification, void* pSender = NULL);
public:
unsigned int muNotificationId; //通知Id
string mstrNotificationName; //通知名称
WNCreticalSection* mpLocker;
protected:
unsigned int muNotificationLevel; //同一线程中PostNotification函数调用的层次
unsigned int muRemoveCount; //要删除的观察者数目,用于同一线程的通知中调用RemoveObserver函数
};
//WNNotificationCenter是通知中心类
//默认会存在一个实例,通过WNNotificationCenter::DefaultCenter()获得
class WNNotificationCenter : public WNObject
{
public:
WNNotificationCenter();
virtual ~WNNotificationCenter(void);
//获得默认通知中心实例
static WNNotificationCenter* DefaultCenter();
//注册通知
//返回通知id
//如果通知未注册则返回新的id,如果已注册则返回已有id
virtual unsigned int RegisterNotification(const char* lpNotificationName);
//根据通知名称获得通知id
//如果指定的名称没有注册,则返回0,已注册返回非0的id
virtual unsigned int GetNotificationIdByName(const char* lpNotificationName);
//根据通知id得到通知名称
virtual const char* GetNotificationNameById(unsigned int uNotificationId);
//添加观察者
//pObserver是要添加的观察者
//lpNotificationName是要观察的消息名称
//pSender是指定的消息发送者,如果为NULL则观察来自所有观察者的lpNotificationName
//返回值为要观察的消息Id
virtual unsigned int AddObserver(WNNotificationObserver* pObserver, const char* lpNotificationName, void* pSender = NULL);
//移除观察者
//pObserver是要移除的观察者
//lpNotificationName是指定的通知,为NULL表示移除此观察者所有的通知,否则移除与lpNotificationName以及pSender匹配的观察者
//pSender是消息的发送者,当lpNotificationName为NULL时被忽略
// 为NULL时表示停止观察所有发送者发送的lpNotificationName所对应的消息
virtual void RemoveObserver(WNNotificationObserver* pObserver, const char* lpNotificationName = NULL, void* pSender = NULL);
//投递通知,低效方法,投递之前会先将lpNotificationName转换为Id
//lpNotificationName是通知名称
//pNotificationData是要投递的数据
//pSender是发送者
//成功返回TRUE,失败返回FALSE
virtual bool PostNotification(const char* lpNotificationName, WNObject* pNotificationData = NULL, void* pSender = NULL);
//投递通知,高效方法
//lpNotificationName是通知Id
//pNotificationData是要投递的数据
//pSender是发送者
//成功返回TRUE,失败返回FALSE
virtual bool PostNotification(unsigned int uNotificationId, WNObject* pNotificationData = NULL, void* pSender = NULL);
//投递通知,最高效方法
//pNotification是要投递的通知,投递之前设置muNotificationId以及mpNotificationData即可
//pSender是发送者
//成功返回TRUE,失败返回FALSE
//由于此方法中的pNotification参数可以使用栈上分配的对象,因此效率最高
//需要注意的是,接收者对pNotification进行Retain操作可能会由于是在栈上分配而导致不可预料的结果
//此时可以检测pNotification的mbIsAllocOnHeap成员来判断pNotification是否为栈上分配的
virtual bool PostNotification(WNNotification* pNotification, void* pSender = NULL);
protected:
WNNotificationObserverList** mppNotificationObserverList; //消息观察者列表数组
unsigned int muNotificationListMaxCount; //消息观察者列表数组最大数量
unsigned int muNextNotificationId; //下一次注册时使用的消息id
WNReadWriteLocker* mpReadWriteLocker; //读写锁
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNOBJECT_H
#define WNOBJECT_H
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
class WNObject;
class WNCreticalSection;
class WNObjectDelegate;
template <class T> class WNSmartPtr;
class WNObjectTypeFnBase
{
public:
virtual ~WNObjectTypeFnBase() { }
virtual void DoDestroy(void* pDes) const { }
};
template <typename T>
class WNObjectTypeFn : public WNObjectTypeFnBase
{
public:
virtual ~WNObjectTypeFn() { }
T* DoConvert(void* pDes) const
{
return (T*)(pDes);
}
virtual void DoDestroy(void* pDes) const
{
delete DoConvert(pDes);
}
};
template <typename T>
static WNObjectTypeFn<T>* getWNObjectTypeFnInstance()
{
static WNObjectTypeFn<T> mInstance;
return &mInstance;
}
//只能以指针形式使用
class WNObject
{
public:
WNObject();
virtual ~WNObject();
//初始化计数器
virtual void ResetRefInfo();
//初始化计数器以及设置托管对象
virtual void ResetRefInfoAndDelegate(WNObjectDelegate* pDelegate = NULL);
//设置对象的安全锁
//为空时表示创建安全锁
//否则使用传入的安全锁
virtual void SetSafeLocker(WNCreticalSection* pLocker = NULL);
//获得对象的安全锁
WNCreticalSection* GetSafeLocker();
//取消安全锁
virtual void ResetSafeLocker();
//增加对象的引用
//返回对象的this指针
virtual WNObject* Retain();
//减少对象的引用
//bClearDelayRelease表示是否清空延迟减少计数器
//返回对象的this指针,如果对象已销毁则返回NULL
virtual WNObject* Release(bool bClearDelayRelease = true);
//自动释放
virtual WNSmartPtr<WNObject*> AutoRelease();
//延迟减少对象的引用(增加延迟减少计数器)
//返回对象的this指针
virtual WNObject* DelayRelease();
//处理延迟减少计数器
//如果bOnlySetZero为TRUE,则仅仅将延迟引用计数器置零,
//默认会做如下操作:
//miRetainCount -= miDelayReleaseCount
//如果当前对象引用为0,则会调用delete操作
virtual WNObject* ClearDelayRelease(bool bOlnySetZero = false);
//当前的引用计数器的值
inline int RetainCount() { return miRetainCount; }
//当前延迟引用计数器的值
inline int DelayCount() { return miDelayReleaseCount; }
//当前实际的引用计数器
inline int RefCount() { return miRetainCount - miDelayReleaseCount; }
//设置或者或其托管对象
inline WNObjectDelegate*& Delegate() { return mpDelegate; }
public:
int miRetainCount : 31; //引用计数器
bool mbIsAllocOnHeap : 1; //是否在堆上分配
int miDelayReleaseCount; //延迟减少计数器
WNObjectDelegate* mpDelegate; //托管对象
WNCreticalSection* mpLoker; //安全锁
bool mbIsOwnLocker; //安全锁是否属于自己
void* mpThis; //当前对象new出来的指针
WNObjectTypeFnBase* mpTypeFn; //用于析构mpThis的对象
};
typedef WNObject* obj;
//WNObject*类型的智能指针,T只允许为指针类型
template <class T>
class WNSmartPtr
{
public:
T ptr;
public:
inline WNSmartPtr() { ptr = 0; }
inline WNSmartPtr(const WNSmartPtr<T>& sPtr):ptr(0) { *this = sPtr; }
inline WNSmartPtr(const T& pPtr):ptr(0) { *this = (obj&)pPtr; }
virtual ~WNSmartPtr(){}
template <typename Ptr>
inline WNSmartPtr(const Ptr pPtr):ptr(0) { *this = (obj&)pPtr; }
virtual bool isEqualTo(const obj& pPtr) const
{
return pPtr == (obj)ptr;
}
template <typename Ptr>
inline bool operator == (const Ptr& pPtr) const
{
return isEqualTo((obj&)pPtr);
}
inline bool operator == (const WNSmartPtr<T>& sPtr) const
{
return *this == (obj&)(sPtr.ptr);
}
template <typename Ptr>
inline bool operator != (const Ptr& pPtr) const
{
return (*this == (obj)pPtr)?false:true;
}
inline bool operator != (const WNSmartPtr<T>& sPtr) const
{
return *this != sPtr.ptr;
}
WNSmartPtr<T>& operator = (const obj& pPtr)
{
pPtr->Retain();
if (ptr)
{
pPtr->Release();
ptr = NULL;
}
ptr = (T&)pPtr;
return *this;
}
template <typename Ptr>
inline WNSmartPtr<T>& operator = (const Ptr& pPtr) { return *this = (obj&)pPtr; }
inline WNSmartPtr<T>& operator = (const WNSmartPtr<T>& sPtr) { return *this = (obj&)(sPtr.ptr); }
template <typename ToType>
inline operator ToType& () const { return (ToType&)ptr; }
template <typename ToType>
inline operator ToType () { return (ToType)ptr; }
inline operator obj& () const { return (obj&)(ptr); }
inline operator obj () { return (obj)(ptr); }
inline T& ref() { return (T&)ptr; }
};
class WNObjectDelegate
{
public:
//当WNObject的muRetainCount以及muDelayReleaseCount的差变为0时触发
//如果返回值为TRUE则会delete此对象
virtual bool OnWNObjectRetainCountIsZero(WNObject* pObject) { return true; }
virtual ~WNObjectDelegate(){}
};
//只能以指针形式使用
template <class T>
class WNObjectEx : public WNObject
{
public:
T dataRef;
};
template <typename WNObjectClass>
WNObjectClass* _WNAlloc()
{
WNObjectClass* pObject = new WNObjectClass;
pObject->mbIsAllocOnHeap = true;
pObject->mpThis = pObject;
pObject->mpTypeFn = getWNObjectTypeFnInstance<WNObjectClass>();
return pObject;
}
template <typename WNObjectClass>
WNObjectClass* _WNSafeAlloc()
{
WNObjectClass* pObject = new WNObjectClass;
pObject->SetSafeLocker();
pObject->mbIsAllocOnHeap = true;
pObject->mpThis = pObject;
pObject->mpTypeFn = getWNObjectTypeFnInstance<WNObjectClass>();
return pObject;
}
#ifndef WNAlloc
#define WNAlloc(WNObjectClass) _WNAlloc<WNObjectClass>()
#endif
#ifndef WNSafeAlloc
#define WNSafeAlloc(WNObjectClass) _WNSafeAlloc<WNObjectClass>()
#endif
//#define doRelease(ppObj) _doRelease((WNObject**)(&(ppObj)))
//void _doRelease(WNObject** ppObj);
//#define doAutoRelease(ppObj) _doDelayRelease((WNObject**)(&(ppObj)))
//void _doDelayRelease(WNObject** ppObj);
#define doRelease(pObj) \
if (pObj) \
{ \
pObj->Release(); \
pObj = 0; \
}
#define doDelayRelease(pObj) \
if (pObj) \
{ \
pObj->DelayRelease(); \
pObj = 0; \
}
//template <typename T>
//void doRelease(T*& pObjRef)
//{
// pObjRef->Release();
// pObjRef = NULL;
//}
//
//template <typename T>
//void doDelayRelease(T*& pObjRef)
//{
// pObjRef->DelayRelease();
// pObjRef = NULL;
//}
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNREADWRITELOCKER_H
#define WNREADWRITELOCKER_H
class WNCreticalSection;
class WNReadWriteLocker
{
public:
WNReadWriteLocker();
virtual ~WNReadWriteLocker();
bool LockRead(unsigned long dwTimeOut = 0);
bool LockWrite(unsigned long dwTimeOut = 0);
bool ReleaseRead();
bool ReleaseWrite();
protected:
bool InternalLockRead();
bool InternalLockWrite();
private:
unsigned long m_dwReadCount;
unsigned long m_dwWriteCount;
bool m_bWriting;
WNCreticalSection* mpLocker;
};
#endif
\ No newline at end of file
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNSOCKETOBSERVER_H
#define WNSOCKETOBSERVER_H
#include "WNCLoopList.h"
#include "WNCreticalSection.h"
#include <string>
using namespace std;
class WNSocketObserverTarget;
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#endif
#ifndef SD_BOTH
#define SD_BOTH 2
#endif
#ifndef SOCKET_ERROR
#define SOCKET_ERROR (-1)
#endif
class IWNSocketObserver
{
public:
virtual bool AddSocket(WNSocketObserverTarget* socketInfo) = 0;
virtual bool RemoveSocket(WNSocketObserverTarget* socketInfo) = 0;
virtual bool StartServer() = 0;
virtual bool StopServer() = 0;
virtual const char* GetServerName() = 0;
virtual ~IWNSocketObserver(){}
virtual bool IsWorking() = 0;
};
typedef WNCLoopList<IWNSocketObserver*> WNSocketObserverList;
class WNSocketObserverTargetDelegate
{
public:
//当前socket可读(或可以进行accept操作)
virtual void OnObserverRead(IWNSocketObserver* observer) = 0;
//当前socket错误
virtual void OnObserverError(IWNSocketObserver* observer) = 0;
virtual ~WNSocketObserverTargetDelegate(){}
};
class WNSocketObserverTarget
{
public:
WNSocketObserverTarget();
virtual ~WNSocketObserverTarget();
enum ObserverState
{
None, //不在观察者server中
Adding, //正在添加至观察者列表
Observering, //正在观察
Removing //正在从观察者列表中移除
};
enum SocketState
{
SS_None, //无状态,无有效socket
SS_Normal, //正常状态,可以读写
SS_Listening, //侦听状态
SS_Accepting, //等待accept
SS_Connecting, //连接状态
SS_Reading, //读状态
SS_Writing, //写状态
SS_Closing //正在关闭
};
virtual void CreateLocker();
virtual void DestroyLocker();
virtual bool TryLock();
virtual bool Lock();
virtual bool Unlock();
public:
int mSocket;
volatile SocketState mSocketState;
string mObserverName;
//CRITICAL_SECTION* mpLocker;
WNCreticalSection* mpLocker;
unsigned long mlLockRef;
unsigned long mdwLockedThreadId;
WNSocketObserverTargetDelegate* mpObserverTargetDelegate;
int miObserverErrorCode;
pthread_t mLockedThreadId;
};
typedef WNCLoopList<WNSocketObserverTarget*> WNSocketObserverTargetList;
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNSOCKETOBSERVERMANAGER_H
#define WNSOCKETOBSERVERMANAGER_H
#include "WNSocketObserver.h"
class WNSocketObserverManager
{
public:
WNSocketObserverManager();
public:
static bool RegisterObserver(IWNSocketObserver* observer);
static IWNSocketObserver* GetObserverByName(const char* lpName);
static WNSocketObserverList* GetObserverList();
static bool AddSocket(WNSocketObserverTarget* socketInfo);
static bool RemoveSocket(WNSocketObserverTarget* socketInfo);
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNSOCKETSELECTOBSERVER_H
#define WNSOCKETSELECTOBSERVER_H
#include "WNSocketObserver.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <pthread.h>
class WNSocketSelectObserver : IWNSocketObserver
{
public:
WNSocketSelectObserver();
~WNSocketSelectObserver();
virtual bool AddSocket(WNSocketObserverTarget* socketInfo);
virtual bool RemoveSocket(WNSocketObserverTarget* socketInfo);
virtual bool StartServer();
virtual bool StopServer();
virtual const char* GetServerName();
virtual bool IsWorking();
protected:
static void* SelectThreadProc(void* lpParameter);
virtual bool InternalStartServer();
virtual bool InternalStopServer();
virtual bool InternalAddSocket(WNSocketObserverTarget* socketInfo);
virtual bool InternalRemoveSocket(WNSocketObserverTarget* socketInfo);
virtual long InternalSelectThreadProc();
virtual void CreateLocker();
virtual void DestroyLocker();
virtual bool TryLock();
virtual bool Lock();
virtual bool Unlock();
protected:
pthread_t mdwThreadId; //select线程id
int mThreadHandle; //select线程handle
bool mbIsWorking; //表示工作线程正在工作
bool mbExitThread; //是否需要退出线程
WNSocketObserverTargetList mTargetList; //目标socket列表
WNCreticalSection* mpOperateLocker; //操作锁
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNTIMER_H
#define WNTIMER_H
#include "ACCallback.h"
class WNTimer;
typedef void (*TimerProc)(long hwnd, unsigned int uMsg, unsigned int* idEvent, unsigned long dwTime);
typedef void (*WNTimerDelegate)(WNTimer* pTimer, unsigned int uFireTimes);
class WNTimer : public ACCallbackEx<WNTimerDelegate>
{
public:
WNTimer();
~WNTimer();
//开始计时器
//uInterval表示触发间隔
//如果计时器已经存在,则重置计时器
void StartTimer(unsigned int uInterval);
//停止计时器
void StopTimer();
//触发计时器(调用一次托管函数)
void Fire();
protected:
void InternalTimerProc(int i);
public:
unsigned int* muTimerId;
unsigned int muFireTimes;
unsigned int muInterval;
ACCallbackEx<TimerProc> mTimerProc;
};
#endif
\ No newline at end of file
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef WNWORKTHREAD_H
#define WNWORKTHREAD_H
//#include "WNInvoker.h"
#include "WNCreticalSection.h"
#include "WNNotificationCenter.h"
#include "WNCLoopList.h"
#include <pthread.h>
class WNWorkThread;
class WNNotification;
class WNNotificationObserver;
class WNNotificationCenter;
#define WN_WORK_THREAD_EXIT false
#define WN_WORK_THREAD_CONTINUE true
typedef pthread_t WNThreadId;
enum ThreadResetFlag
{
TRF_ResetMember, //重置成员信息
TRF_DeleteInstance //delete实例
};
class WNWorkThreadDelegate
{
public:
virtual bool OnWorkThreadStart(WNWorkThread* objThread) { return WN_WORK_THREAD_CONTINUE; }
virtual bool OnWorkThreadProc(WNWorkThread* objThread, unsigned int& uStep) { return WN_WORK_THREAD_EXIT; }
virtual unsigned int OnWorkThreadProcEnd(WNWorkThread* objThread) { return 0; }
virtual unsigned int OnWorkThreadNeedSleep(WNWorkThread* objThread) { return 1; }
virtual ~WNWorkThreadDelegate(){}
};
class WNThreadObserverInfoItem
{
public:
WNThreadObserverInfoItem();
WNNotificationObserver* mpObserver;
void* mpSender;
};
typedef WNCLoopList<WNThreadObserverInfoItem> WNThreadObserverInfoItemList;
class WNThreadObserverInfo
{
public:
WNThreadObserverInfo();
unsigned int muNotificationId;
WNNotificationCenter* mpCenter;
WNThreadObserverInfoItemList mObserverList;
};
typedef WNCLoopList<WNThreadObserverInfo> WNThreadObserverInfoList;
class WNWorkThread : public WNNotificationObserver//, public WNInvoker
{
public:
typedef void (*WNThreadDestroyFn)(WNWorkThread* pThread);
public:
WNWorkThread(void);
virtual ~WNWorkThread(void);
static unsigned int GetTickCount();
//线程睡眠,默认单位是毫秒
//最终的睡眠时间是uTimeOut * uMultiplier,单位是微妙
static void Sleep(unsigned int uTimeout, unsigned uMultiplier = 1000);
static void DoEvents(WNWorkThread* pThread = NULL);
static void DoEvents(unsigned int uTimeOut, WNWorkThread* pThread = NULL);
static void DoEventsAndSleep(unsigned int uSleepTime, WNWorkThread* pThread = NULL);
static void DoEventsAndSleep(unsigned int uTimeOut, unsigned int uSleepTime, WNWorkThread* pThread = NULL);
static WNWorkThread* GetCurrentThread();
static WNWorkThread* GetMainThread();
//外部线程调用,结束指定线程
//linux下无法使用
static bool DoTerminateThread(WNThreadId threadId, unsigned int uExitCode = 0 );
//内部线程调用,结束当前函数执行线程
//不建议直接调用,建议使用EndWork()结束线程
static void DoExitThread(unsigned int uExitCode = 0);
virtual void StartWork();
//结束线程
//dwTimeOut表示正常结束后超出多长时间后强制结束线程
//linux下强制结束线程尚未实现
virtual void EndWork(unsigned int dwTimeOut = 500);
//返回是否为主线程
virtual bool IsMainThread();
//返回线程是否正在运行
virtual bool IsThreadRunning();
//返回是否为当前线程
virtual bool IsCurrentThread();
inline WNWorkThreadDelegate*& Delegate() { return mpThreadDelegate; }
inline WNThreadId ThreadId() { return mThreadId; }
inline ThreadResetFlag& ResetFlag( ) { return mResetFlag; }
inline WNThreadDestroyFn ThreadDestroyFn() { return mpThreadDestroyFn; }
//在当前线程添加观察者,指定发送者以及消息中心的通知(字符串),当前线程作为消息中转站
//只有当线程在工作的时候才会有效
//pObserver是观察者
//lpNotificationName是要观察的通知名称
//pSender是发送者,为NULL时表示观察所有发送者发送的lpNotificationName
//pNotification是指定的消息中心,为默认值NULL是表示使用WNNotificationCenter::DefaultCenter()
//返回值为通知Id,返回值为非0表示成功,否则表示失败
virtual unsigned int AddObserve4Notification(WNNotificationObserver* pObserver, const char* lpNotificationName, void* pSender = NULL, WNNotificationCenter* pNotificationCenter = NULL);
//在当前线程移除观察者,指定发送者以及消息中心的通知(字符串),当前线程作为消息中转站
//只有当线程在工作的时候才会有效
//pObserver是观察者
//lpNotificationName是要停止观察的消息名称
//pSender是发送者,为NULL时表示停止观察所有发送者发送的lpNotificationName所对应的消息
//当lpNotificationName为NULL时表示停止观察所有的消息
//pNotification是指定的消息中心,为默认值NULL是表示使用WNNotificationCenter::DefaultCenter()
virtual void RemoveObserve4Notification(WNNotificationObserver* pObserver, const char* lpNotificationName = NULL, void* pSender = NULL, WNNotificationCenter* pNotificationCenter = NULL);
//向当前线程投递消息
virtual bool PostThreadMessage(WNNotification *pNotification);
//处理队列中的线程消息
//返回false表示线程队列中无消息
//返回true表示处理了一个线程消息
virtual bool ProcessMessageInQueue();
//清空线程消息队列
virtual void ClearMessageQueue();
protected:
virtual void OnReceiveNotification(WNNotification* pNotification);
protected:
static void* InternalThreadMain( void* lpParam );
//创建线程
//成功返回true,失败返回false
virtual bool CreateThread();
virtual unsigned int ThreadMain();
virtual bool ThreadProc(unsigned int uStep);
//重置为初始状态(StartWork之前的状态)
//mpThreadDelegate不会重置
virtual void DoReset();
//等待线程结束,在外部线程使用
//dwTimeOut表示超时
//如果在dwTimeOut之内正常结束,则返回true,否则返回false
virtual bool WaitThreadEnd(unsigned int dwTimeOut = 500);
protected:
WNWorkThreadDelegate* mpThreadDelegate;
volatile bool mbExitOutThread; //线程外退出标志
volatile bool mbExitInThread; //线程内退出标志
WNThreadId mThreadId;
void* mThreadHandle;
unsigned int muLastThreadExitCode; //最后一次线程退出代码
volatile bool mbIsThreadRunning; //线程是否正在运行
ThreadResetFlag mResetFlag; //线程重置标志位,线程退出时有效,TRF_DeleteInstance只能在线程自己结束的情况下使用
WNThreadDestroyFn mpThreadDestroyFn; //线程销毁函数
WNCLoopList<WNNotification*> mMsgQueue; //消息处理队列
WNCreticalSection mMsgQueueLocker; //消息处理队列锁
WNThreadObserverInfoList mObserverInfoList; //消息转发映射表
WNCreticalSection mObserverListLocker; //消息转发映射表锁
};
#endif
/*utf8解析行 Don't remove or modify this first line!*/
#ifndef CFG_INI_FILE_H_
#define CFG_INI_FILE_H_
#ifdef __cplusplus
extern "C"
{
#endif
int read_profile_string( char *section, char *key,char *value, int size,char *default_value, const char *file);
int read_profile_int( char *section, char *key,int default_value, const char *file);
int write_profile_string( char *section, char *key, char *value, const char *file);
#ifdef __cplusplus
};
#endif
#endif
# Copyright (C) 2011 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
CFLAGS += -g
CXXFLAGS += -fPIE
#include $(ANDROID_BUILD_TOP)/external/stlport/stlport.mk
include $(ANDROID_BUILD_TOP)/external/stlport/libstlport.mk
LOCAL_MODULE := libWaninCommon
LOCAL_C_INCLUDES += \
$(ANDROID_BUILD_TOP)/wanin/CommonLibraries/include
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_SRC_FILES := WNObject.cpp WNCStringList.cpp IniFileManager.cpp WNWorkThread.cpp WNSocketObserverManager.cpp WNSocketSelectObserver.cpp WNSocketObserver.cpp WNCommonSocket.cpp WNNotificationCenter.cpp WNByteBufferManager.cpp WNByteBuffer.cpp WNReadWriteLocker.cpp MD5Checksum.cpp WNCreticalSection.cpp WNBitIndex.cpp
LOCAL_SHARED_LIBRARIES := liblog libstlport
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
# Copyright (C) 2011 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libWaninCommon
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/../include/
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_SRC_FILES := WNObject.cpp WNCStringList.cpp IniFileManager.cpp WNSocketObserverManager.cpp WNSocketSelectObserver.cpp WNSocketObserver.cpp WNCommonSocket.cpp WNNotificationCenter.cpp WNByteBufferManager.cpp WNByteBuffer.cpp WNReadWriteLocker.cpp MD5Checksum.cpp WNCreticalSection.cpp WNBitIndex.cpp
LOCAL_SHARED_LIBRARIES := liblog libstlport
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
APP_CFLAGS += -fexceptions
APP_STL := stlport_static
/*utf8解析行 Don't remove or modify this first line!*/
#include "IniFileManager.h"
#include<stdlib.h>
#include <string>
using namespace std;
static const u_char charmap[] = {
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
};
int strcasecmp(const char *s1, const char* s2)
{
register const u_char *cm = charmap,
*us1 = (const u_char *)s1,
*us2 = (const u_char *)s2;
while (cm[*us1] == cm[*us2++])
if (*us1++ == '\0')
return (0);
return (cm[*us1] - cm[*--us2]);
}
bool NoCase::compare (const string& x, const string& y)
{
/*string::const_iterator p = x.begin();
string::const_iterator q = y.begin();
while (p != x.end() && q != y.end() && toupper(*p) == toupper(*q))
{
++p;
++q;
}
if (p == x.end())
{
return (q == y.end());
}
if (q == y.end())
{
return false;
}
return (toupper(*p) < toupper(*q));*/
int ret = strcasecmp(x.c_str(),y.c_str());
return (0 == ret) ? true : false;
}
IniKeyInfo::IniKeyInfo()
:m_strKeyName((""))
,m_strKeyValue((""))
,m_strKeyTrimLeft((""))
,m_strKeyTrimRight((""))
,m_strValueTrimLeft((""))
,m_strValueTrimRight((""))
,m_pSection(NULL)
{
}
void IniKeyInfo::SetKeyName(const char* lpKeyName, bool bDoTrim /* = true */)
{
if (!lpKeyName)
{
m_strKeyName = ("");
}
else
{
m_strKeyName = lpKeyName;
}
if (bDoTrim)
{
//得到key的有效以及无效字符串
TrimAndGetTrimValue(m_strKeyName, m_strKeyTrimLeft, m_strKeyTrimRight);
}
}
void IniKeyInfo::SetKeyValue(const char* lpKeyValue, bool bDoTrim /* = true */)
{
if (!lpKeyValue)
{
m_strKeyValue = ("");
}
else
{
m_strKeyValue = lpKeyValue;
}
if (bDoTrim)
{
//得到value的有效以及无效字符串
TrimAndGetTrimValue(m_strKeyValue, m_strValueTrimLeft, m_strValueTrimRight);
}
}
void IniKeyInfo::SetMultiLineString( const char* lpKeyValue )
{
m_strKeyValue = lpKeyValue;
//m_strKeyValue.replace(("\r\n"), ("<br>"));
string searchString = "\r";
string replaceString = "<\r>";
string::size_type pos = 0;
while ( (pos = m_strKeyValue.find(searchString, pos)) != string::npos ) {
m_strKeyValue.replace( pos, searchString.size(), replaceString );
pos++;
}
searchString = "\n";
replaceString = "<\n>";
pos = 0;
while ( (pos = m_strKeyValue.find(searchString, pos)) != string::npos ) {
m_strKeyValue.replace( pos, searchString.size(), replaceString );
pos++;
}
}
long IniKeyInfo::ToLong(long lDefault /* = 0 */)
{
if (m_strKeyValue == (""))
{
return lDefault;
}
else if (NoCase::compare(m_strKeyValue.substr(0,5),(("[Val]"))))
{
return atol(m_strKeyValue.substr(5).c_str());
}
else if(NoCase::compare(m_strKeyValue.substr(0,5).c_str(),"[Sec]"))
{
int iPos = m_strKeyValue.find((","));
string strSec = m_strKeyValue.substr(5, iPos - 5);
string strKey = m_strKeyValue.substr(iPos + 1);
return m_pSection->GetManager()->ToLong(strSec.c_str(), strKey.c_str(), lDefault);
}
return atol(m_strKeyValue.c_str());
}
unsigned long IniKeyInfo::ToULong(unsigned long ulDefault /* = 0 */)
{
if (m_strKeyValue == (""))
{
return ulDefault;
}
else if (NoCase::compare(m_strKeyValue.substr(0,5).c_str(),"[Val]"))
{
return strtoul(m_strKeyValue.substr(5).c_str(), NULL, 10);
}
else if (NoCase::compare(m_strKeyValue.substr(0,5).c_str(),"[Sec]"))
{
int iPos = m_strKeyValue.find((","));
string strSec = m_strKeyValue.substr(5, iPos - 5);
string strKey = m_strKeyValue.substr(iPos + 1);
return m_pSection->GetManager()->ToULong(strSec.c_str(), strKey.c_str(), ulDefault);
}
return strtoul(m_strKeyValue.c_str(), NULL, 10);
return 0;
}
long IniKeyInfo::ToHex(long lDefault /* = 0 */)
{
if (m_strKeyValue == (""))
{
return lDefault;
}
else if (NoCase::compare(m_strKeyValue.substr(0,5),"[Val]"))
{
return strtol(m_strKeyValue.substr(5).c_str(), NULL, 16);
}
else if (NoCase::compare(m_strKeyValue.substr(0,5),"[Sec]"))
{
int iPos = m_strKeyValue.find((","));
string strSec = m_strKeyValue.substr(5, iPos - 5);
string strKey = m_strKeyValue.substr(iPos + 1);
return m_pSection->GetManager()->ToHex(strSec.c_str(), strKey.c_str(), lDefault);
}
return strtol(m_strKeyValue.c_str(),0,16);
}
unsigned long IniKeyInfo::ToUHex(unsigned long ulDefault /* = 0 */)
{
if (m_strKeyValue == (""))
{
return ulDefault;
}
else if (NoCase::compare(m_strKeyValue.substr(0,5),"[Val]"))
{
return strtoul(m_strKeyValue.substr(5).c_str(), NULL, 16);
}
else if (NoCase::compare(m_strKeyValue.substr(0,5),"[Sec]"))
{
int iPos = m_strKeyValue.find((","));
string strSec = m_strKeyValue.substr(5, iPos - 5);
string strKey = m_strKeyValue.substr(iPos + 1);
return m_pSection->GetManager()->ToUHex(strSec.c_str(), strKey.c_str(), ulDefault);
}
return strtoul(m_strKeyValue.c_str(), NULL, 16);
}
double IniKeyInfo::ToDouble(double dblDefault /* = 0.0 */)
{
if (m_strKeyValue == (""))
{
return dblDefault;
}
else if (NoCase::compare(m_strKeyValue.substr(0,5),"[Val]"))
{
return atof(m_strKeyValue.substr(5).c_str());
}
else if (NoCase::compare(m_strKeyValue.substr(0,5),"[Sec]"))
{
int iPos = m_strKeyValue.find((","));
string strSec = m_strKeyValue.substr(5, iPos - 5);
string strKey = m_strKeyValue.substr(iPos + 1);
return m_pSection->GetManager()->ToDouble(strSec.c_str(), strKey.c_str(), dblDefault);
}
return atof(m_strKeyValue.c_str());
}
string IniKeyInfo::ToString(const char* lpDefault /* = ("") */)
{
if (m_strKeyValue == (""))
{
return lpDefault;
}
else if (NoCase::compare(m_strKeyValue.substr(0,5),"[Val]"))
{
return m_strKeyValue.substr(5);
}
else if (NoCase::compare(m_strKeyValue.substr(0,5),"[Sec]"))
{
int iPos = m_strKeyValue.find((","));
string strSec = m_strKeyValue.substr(5, iPos - 5);
string strKey = m_strKeyValue.substr(iPos + 1);
return m_pSection->GetManager()->ToString(strSec.c_str(), strKey.c_str(), lpDefault );
}
return m_strKeyValue;
}
string IniKeyInfo::ToMultiLineString( const char* lpDefault /*= ("")*/ )
{
string strRet = ToString(lpDefault);
/*strRet.Replace(("<br>"), ("\r\n"));*/
string searchString = "<\r>";
string replaceString = "\r";
string::size_type pos = 0;
while ( (pos = strRet.find(searchString, pos)) != string::npos ) {
strRet.replace( pos, searchString.size(), replaceString );
pos++;
}
searchString = "<\n>";
replaceString = "\n";
pos = 0;
while ( (pos = strRet.find(searchString, pos)) != string::npos ) {
strRet.replace( pos, searchString.size(), replaceString );
pos++;
}
return strRet;
}
#define KEY_NAME_EX (m_strKeyTrimLeft + m_strKeyName + m_strKeyTrimRight)
#define KEY_VALUE_EX (m_strValueTrimLeft + m_strKeyValue + m_strValueTrimRight)
string IniKeyInfo::GetText()
{
if (m_strKeyName == (""))
{
return KEY_VALUE_EX;
}
else
{
return KEY_NAME_EX + ('=') + KEY_VALUE_EX;
}
}
string IniKeyInfo::GetTextEx()
{
if (m_strKeyName == (""))
{
if (m_strKeyValue == (""))
{
return KEY_VALUE_EX;
}
else
{
return SplitStrP() + KEY_VALUE_EX;
}
}
else
{
return SplitStrP() + KEY_NAME_EX + ('=') + KEY_VALUE_EX;
}
}
void IniKeyInfo::TrimAndGetTrimValue( string& strSrc, string& strTrimLeft, string& strTrimRight )
{
int iLen = strSrc.length();
//得到左边的无效字符串
strTrimLeft = ("");
for (int i = 0; i < iLen; i++)
{
if ((strSrc[i] != (' ')) && (strSrc[i] != ('\t')))
{
if (i)
{
strTrimLeft = strSrc.substr(0,i);
}
break;
}
}
//得到右边的无效字符串
strTrimRight= ("");
for (int i = 0; i < iLen; i++)
{
if ((strSrc[iLen - i - 1] != (' ')) && (strSrc[iLen - i - 1] != ('\t')))
{
if (i)
{
strTrimRight = strSrc.substr(iLen - i);
}
break;
}
}
//修改strSrc为有效字符串
int iStart = strTrimLeft.length();
int iEnd = iLen - strTrimRight.length();
int iCount = iEnd - iStart;
if (iCount != iLen)
{
strSrc = strSrc.substr(iStart, iCount);
}
}
inline const char* IniKeyInfo::SplitStrP()
{
return m_pSection->GetManager()->SplitStrP();
}
inline string& IniKeyInfo::SplitStrR()
{
return m_pSection->GetManager()->SplitStrR();
}
IniSectionInfo::IniSectionInfo()
:m_strSectionName((""))
,m_pManager(NULL)
{
}
PIniKeyInfo IniSectionInfo::AddKey(const char* lpKeyName, const char* lpKeyValue, bool bReplace /* = true */)
{
PIniKeyInfo pNode = AddKey(lpKeyName);
if (bReplace)
{
pNode->SetKeyValue(lpKeyValue);
}
return pNode;
}
PIniKeyInfo IniSectionInfo::AddKeyEx(const char* lpKeyName)
{
PNode pRet = new Node;
pRet->data.SetKeyName(lpKeyName);
pRet->data.SetSection(this);
AppendNode(pRet);
return &(pRet->data);
}
PIniKeyInfo IniSectionInfo::AddKeyEx(const char* lpKeyName, const char* lpKeyValue)
{
PNode pRet = new Node;
pRet->data.SetKeyName(lpKeyName);
pRet->data.SetKeyValue(lpKeyValue);
pRet->data.SetSection(this);
AppendNode(pRet);
return &(pRet->data);
}
PIniKeyInfo IniSectionInfo::ParseData(const char* lpData, bool bReplace /* = true */)
{
string strData(lpData);
string strSplit(("="));
if (strData == "")
{
AddKeyEx((""), lpData);
}
else if (strData[0] == (':'))
{
return AddKeyEx((""), lpData);
}
else
{
int iPos = strData.find(strSplit);
string strKeyName = strData.substr(0, iPos);
string strKeyValue = strData.substr(iPos + strSplit.length());
if (strKeyName == (""))
{
return AddKeyEx((""), lpData);
}
else
{
return AddKey(strKeyName.c_str(), strKeyValue.c_str(), bReplace);
}
}
return NULL;
}
PIniKeyInfo IniSectionInfo::ParseDataEx(const char* lpData)
{
string strData(lpData);
string strSplit(("="));
if (strData == "")
{
AddKeyEx((""), lpData);
}
else if (strData[0] == (':'))
{
return AddKeyEx((""), lpData);
}
else
{
int iPos = strData.find(strSplit);
if (iPos == -1)
{
return AddKeyEx((""), lpData);
}
else
{
string strKeyName = strData.substr(0, iPos);
string strKeyValue = strData.substr(iPos + strSplit.length());
return AddKeyEx(strKeyName.c_str(), strKeyValue.c_str());
}
}
return 0;
}
PIniKeyInfo IniSectionInfo::GetKey(const char* lpKeyName, bool bAdd /* = false */)
{
for (MoveBegin(); Current() != Head(); MoveNext())
{
if (NoCase::compare(Current()->data.KeyName(),lpKeyName))
{
return &(Current()->data);
}
}
if (bAdd)
{
return AddKeyEx(lpKeyName);
}
else
{
return NULL;
}
return 0;
}
long IniSectionInfo::ToLong(const char* lpKeyName, long lDefault /* = 0 */)
{
PIniKeyInfo pKeyInfo = GetKey(lpKeyName);
if (pKeyInfo)
{
return pKeyInfo->ToLong(lDefault);
}
else
{
return lDefault;
}
}
unsigned long IniSectionInfo::ToULong(const char* lpKeyName, unsigned long ulDefault /* = 0 */)
{
PIniKeyInfo pKeyInfo = GetKey(lpKeyName);
if (pKeyInfo)
{
return pKeyInfo->ToULong(ulDefault);
}
else
{
return ulDefault;
}
}
long IniSectionInfo::ToHex(const char* lpKeyName, long lDefault /* = 0 */)
{
PIniKeyInfo pKeyInfo = GetKey(lpKeyName);
if (pKeyInfo)
{
return pKeyInfo->ToHex(lDefault);
}
else
{
return lDefault;
}
}
unsigned long IniSectionInfo::ToUHex(const char* lpKeyName, unsigned long ulDefault /* = 0 */)
{
PIniKeyInfo pKeyInfo = GetKey(lpKeyName);
if (pKeyInfo)
{
return pKeyInfo->ToUHex(ulDefault);
}
else
{
return ulDefault;
}
}
double IniSectionInfo::ToDouble(const char* lpKeyName, double dblDefault /* = 0.0 */)
{
PIniKeyInfo pKeyInfo = GetKey(lpKeyName);
if (pKeyInfo)
{
return pKeyInfo->ToDouble(dblDefault);
}
else
{
return dblDefault;
}
}
string IniSectionInfo::ToString(const char* lpKeyName, const char* lpDefault /* = ("") */)
{
PIniKeyInfo pKeyInfo = GetKey(lpKeyName);
if (pKeyInfo)
{
return pKeyInfo->ToString(lpDefault);
}
else
{
return lpDefault;
}
}
string IniSectionInfo::ToMultiLineString( const char* lpKeyName, const char* lpDefault /*= ("")*/ )
{
PIniKeyInfo pKeyInfo = GetKey(lpKeyName);
if (pKeyInfo)
{
return pKeyInfo->ToMultiLineString(lpDefault);
}
else
{
return lpDefault;
}
}
string IniSectionInfo::GetText()
{
string strRet((""));
if (m_strSectionName != (""))
{
strRet = ("[") + m_strSectionName + ("]");
for (MoveBegin(); Current() != Head(); MoveNext())
{
strRet += SplitStrP();
strRet += Current()->data.GetText();
}
}
else
{
for (MoveBegin(); Current() != Head(); MoveNext())
{
strRet += Current()->data.GetText();
if (Current() != End())
{
strRet += SplitStrP();
}
}
}
return strRet;
}
string IniSectionInfo::GetTextEx()
{
string strRet((""));
if (m_strSectionName != (""))
{
strRet = ("[") + m_strSectionName + ("]");
}
else
{
return strRet;
}
for (MoveBegin(); Current() != Head(); MoveNext())
{
strRet += Current()->data.GetTextEx();
}
return strRet;
}
void IniSectionInfo::JoinTo(IniSectionInfo& tarSection)
{
for (MoveBegin(); Current() != Head(); MoveNext())
{
PIniKeyInfo pTarKey = tarSection.GetKey(Current()->data.KeyName().c_str());
if (!pTarKey)
{
tarSection.AddKeyEx(Current()->data.KeyName().c_str(), Current()->data.KeyValue().c_str());
}
}
}
inline const char* IniSectionInfo::SplitStrP()
{
return m_pManager->SplitStrP();
}
inline string& IniSectionInfo::SplitStrR()
{
return m_pManager->SplitStrR();
}
IniFileManager::IniFileManager(bool bAutoSave /* = false */)
:mstrIniFileName((""))
,mstrLineSplit(INI_CRLF)
,m_bUnicode(false)
,m_bAutoSave(bAutoSave)
{
Head()->data.SetManager(this);
}
IniFileManager::~IniFileManager()
{
if (DidStateChanged())
{
SaveFile();
}
}
PIniSectionInfo IniFileManager::AddSectionEx(const char* lpSectionName)
{
PNode pRet = new Node;
pRet->data.SectionName() = lpSectionName;
pRet->data.SetManager(this);
AppendNode(pRet);
return &(pRet->data);
}
PIniSectionInfo IniFileManager::GetSection(const char* lpSectionName, bool bAdd /* = false */)
{
string strSecName(lpSectionName);
if (strSecName == (""))
{
return &(Head()->data);
}
if (ListCount())
{
for (MoveBegin(); Current() != Head(); MoveNext())
{
if (NoCase::compare(Current()->data.SectionName().c_str(),(lpSectionName)))
{
return &(Current()->data);
}
}
}
if (bAdd)
{
return AddSectionEx(lpSectionName);
}
else
{
return NULL;
}
}
bool IniFileManager::ParseSectionName(const char* lpData, string& strSectionName)
{
string strData(lpData);
if (strData.substr(0,1) == ("[") && strData.substr(strData.length() - 1) == ("]") && strData.length() > 2 )
{
strSectionName = strData.substr(1, strData.length() - 2);
return true;
}
else
{
strSectionName = strData;
return false;
}
return true;
}
PIniSectionInfo IniFileManager::ParseLine(const char* lpData, bool* pbReplace /* = NULL */)
{
string strSectionName((""));
//if (strSectionName == lpData)
//{
// return NULL;
//}
if (ParseSectionName(lpData, strSectionName))
{
if (!pbReplace)
{
return AddSectionEx(strSectionName.c_str());
}
else
{
return AddSection(strSectionName.c_str(), *pbReplace);
}
}
else
{
if (!pbReplace)
{
PIniSectionInfo pRet = &(MoveEnd()->data);
pRet->ParseDataEx(lpData);
return pRet;
}
else
{
PIniSectionInfo pRet = &(MoveEnd()->data);
pRet->ParseData(lpData, *pbReplace);
return pRet;
}
}
return NULL;
}
bool IniFileManager::ParseData(const char* lpData, bool* pbReplace /* = NULL */)
{
if (!pbReplace)
{
Head()->data.ClearList();
ClearList();
}
string strData(lpData);
string strSplit((""));
string strLine((""));
int iPos = 0;
int iLastPos = 0;
//检查行分隔符
while (true)
{
if (string::npos != strData.find("\r\n"))
{
//找到"\r\n"作为换行行分隔符
strSplit = "\r\n";
break;
}
if (string::npos != strData.find("\n"))
{
//找到"\n"(0x0A)作为换行分隔符
strSplit = "\n";
break;
}
if (string::npos != strData.find("\r"))
{
//找到"\r"(0x0D)作为换行分隔符
strSplit = "\r";
break;
}
//使用默认换行分隔符
strSplit = INI_CRLF;
break;
}
while (true)
{
iLastPos = strData.find(strSplit, iPos);
if (iLastPos == -1)
{
strLine = strData.substr(iPos);
ParseLine(strLine.c_str());
if (m_bAutoSave)
{
SaveState();
}
//保存换行分隔符
mstrLineSplit = strSplit;
return true;
}
else
{
strLine = strData.substr(iPos, iLastPos - iPos);
ParseLine(strLine.c_str());
iPos += strLine.length();
iPos += strSplit.length();
}
}
//保存换行分隔符
mstrLineSplit = strSplit;
return true;
}
bool IniFileManager::ParseFile(const char* lpFileName, bool* pbReplace /* = NULL */)
{
int filesize = 0;
FILE *fp;
fp = fopen(lpFileName, "rb");
if(fp == NULL)
{
if (m_bAutoSave)
{
mstrIniFileName = lpFileName;
SaveState();
}
return false;
}
fseek(fp, 0L, SEEK_END);
filesize = ftell(fp);
//fclose(fp);
if (filesize == 0)
{
return false;
}
char* pbData = new char[filesize + 1];
memset(pbData, 0x00,filesize + 1);
fseek(fp, 0L, 0);
fread(pbData,filesize,1,fp);
fclose(fp);
bool bRet = false;
if((pbData[0] == 0xEE) && (pbData[1] == 0xBB) && (pbData[2] == 0xBF)){
m_bUnicode = true;
bRet = ParseData(reinterpret_cast<const char*>(pbData + 3), pbReplace);
}else{
bRet = ParseData(reinterpret_cast<const char*>(pbData), pbReplace);
}
/*if (!bRet)
{
if (m_bAutoSave)
{
mstrIniFileName = lpFileName;
SaveState();
}
delete[] pbData;
return false;
}
else*/
{
//mstrIniFileName = lpFileName;
/* if ((pbData[0] == 0xFF) && (pbData[1] == 0xFE))
{
bRet = ParseData(reinterpret_cast<const char*>(pbData + 2), pbReplace);
m_bUnicode = true;
}
else
{
m_bUnicode = false;
int iSize = ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, reinterpret_cast<LPCSTR>(pbData), -1, NULL, 0);
if (!iSize)
{
bRet = ParseData(reinterpret_cast<const char*>(pbData), pbReplace);
}
else
{
string strData((""));
char* lpData = strData.GetBuffer((iSize + 1) * sizeof(TCHAR));
memset(lpData, (iSize + 1) * sizeof(TCHAR));
::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, reinterpret_cast<LPCSTR>(pbData), -1, lpData, (iSize + 1) * sizeof(TCHAR));
strData.ReleaseBuffer();
bRet = ParseData(strData, pbReplace);
}
}*/
mstrIniFileName = lpFileName;
delete[] pbData;
return bRet;
}
return true;
}
bool IniFileManager::SaveFile(const char* lpFileName /* = NULL */, bool* pbUnicode /* = NULL */)
{
string strFileName = lpFileName?lpFileName:mstrIniFileName;
if (strFileName == (""))
{
return false;
}
string strText = ("");
bool bUnicode = m_bUnicode;
if (!pbUnicode)
{
bUnicode = m_bUnicode;
}
else
{
bUnicode = *pbUnicode;
}
if (bUnicode)
{
strText = ("\xEF\xBB\xBF");
}
strText += GetText();
FILE *fp = NULL;
fp = fopen(strFileName.c_str(), "wb+");
if(fp == NULL)
return false;
fwrite(strText.c_str(),strText.length(),1,fp);
fclose(fp);
//save tor file wlf
/*if (bUnicode)
{
int iLen = strText.GetLength();
char* lpData = strText.GetBuffer((iLen + 1) * sizeof(TCHAR));
bool bRet = ::SaveFile(strFileName, lpData, iLen * sizeof(TCHAR));
strText.ReleaseBuffer();
return bRet;
}
else
{
int iLen = strText.GetLength();
int iBufLen = (iLen + 1) * sizeof(TCHAR);
char* lpData = strText.GetBuffer(iBufLen);
unsigned char* pData = new unsigned char[iBufLen];
memset(pData, iBufLen);
int iWrite = ::WideCharToMultiByte(CP_ACP, 0, lpData, -1, reinterpret_cast<LPSTR>(pData), iBufLen, NULL, NULL);
bool bRet = ::SaveFile(strFileName, pData, iWrite - 1);
strText.ReleaseBuffer();
delete[] pData;
return bRet;
}
*/
return true;
}
bool IniFileManager::SaveFileEx(const char* lpFileName /* = NULL */, bool* pbUnicode /* = NULL */)
{
string strFileName = lpFileName?lpFileName:mstrIniFileName;
strFileName = lpFileName;
if (strFileName == (""))
{
return false;
}
string strText = ("");
bool bUnicode = m_bUnicode;
if (!pbUnicode)
{
bUnicode = m_bUnicode;
}
else
{
bUnicode = *pbUnicode;
}
if (bUnicode)
{
strText = ("\xEF\xBB\xBF");
}
strText += GetTextEx();
FILE *fp = NULL;
fp = fopen(strFileName.c_str(), "wb+");
if(fp == NULL){
perror("t:");
return false;
}
fwrite(strText.c_str(),strText.length(),1,fp);
fclose(fp);
bool bRet = true;
return bRet;
}
long IniFileManager::ToLong(const char* lpSectionName, const char* lpKeyName, long lDefault /* = 0 */)
{
PIniSectionInfo pSectionInfo = GetSection(lpSectionName);
if (!pSectionInfo)
{
return lDefault;
}
if (pSectionInfo == &(Head()->data))
{
return lDefault;
}
else
{
return pSectionInfo->ToLong(lpKeyName, lDefault);
}
}
unsigned long IniFileManager::ToULong(const char* lpSectionName, const char* lpKeyName, unsigned long ulDefault /* = 0 */)
{
PIniSectionInfo pSectionInfo = GetSection(lpSectionName);
if (!pSectionInfo)
{
return ulDefault;
}
if (pSectionInfo == &(Head()->data))
{
return ulDefault;
}
else
{
return pSectionInfo->ToULong(lpKeyName, ulDefault);
}
}
long IniFileManager::ToHex(const char* lpSectionName, const char* lpKeyName, long lDefault /* = 0 */)
{
PIniSectionInfo pSectionInfo = GetSection(lpSectionName);
if (!pSectionInfo)
{
return lDefault;
}
if (pSectionInfo == &(Head()->data))
{
return lDefault;
}
else
{
return pSectionInfo->ToHex(lpKeyName, lDefault);
}
}
unsigned long IniFileManager::ToUHex(const char* lpSectionName, const char* lpKeyName, unsigned long ulDefault /* = 0 */)
{
PIniSectionInfo pSectionInfo = GetSection(lpSectionName);
if (!pSectionInfo)
{
return ulDefault;
}
if (pSectionInfo == &(Head()->data))
{
return ulDefault;
}
else
{
return pSectionInfo->ToUHex(lpKeyName, ulDefault);
}
}
double IniFileManager::ToDouble( const char* lpSectionName, const char* lpKeyName, double dblDefault /*= 0.0*/ )
{
PIniSectionInfo pSectionInfo = GetSection(lpSectionName);
if (!pSectionInfo)
{
return dblDefault;
}
if (pSectionInfo == &(Head()->data))
{
return dblDefault;
}
else
{
return pSectionInfo->ToDouble(lpKeyName, dblDefault);
}
}
string IniFileManager::ToString(const char* lpSectionName, const char* lpKeyName, const char* lpDefault /* = ("") */)
{
PIniSectionInfo pSectionInfo = GetSection(lpSectionName);
if (!pSectionInfo)
{
return lpDefault;
}
if (pSectionInfo == &(Head()->data))
{
return lpDefault;
}
else
{
return pSectionInfo->ToString(lpKeyName, lpDefault);
}
}
string IniFileManager::ToMultiLineString( const char* lpSectionName, const char* lpKeyName, const char* lpDefault /*= ("")*/ )
{
PIniSectionInfo pSectionInfo = GetSection(lpSectionName);
if (!pSectionInfo)
{
return lpDefault;
}
if (pSectionInfo == &(Head()->data))
{
return lpDefault;
}
else
{
return pSectionInfo->ToMultiLineString(lpKeyName, lpDefault);
}
}
string IniFileManager::GetText()
{
string strRet = Head()->data.GetText();
if (!ListCount())
{
return strRet;
}
for (MoveBegin(); Current() != Head(); MoveNext())
{
if (strRet == "")
{
strRet += Current()->data.GetText();
}
else
{
strRet +=SplitStrP();
strRet += Current()->data.GetText();
}
}
return strRet;
if (strRet == (""))
{
MoveBegin();
if (Current() != Head())
{
strRet = Current()->data.GetText();
}
else
{
return strRet;
}
while (strRet == (""))
{
MoveNext();
if (Current() != Head())
{
strRet = Current()->data.GetText();
}
else
{
return strRet;
}
}
if (strRet.substr(strRet.length() - SplitStrR().length()) != SplitStrP())
{
strRet += SplitStrP();
}
for (MoveNext(); Current() != Head(); MoveNext())
{
strRet += SplitStrP();
strRet += Current()->data.GetText();
}
}
else
{
for (MoveBegin(); Current() != Head(); MoveNext())
{
if (strRet.substr(strRet.length() - SplitStrR().length()) != SplitStrP())
{
strRet += SplitStrP();
}
strRet += SplitStrP();
strRet += Current()->data.GetText();
}
}
return strRet;
}
string IniFileManager::GetTextEx()
{
string strRet((""));
MoveBegin();
if (Current() != Head())
{
strRet = Current()->data.GetTextEx();
}
else
{
return strRet;
}
while (strRet == (""))
{
MoveNext();
if (Current() != Head())
{
strRet = Current()->data.GetTextEx();
}
else
{
return strRet;
}
}
for (MoveNext(); Current() != Head(); MoveNext())
{
strRet += SplitStrP();
strRet += SplitStrP();
strRet += Current()->data.GetTextEx();
}
return strRet;
}
void IniFileManager::JoinTo(IniFileManager& tarIniManager)
{
for (MoveBegin(); Current() != Head(); MoveNext())
{
PIniSectionInfo pTarSection = tarIniManager.GetSection(Current()->data.SectionName().c_str(), true);
Current()->data.JoinTo(*pTarSection);
}
}
void IniFileManager::SetAutoSave( bool bAutoSave )
{
if (bAutoSave == m_bAutoSave)
{
return;
}
m_bAutoSave = bAutoSave;
if (m_bAutoSave && mstrIniFileName != (""))
{
SaveState();
}
}
void IniFileManager::SaveState()
{
mstrContentSaved = GetTextEx();
}
bool IniFileManager::DidStateChanged()
{
if (m_bAutoSave)
{
return (mstrContentSaved == GetTextEx())?false:true;
}
else
{
return false;
}
}
bool IniFileManager::DidStateChangedEx()
{
return (mstrContentSaved == GetTextEx())?false:true;
}
inline const char* IniFileManager::SplitStrP()
{
return mstrLineSplit.c_str();
}
inline string& IniFileManager::SplitStrR()
{
return mstrLineSplit;
}
/*utf8解析行 Don't remove or modify this first line!*/
// MD5Checksum.cpp: implementation of the MD5Checksum class.
//
//////////////////////////////////////////////////////////////////////
/****************************************************************************************
This software is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
Incorporation of this statement is a condition of use; please see the RSA
Data Security Inc copyright notice below:-
Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
rights reserved.
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.
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.
*****************************************************************************************/
/****************************************************************************************
This implementation of the RSA MD5 Algorithm was written by Langfine Ltd
(www.langfine.com).
Langfine Ltd 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.
In addition to the above, Langfine make no warrant or assurances regarding the
accuracy of this implementation of the MD5 checksum algorithm nor any assurances regarding
its suitability for any purposes.
This implementation may be used freely provided that Langfine is credited
in a copyright or similar notices (eg, RSA MD5 Algorithm implemented by Langfine
Ltd.) and provided that the RSA Data Security notices are complied with.
*/
#ifdef __WINOS__
#include "stdafx.h"
#endif
#include "MD5Checksum.h"
#include "MD5ChecksumDefines.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/*****************************************************************************************
FUNCTION: CMD5Checksum::GetMD5
DETAILS: static, public
DESCRIPTION: Gets the MD5 checksum for a specified file
RETURNS: string : the hexadecimal MD5 checksum for the specified file
ARGUMENTS: string& strFilePath : the full pathname of the specified file
NOTES: Provides an interface to the CMD5Checksum class. 'strFilePath' name should
hold the full pathname of the file, eg C:\My Documents\Arcticle.txt.
NB. If any problems occur with opening or reading this file, a CFileException
will be thrown; callers of this function should be ready to catch this
exception.
*****************************************************************************************/
string CMD5Checksum::GetMD5(const string& strFilePath)
{
//open the file as a binary file in readonly mode, denying write access
fstream File;
File.open(strFilePath.c_str(),ios::in | ios::out | ios::binary);
if(File.is_open()){
//the file has been successfully opened, so now get and return its checksum
return GetMD5(File);
}else{
return "error";
}
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::GetMD5
DETAILS: static, public
DESCRIPTION: Gets the MD5 checksum for a specified file
RETURNS: string : the hexadecimal MD5 checksum for the specified file
ARGUMENTS: CFile& File : the specified file
NOTES: Provides an interface to the CMD5Checksum class. 'File' should be open in
binary readonly mode before calling this function.
NB. Callers of this function should be ready to catch any CFileException
thrown by the CFile functions
*****************************************************************************************/
string CMD5Checksum::GetMD5(fstream & File)
{
//try
//{
CMD5Checksum MD5Checksum; //checksum object
int nLength = 0; //number of bytes read from the file
const int nBufferSize = 1024; //checksum the file in blocks of 1024 bytes
unsigned char Buffer[nBufferSize]; //buffer for data read from the file
//checksum the file in blocks of 1024 bytes
char bu[1024];
File.seekg (0, File.beg);
File.read( bu, nBufferSize);
nLength = File.gcount();
while (nLength > 0 )
{
MD5Checksum.Update( Buffer, nLength );
nLength = File.gcount();
}
//finalise the checksum and return it
return MD5Checksum.Final();
//}
//report any file exceptions in debug mode only
/*catch (CFileException* e )
{
TRACE0("CMD5Checksum::GetMD5: CFileException caught");
throw e;
}*/
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::GetMD5
DETAILS: static, public
DESCRIPTION: Gets the MD5 checksum for data in a unsigned char array
RETURNS: string : the hexadecimal MD5 checksum for the specified data
ARGUMENTS: unsigned char* pBuf : pointer to the unsigned char array
unsigned int nLength : number of BYTEs of data to be checksumed
NOTES: Provides an interface to the CMD5Checksum class. Any data that can
be cast to a unsigned char array of known length can be checksummed by this
function. Typically, string and char arrays will be checksumed,
although this function can be used to check the integrity of any unsigned char array.
A buffer of zero length can be checksummed; all buffers of zero length
will return the same checksum.
*****************************************************************************************/
string CMD5Checksum::GetMD5(unsigned char* pBuf, unsigned int nLength)
{
//entry invariants
//wlfAfxIsValidAddress(pBuf,nLength,FALSE);
//calculate and return the checksum
CMD5Checksum MD5Checksum;
MD5Checksum.Update( pBuf, nLength );
return MD5Checksum.Final();
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::RotateLeft
DETAILS: private
DESCRIPTION: Rotates the bits in a 32 bit unsigned long left by a specified amount
RETURNS: The rotated unsigned long
ARGUMENTS: unsigned long x : the value to be rotated
int n : the number of bits to rotate by
*****************************************************************************************/
unsigned long CMD5Checksum::RotateLeft(unsigned long x, int n)
{
//check that unsigned long is 4 bytes long - true in Visual C++ 6 and 32 bit Windows
// ASSERT( sizeof(x) == 4 );
//rotate and return x
return (x << n) | (x >> (32-n));
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::FF
DETAILS: protected
DESCRIPTION: Implementation of basic MD5 transformation algorithm
RETURNS: none
ARGUMENTS: unsigned long &A, B, C, D : Current (partial) checksum
unsigned long X : Input data
unsigned long S : MD5_SXX Transformation constant
unsigned long T : MD5_TXX Transformation constant
NOTES: None
*****************************************************************************************/
void CMD5Checksum::FF( unsigned long& A, unsigned long B, unsigned long C, unsigned long D, unsigned long X, unsigned long S, unsigned long T)
{
unsigned long F = (B & C) | (~B & D);
A += F + X + T;
A = RotateLeft(A, S);
A += B;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::GG
DETAILS: protected
DESCRIPTION: Implementation of basic MD5 transformation algorithm
RETURNS: none
ARGUMENTS: unsigned long &A, B, C, D : Current (partial) checksum
unsigned long X : Input data
unsigned long S : MD5_SXX Transformation constant
unsigned long T : MD5_TXX Transformation constant
NOTES: None
*****************************************************************************************/
void CMD5Checksum::GG( unsigned long& A, unsigned long B, unsigned long C, unsigned long D, unsigned long X, unsigned long S, unsigned long T)
{
unsigned long G = (B & D) | (C & ~D);
A += G + X + T;
A = RotateLeft(A, S);
A += B;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::HH
DETAILS: protected
DESCRIPTION: Implementation of basic MD5 transformation algorithm
RETURNS: none
ARGUMENTS: unsigned long &A, B, C, D : Current (partial) checksum
unsigned long X : Input data
unsigned long S : MD5_SXX Transformation constant
unsigned long T : MD5_TXX Transformation constant
NOTES: None
*****************************************************************************************/
void CMD5Checksum::HH( unsigned long& A, unsigned long B, unsigned long C, unsigned long D, unsigned long X, unsigned long S, unsigned long T)
{
unsigned long H = (B ^ C ^ D);
A += H + X + T;
A = RotateLeft(A, S);
A += B;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::II
DETAILS: protected
DESCRIPTION: Implementation of basic MD5 transformation algorithm
RETURNS: none
ARGUMENTS: unsigned long &A, B, C, D : Current (partial) checksum
unsigned long X : Input data
unsigned long S : MD5_SXX Transformation constant
unsigned long T : MD5_TXX Transformation constant
NOTES: None
*****************************************************************************************/
void CMD5Checksum::II( unsigned long& A, unsigned long B, unsigned long C, unsigned long D, unsigned long X, unsigned long S, unsigned long T)
{
unsigned long I = (C ^ (B | ~D));
A += I + X + T;
A = RotateLeft(A, S);
A += B;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::ByteToDWord
DETAILS: private
DESCRIPTION: Transfers the data in an 8 bit array to a 32 bit array
RETURNS: void
ARGUMENTS: unsigned long* Output : the 32 bit (unsigned long) destination array
unsigned char* Input : the 8 bit (unsigned char) source array
unsigned int nLength : the number of 8 bit data items in the source array
NOTES: Four BYTES from the input array are transferred to each unsigned long entry
of the output array. The first unsigned char is transferred to the bits (0-7)
of the output unsigned long, the second unsigned char to bits 8-15 etc.
The algorithm assumes that the input array is a multiple of 4 bytes long
so that there is a perfect fit into the array of 32 bit words.
*****************************************************************************************/
void CMD5Checksum::ByteToDWord(unsigned long* Output, unsigned char* Input, unsigned int nLength)
{
//entry invariants
// ASSERT( nLength % 4 == 0 );
//wlf ASSERT( AfxIsValidAddress(Output, nLength/4, TRUE) );
//wlf ASSERT( AfxIsValidAddress(Input, nLength, FALSE) );
//initialisations
unsigned int i=0; //index to Output array
unsigned int j=0; //index to Input array
//transfer the data by shifting and copying
for ( ; j < nLength; i++, j += 4)
{
Output[i] = (unsigned long)Input[j] |
(unsigned long)Input[j+1] << 8 |
(unsigned long)Input[j+2] << 16 |
(unsigned long)Input[j+3] << 24;
}
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::Transform
DETAILS: protected
DESCRIPTION: MD5 basic transformation algorithm; transforms 'm_lMD5'
RETURNS: void
ARGUMENTS: unsigned char Block[64]
NOTES: An MD5 checksum is calculated by four rounds of 'Transformation'.
The MD5 checksum currently held in m_lMD5 is merged by the
transformation process with data passed in 'Block'.
*****************************************************************************************/
void CMD5Checksum::Transform(unsigned char Block[64])
{
//initialise local data with current checksum
unsigned long a = m_lMD5[0];
unsigned long b = m_lMD5[1];
unsigned long c = m_lMD5[2];
unsigned long d = m_lMD5[3];
//copy BYTES from input 'Block' to an array of ULONGS 'X'
unsigned long X[16];
ByteToDWord( X, Block, 64 );
//Perform Round 1 of the transformation
FF (a, b, c, d, X[ 0], MD5_S11, MD5_T01);
FF (d, a, b, c, X[ 1], MD5_S12, MD5_T02);
FF (c, d, a, b, X[ 2], MD5_S13, MD5_T03);
FF (b, c, d, a, X[ 3], MD5_S14, MD5_T04);
FF (a, b, c, d, X[ 4], MD5_S11, MD5_T05);
FF (d, a, b, c, X[ 5], MD5_S12, MD5_T06);
FF (c, d, a, b, X[ 6], MD5_S13, MD5_T07);
FF (b, c, d, a, X[ 7], MD5_S14, MD5_T08);
FF (a, b, c, d, X[ 8], MD5_S11, MD5_T09);
FF (d, a, b, c, X[ 9], MD5_S12, MD5_T10);
FF (c, d, a, b, X[10], MD5_S13, MD5_T11);
FF (b, c, d, a, X[11], MD5_S14, MD5_T12);
FF (a, b, c, d, X[12], MD5_S11, MD5_T13);
FF (d, a, b, c, X[13], MD5_S12, MD5_T14);
FF (c, d, a, b, X[14], MD5_S13, MD5_T15);
FF (b, c, d, a, X[15], MD5_S14, MD5_T16);
//Perform Round 2 of the transformation
GG (a, b, c, d, X[ 1], MD5_S21, MD5_T17);
GG (d, a, b, c, X[ 6], MD5_S22, MD5_T18);
GG (c, d, a, b, X[11], MD5_S23, MD5_T19);
GG (b, c, d, a, X[ 0], MD5_S24, MD5_T20);
GG (a, b, c, d, X[ 5], MD5_S21, MD5_T21);
GG (d, a, b, c, X[10], MD5_S22, MD5_T22);
GG (c, d, a, b, X[15], MD5_S23, MD5_T23);
GG (b, c, d, a, X[ 4], MD5_S24, MD5_T24);
GG (a, b, c, d, X[ 9], MD5_S21, MD5_T25);
GG (d, a, b, c, X[14], MD5_S22, MD5_T26);
GG (c, d, a, b, X[ 3], MD5_S23, MD5_T27);
GG (b, c, d, a, X[ 8], MD5_S24, MD5_T28);
GG (a, b, c, d, X[13], MD5_S21, MD5_T29);
GG (d, a, b, c, X[ 2], MD5_S22, MD5_T30);
GG (c, d, a, b, X[ 7], MD5_S23, MD5_T31);
GG (b, c, d, a, X[12], MD5_S24, MD5_T32);
//Perform Round 3 of the transformation
HH (a, b, c, d, X[ 5], MD5_S31, MD5_T33);
HH (d, a, b, c, X[ 8], MD5_S32, MD5_T34);
HH (c, d, a, b, X[11], MD5_S33, MD5_T35);
HH (b, c, d, a, X[14], MD5_S34, MD5_T36);
HH (a, b, c, d, X[ 1], MD5_S31, MD5_T37);
HH (d, a, b, c, X[ 4], MD5_S32, MD5_T38);
HH (c, d, a, b, X[ 7], MD5_S33, MD5_T39);
HH (b, c, d, a, X[10], MD5_S34, MD5_T40);
HH (a, b, c, d, X[13], MD5_S31, MD5_T41);
HH (d, a, b, c, X[ 0], MD5_S32, MD5_T42);
HH (c, d, a, b, X[ 3], MD5_S33, MD5_T43);
HH (b, c, d, a, X[ 6], MD5_S34, MD5_T44);
HH (a, b, c, d, X[ 9], MD5_S31, MD5_T45);
HH (d, a, b, c, X[12], MD5_S32, MD5_T46);
HH (c, d, a, b, X[15], MD5_S33, MD5_T47);
HH (b, c, d, a, X[ 2], MD5_S34, MD5_T48);
//Perform Round 4 of the transformation
II (a, b, c, d, X[ 0], MD5_S41, MD5_T49);
II (d, a, b, c, X[ 7], MD5_S42, MD5_T50);
II (c, d, a, b, X[14], MD5_S43, MD5_T51);
II (b, c, d, a, X[ 5], MD5_S44, MD5_T52);
II (a, b, c, d, X[12], MD5_S41, MD5_T53);
II (d, a, b, c, X[ 3], MD5_S42, MD5_T54);
II (c, d, a, b, X[10], MD5_S43, MD5_T55);
II (b, c, d, a, X[ 1], MD5_S44, MD5_T56);
II (a, b, c, d, X[ 8], MD5_S41, MD5_T57);
II (d, a, b, c, X[15], MD5_S42, MD5_T58);
II (c, d, a, b, X[ 6], MD5_S43, MD5_T59);
II (b, c, d, a, X[13], MD5_S44, MD5_T60);
II (a, b, c, d, X[ 4], MD5_S41, MD5_T61);
II (d, a, b, c, X[11], MD5_S42, MD5_T62);
II (c, d, a, b, X[ 2], MD5_S43, MD5_T63);
II (b, c, d, a, X[ 9], MD5_S44, MD5_T64);
//add the transformed values to the current checksum
m_lMD5[0] += a;
m_lMD5[1] += b;
m_lMD5[2] += c;
m_lMD5[3] += d;
}
/*****************************************************************************************
CONSTRUCTOR: CMD5Checksum
DESCRIPTION: Initialises member data
ARGUMENTS: None
NOTES: None
*****************************************************************************************/
CMD5Checksum::CMD5Checksum()
{
// zero members
memset( m_lpszBuffer, 0, 64 );
m_nCount[0] = m_nCount[1] = 0;
// Load magic state initialization constants
m_lMD5[0] = MD5_INIT_STATE_0;
m_lMD5[1] = MD5_INIT_STATE_1;
m_lMD5[2] = MD5_INIT_STATE_2;
m_lMD5[3] = MD5_INIT_STATE_3;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::DWordToByte
DETAILS: private
DESCRIPTION: Transfers the data in an 32 bit array to a 8 bit array
RETURNS: void
ARGUMENTS: unsigned char* Output : the 8 bit destination array
unsigned long* Input : the 32 bit source array
unsigned int nLength : the number of 8 bit data items in the source array
NOTES: One unsigned long from the input array is transferred into four BYTES
in the output array. The first (0-7) bits of the first unsigned long are
transferred to the first output unsigned char, bits bits 8-15 are transferred from
the second unsigned char etc.
The algorithm assumes that the output array is a multiple of 4 bytes long
so that there is a perfect fit of 8 bit BYTES into the 32 bit DWORDs.
*****************************************************************************************/
void CMD5Checksum::DWordToByte(unsigned char* Output, unsigned long* Input, unsigned int nLength )
{
//entry invariants
//wlf ASSERT( nLength % 4 == 0 );
//wlf ASSERT( AfxIsValidAddress(Output, nLength, TRUE) );
//wlf ASSERT( AfxIsValidAddress(Input, nLength/4, FALSE) );
//transfer the data by shifting and copying
unsigned int i = 0;
unsigned int j = 0;
for ( ; j < nLength; 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);
}
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::Final
DETAILS: protected
DESCRIPTION: Implementation of main MD5 checksum algorithm; ends the checksum calculation.
RETURNS: string : the final hexadecimal MD5 checksum result
ARGUMENTS: None
NOTES: Performs the final MD5 checksum calculation ('Update' does most of the work,
this function just finishes the calculation.)
*****************************************************************************************/
string CMD5Checksum::Final()
{
//Save number of bits
unsigned char Bits[8];
DWordToByte( Bits, m_nCount, 8 );
//Pad out to 56 mod 64.
unsigned int nIndex = (unsigned int)((m_nCount[0] >> 3) & 0x3f);
unsigned int nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex);
Update( PADDING, nPadLen );
//Append length (before padding)
Update( Bits, 8 );
//Store final state in 'lpszMD5'
const int nMD5Size = 16;
unsigned char lpszMD5[ nMD5Size ];
DWordToByte( lpszMD5, m_lMD5, nMD5Size );
//Convert the hexadecimal checksum to a string
string strMD5;
for ( int i=0; i < nMD5Size; i++)
{
string Str;
if (lpszMD5[i] == 0) {
Str = string("00");
}
else if (lpszMD5[i] <= 15) {
//Str.Format("0%x",lpszMD5[i]);
Str.append("0%x",lpszMD5[i]);
}
else {
Str.append("%x",lpszMD5[i]);
}
// ASSERT( Str.length() == 2 );
strMD5 += Str;
}
// ASSERT( strMD5.length() == 32 );
return strMD5;
}
/*****************************************************************************************
FUNCTION: CMD5Checksum::Update
DETAILS: protected
DESCRIPTION: Implementation of main MD5 checksum algorithm
RETURNS: void
ARGUMENTS: unsigned char* Input : input block
unsigned int nInputLen : length of input block
NOTES: Computes the partial MD5 checksum for 'nInputLen' bytes of data in 'Input'
*****************************************************************************************/
void CMD5Checksum::Update( unsigned char* Input, unsigned long nInputLen )
{
//Compute number of bytes mod 64
unsigned int nIndex = (unsigned int)((m_nCount[0] >> 3) & 0x3F);
//Update number of bits
if ( ( m_nCount[0] += nInputLen << 3 ) < ( nInputLen << 3) )
{
m_nCount[1]++;
}
m_nCount[1] += (nInputLen >> 29);
//Transform as many times as possible.
unsigned int i=0;
unsigned int nPartLen = 64 - nIndex;
if (nInputLen >= nPartLen)
{
memcpy( &m_lpszBuffer[nIndex], Input, nPartLen );
Transform( m_lpszBuffer );
for (i = nPartLen; i + 63 < nInputLen; i += 64)
{
Transform( &Input[i] );
}
nIndex = 0;
}
else
{
i = 0;
}
// Buffer remaining input
memcpy( &m_lpszBuffer[nIndex], &Input[i], nInputLen-i);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*utf8解析行 Don't remove or modify this first line!*/
#ifdef __WINOS__
#include "stdafx.h"
#endif
#include "WNBitIndex.h"
#include "WNObject.h"
#include <memory.h>
#define LeafsInfoCount 65536
#define ValueCount 16
//保存WNBitNode(WNBitNodeEx、WNByteNode)类中muLeafsInfo与mppLeafs的关系
//如要取得mppLeafs中数值为v(范围0-15)的节点的方法如下:
// 1、检查v所对应的节点序号是否存在,即判定mLeafsInfoMap[muLeafsInfo][v]是否为0
// 2、如v所对应的节点序号index不为0,则通过mppLeafs[index - 1]即可获得节点指针
//条件语句如果下:
// return mLeafsInfoMap[muLeafsInfo][v]?mppLeafs[mLeafsInfoMap[muLeafsInfo][v] - 1]:NULL;
unsigned int mLeafsInfoMap[LeafsInfoCount][ValueCount+1] = { { 0 } };
//节点值所对应的muLeafsInfo中的位
unsigned int mLeafsValueBit[ValueCount] = {
0x1, 0x2, 0x4, 0x8,
0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800,
0x1000, 0x2000, 0x4000, 0x8000
};
//默认的子节点列表,全0,包含Data
WNBitNode* mDefLeafs[ValueCount+1] = { 0 };
#define LowHalfByte 0
#define HighHalfByte 1
//保存一个字节的高4位和低4位值的数组
unsigned int mHalfByteValue[256][2] = { { 0 } };
//用于创建WNBitNode的叶子信息(muLeafsInfo)与叶子节点(mpLeafs)的对照表
class WNBitNodeLeafsInfoMapCreator
{
public:
WNBitNodeLeafsInfoMapCreator();
};
//用于初始化mLeafsInfoMap
WNBitNodeLeafsInfoMapCreator mBitNodeLeafsInfoMapCreator;
//==================================================================================================
//WNBitNodeLeafsInfoMapCreator======================================================================
//==================================================================================================
WNBitNodeLeafsInfoMapCreator::WNBitNodeLeafsInfoMapCreator()
{
//初始化节点信息与节点的映射表
for (int i = 0; i < LeafsInfoCount; i++)
{
int iIndex = -1;
int iValue = i;
int iValueCount = ValueCount;
int iNextLocal = 1;
//子节点数量置0
mLeafsInfoMap[i][ValueCount] = 0;
while (iValueCount--)
{
iIndex++;
if ((iValue & 1))
{
//有值,设置节点位置,从1开始
mLeafsInfoMap[i][iIndex] = iNextLocal;
iNextLocal++;
//增加子节点数量
mLeafsInfoMap[i][ValueCount] += 1;
}
else
{
mLeafsInfoMap[i][iIndex] = 0;
}
iValue = (iValue >> 1);
}
}
//初始化字节高4位以及低4位值信息
for (int i = 0; i < 256; i++)
{
mHalfByteValue[i][LowHalfByte] = i & 0x0F;
mHalfByteValue[i][HighHalfByte] = (i >> 4) ;
}
}
//===================================================================================================
//WNBitNode==========================================================================================
//===================================================================================================
#define ValueIndex (mLeafsInfoMap[muLeafsInfo][ValueCount])
#define ArraySizeWithValue (mLeafsInfoMap[muLeafsInfo][ValueCount] + 1)
#define ArraySizeWithoutValue (mLeafsInfoMap[muLeafsInfo][ValueCount])
WNBitNode* WNBitNode::NullPtr = 0;
WNBitNode::WNBitNode()
{
memset(this,0x00, sizeof(WNBitNode));
mppLeafs = mDefLeafs;
}
WNBitNode::~WNBitNode()
{
if (mppLeafs != mDefLeafs)
{
//有叶子节点或者数据
if (mbHasData && mbIsWNObjectPtr)
{
//有数据
if (mbIsWNObjectPtr)
{
((WNObject*)(Data()))->Release();
}
}
if (!mbDoNotFreeLeafs)
{
//删除所有子节点
unsigned int uCount = LeafsCount();
for (unsigned int i = 0; i < uCount; i++)
{
delete mppLeafs[i];
}
}
//删除子节点以及数据列表
delete[] mppLeafs;
}
}
void WNBitNode::ReInit()
{
if (mppLeafs != mDefLeafs)
{
//有叶子节点或者数据
if (mbHasData && mbIsWNObjectPtr)
{
//有数据
if (mbIsWNObjectPtr)
{
((WNObject*)(Data()))->Release();
}
}
if (!mbDoNotFreeLeafs)
{
//删除所有子节点
unsigned int uCount = LeafsCount();
for (unsigned int i = 0; i < uCount; i++)
{
delete mppLeafs[i];
}
}
//删除子节点以及数据列表
delete[] mppLeafs;
}
memset(this,0x00, sizeof(WNBitNode));
mppLeafs = mDefLeafs;
}
inline WNBitNode* WNBitNode::ChildNode( unsigned int uChildValue )
{
return mLeafsInfoMap[muLeafsInfo][uChildValue]?mppLeafs[mLeafsInfoMap[muLeafsInfo][uChildValue] - 1]:NULL;
}
inline WNBitNode*& WNBitNode::ChildNodeRef( unsigned int uChildValue )
{
return mLeafsInfoMap[muLeafsInfo][uChildValue]?mppLeafs[mLeafsInfoMap[muLeafsInfo][uChildValue] - 1]:NullPtr;
}
WNBitNode* WNBitNode::AttatchChildNode( WNBitNode* pNewNode, bool bRemoveOldNode /*= true*/ )
{
//获得旧节点
WNBitNode* pOldChild = ChildNode(pNewNode->muNodeValue);
//判断要添加的节点与旧节点是否相同
if (pNewNode == pOldChild)
{
//要添加的节点与已有节点为同一节点
return NULL;
}
if (!pOldChild)
{
//旧节点不存在
//添加新节点
//首先得到新的节点信息
unsigned int uNewLeafsInfo = muLeafsInfo | mLeafsValueBit[pNewNode->muNodeValue];
//创建新的节点数组
WNBitNode** pNewLeafs = new WNBitNode*[LeafsAndValueCount() + 1];
//拷贝原数组的内容至新的节点数组
unsigned int uNewIndex = 0;
for (unsigned int i = 0; i < LeafsCount(); i++)
{
//得到当前第i个子节点的新序号
uNewIndex = mLeafsInfoMap[uNewLeafsInfo][mppLeafs[i]->muNodeValue] - 1;
pNewLeafs[uNewIndex] = mppLeafs[i];
}
//拷贝数据
if (mbHasData)
{
pNewLeafs[mLeafsInfoMap[uNewIndex][ValueCount]] = (WNBitNode*)Data();
}
//删除元节点数组
if (mppLeafs != mDefLeafs)
{
delete mppLeafs;
mppLeafs = mDefLeafs;
}
//设置新数组
mppLeafs = pNewLeafs;
//设置新节点信息
muLeafsInfo = uNewLeafsInfo;
}
//设置新节点
ChildNodeRef(pNewNode->muNodeValue) = pNewNode;
//返回旧节点
return pOldChild;
}
WNBitNode* WNBitNode::DetatchChildNode( unsigned int uChildValue )
{
//获得要分离的节点
WNBitNode* pTargetNode = ChildNode(uChildValue);
if (pTargetNode)
{
//存在指定值的节点
//从节点列表中删除指定的节点
//首先获得新节点列表
//首先得到新的节点信息
unsigned int uNewLeafsInfo = muLeafsInfo ^ mLeafsValueBit[uChildValue];
//创建新的节点数组
WNBitNode** pNewLeafs = new WNBitNode*[LeafsAndValueCount() - 1];
//拷贝原数组内容至新数组(不包含uChildValue节点)
unsigned int uNewIndex = 0;
for (unsigned int i = 0; i < LeafsCount(); i++)
{
//判断第i个子节点是否为要分离的节点
if (mppLeafs[i] != pTargetNode)
{
//不是要分离的节点,拷贝
//得到当前第i个子节点的新序号
uNewIndex = mLeafsInfoMap[uNewLeafsInfo][mppLeafs[i]->muNodeValue] - 1;
pNewLeafs[uNewIndex] = mppLeafs[i];
}
}
//拷贝数据
if (mbHasData)
{
pNewLeafs[mLeafsInfoMap[uNewIndex][ValueCount]] = (WNBitNode*)Data();
}
//删除元节点数组
if (mppLeafs != mDefLeafs)
{
delete mppLeafs;
mppLeafs = mDefLeafs;
}
//设置新数组
mppLeafs = pNewLeafs;
//设置新节点信息
muLeafsInfo = uNewLeafsInfo;
}
//返回要分离的节点
return pTargetNode;
}
WNBitNode* WNBitNode::AddChildNode( unsigned int uChildValue )
{
WNBitNode* pChildNode = ChildNode(uChildValue);
if (!pChildNode)
{
//要添加的节点不存在
pChildNode = new WNBitNode;
//设置节点值
pChildNode->muNodeValue = uChildValue;
//添加节点
AttatchChildNode(pChildNode);
}
return pChildNode;
}
void WNBitNode::RemoveChildNode( unsigned int uChildValue )
{
//记录下分离的子节点
WNBitNode* pChildNode = DetatchChildNode(uChildValue);
if (pChildNode)
{
//子节点不为空,删除
delete pChildNode;
}
}
inline unsigned int WNBitNode::LeafsCount()
{
return mLeafsInfoMap[muLeafsInfo][ValueCount];
}
inline unsigned int WNBitNode::LeafsAndValueCount()
{
return mbHasData?(LeafsCount() + 1):LeafsCount();
}
inline void* WNBitNode::Data()
{
return mbHasData?mppLeafs[mLeafsInfoMap[muLeafsInfo][ValueCount]]:NULL;
}
inline void*& WNBitNode::DataRef()
{
return (void*&)(mbHasData?mppLeafs[mLeafsInfoMap[muLeafsInfo][ValueCount]]:NullPtr);
}
void* WNBitNode::SetData(void* pNewData, bool bIsWNObject /* = false */)
{
if (bIsWNObject && pNewData)
{
//是WNObject*类型的数据,首先记录新数据
((WNObject*)pNewData)->Retain();
}
void*& pData = DataRef();
void* pOldData = pData;
if (mbIsWNObjectPtr && pOldData)
{
//当前数据是WNObject*类型的数据,释放引用
((WNObject*&)pOldData)->Release();
pData = NULL;
pOldData = NULL;
}
if (mbHasData)
{
//已有旧数据
if (pNewData)
{
//新旧数据均存在,使用新数据替换旧数据
mppLeafs[ValueIndex] = (WNBitNode*)pNewData;
}
else
{
//旧数据存在且新数据不存在,删除旧数据
//首先初始化一个新的节点数组ppNewLeafs
//如果当前子节点数为0,则设置新节点数组为mDefLeafs
WNBitNode** ppNewLeafs = mDefLeafs;
if (LeafsCount())
{
//如果有子节点
ppNewLeafs = new WNBitNode*[ArraySizeWithoutValue];
//复制子节点信息
memcpy(ppNewLeafs, mppLeafs, LeafsCount() * sizeof(WNBitNode*));
}
if (mppLeafs != mDefLeafs)
{
//删除老的叶子节点数组
delete[] mppLeafs;
}
//设置ppNewLeafs为当前叶子节点数组
mppLeafs = ppNewLeafs;
//设置当前数据为不存在
mbHasData = false;
}
}
else
{
//不存在旧数据
if (pNewData)
{
//新数据存在且旧数据不存在,添加新数据
//首先初始化一个新的节点数组ppNewLeafs
WNBitNode** ppNewLeafs = new WNBitNode*[ArraySizeWithValue];
//设置数据
ppNewLeafs[ValueIndex] = (WNBitNode*)pNewData;
if (LeafsCount())
{
//存在叶子节点信息
//拷贝叶子节点信息至新节点数组
memcpy(ppNewLeafs, mppLeafs, LeafsCount() * sizeof(WNBitNode*));
}
if (mppLeafs != mDefLeafs)
{
//删除老的叶子节点数组
delete[] mppLeafs;
}
//设置ppNewLeafs为当前叶子节点数组
mppLeafs = ppNewLeafs;
//设置当前数据为存在
mbHasData = true;
}
else
{
//新旧都数据均不存在
//不做任何操作
}
}
return pOldData;
}
//===================================================================================================
//WNBitIndex=========================================================================================
//===================================================================================================
WNBitIndex::WNBitIndex()
:mpNodeHeapManager(NULL)
{
memset(mpRoot, 0x00,sizeof(mpRoot));
mpNodeHeapManager = new NodeHeapManager;
}
WNBitIndex::~WNBitIndex()
{
ClearAll();
delete mpNodeHeapManager;
}
void* WNBitIndex::SetItem(const void* pKey, unsigned int uKeyLen, void* pData, bool mbIsWNObject /* = false */)
{
if (!pData)
{
//pData为NULL,删除指定的数据
return RemoveItem(pKey, uKeyLen);
}
WNBitNode* pNode = AddNode(pKey, uKeyLen);
if (!pNode)
{
//添加节点失败,返回
return NULL;
}
return pNode->SetData(pData, mbIsWNObject);
}
void* WNBitIndex::GetItem(const void* pKey, unsigned int uKeyLen )
{
if (!uKeyLen || !pKey)
{
//uKeyLen不能为0
return NULL;
}
WNBitNode* pFindNode = FindNode(pKey, uKeyLen);
return pFindNode?pFindNode->Data():NULL;
}
void* WNBitIndex::RemoveItem(const void* pKey, unsigned int uKeyLen )
{
if (!uKeyLen || !pKey)
{
//uKeyLen不能为0
return NULL;
}
//首先查找第一个字节
unsigned char* pchKey = (unsigned char*)pKey;
WNBitNode* pNode = mpRoot[*pchKey];
if (!pNode)
{
//第一个字节不存在,返回NULL
return NULL;
}
else
{
//第一个字节存在
pchKey++;
uKeyLen--;
}
if (!uKeyLen)
{
//要移除的的节点关键字只有一个字节
//第一个字节不做删除操作
//删除数据后返回
return pNode->SetData(NULL);
}
//关键字长度大于1字节时,遍历关键字所对应的其余所有节点
//如果关键字存在且某个节点之下都只有一个子节点,且只有关键字所对应的数据节点,则可删除此节点
WNBitNode* pRemoveNode = NULL; //起始无效节点的父节点
unsigned int uRemoveChildValue = 0; //起始无效节点的子节点值
WNBitNode* pParentNode = NULL;
WNBitNode* pFindNode = pNode;
while (uKeyLen--)
{
//查找高字节
pParentNode = pFindNode;
pFindNode = pFindNode->ChildNode((*pchKey) >> 4);
if (!pFindNode)
{
return NULL;
}
//检查节点是否符合删除条件
if (!pRemoveNode)
{
//没有删除起始节点
if (pFindNode->LeafsAndValueCount() == 1)
{
//当前节点只有一个子节点
//设置当前节点为删除起始节点
pRemoveNode = pParentNode;
uRemoveChildValue = ((*pchKey) >> 4);
}
}
else if (pFindNode->LeafsAndValueCount() != 1)
{
//有删除起始节点且当前节点子节点不为1
//需要重新查找删除起始节点
pRemoveNode = NULL;
}
//查找低字节
pParentNode = pFindNode;
pFindNode = pFindNode->ChildNode((*pchKey) & 0x0F);
if (!pFindNode)
{
return NULL;
}
//检查节点是否符合删除条件
if (!pRemoveNode)
{
//没有删除起始节点
if (pFindNode->LeafsAndValueCount() == 1)
{
//当前节点只有一个子节点
//设置当前节点为删除起始节点
pRemoveNode = pParentNode;
uRemoveChildValue = ((*pchKey) & 0x0F);
}
}
else if (pFindNode->LeafsAndValueCount() != 1)
{
//有删除起始节点且当前节点子节点不为1
//需要重新查找删除起始节点
pRemoveNode = NULL;
}
pchKey++;
}
void* pRet = NULL;
if (pFindNode)
{
//找到关键字所对应的节点
if (pFindNode->mbHasData)
{
//关键字存在
pRet = pFindNode->SetData(NULL);
}
if (pRemoveNode)
{
//删除无效节点
pRemoveNode->RemoveChildNode(uRemoveChildValue);
}
}
return pRet;
}
WNBitNode* WNBitIndex::FindNode(const void* pKey, unsigned int uKeyLen )
{
if (!uKeyLen || !pKey)
{
//uKeyLen不能为0
return NULL;
}
unsigned char* pchKey = (unsigned char*)pKey;
//寻找第一个字节
//首先判断第一个字节是否存在
WNBitNode* pNode = mpRoot[*pchKey];
if (!pNode)
{
//第一个字节不存在
return NULL;
}
else
{
pchKey++;
uKeyLen--;
}
WNBitNode* pFindNode = pNode;
while (uKeyLen--)
{
//查找高字节
pFindNode = pFindNode->ChildNode((*pchKey) >> 4);
if (!pFindNode)
{
return NULL;
}
//查找低字节
pFindNode = pFindNode->ChildNode((*pchKey) & 0x0F);
if (!pFindNode)
{
return NULL;
}
pchKey++;
}
return pFindNode;
}
WNBitNode* WNBitIndex::AddNode(const void* pKey, unsigned int uKeyLen )
{
if (!uKeyLen || !pKey)
{
//uKeyLen不能为0
return NULL;
}
unsigned char* pchKey = (unsigned char*)pKey;
//添加第一个字节
//首先判断第一个字节是否存在
WNBitNode* pNode = mpRoot[*pchKey];
if (!pNode)
{
//第一个字节不存在
//创建第一个字节所对应值的节点
mpRoot[*pchKey] = new WNBitNode;
pNode = mpRoot[*pchKey];
pNode->muNodeValue = *pchKey;
pNode->mbIsEndBit = true;
}
pchKey++;
uKeyLen--;
WNBitNode* pNewNode = pNode;
while (uKeyLen--)
{
//添加高字节
pNewNode = pNewNode->AddChildNode((*pchKey) >> 4);
//添加低字节
pNewNode = pNewNode->AddChildNode((*pchKey) & 0x0F);
//设置结束字节
pNewNode->mbIsEndBit = true;
pchKey++;
}
//返回pKey的关联节点
return pNewNode;
}
void WNBitIndex::ClearAll()
{
for (unsigned int i = 0; i < sizeof(mpRoot) / sizeof(WNBitNode*); i++)
{
if (mpRoot[i])
{
delete mpRoot[i];
mpRoot[i] = NULL;
}
}
}
/*utf8解析行 Don't remove or modify this first line!*/
//nclude "stdafx.h"
#include "WNByteBuffer.h"
#include <memory.h>
ByteBuffer::ByteBuffer(unsigned long dwBufferSize /* = DEFAULT_BUFFER_SIZE */)
:m_dwFlag(0)
,m_pBuffer(NULL)
,m_dwBufferSize(0)
,m_dwValidSize(0)
,m_pPos(NULL)
{
if (dwBufferSize)
{
InitBuffer(dwBufferSize);
}
}
ByteBuffer::ByteBuffer( ByteBuffer& srcByteBuffer )
:m_pBuffer(NULL)
,m_dwBufferSize(0)
,m_dwValidSize(0)
,m_pPos(NULL)
{
*this = srcByteBuffer;
}
ByteBuffer::ByteBuffer( void* pData, unsigned long dwSize )
:m_pBuffer(NULL)
,m_dwBufferSize(0)
,m_dwValidSize(0)
,m_pPos(NULL)
{
ReadMemory(pData, dwSize);
}
ByteBuffer::~ByteBuffer()
{
ReleaseBuffer();
}
bool ByteBuffer::InitBuffer(unsigned long dwBufferSize /* = DEFAULT_BUFFER_SIZE */, bool bReserveData /* = false */, bool bReservePos /* = false */)
{
WNByteBuffer newBuffer(0);
if (!dwBufferSize)
{
ReleaseBuffer();
return true;
}
if (dwBufferSize)
{
newBuffer.m_pBuffer = new unsigned char[dwBufferSize + 2];
memset(newBuffer.m_pBuffer, 0, dwBufferSize + 2);
newBuffer.m_dwFlag = m_dwFlag;
newBuffer.m_dwBufferSize = dwBufferSize;
newBuffer.m_dwValidSize = dwBufferSize;
newBuffer.m_pPos = newBuffer.m_pBuffer;
}
if (bReserveData && m_pBuffer)
{
memcpy(newBuffer.m_pBuffer, m_pBuffer, (dwBufferSize > m_dwBufferSize)?m_dwBufferSize:dwBufferSize);
}
if (bReservePos)
{
newBuffer.SetPos(GetPos());
newBuffer.SetValidSize(GetValidSize());
}
ReleaseBuffer();
m_dwFlag = newBuffer.m_dwFlag;
m_pBuffer = newBuffer.m_pBuffer;
m_dwBufferSize = newBuffer.m_dwBufferSize;
m_dwValidSize = newBuffer.m_dwValidSize;
m_pPos = newBuffer.m_pPos;
newBuffer.m_pBuffer = NULL;
return true;
}
bool ByteBuffer::ReleaseBuffer()
{
if (m_pBuffer)
{
delete[] m_pBuffer;
m_pBuffer = NULL;
m_pPos = NULL;
m_dwBufferSize = 0;
m_dwValidSize = 0;
}
return true;
}
//bool ByteBuffer::ReadFile(FILE* pFile, unsigned long dwReadSize /* = 0 */)
//{
// if (!pFile)
// {
// return FALSE;
// }
// if (!dwReadSize)
// {
// if (m_pBuffer)
// {
// dwReadSize = m_dwBufferSize;
// }
// else
// {
// InitBuffer(dwReadSize);
// }
// }
// else if (dwReadSize != m_dwBufferSize)
// {
// InitBuffer(dwReadSize);
// }
//
// unsigned long dwReadCount = fread(m_pBuffer, dwReadSize, 1, pFile);
//#ifndef MAC_PROGRAME
// return (dwReadCount == dwReadSize)?true:FALSE;
//#else
// return (dwReadCount == 1)?true:FALSE;
//#endif
//}
bool ByteBuffer::ReadMemory(const void* pSrcData, unsigned long dwReadSize /* = 0 */)
{
if (!pSrcData)
{
return false;
}
if (!dwReadSize)
{
if (m_pBuffer)
{
dwReadSize = m_dwBufferSize;
}
else
{
InitBuffer(dwReadSize);
}
}
else if (dwReadSize != m_dwBufferSize)
{
InitBuffer(dwReadSize);
}
memcpy(m_pBuffer, pSrcData, dwReadSize);
return true;
}
unsigned long ByteBuffer::OutputWithPos(void* pTarData, unsigned long dwOutputSize /* = 0 */, const unsigned long* pdwPos /* = NULL */)
{
if (!(m_pBuffer && m_dwBufferSize))
{
return 0;
}
if (!pTarData)
{
return 0;
}
if (!dwOutputSize)
{
dwOutputSize = m_dwBufferSize;
}
if (pdwPos)
{
m_pPos = m_pBuffer + *pdwPos;
}
if (m_pPos >= m_pBuffer + m_dwBufferSize)
{
return 0;
}
else if (m_pPos + dwOutputSize < m_pBuffer + m_dwBufferSize)
{
memcpy(pTarData, m_pPos, dwOutputSize);
m_pPos += dwOutputSize;
return dwOutputSize;
}
else
{
dwOutputSize = m_pBuffer + m_dwBufferSize - m_pPos;
memcpy(pTarData, m_pPos, dwOutputSize);
m_pPos += dwOutputSize;
return dwOutputSize;
}
}
unsigned long ByteBuffer::InputWithPos(const void* pSrcData, unsigned long dwInputSize /*= 0*/, const unsigned long* pdwPos /*= NULL */ )
{
if (!(m_pBuffer && m_dwBufferSize))
{
return 0;
}
if (!pSrcData)
{
return 0;
}
if (!dwInputSize)
{
return 0;
}
if (pdwPos)
{
m_pPos = m_pBuffer + *pdwPos;
}
if (m_pPos >= m_pBuffer + m_dwBufferSize)
{
return 0;
}
else if (m_pPos + dwInputSize > m_pBuffer + m_dwBufferSize)
{
unsigned char* pOldPos = m_pPos;
InitBuffer(m_dwBufferSize + dwInputSize, true);
m_pPos = pOldPos;
memcpy(m_pPos, pSrcData, dwInputSize);
m_pPos += dwInputSize;
return dwInputSize;
}
else
{
memcpy(m_pPos, pSrcData, dwInputSize);
m_pPos = m_pPos + dwInputSize;
return dwInputSize;
}
}
ByteBuffer& ByteBuffer::operator = ( const ByteBuffer& SrcByteBuffer )
{
if (!SrcByteBuffer.m_pBuffer)
{
ReleaseBuffer();
}
else
{
InitBuffer(SrcByteBuffer.m_dwBufferSize);
memcpy(m_pBuffer, SrcByteBuffer.m_pBuffer, m_dwBufferSize);
}
return *this;
}
ByteBuffer& ByteBuffer::operator=( const char* strData )
{
unsigned long dwSize = strlen(strData);
InitBuffer(dwSize);
memcpy(m_pBuffer, strData, dwSize);
return *this;
}
bool ByteBuffer::operator==( const ByteBuffer& srcData )
{
if (&srcData == this)
{
return true;
}
else if (m_dwBufferSize == srcData.m_dwBufferSize)
{
if (m_pBuffer && srcData.m_pBuffer)
{
for (unsigned long i = 0; i < m_dwBufferSize; i++)
{
if (m_pBuffer[i] != srcData.m_pBuffer[i])
{
return false;
}
}
return true;
}
else if (!m_pBuffer && !srcData.m_pBuffer)
{
return true;
}
}
return false;
}
bool ByteBuffer::operator==( const char* strSrc )
{
if (!strSrc)
{
return false;
}
if (m_pBuffer)
{
if (!strcmp((char*)m_pBuffer, strSrc))
{
return true;
}
}
else if (!strSrc)
{
return true;
}
return false;
}
//bool ByteBuffer::SaveFile(const char* strFilename, bool bUseValidSize /* = true */)
//{
// FILE* pFile = fopen(strFilename, "wb");
// if (!pFile)
// {
// return FALSE;
// }
// fwrite(m_pBuffer, bUseValidSize?m_dwValidSize:m_dwBufferSize, 1, pFile);
// fclose(pFile);
// return true;
//}
unsigned long ByteBuffer::SetValidString( unsigned long dwStrLen )
{
if (dwStrLen < m_dwBufferSize)
{
memset(m_pBuffer + dwStrLen, m_dwBufferSize - dwStrLen, 0);
m_dwValidSize = dwStrLen;
}
return m_dwValidSize;
}
unsigned long ByteBuffer::SetValidSize( unsigned long dwSize )
{
if (dwSize < m_dwBufferSize)
{
m_dwValidSize = dwSize;
}
else
{
m_dwValidSize = m_dwBufferSize;
}
return m_dwValidSize;
}
WNByteBuffer::WNByteBuffer( unsigned long dwBufferSize /*= DEFAULT_BUFFER_SIZE*/ )
:ByteBuffer(dwBufferSize)
,mpBufferManager(NULL)
{
}
/*utf8解析行 Don't remove or modify this first line!*/
#ifdef __WINOS__
#include "StdAfx.h"
#endif
#define DEFAULT_BUFFER_SIZE 0
#include "WNByteBufferManager.h"
WNByteBufferList::WNByteBufferList()
:muBufferSize(0)
{
}
WNByteBufferManager::WNByteBufferManager(unsigned int uMinBufferSize /* = DefMinBufferSize */, unsigned int uSetpBufferSize /* = DefSetpBufferSize */, unsigned int uMaxBufferSize /* = DefMaxBufferSize */)
:mpBufferList(NULL)
,muListCount(0)
,muMinBufferSize(0)
,muStepBufferSize(0)
,muMaxBufferSize(0)
,muAllBufferSize(0)
,muMaxAllBufferSize(DefMaxAllBufferSize)
,muAllBufferCount(0)
,muMaxAllBufferCount(DefMaxBufferCount)
{
InitManager(uMinBufferSize, uSetpBufferSize, uMaxBufferSize);
}
WNByteBufferManager::~WNByteBufferManager(void)
{
FreeManager();
}
//进1取整宏
#define INTV(x, y) ((x + y - 1) / y)
void WNByteBufferManager::InitManager( unsigned int uMinBufferSize, unsigned int uStepBufferSize, unsigned int uMaxBufferSize )
{
if (!uStepBufferSize)
{
uStepBufferSize = DefSetpBufferSize;
}
if (uMaxBufferSize < uMinBufferSize)
{
uMaxBufferSize = uMinBufferSize;
}
if (muListCount)
{
if (uMaxBufferSize != muMaxBufferSize)
{
FreeManager();
}
else if (uStepBufferSize != muStepBufferSize)
{
FreeManager();
}
else if (INTV((uMaxBufferSize - uMinBufferSize), uStepBufferSize) != INTV((muMaxBufferSize - muMinBufferSize), muStepBufferSize))
{
FreeManager();
}
else
{
//所有参数相同,无需重新初始化
return;
}
}
muMinBufferSize = uMinBufferSize;
muStepBufferSize= uStepBufferSize;
muMaxBufferSize = uMaxBufferSize;
muListCount = INTV((muMaxBufferSize - muMinBufferSize), muStepBufferSize) + 1;
//初始化自由缓冲区列表数组
mpBufferList = new WNByteBufferList[muListCount + 1];
for (unsigned int i = 1; i <= muListCount; i++)
{
mpBufferList[i].muBufferSize = muMinBufferSize + muStepBufferSize * (i - 1);
}
}
void WNByteBufferManager::FreeManager()
{
if (!muListCount)
{
return;
}
delete [] mpBufferList;
mpBufferList = NULL;
muListCount = 0;
muMinBufferSize = 0;
muStepBufferSize = 0;
muMaxBufferSize = 0;
muAllBufferSize = 0;
muAllBufferCount = 0;
}
void WNByteBufferManager::InitBuffers( unsigned int uBufferSize, unsigned int uCount /*= 1*/ )
{
if (!muListCount)
{
return;
}
WNByteBufferList* pBufferList = GetListByBufferSize(uBufferSize);
for (unsigned int i = 0; i < uCount; i++)
{
WNByteBufferList::PNode pNode = new WNByteBufferList::Node;
pNode->data.InitBuffer(pBufferList->muBufferSize);
muAllBufferSize += pBufferList->muBufferSize?pBufferList->muBufferSize:uBufferSize;
muAllBufferCount++;
pBufferList->AppendNode(pNode);
}
}
WNByteBuffer* WNByteBufferManager::GetBuffer(unsigned int uBufferSize, bool mbThreadSafeBuffer /* = FALSE */)
{
if (!muListCount)
{
return NULL;
}
WNByteBufferList::PNode pNode = NULL;
Lock();
WNByteBufferList* pBufferList = GetListByBufferSize(uBufferSize);
if (pBufferList->ListCount())
{
pNode = pBufferList->DetachNode(pBufferList->Begin());
muAllBufferSize -= pNode->data.BufferSize();
muAllBufferCount--;
pNode->data.MovePosBegin();
Unlock();
}
else
{
if (pBufferList->muBufferSize)
{
//如果缓冲区列表指定的缓冲区大小不为0,则表示在范围内
uBufferSize = pBufferList->muBufferSize;
}
//Unlock();
pNode = new WNByteBufferList::Node;
if (!pNode)
{
return NULL;
}
pNode->data.mbIsAllocOnHeap = true;
if (!pNode->data.InitBuffer(uBufferSize))
{
delete pNode;
return NULL;
}
if (mbThreadSafeBuffer)
{
pNode->data.SetSafeLocker();
}
pNode->data.mpThis = pNode;
pNode->data.mpTypeFn = getWNObjectTypeFnInstance<WNByteBufferList::Node>();
pNode->data.mpBufferManager = this;
pNode->data.Delegate() = this;
pNode->data.Retain();
Unlock();
}
pNode->data.DelayRelease();
return (WNByteBuffer*)(&(pNode->data));
//return (WNByteBuffer*)(pNode->data.DelayRelease());
}
void WNByteBufferManager::FreeBuffer( WNByteBuffer* pBuffer )
{
if (!muListCount)
{
return;
}
Lock();
if ((muAllBufferCount >= muMaxAllBufferCount) || (muAllBufferSize >= muMaxAllBufferSize))
{
WNByteBufferList::PNode pNode = (WNByteBufferList::PNode)pBuffer;
delete pNode;
}
else
{
WNByteBufferList* pBufferList = GetListByBufferSize(pBuffer->BufferSize());
pBufferList->AppendNode((WNByteBufferList::PNode)pBuffer);
pBuffer->ResetRefInfo();
muAllBufferCount++;
muAllBufferSize += pBuffer->BufferSize();
}
Unlock();
}
void WNByteBufferManager::SetMaxAllBufferSize( unsigned int uSize )
{
muMaxAllBufferSize = uSize;
return;
}
void WNByteBufferManager::SetMaxBufferCount( unsigned int uCount )
{
muMaxAllBufferCount = uCount;
return;
}
WNByteBufferList* WNByteBufferManager::GetListByBufferSize( unsigned int uBufferSize )
{
if (uBufferSize < muMinBufferSize)
{
uBufferSize = muMinBufferSize;
}
if (uBufferSize > mpBufferList[muListCount].muBufferSize)
{
return mpBufferList;
}
else
{
return mpBufferList + INTV((uBufferSize - muMinBufferSize), muStepBufferSize) + 1;
}
}
bool WNByteBufferManager::OnWNObjectRetainCountIsZero( WNObject* pObject )
{
if (!muListCount)
{
return true;
}
Lock();
if ((muAllBufferCount >= muMaxAllBufferCount) || (muAllBufferSize >= muMaxAllBufferSize))
{
Unlock();
return true;
}
else
{
WNByteBufferList::PNode pNode = NULL;
pNode = (WNByteBufferList::PNode)(pObject->mpThis);
WNByteBufferList* pBufferList = GetListByBufferSize(pNode->data.BufferSize());
pBufferList->AppendNode(pNode);
pNode->data.ResetRefInfo();
muAllBufferCount++;
muAllBufferSize += pNode->data.BufferSize();
Unlock();
return false;
}
}
/*utf8解析行 Don't remove or modify this first line!*/
#ifdef __WINOS__
#include "stdafx.h"
#endif
#include "WNCStringList.h"
WNCStringList::WNCStringList(const char* lpStringList, const char* lpSplit /* = _T("|") */)
{
CreateList(lpStringList, lpSplit);
}
WNCStringList::WNCStringList(const string& strStringList, const string& strSplit /* = _T("|") */)
{
CreateList(strStringList, strSplit);
}
void WNCStringList::CreateList(const char* lpStringList /* = _T("") */, const char* lpSplit /* = _T("|") */)
{
if (!lpStringList)
{
return;
}
string strList(lpStringList);
string strSplit(lpSplit);
if (strSplit == "")
{
string strToken;
while (*lpStringList)
{
PNode node = new Node;
node->data = lpStringList;
AppendNode(node);
lpStringList += node->data.length();
lpStringList++;
}
}
else
{
return CreateList(strList, strSplit);
}
}
void WNCStringList::CreateList(const string& strStringList, const string& strSplit)
{
ClearList();
string strToken;
int pos = 0;
int lastPos = 0;
pos = strStringList.find(strSplit, lastPos);
while (pos != -1)
{
if ((pos - lastPos) >= 1)
{
strToken = strStringList.substr(lastPos, pos - lastPos);
PNode node = new Node;
node->data = strToken;
AppendNode(node);
}
lastPos = pos + strSplit.length();
pos = strStringList.find(strSplit, lastPos);
}
if (pos == -1 && lastPos == 0)
{
PNode node = new Node;
node->data = strStringList;
AppendNode(node);
}
else if (lastPos != 0)
{
long len = strStringList.length();
if (len > lastPos)
{
strToken = strStringList.substr(lastPos, len - lastPos);
PNode node = new Node;
node->data = strToken;
AppendNode(node);
}
}
MoveBegin();
}
string WNCStringList::Join(const char* lpSplit /* = _T */)
{
string strRet("");
for (PNode node = Begin(); node != Head(); node = node->nextNode)
{
if (node != Begin())
{
strRet += lpSplit;
}
strRet += node->data;
}
return strRet;
}
/*utf8解析行 Don't remove or modify this first line!*/
#include "WNCommonSocket.h"
#include "WNCStringList.h"
#include "WNSocketObserverManager.h"
#include "stdio.h"
#include <stdlib.h>
#include <netinet/tcp.h>
//#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <sstream>
#include <errno.h>
DWORD mdwMainThreadId = 0;
#ifndef WIN32
#define ioctlsocket ioctl
#endif
WNCommonSocket::WNCommonSocket(void)
:mhwnd(NULL)
//,mbHasWindowMessage(FALSE)
,mThreadHandle(NULL)
,mdwThreadId(0)
,mpRunLoopThread(NULL)
,muRunLoopThreadSleepTime(1)
,miSocketInitProtocalFamily(AF_INET)
,miSocketInitType(SOCK_STREAM)
,miSocketInitProtocal(0)
,mbExitThread(FALSE)
,mbIsThreadRunning(FALSE)
,mpCommonSocketDelegate(NULL)
,mstrSocketIdentity(_T(""))
,mUserInfo(NULL)
,mpACWinProc(NULL)
,mpReceiveBuffer(NULL)
,mpReceiveBufferPos(NULL)
,muAvailableReceiveLen(0)
,mbOnRead(FALSE)
,mbOnError(FALSE)
,mpReadObserver(NULL)
,mpErrorObserver(NULL)
{
#ifdef WIN32
muMsgOnWNObserverRead = ::RegisterWindowMessage(_T("OnWNObserverRead"));
muMsgOnWNObserverError = ::RegisterWindowMessage(_T("OnWNObserverError"));
muMsgNeedDestroyWindow = ::RegisterWindowMessage(_T("NeedDestroyWindow"));
#endif
}
WNCommonSocket::~WNCommonSocket(void)
{
if (mSocket != INVALID_SOCKET)
CloseSocket();
}
BOOL WNCommonSocket::CreateSocket( )
{
if (mSocket != INVALID_SOCKET)
{
//必须首先关闭socket
return FALSE;
}
if (!miSocketInitProtocal)
{
if (miSocketInitType == SOCK_STREAM)
{
miSocketInitProtocal = IPPROTO_TCP;
}
if (miSocketInitType == SOCK_DGRAM)
{
miSocketInitProtocal = IPPROTO_UDP;
}
}
mSocket = ::socket(miSocketInitProtocalFamily, miSocketInitType, miSocketInitProtocal);
if (mSocket != INVALID_SOCKET)
{
if (miSocketInitType == SOCK_STREAM)
{
int iValue = 1;
int iLen = sizeof(iValue);
SetSockOpt(TCP_NODELAY, &iValue, iLen, IPPROTO_TCP);
}
return TRUE;
}
else
{
return FALSE;
}
}
BOOL WNCommonSocket::SetSocketAddress( LPCTSTR lpAddress )
{
SOCKADDR addrIn;
memset(&addrIn, 0, sizeof(addrIn));
Ipv4StringToData(lpAddress, addrIn);
if (!::bind(mSocket, &addrIn, sizeof(addrIn)))
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL WNCommonSocket::SetSocketAddress( LPCTSTR lpAddress, UINT uPort )
{
SOCKADDR addrIn;
memset(&addrIn, 0, sizeof(addrIn));
Ipv4StringToData(lpAddress, addrIn);
((SOCKADDR_IN*)&addrIn)->sin_port = htons(uPort);
if (!::bind(mSocket, &addrIn, sizeof(addrIn)))
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL WNCommonSocket::SetSocketAddress( SOCKADDR* pSockAddr )
{
if (!::bind(mSocket, pSockAddr, sizeof(*pSockAddr)))
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL WNCommonSocket::EnterObserverLoop( BOOL bInNewThread )
{
if (mSocket == INVALID_SOCKET)
{
//无效socket
return FALSE;
}
if (mhwnd || mpRunLoopThread)
{
//已经进入监控循环
return FALSE;
}
if (bInNewThread)
{
//创建新线程循环,在新线程循环中处理socket事件
mbOnRead = FALSE;
mbOnError = FALSE;
mpReadObserver = NULL;
mpErrorObserver = NULL;
mpObserverTargetDelegate = this;
WNSocketObserverManager::AddSocket(this);
mpRunLoopThread = new WNWorkThread;
mpRunLoopThread->Delegate() = this;
mpRunLoopThread->StartWork();
if (mpRunLoopThread->ThreadId())
{
return TRUE;
}
else
{
return FALSE;
}
}
else
{
//在当前线程循环中处理socket事件,创建一个窗口
if (!mhwnd)
{
CreateSocketWindow();
}
if (mhwnd)
{
//进入循环
mpObserverTargetDelegate = this;
if (!WNSocketObserverManager::AddSocket(this))
{
DestroySocketWindow();
return FALSE;
}
return TRUE;
}
else
{
return FALSE;
}
}
}
BOOL WNCommonSocket::ExitObserverLoop()
{
//Lock();
#ifdef WIN32
if (mhwnd)
{
//TRACE("mdwWindowThreadId != ::GetCurrentThreadId()1\n");
//有窗口,销毁窗口
if (mdwWindowThreadId != ::GetCurrentThreadId())
{
//TRACE("mdwWindowThreadId != ::GetCurrentThreadId()2\n");
//Unlock();
//TRACE("mdwWindowThreadId != ::GetCurrentThreadId()3\n");
::PostMessage(mhwnd, muMsgNeedDestroyWindow, (WPARAM)&mhwnd, NULL);
DWORD dwTime = ::GetTickCount();
while (mhwnd && (::GetTickCount() - dwTime < 3000))
{
::Sleep(10);
}
if (mhwnd)
{
DestroySocketWindow();
}
//TRACE("mdwWindowThreadId != ::GetCurrentThreadId()4\n");
//Lock();
//TRACE("WNCommonSocket::ExitObserverLooop Lock()\n");
}
else
{
DestroySocketWindow();
}
}
#endif
if (!mpRunLoopThread)
{
return TRUE;
}
if (!mpRunLoopThread->ThreadId())
{
return TRUE;
}
WNSocketObserverManager::RemoveSocket(this);
mpRunLoopThread->ResetFlag() = TRF_DeleteInstance;
mpRunLoopThread->EndWork();
mpRunLoopThread = NULL;
return TRUE;
}
void WNCommonSocket::CloseSocket()
{
ExitObserverLoop();
mpCommonSocketDelegate = NULL;
Lock();
if (mSocket != INVALID_SOCKET)
{
::shutdown(mSocket, SD_BOTH);
::close(mSocket);
mSocket = INVALID_SOCKET;
mSocketState = SS_None;
}
Unlock();
}
BOOL WNCommonSocket::AcceptSocket(WNCommonSocket* pNewSocket, SOCKADDR* pSockAddr /* = NULL */, int* pSockAddrLen /* = NULL */)
{
Lock();
SOCKET sockAccept = ::accept(mSocket, pSockAddr, pSockAddrLen);
if (sockAccept != INVALID_SOCKET)
{
pNewSocket->mSocket = sockAccept;
Unlock();
return TRUE;
}
else
{
Unlock();
return FALSE;
}
}
BOOL WNCommonSocket::AcceptSocket( WNCommonSocket& newSocket, CString* pstrSockAddr /*= NULL*/, int* pSockAddrLen /*= NULL*/ )
{
SOCKADDR sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
int iSockAddrLen = 0;
BOOL bRet = AcceptSocket(&newSocket, &sockAddr, &iSockAddrLen);
if (pstrSockAddr)
{
Ipv4DataToString(sockAddr, *pstrSockAddr, TRUE);
}
if (pSockAddrLen)
{
*pSockAddrLen = iSockAddrLen;
}
return bRet;
}
BOOL WNCommonSocket::ConnectSocket( LPCTSTR lpszHostAddress )
{
SOCKADDR hostAddress;
memset(&hostAddress, 0, sizeof(hostAddress));
Ipv4StringToData(lpszHostAddress, hostAddress);
return ConnectSocket(&hostAddress);
}
BOOL WNCommonSocket::ConnectSocket( SOCKADDR* pHostAddress )
{
Lock();
if (::connect(mSocket, pHostAddress, sizeof(*pHostAddress)) != SOCKET_ERROR)
{
Unlock();
return TRUE;
}
else
{
Unlock();
int iError = GetLastError();
return FALSE;
}
}
BOOL WNCommonSocket::IOCtl( long lCommand, DWORD* lpArgument )
{
Lock();
if (SOCKET_ERROR != ::ioctlsocket(mSocket, lCommand, lpArgument))
{
Unlock();
return TRUE;
}
else
{
Unlock();
return FALSE;
}
}
BOOL WNCommonSocket::SetSockOpt( int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel /*= SOL_SOCKET*/ )
{
Lock();
if (::setsockopt(mSocket, nLevel, nOptionName, (const char*)lpOptionValue, nOptionLen) != SOCKET_ERROR)
{
Unlock();
return TRUE;
}
else
{
Unlock();
return FALSE;
}
}
BOOL WNCommonSocket::GetSockOpt( int nOptionName, void* lpOptionValue,int* lpOptionLen, int nLevel /*= SOL_SOCKET*/ )
{
Lock();
if (::getsockopt(mSocket, nLevel, nOptionName, (char*)lpOptionValue, lpOptionLen) != SOCKET_ERROR)
{
Unlock();
return TRUE;
}
else
{
Unlock();
return FALSE;
}
}
BOOL WNCommonSocket::Listen( int nConnectionBacklog )
{
if (mSocketState == SS_Listening)
{
return TRUE;
}
Lock();
if (::listen(mSocket, nConnectionBacklog) != SOCKET_ERROR)
{
//设置当前socket状态
mSocketState = SS_Listening;
Unlock();
return TRUE;
}
else
{
Unlock();
return FALSE;
}
}
BOOL WNCommonSocket::GetPeerName( CString& strIp, UINT& uPort )
{
SOCKADDR addr;
memset(&addr, 0, sizeof(addr));
int iLen = sizeof(addr);
int iRet = GetPeerName(&addr, &iLen);
if (iRet != SOCKET_ERROR)
{
uPort = ntohs(((SOCKADDR_IN*)&addr)->sin_port);
Ipv4DataToString(addr, strIp, FALSE);
return TRUE;
}
else
{
return FALSE;
}
}
BOOL WNCommonSocket::GetPeerName( SOCKADDR* lpSockAddr, int* lpSockAddrLen )
{
Lock();
int iRet = ::getpeername(mSocket, lpSockAddr, lpSockAddrLen);
Unlock();
if (iRet != SOCKET_ERROR)
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL WNCommonSocket::GetSockName( CString& strIp, UINT& uPort )
{
SOCKADDR addr;
memset(&addr, 0, sizeof(addr));
int iLen = sizeof(addr);
int iRet = GetSockName(&addr, &iLen);
if (iRet != SOCKET_ERROR)
{
uPort = ntohs(((SOCKADDR_IN*)&addr)->sin_port);
Ipv4DataToString(addr, strIp, FALSE);
return TRUE;
}
else
{
return FALSE;
}
}
BOOL WNCommonSocket::GetSockName( SOCKADDR* lpSockAddr, int* lpSockAddrLen )
{
Lock();
int iRet = ::getsockname(mSocket, lpSockAddr, lpSockAddrLen);
Unlock();
if (iRet != SOCKET_ERROR)
{
return TRUE;
}
else
{
return FALSE;
}
}
void WNCommonSocket::SetReceiveBuffer( void* pBuffer, UINT uBufferLen )
{
mpReceiveBuffer = (char*)pBuffer;
mpReceiveBufferPos = mpReceiveBuffer;
muAvailableReceiveLen = uBufferLen;
}
DWORD WNCommonSocket::ReceivedDataLen()
{
Lock();
DWORD dwLen = 0;
::ioctlsocket(mSocket, FIONREAD, &dwLen);
Unlock();
return dwLen;
}
int WNCommonSocket::Receive( void* lpBuf, int nBufLen, int nFlags /*= 0*/ )
{
Lock();
int iRet = ::recv(mSocket, (char*)lpBuf, nBufLen, nFlags);
//检查是否需要进入runloop
if ((iRet > 0) && !mpObserverTargetDelegate)
{
if (mhwnd || mpRunLoopThread)
{
mpObserverTargetDelegate = this;
}
}
Unlock();
return iRet;
}
int WNCommonSocket::ReceiveFrom( void* lpBuf, int nBufLen, CString& rSocketAddress, int nFlags /*= 0*/ )
{
SOCKADDR sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
int iSockAddrLen = sizeof(sockAddr);
int iRet = ReceiveFrom(lpBuf, nBufLen, &sockAddr, &iSockAddrLen, nFlags);
if (iRet != SOCKET_ERROR)
{
Ipv4DataToString(sockAddr, rSocketAddress, TRUE);
}
return iRet;
}
int WNCommonSocket::ReceiveFrom(void* lpBuf, int nBufLen, SOCKADDR* pSocketAddress, int* pSockAddrLen, int nFlags /* = 0 */)
{
if (mSocket != INVALID_SOCKET)
{
Lock();
int iRet = ::recvfrom(mSocket, (char*)lpBuf, nBufLen, nFlags, pSocketAddress, pSockAddrLen);
//检查是否需要进入runloop
if ((iRet > 0) && !mpObserverTargetDelegate)
{
if (mhwnd || mpRunLoopThread)
{
mpObserverTargetDelegate = this;
}
}
Unlock();
return iRet;
}
else
{
return 0;
}
}
int WNCommonSocket::Send( const void* lpBuf, int nBufLen, int nFlags /*= 0*/ )
{
Lock();
if (mSocket != INVALID_SOCKET)
{
int iRet = ::send(mSocket, (const char*)lpBuf, nBufLen, nFlags);
Unlock();
return iRet;
}
else
{
Unlock();
return 0;
}
}
int WNCommonSocket::SendTo( const void* lpBuf, int nBufLen, LPCTSTR lpSocketAddress, int nFlags /*= 0*/ )
{
SOCKADDR addr = Ipv4StringToData(lpSocketAddress);
return SendTo(lpBuf, nBufLen, &addr, nFlags);
}
int WNCommonSocket::SendTo(const void* lpBuf, int nBufLen, SOCKADDR* pSocketAddress, int nFlags /*= 0*/)
{
if (mSocket != INVALID_SOCKET)
{
Lock();
int iRet = ::sendto(mSocket, (const char*)lpBuf, nBufLen, nFlags, pSocketAddress, sizeof(*pSocketAddress));
Unlock();
return iRet;
}
else
{
return 0;
}
}
#ifdef WIN32
//通过一个地址取模块句柄
HMODULE ModuleHandleByAddr(const void* ptrAddr)
{
MEMORY_BASIC_INFORMATION info;
::VirtualQuery(ptrAddr, &info, sizeof(info));
return (HMODULE)info.AllocationBase;
}
//获得当前模块句柄
HMODULE ThisModuleHandle()
{
static HMODULE sInstance = ModuleHandleByAddr((void*)&ThisModuleHandle);
return sInstance;
}
LRESULT CALLBACK WNCommonSocketWindowProcedure (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static UINT uMsgOnWNObserverRead = ::RegisterWindowMessage(_T("OnWNObserverRead"));
static UINT uMsgOnWNObserverError = ::RegisterWindowMessage(_T("OnWNObserverError"));
static UINT uMsgNeedDestroy = ::RegisterWindowMessage(_T("NeedDestroyWindow"));
//__try
{
if (uMsg == uMsgNeedDestroy)
{
::DestroyWindow(hwnd);
*((HWND*)(wParam)) = NULL;
return 0;
}
else if (uMsg == uMsgOnWNObserverRead)
{
return ((WNCommonSocket*)lParam)->DoProcessObserverRead((IWNSocketObserver*)wParam);
}
else if (uMsg == uMsgOnWNObserverError)
{
return ((WNCommonSocket*)lParam)->DoProcessObserverError((IWNSocketObserver*)wParam);
}
else
{
return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
//__except(EXCEPTION_EXECUTE_HANDLER)
{
return 0;
}
}
#endif
//创建当前socket窗口
BOOL WNCommonSocket::CreateSocketWindow()
{
#ifdef WIN32
if (mhwnd)
{
return FALSE;
}
static BOOL bHasRegister = FALSE;
static LPCTSTR lpClassName = _T("WNCommonSocketWindow");
//检查是否需要进行窗口注册
if (!bHasRegister)
{
//需要注册窗口
WNDCLASSEX wcex = { 0 };
//WNDCLASSEX 的大小。我们可以用sizeof(WNDCLASSEX)来获得准确的值。
wcex.cbSize = sizeof(WNDCLASSEX);
//从这个窗口类派生的窗口具有的风格。您可以用“or”操作符来把几个风格或到一起。
wcex.style = CS_HREDRAW | CS_VREDRAW;
//窗口处理函数的指针。
wcex.lpfnWndProc = &WNCommonSocketWindowProcedure;
//指定紧跟在窗口类结构后的附加字节数。
wcex.cbClsExtra = 0;
//指定紧跟在窗口事例后的附加字节数。如果一个应用程序在资源中用CLASS伪指令注册一个对话框类时,则必须把这个成员设成DLGWINDOWEXTRA。
wcex.cbWndExtra = 0;
//本模块的事例句柄。
wcex.hInstance = ThisModuleHandle();
//图标的句柄。
wcex.hIcon = NULL;
//和窗口类关联的小图标。如果该值为NULL。则把hIcon中的图标转换成大小合适的小图标。
wcex.hIconSm = NULL;
//光标的句柄。
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
//背景画刷的句柄。
wcex.hbrBackground = ::CreateSolidBrush(RGB(236,233,216));
//指向菜单的指针。
wcex.lpszMenuName = NULL;
//指向类名称的指针。
wcex.lpszClassName = lpClassName;
// 注册窗体类,如果失败退出
if (!::RegisterClassEx (&wcex))
{
return FALSE;
}
else
{
//记录注册结果
bHasRegister = TRUE;
}
}
//创建窗口
mhwnd = ::CreateWindowEx (
WS_EX_APPWINDOW,
lpClassName, /* 类名 */
lpClassName, /* 标题 */
WS_OVERLAPPEDWINDOW, /* 窗体样式 */
CW_USEDEFAULT, /* X坐标 */
CW_USEDEFAULT, /* Y坐标 */
100, /* 宽 */
100, /* 长 */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
ThisModuleHandle(), /* Program Instance handler */
NULL /* No Window Creation data */
);
if (!mhwnd)
{
//创建窗口失败
return FALSE;
}
////设置窗口处理函数
//if (mpACWinProc)
//{
// delete mpACWinProc;
//}
//mpACWinProc = new ACWinProc;
//mpACWinProc->Assign(this, &WNCommonSocket::ACWindowProc);
//WNDPROC lpWinProc = *mpACWinProc;
////已经知道旧的消息处理函数是DefWindowProc,所以无需保存
//::SetWindowLongPtr(mhwnd, GWLP_WNDPROC, reinterpret_cast<LONG>(lpWinProc));
mdwWindowThreadId = ::GetCurrentThreadId();
#endif
return TRUE;
}
BOOL WNCommonSocket::DestroySocketWindow()
{
#ifdef WIN32
if (mhwnd)
{
//::SetWindowLongPtr(mhwnd, GWLP_WNDPROC, reinterpret_cast<LONG>(&::DefWindowProc));
::DestroyWindow(mhwnd);
mhwnd = NULL;
}
#endif
return TRUE;
}
LRESULT WNCommonSocket::InternalWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
#ifdef WIN32
// mbHasWindowMessage = FALSE;
// if (mSocketState == SS_Closing)
// {
// return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
// }
if (uMsg == muMsgOnWNObserverRead)
{
return DoProcessObserverRead((IWNSocketObserver*)wParam);
}
else if (uMsg == muMsgOnWNObserverError)
{
return DoProcessObserverError((IWNSocketObserver*)wParam);
}
else if (uMsg == muMsgNeedDestroyWindow)
{
DestroySocketWindow();
}
else
{
return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
}
#endif
return 0;
}
LRESULT WNCommonSocket::ACWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
return InternalWindowProc(hwnd, uMsg, wParam, lParam);
}
DWORD WINAPI WNCommonSocket::RunLoopThreadProc( LPVOID lpParameter )
{
WNCommonSocket* pSocket = (WNCommonSocket*)lpParameter;
return pSocket->InternalRunLoopThreadProc();
}
DWORD WNCommonSocket::InternalRunLoopThreadProc()
{
#ifdef WIN32
mbIsThreadRunning = TRUE;
//首先进入循环
mpObserverTargetDelegate = this;
CString strOut;
strOut.Format(_T("WNCommonSocket::InternalRunLoopThreadProc begin %d"), this);
//OutputDebugString(strOut);
CString strSelf = mstrSocketIdentity;
//创建消息队列,等待退出
MSG msg;
::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
if (!WNSocketObserverManager::AddSocket(this))
{
return FALSE;
}
while (!mbExitThread)
{
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (!msg.hwnd && (msg.message == muMsgOnWNObserverRead))
{
((WNCommonSocket*)msg.lParam)->DoProcessObserverRead((IWNSocketObserver*)msg.wParam);
}
else if (!msg.hwnd && (msg.message == muMsgOnWNObserverError))
{
((WNCommonSocket*)msg.lParam)->DoProcessObserverError((IWNSocketObserver*)msg.wParam);
}
else
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
UINT uSleepTime = 1;
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketThreadProc(&uSleepTime);
}
if (!mbExitThread && uSleepTime)
{
::Sleep(uSleepTime);
}
//Sleep(5);
}
//strOut.Format(_T("WNCommonSocket::InternalRunLoopThreadProc end %d"), this);
//OutputDebugString(strOut);
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
}
mbIsThreadRunning = FALSE;
#endif
return 0;
}
SOCKADDR WNCommonSocket::Ipv4StringToData( LPCTSTR lpAddress )
{
SOCKADDR addrData;
memset(&addrData, 0, sizeof(addrData));
Ipv4StringToData(lpAddress, addrData);
return addrData;
}
BOOL WNCommonSocket::Ipv4StringToData( LPCTSTR lpAddress, SOCKADDR& addrData )
{
SOCKADDR_IN& AddrIn = (SOCKADDR_IN&)addrData;
if (!lpAddress)
{
//地址不能为空
return FALSE;
}
WNCStringList lstAdrees;
WNCStringList lstIp;
lstAdrees.CreateList(lpAddress, _T(":"));
if (lstAdrees.ListCount() == 1)
{
//只有ip
lstIp.CreateList(lpAddress, _T("."));
}
else if (lstAdrees.ListCount() == 2)
{
//有ip以及端口
lstIp.CreateList(lstAdrees.BeginData().c_str(), _T("."));
}
else
{
//非法ip,无法转换
return FALSE;
}
if (lstIp.ListCount() != 4)
{
//非法ip,无法转换
return FALSE;
}
AddrIn.sin_family = AF_INET;
//如果不需要设置端口,默认为0
if (lstAdrees.ListCount() == 2)
{
//需要设置端口
AddrIn.sin_port = htons((USHORT)_tcstoul(lstAdrees.EndData().c_str(), NULL, 10));
}
unsigned char* pCharAddr = (unsigned char*)(&(AddrIn.sin_addr));
pCharAddr += 3;
for (lstIp.MoveEnd(); lstIp.NotHead(); lstIp.MovePrev())
{
*pCharAddr = (unsigned char)_tcstoul(lstIp.CurrentData().c_str(), NULL, 10);
pCharAddr--;
}
//char* pch = inet_ntoa(AddrIn.sin_addr);
//OutputDebugStringA(inet_ntoa(AddrIn.sin_addr));
return TRUE;
}
CString WNCommonSocket::Ipv4DataToString( SOCKADDR& addrIn, BOOL bWithPort )
{
SOCKADDR_IN& AddrIn = (SOCKADDR_IN&)addrIn;
unsigned char* pCharAddr = (unsigned char*)(&(AddrIn.sin_addr));
CString strRet = _T("");
Ipv4DataToString(addrIn, strRet, bWithPort);
return strRet;
}
BOOL WNCommonSocket::Ipv4DataToString( SOCKADDR& addrIn, CString& strAddr, BOOL bWithPort )
{
SOCKADDR_IN& AddrIn = (SOCKADDR_IN&)addrIn;
unsigned char* pCharAddr = (unsigned char*)(&(AddrIn.sin_addr));
if (bWithPort)
{
ostringstream strKeystream;
strKeystream << (int)pCharAddr[0] << "." << (int)pCharAddr[1] << "." << (int)pCharAddr[2] << "." << (int)pCharAddr[3] << ":" << (int)ntohs(AddrIn.sin_port);
//Addr.Format(("%d.%d.%d.%d:%u"), pCharAddr[0], pCharAddr[1], pCharAddr[2], pCharAddr[3], ntohs(AddrIn.sin_port));
strAddr = strKeystream.str();
}
else
{
//Addr.Format(("%d.%d.%d.%d"), pCharAddr[0], pCharAddr[1], pCharAddr[2], pCharAddr[3]);
ostringstream strKeystream;
strKeystream << (int)pCharAddr[0] << "." << (int)pCharAddr[1] << "." << (int)pCharAddr[2] << "." << (int)pCharAddr[3];
//Addr.Format(("%d.%d.%d.%d:%u"), pCharAddr[0], pCharAddr[1], pCharAddr[2], pCharAddr[3], ntohs(AddrIn.sin_port));
strAddr = strKeystream.str();
}
return TRUE;
}
int WNCommonSocket::GetLastError()
{
return errno;
}
bool WNCommonSocket::OnWorkThreadProc( WNWorkThread* objThread, unsigned int& uStep )
{
if (objThread != this->mpRunLoopThread)
{
return WN_WORK_THREAD_EXIT;
}
if (mbOnRead)
{
mbOnRead = FALSE;
IWNSocketObserver* pObserver = (IWNSocketObserver*)mpReadObserver;
DoProcessObserverRead(pObserver);
muRunLoopThreadSleepTime = 0;
}
else if (mbOnError)
{
mbOnError = FALSE;
IWNSocketObserver* pObserver = (IWNSocketObserver*)mpErrorObserver;
DoProcessObserverError(pObserver);
muRunLoopThreadSleepTime = 0;
}
else
{
UINT uSleepTime = 5;
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketThreadProc(&uSleepTime);
}
if (uSleepTime)
{
muRunLoopThreadSleepTime = uSleepTime;
}
}
return WN_WORK_THREAD_CONTINUE;
}
unsigned int WNCommonSocket::OnWorkThreadNeedSleep( WNWorkThread* objThread )
{
return muRunLoopThreadSleepTime;
}
void WNCommonSocket::OnObserverRead( IWNSocketObserver* observer )
{
#ifdef WIN32
if (mhwnd)
{
//mbHasWindowMessage = TRUE;
::PostMessage(mhwnd, muMsgOnWNObserverRead, (WPARAM)observer, (LPARAM)this);
}
else if (mdwThreadId)
{
//DoPorcessTcpDataRead();
::PostThreadMessage(mdwThreadId, muMsgOnWNObserverRead, (WPARAM)observer, (LPARAM)this);
}
#endif
mbOnRead = TRUE;
mpReadObserver = observer;
}
void WNCommonSocket::OnObserverError( IWNSocketObserver* observer )
{
#ifdef WIN32
if (mhwnd)
{
::PostMessage(mhwnd, muMsgOnWNObserverError, (WPARAM)observer, (LPARAM)this);
}
else if (mdwThreadId)
{
::PostThreadMessage(mdwThreadId, muMsgOnWNObserverError, (WPARAM)observer, (LPARAM)this);
}
#endif
mbOnError = TRUE;
mpErrorObserver = observer;
}
#define RECEIV_BUF_LEN (mpReceiveBufferPos + muAvailableReceiveLen - mpReceiveBuffer)
BOOL WNCommonSocket::DoPorcessTcpDataRead()
{
DWORD dwUnreadLen = 0;
::ioctlsocket(mSocket, FIONREAD, &dwUnreadLen);
int iRet = 0;
while (true)
{
if (!dwUnreadLen)
{
//检查是否需要进入runloop
if (!mpObserverTargetDelegate)
{
if (mhwnd || mpRunLoopThread)
{
mpObserverTargetDelegate = this;
}
}
break;
}
if (!muAvailableReceiveLen)
{
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketReceive(this, dwUnreadLen);
}
break;
}
else if (muAvailableReceiveLen <= dwUnreadLen)
{
iRet = ::recv(mSocket, mpReceiveBufferPos, muAvailableReceiveLen, 0);
if (iRet != (int)muAvailableReceiveLen)
{
return false;
}
dwUnreadLen -= iRet;
muAvailableReceiveLen -= iRet;
mpReceiveBufferPos += iRet;
if (iRet == 0)
{
//socket已关闭
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketClose(this);
}
return true;
}
else
{
//通知缓冲区已满
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketRecvBufferFulled(this, mpReceiveBuffer, RECEIV_BUF_LEN, dwUnreadLen);
}
}
}
else
{
iRet = ::recv(mSocket, mpReceiveBufferPos, dwUnreadLen, 0);
if (iRet != (int)dwUnreadLen)
{
return false;
}
dwUnreadLen -= iRet;
muAvailableReceiveLen -= iRet;
mpReceiveBufferPos += iRet;
if (iRet == 0)
{
//socket已关闭
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketClose(this);
}
return true;
}
//检查是否需要进入runloop
if (!mpObserverTargetDelegate)
{
if (mhwnd || mpRunLoopThread)
{
mpObserverTargetDelegate = this;
}
}
break;
}
}
return true;
}
BOOL WNCommonSocket::DoProcessUdpDataRead()
{
DWORD dwUnreadLen = 0;
::ioctlsocket(mSocket, FIONREAD, &dwUnreadLen);
while (dwUnreadLen)
{
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketReceive(this, dwUnreadLen);
::ioctlsocket(mSocket, FIONREAD, &dwUnreadLen);
}
else
{
break;
}
}
return true;
}
BOOL WNCommonSocket::DoProcessObserverRead( IWNSocketObserver* observer )
{
if (!mpCommonSocketDelegate)
{
if (!mpObserverTargetDelegate)
{
mpObserverTargetDelegate = this;
}
return FALSE;
}
if (mSocketState == SS_Listening)
{
//监听状态,说明有socket请求连接
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketAccept(this);
}
}
else
{
//非监听状态,首先检测是否关闭
if (miSocketInitType == SOCK_DGRAM)
{
//有内容可读
DoProcessUdpDataRead();
return TRUE;
}
char buf[1] = { 0 };
int iRet = 0;
iRet = ::recv(mSocket, buf, 1, MSG_PEEK);
if (iRet == 0)
{
//socket已关闭
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketClose(this);
}
}
else if (iRet != SOCKET_ERROR)
{
//有内容可读
if (miSocketInitType == SOCK_STREAM)
{
DoPorcessTcpDataRead();
}
else
{
DWORD dwUnreadLen = 0;
::ioctlsocket(mSocket, FIONREAD, &dwUnreadLen);
if (mpCommonSocketDelegate)
{
mpCommonSocketDelegate->OnCommonSocketReceive(this, dwUnreadLen);
}
}
}
else
{
//读取错误
int iError = GetLastError();
return FALSE;
}
}
return TRUE;
}
BOOL WNCommonSocket::DoProcessObserverError( IWNSocketObserver* observer )
{
if (!mpCommonSocketDelegate)
{
return FALSE;
}
mpCommonSocketDelegate->OnCommonSocketError(this, miObserverErrorCode);
return TRUE;
}
/*utf8解析行 Don't remove or modify this first line!*/
#ifdef __WINOS__
#include "StdAfx.h"
#endif
#include "WNCreticalSection.h"
#include "stdio.h"
class CreticalSectionAttr
{
public:
pthread_mutexattr_t mattr;
public:
CreticalSectionAttr()
{
pthread_mutexattr_init(&mattr);
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
}
~CreticalSectionAttr()
{
pthread_mutexattr_destroy(&mattr);
}
pthread_mutexattr_t* getAttr()
{
return &mattr;
}
};
CreticalSectionAttr mCreticalSectionAttr;
WNCreticalSection::WNCreticalSection(void)
:mpLocker(NULL)
{
CreateLocker();
}
WNCreticalSection::~WNCreticalSection(void)
{
DestroyLocker();
}
void WNCreticalSection::CreateLocker()
{
if (!mpLocker)
{
mpLocker = new pthread_mutex_t;
pthread_mutex_init(mpLocker, mCreticalSectionAttr.getAttr());
}
}
void WNCreticalSection::DestroyLocker()
{
if (mpLocker)
{
pthread_mutex_destroy(mpLocker);
delete mpLocker;
mpLocker = NULL;
}
}
bool WNCreticalSection::TryLock()
{
if (mpLocker)
{
//pthread_mutex_lock(mpLocker);
/*struct timespec lockwait = {0,50000000};
int ret = pthread_mutex_timedlock(mpLocker,&lockwait);
return (ret == 0) ? true : false;*/
int ret = pthread_mutex_trylock(mpLocker);
return (ret == 0) ? true : false;
}
else
{
//没有初始化锁,默认返回TRUE表示可以操作
return true;
}
return true;
}
bool WNCreticalSection::Lock()
{
if (mpLocker)
{
while(pthread_mutex_lock(mpLocker))
{
printf("WNCreticalSection lock failed!");
}
}
//没有初始化锁,默认返回TRUE表示可以操作
return true;
}
bool WNCreticalSection::Unlock()
{
if (mpLocker)
{
pthread_mutex_unlock(mpLocker);
}
return true;
}
WNCreticalSectionAutoLocker::WNCreticalSectionAutoLocker()
:mpLocker(NULL)
,mpLocking(NULL)
{
}
WNCreticalSectionAutoLocker::WNCreticalSectionAutoLocker(WNCreticalSection* pCreiticalSection, bool bLocker /* = TRUE */)
:mpLocker(NULL)
,mpLocking(NULL)
{
mpLocker = pCreiticalSection;
if (bLocker)
{
Lock();
}
}
WNCreticalSectionAutoLocker::~WNCreticalSectionAutoLocker()
{
if (mpLocker && mpLocking)
{
mpLocker->Unlock();
}
}
bool WNCreticalSectionAutoLocker::TryLock()
{
if (mpLocker)
{
if (mpLocking == mpLocker)
{
return true;
}
else if (!mpLocking)
{
if (mpLocker->TryLock())
{
mpLocking = mpLocker;
return true;
}
else
{
mpLocking = NULL;
return false;
}
}
else if (mpLocker->TryLock())
{
mpLocking = mpLocker;
return true;
}
else
{
mpLocking = NULL;
return false;
}
}
else
{
//未设置锁对象
//默认为成功锁定
return true;
}
}
void WNCreticalSectionAutoLocker::Lock()
{
if (mpLocker)
{
if (!mpLocking || (mpLocking != mpLocker))
{
mpLocker->Lock();
mpLocking = mpLocker;
}
}
}
void WNCreticalSectionAutoLocker::Unlock()
{
if (!mpLocker)
{
return;
}
if (mpLocking == mpLocker)
{
mpLocker->Unlock();
}
mpLocking = NULL;
}
/*utf8解析行 Don't remove or modify this first line!*/
//#include "stdafx.h"
#include "WNInvoker.h"
WNInvokeInfo::WNInvokeInfo()
:mbInvoked(FALSE)
,muInvokeTime(0)
,mpReturnValue(NULL)
{
}
WNInvokeInfo::~WNInvokeInfo()
{
Reset();
}
//======================================================================================================
void WNInvokeInfo::Reset()
{
mbInvoked = FALSE;
muInvokeTime = 0;
mpReturnValue = NULL;
}
void WNInvoker::AddInvokeInfo( WNInvokeInfo* pInvokeInfo )
{
if (!pInvokeInfo)
{
return;
}
mInvokeLocker.LockWrite();
if (!mInvokeList.ListCount())
{
pInvokeInfo->Retain();
mInvokeList.AppendNode(pInvokeInfo);
mInvokeLocker.ReleaseWrite();
return;
}
else
{
WNCLoopList<WNInvokeInfo*>::PNode pNode = NULL;
for (mInvokeList.MoveEnd(); mInvokeList.NotHead(); mInvokeList.MovePrev())
{
pNode = mInvokeList.Current();
if (pNode->data->muInvokeTime <= pInvokeInfo->muInvokeTime)
{
pInvokeInfo->Retain();
mInvokeList.AppendNode(pInvokeInfo, pNode);
mInvokeLocker.ReleaseWrite();
return;
}
}
pInvokeInfo->Retain();
mInvokeList.PreAppendNode(pInvokeInfo);
mInvokeLocker.ReleaseWrite();
return;
}
}
BOOL WNInvoker::DoCheckAndInvoke()
{
if (!DoCheckInvoke())
{
return FALSE;
}
if (!DoInvoke())
{
return FALSE;
}
while (DoCheckInvoke())
{
DoInvoke();
}
return TRUE;
}
BOOL WNInvoker::DoCheckInvoke()
{
mInvokeLocker.LockRead();
if (!mInvokeList.ListCount())
{
mInvokeLocker.ReleaseRead();
return FALSE;
}
UINT uCurrentTime = getCurrentTime();
if (mInvokeList.BeginData()->muInvokeTime <= uCurrentTime)
{
mInvokeLocker.ReleaseRead();
return TRUE;
}
else
{
mInvokeLocker.ReleaseRead();
return FALSE;
}
}
BOOL WNInvoker::DoInvoke()
{
mInvokeLocker.LockWrite();
if (!mInvokeList.ListCount())
{
mInvokeLocker.ReleaseWrite();
return FALSE;
}
WNInvokeInfo* pInvokeInfo = mInvokeList.BeginData();
mInvokeList.RemoveNode(mInvokeList.Begin());
pInvokeInfo->InvokeMemberFunc();
pInvokeInfo->Release();
mInvokeLocker.ReleaseWrite();
return TRUE;
}
/*utf8解析行 Don't remove or modify this first line!*/
#include "stdafx.h"
#include "WNNetworkInfo.h"
WNAddrData::WNAddrData()
:m_strAdapterName(_T(""))
,m_strAdapterInfo(_T(""))
,m_strIp(_T("0.0.0.0"))
,m_uMacLen(0)
,m_strVirtualMac(_T(""))
,m_bIsVirtual(FALSE)
,m_uType(0)
,m_nIPCount(0)
{
ZeroMemory(m_MacAddr, MAC_LENGTH);
}
WNAddrData::WNAddrData( const WNAddrData& data )
{
m_strAdapterName = data.m_strAdapterName;
m_strAdapterInfo = data.m_strAdapterInfo;
m_strIp = data.m_strIp;
m_uMacLen = data.m_uMacLen;
m_strVirtualMac = data.m_strVirtualMac;
m_bIsVirtual = data.m_bIsVirtual;
m_uType = data.m_uType;
CopyMemory(m_MacAddr, data.m_MacAddr, MAC_LENGTH);
}
CString WNAddrData::GetMacAddress()
{
if (m_strVirtualMac != _T(""))
{
return m_strVirtualMac;
}
CString strRet = _T("");
CString strCh = _T("");
for (UINT i = 0; i < m_uMacLen; i++)
{
strCh.Format(_T("%02X"), m_MacAddr[i]);
strRet += strCh;
}
return strRet;
}
WNAddrData& WNAddrData::operator=( const WNAddrData& data )
{
if (this == &data)
{
return *this;
}
m_strAdapterName = data.m_strAdapterName;
m_strAdapterInfo = data.m_strAdapterInfo;
m_strIp = data.m_strIp;
m_uMacLen = data.m_uMacLen;
m_strVirtualMac = data.m_strVirtualMac;
m_bIsVirtual = data.m_bIsVirtual;
m_strBroadCastIp = data.m_strBroadCastIp;
m_strSubnetMask = data.m_strSubnetMask;
m_uType = data.m_uType;
m_dwStartIp = data.m_dwStartIp;
m_dwEndIp = data.m_dwEndIp;
m_dwAdapterIndex = data.m_dwAdapterIndex;
m_nIPCount = data.m_nIPCount;
for(int iIndex = 0; iIndex < m_nIPCount; ++iIndex)
m_strIPList[iIndex] = data.m_strIPList[iIndex];
CopyMemory(m_MacAddr, data.m_MacAddr, MAC_LENGTH);
return *this;
}
WNNetworkInfo::WNNetworkInfo()
{
ReInit();
}
VOID WNNetworkInfo::ReInit()
{
WNAddrData macDatas[ADAPTER_COUNT_MAX];
LONG lInsertCount = GetSystemMacInfo(macDatas);
m_lCount = 0;
//for (LONG j = 1; j < lInsertCount; j++)
//{
// if (macDatas[j].m_uType != MIB_IF_TYPE_PPP)
// {
// m_MacData[m_lSystemIdCount] = macDatas[0];
// CopyMemory(m_MacData[m_lSystemIdCount].m_MacAddr, macDatas[j].m_MacAddr, MAC_LENGTH);
// m_MacData[m_lSystemIdCount].m_strIp = macDatas[j].m_strIp;
// m_lSystemIdCount++;
// }
//}
for (LONG i = 0; i < lInsertCount; i++)
{
if (macDatas->m_uType != MIB_IF_TYPE_PPP)
{
m_AddrData[m_lCount] = macDatas[i];
m_lCount++;
}
}
for (LONG i = 0; i < lInsertCount; i++)
{
if (macDatas->m_uType == MIB_IF_TYPE_PPP)
{
for (LONG j = 0; j < lInsertCount; j++)
{
if (macDatas[j].m_uType != MIB_IF_TYPE_PPP)
{
m_AddrData[m_lCount] = macDatas[i];
CopyMemory(m_AddrData[m_lCount].m_MacAddr, macDatas[j].m_MacAddr, MAC_LENGTH);
m_lCount++;
}
}
}
}
}
BOOL WNNetworkInfo::IsConnectedAdapter(DWORD dwIndex)
{
MIB_IFROW ifRow;
ZeroMemory(&ifRow, sizeof(ifRow));
ifRow.dwIndex = dwIndex;
DWORD dwRet = GetIfEntry(&ifRow);
if (dwRet != NO_ERROR)
{
OutputDebugString(_T("GetIfEntry return is not NO_ERROR"));
return FALSE;
}
if (ifRow.dwOperStatus != MIB_IF_OPER_STATUS_OPERATIONAL)
{
OutputDebugString(_T("ifRow.dwOperStatus != MIB_IF_OPER_STATUS_CONNECTED"));
CString strOut;
strOut.Format(_T("State is %d"), ifRow.dwOperStatus);
OutputDebugString(strOut);
return FALSE;
}
return TRUE;
}
//get system Ethernet adapters
LONG WNNetworkInfo::GetSystemMacInfo(WNAddrData* pAddrData)
{
IP_ADAPTER_INFO ipAdapterInfo[ADAPTER_COUNT_MAX];
ULONG uBufferSize = sizeof(IP_ADAPTER_INFO) * ADAPTER_COUNT_MAX;
DWORD dwRet = GetAdaptersInfo(ipAdapterInfo, &uBufferSize);
if (ERROR_SUCCESS != dwRet)
{
return FALSE;
}
//Add a virtual networkcard at first
//pMacData->m_strAdapterName = _T("E Virtual NetworkCard");
//pMacData->m_bIsVirtual = TRUE;
//pMacData++;
LONG lRet = 0;
PIP_ADAPTER_INFO pInfo = ipAdapterInfo;
PIP_ADDR_STRING pIpInfo = &(pInfo->IpAddressList);
while (pInfo)
{
if (MIB_IF_TYPE_ETHERNET == pInfo->Type || MIB_IF_TYPE_PPP == pInfo->Type || TRUE)
{
if (IsConnectedAdapter(pInfo->Index) || MIB_IF_TYPE_PPP == pInfo->Type)
{
pAddrData->m_dwAdapterIndex = pInfo->Index;
CopyMemory(pAddrData->m_MacAddr, pInfo->Address, pInfo->AddressLength);
pAddrData->m_uMacLen = pInfo->AddressLength;
LPTSTR pBuf = pAddrData->m_strAdapterInfo.GetBuffer(sizeof(pInfo->Description) * sizeof(TCHAR));
//pMacData->m_strAdapterInfo.Format(_T("%s"), pInfo->Description);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pInfo->Description, -1, pBuf, sizeof(pInfo->Description));
pAddrData->m_strAdapterInfo.ReleaseBuffer();
pBuf = pAddrData->m_strAdapterName.GetBuffer(sizeof(pInfo->AdapterName) * sizeof(TCHAR));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pInfo->AdapterName, -1, pBuf, sizeof(pInfo->AdapterName));
pAddrData->m_strAdapterName.ReleaseBuffer();
pBuf = pAddrData->m_strIp.GetBuffer(sizeof(pIpInfo->IpAddress) * sizeof(TCHAR));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pIpInfo->IpAddress.String, -1, pBuf, sizeof(pIpInfo->IpAddress.String) * sizeof(TCHAR));
pAddrData->m_strIp.ReleaseBuffer();
pBuf = pAddrData->m_strSubnetMask.GetBuffer(sizeof(pIpInfo->IpMask) * sizeof(TCHAR));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pIpInfo->IpMask.String, -1, pBuf, sizeof(pIpInfo->IpMask.String) * sizeof(TCHAR));
pAddrData->m_strSubnetMask.ReleaseBuffer();
in_addr broadcast;
broadcast.S_un.S_addr = (inet_addr( CT2A(pAddrData->m_strIp))
& inet_addr( CT2A(pAddrData->m_strSubnetMask)))
| (~inet_addr( CT2A(pAddrData->m_strSubnetMask)));
pAddrData->m_strBroadCastIp = inet_ntoa(broadcast);
pAddrData->m_dwStartIp = (ntohl(inet_addr( CT2A(pAddrData->m_strSubnetMask))) & ntohl(inet_addr( CT2A(pAddrData->m_strIp)))) + 1;
pAddrData->m_dwEndIp = ntohl(inet_addr( CT2A(pAddrData->m_strBroadCastIp) )) - 1;
if((pAddrData->m_dwEndIp - pAddrData->m_dwStartIp) > 1000)
{
pAddrData->m_dwEndIp = pAddrData->m_dwStartIp + 1000;
}
pAddrData->m_uType = pInfo->Type;
OutputDebugStringV(pAddrData->m_strAdapterName);
OutputDebugStringV(pAddrData->m_strAdapterInfo);
OutputDebugStringV(pAddrData->GetMacAddress());
OutputDebugStringV(pAddrData->m_strIp);
if(!pAddrData->m_strIp.IsEmpty())
{
pAddrData->m_strIPList[pAddrData->m_nIPCount] = pAddrData->m_strIp;
++pAddrData->m_nIPCount;
}
if (pIpInfo->Next)
{
pIpInfo = pIpInfo->Next;
}
else
{
pInfo = pInfo->Next;
pIpInfo = &(pInfo->IpAddressList);
}
lRet++;
pAddrData++;
}
else
{
pInfo = pInfo->Next;
pIpInfo = &(pInfo->IpAddressList);
}
}
else
{
pInfo = pInfo->Next;
pIpInfo = &(pInfo->IpAddressList);
}
}
return lRet;
}
WNAddrData* WNNetworkInfo::GetAdapterInfo(LONG lIndex)
{
if (lIndex >= m_lCount)
{
return NULL;
}
else
{
return &m_AddrData[lIndex];
}
}
VOID WNNetworkInfo::SetVirtualMac( CString& strMac )
{
OutputDebugStringV(_T("SetVirtualMac %s"), strMac);
for (LONG i = 0; i < m_lCount; i++)
{
m_AddrData[i].m_strVirtualMac = strMac;
}
}
void WNNetworkInfo::OutputAdapterInfo()
{
for (int i = 0; i < m_lCount; i++)
{
OutputDebugStringV(_T("Adapter %d:"), i);
OutputDebugStringV(_T("Name is %s, VirtualMac is %d"), m_AddrData[i].m_strAdapterName, m_AddrData[i].IsVirtual());
OutputDebugStringV(_T("Ip is %s"), m_AddrData[i].m_strIp);
OutputDebugStringV(_T("MacAddress is %s"), m_AddrData[i].GetMacAddress());
}
}
\ No newline at end of file
/*utf8解析行 Don't remove or modify this first line!*/
#include "WNObject.h"
#include "WNCreticalSection.h"
#include "WNNotificationCenter.h"
#include "WNReadWriteLocker.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sstream>
#include <cstring>
#include "WNWorkThread.h"
using namespace std;
//===================================================================================================
//WNNotification=====================================================================================
//===================================================================================================
WNNotification::WNNotification(unsigned int uParamsCount /* = DEF_NT_PARAMS_COUNT */)
:muNotificationId(0)
,mpNotificationSender(0)
,mpNotificationData(NULL)
,mpNotificationCenter(NULL)
,muParamsCount(uParamsCount)
{
memset(mParams, 0, muParamsCount * sizeof(unsigned int));
}
WNNotification::~WNNotification()
{
doRelease(mpNotificationData);
}
const char* WNNotification::NotificationName()
{
if (mpNotificationCenter)
{
return mpNotificationCenter->GetNotificationNameById(muNotificationId);
}
else
{
return WNNotificationCenter::DefaultCenter()->GetNotificationNameById(muNotificationId);
}
}
bool WNNotification::IsNotification( const char* lpNotificationName )
{
if (!muNotificationId)
{
return false;
}
if (mpNotificationCenter)
{
return mpNotificationCenter->GetNotificationIdByName(lpNotificationName) == muNotificationId;
}
else
{
return WNNotificationCenter::DefaultCenter()->GetNotificationIdByName(lpNotificationName) == muNotificationId;
}
}
unsigned int WNNotification::GetSize()
{
return sizeof(WNNotification) + muParamsCount * sizeof(unsigned int) - DEF_NT_PARAMS_COUNT * sizeof(unsigned int);
}
WNNotification* WNNotification::GetCopy()
{
return NULL;
}
void WNNotification::CopyTo(WNNotification* pNotification)
{
}
//===================================================================================================
//WNNotificationObserver=============================================================================
//===================================================================================================
unsigned int WNNotificationObserver::StartObserveNotification(const char* lpNotificationName, void* pSender /* = NULL */, WNNotificationCenter* pNotificationCenter /* = NULL */)
{
if (!pNotificationCenter)
{
pNotificationCenter = WNNotificationCenter::DefaultCenter();
}
return pNotificationCenter->AddObserver(this, lpNotificationName, pSender);
}
void WNNotificationObserver::StopObserveNotification(const char* lpNotificationName /* = NULL */, void* pSender /* = NULL */, WNNotificationCenter* pNotificationCenter /* = NULL */)
{
if (!pNotificationCenter)
{
pNotificationCenter = WNNotificationCenter::DefaultCenter();
}
return pNotificationCenter->RemoveObserver(this, lpNotificationName, pSender);
}
unsigned int WNNotificationObserver::StartObserveNotificationOnThread(const char *lpNotificationName, WNWorkThread* pThread /*= NULL*/, void *pSender /*= NULL*/, WNNotificationCenter *pNotificationCenter /*= NULL*/)
{
if (!pThread)
{
pThread = WNWorkThread::GetCurrentThread();
}
if (!pThread)
{
return 0;
}
return pThread->AddObserve4Notification(this, lpNotificationName, pSender, pNotificationCenter);
}
void WNNotificationObserver::StopObserveNotificationOnThread(const char* lpNotificationName /*= NULL*/, WNWorkThread* pThread /*= NULL*/, void* pSender /*= NULL*/, WNNotificationCenter* pNotificationCenter /*= NULL*/)
{
if (!pThread)
{
pThread = WNWorkThread::GetCurrentThread();
}
if (!pThread)
{
return;
}
pThread->RemoveObserve4Notification(this, lpNotificationName, pSender, pNotificationCenter);
}
//===================================================================================================
//WNNotificationObserver=============================================================================
//===================================================================================================
WNObserverInfo::WNObserverInfo()
:mpNotificationReceiver(NULL)
,mpNotificationSender(NULL)
,mbIsValid(false)
{
}
//===================================================================================================
//WNNotificationObserverList=========================================================================
//===================================================================================================
WNNotificationObserverList::WNNotificationObserverList()
:muNotificationId(0)
,mstrNotificationName("")
,mpLocker(NULL)
,muNotificationLevel(0)
,muRemoveCount(0)
{
mpLocker = new WNCreticalSection;
}
WNNotificationObserverList::~WNNotificationObserverList()
{
delete mpLocker;
}
void WNNotificationObserverList::AddObserver( WNNotificationObserver* pObserver, void* pSender )
{
WNNotificationObserverList::PNode pNode = NULL;
mpLocker->Lock();
//从已有观察者中寻找
for (pNode = Begin(); pNode != Head(); pNode = pNode->nextNode)
{
if (pNode->data.mpNotificationReceiver == pObserver)
{
break;
}
}
if (pNode == Head())
{
//没有找到
pNode = new WNNotificationObserverList::Node;
AppendNode(pNode);
}
pNode->data.mpNotificationReceiver = pObserver;
pNode->data.mpNotificationSender = pSender;
pNode->data.mbIsValid = true;
mpLocker->Unlock();
}
void WNNotificationObserverList::RemoveObserver(WNNotificationObserver* pObserver, void* pSender)
{
WNNotificationObserverList::PNode pNode = NULL;
mpLocker->Lock();
//从已有观察者中寻找
for (pNode = Begin(); pNode != Head(); pNode = pNode->nextNode)
{
if ((pNode->data.mpNotificationReceiver == pObserver) && (pNode->data.mpNotificationSender == pSender))
{
//判断是否当前对象是否在当前线程的OnReceiveNotification通知中
if (muNotificationLevel)
{
//在通知中
if (pNode->data.mbIsValid)
{
pNode->data.mbIsValid = false;
muRemoveCount++;
}
}
else
{
//不在通知中
RemoveNode(pNode);
}
break;
}
}
mpLocker->Unlock();
}
void WNNotificationObserverList::PostNotification( WNNotification* pNotification, void* pSender /*= NULL*/ )
{
WNNotificationObserverList::PNode pNode = NULL;
mpLocker->Lock();
muNotificationLevel++;
pNotification->mpNotificationSender = pSender;
for (pNode = Begin(); pNode != Head(); pNode = pNode->nextNode)
{
if ((pNode->data.mpNotificationSender == pSender) && (pNode->data.mbIsValid))
{
pNode->data.mpNotificationReceiver->OnReceiveNotification(pNotification);
}
else if ((pNode->data.mpNotificationSender == NULL) && (pNode->data.mbIsValid))
{
pNode->data.mpNotificationReceiver->OnReceiveNotification(pNotification);
}
}
//删除无效观察者
if (muRemoveCount && (muNotificationLevel == 1))
{
for (pNode = Begin(); pNode != Head();)
{
pNode = pNode->nextNode;
if (!(pNode->prevNode->data.mbIsValid))
{
RemoveNode(pNode->prevNode);
}
}
muRemoveCount = 0;
}
muNotificationLevel--;
mpLocker->Unlock();
}
//===================================================================================================
//WNNotificationCenter===============================================================================
//===================================================================================================
#define DefInitNotificationCount 256
WNNotificationCenter* mpDefaultCenter = NULL; //默认的消息中心
//WNNotificationCenter mDefaultCenterCreator; //用于在构造函数中创建默认的消息中心
//如果存在多个模块,使用第一个作为默认的消息中心
WNNotificationCenter::WNNotificationCenter()
:mppNotificationObserverList(NULL)
,muNotificationListMaxCount(0)
,muNextNotificationId(1)
{
//有效元素从0开始
mppNotificationObserverList = new WNNotificationObserverList*[DefInitNotificationCount + 1];
memset(mppNotificationObserverList, 0x00,sizeof(WNNotificationObserverList*) * (DefInitNotificationCount + 1));
muNotificationListMaxCount = DefInitNotificationCount;
mpReadWriteLocker = new WNReadWriteLocker;
}
WNNotificationCenter::~WNNotificationCenter( void )
{
// printf("enter WNNotificationCenter::~WNNotificationCenter\n");
mpReadWriteLocker->LockWrite();
if (mppNotificationObserverList)
{
for (unsigned int i = 1; i < muNextNotificationId; i++)
{
delete mppNotificationObserverList[i];
}
delete[] mppNotificationObserverList;
mppNotificationObserverList = NULL;
}
mpReadWriteLocker->ReleaseWrite();
delete mpReadWriteLocker;
// printf("exit WNNotificationCenter::~WNNotificationCenter\n");
}
WNNotificationCenter* WNNotificationCenter::DefaultCenter()
{
static WNNotificationCenter mDefaultCenter;
if (!mpDefaultCenter)
{
//判断是否已经存在默认的消息中心
//通过环境变量保证系统中只存在一个消息中心
char* value=0;
ostringstream strKeystream;
ostringstream strValuestream;
strKeystream << "WNNotificationCenter_P" << getpid();
value = getenv(strKeystream.str().c_str());
if(0 == value){
mpDefaultCenter = &mDefaultCenter;
strValuestream << (long)mpDefaultCenter;
if( 0 == setenv(strKeystream.str().c_str(),strValuestream.str().c_str(),1)){
}
}else{
mpDefaultCenter = (WNNotificationCenter*)atol(value);
}
}
return mpDefaultCenter;
}
unsigned int WNNotificationCenter::RegisterNotification( const char* lpNotificationName )
{
unsigned int uId = GetNotificationIdByName(lpNotificationName);
if (uId)
{
return uId;
}
//消息未注册
//注册消息
mpReadWriteLocker->LockWrite();
if (muNextNotificationId > muNotificationListMaxCount)
{
//消息队列数组已满,需要扩展空间
//扩展DefInitNotificationCount个大小
WNNotificationObserverList** pNewArray = new WNNotificationObserverList*[muNotificationListMaxCount + DefInitNotificationCount + 1];
muNotificationListMaxCount += DefInitNotificationCount;
//复制原来的指针数组至新数组
memcpy(pNewArray, mppNotificationObserverList, sizeof(WNNotificationObserverList*) * (muNotificationListMaxCount + 1));
//删除原来的数组
delete[] mppNotificationObserverList;
//指向新数组
mppNotificationObserverList = pNewArray;
}
//加入新id
mppNotificationObserverList[muNextNotificationId] = new WNNotificationObserverList;
mppNotificationObserverList[muNextNotificationId]->mstrNotificationName = lpNotificationName;
mppNotificationObserverList[muNextNotificationId]->muNotificationId = muNextNotificationId;
uId = muNextNotificationId++;
mpReadWriteLocker->ReleaseWrite();
return uId;
}
unsigned int WNNotificationCenter::GetNotificationIdByName( const char* lpNotificationName )
{
unsigned int uId = 0;
mpReadWriteLocker->LockRead();
for (unsigned int i = 1; i < muNextNotificationId; i++)
{
if (!::strcmp((const char*)(mppNotificationObserverList[i]->mstrNotificationName.c_str()), lpNotificationName))
{
uId = i;
break;
}
}
mpReadWriteLocker->ReleaseRead();
return uId;
}
const char* WNNotificationCenter::GetNotificationNameById( unsigned int uNotificationId )
{
if (!uNotificationId)
{
return NULL;
}
const char* lpNotificationName = NULL;
mpReadWriteLocker->LockRead();
if (uNotificationId < muNextNotificationId)
{
lpNotificationName = mppNotificationObserverList[uNotificationId]->mstrNotificationName.c_str();
}
mpReadWriteLocker->ReleaseRead();
return lpNotificationName;
}
unsigned int WNNotificationCenter::AddObserver( WNNotificationObserver* pObserver, const char* lpNotificationName, void* pSender /*= NULL*/ )
{
if (!pObserver || !lpNotificationName)
{
return 0;
}
//注册消息
unsigned int uId = RegisterNotification(lpNotificationName);
//添加观察者
mppNotificationObserverList[uId]->AddObserver(pObserver, pSender);
return uId;
}
void WNNotificationCenter::RemoveObserver( WNNotificationObserver* pObserver, const char* lpNotificationName /*= NULL*/, void* pSender /*= NULL*/ )
{
if (!pObserver)
{
return;
}
//移除监视
if (lpNotificationName)
{
//在指定消息名称的观察者中移除
unsigned int uId = GetNotificationIdByName(lpNotificationName);
if (!uId)
{
return;
}
mppNotificationObserverList[uId]->RemoveObserver(pObserver, pSender);
}
else
{
mpReadWriteLocker->LockWrite();
unsigned int uNextNotificationId = muNextNotificationId;
mpReadWriteLocker->ReleaseWrite();
for (unsigned int i = 1; i < uNextNotificationId; i++)
{
mppNotificationObserverList[i]->RemoveObserver(pObserver, pSender);
}
}
return;
}
bool WNNotificationCenter::PostNotification( const char* lpNotificationName, WNObject* pNotificationData /*= NULL*/, void* pSender /*= NULL*/ )
{
if (!lpNotificationName)
{
return false;
}
unsigned int uId = GetNotificationIdByName(lpNotificationName);
if (!uId)
{
return false;
}
return PostNotification(uId, pNotificationData, pSender);
}
bool WNNotificationCenter::PostNotification( unsigned int uNotificationId, WNObject* pNotificationData /*= NULL*/, void* pSender /*= NULL*/ )
{
mpReadWriteLocker->LockRead();
WNNotificationObserverList* pList = mppNotificationObserverList[uNotificationId];
if (!pList)
{
mpReadWriteLocker->ReleaseRead();
return false;
}
if (!pList->ListCount())
{
mpReadWriteLocker->ReleaseRead();
return true;
}
if (!uNotificationId || (uNotificationId >= muNextNotificationId))
{
mpReadWriteLocker->ReleaseRead();
return false;
}
mpReadWriteLocker->ReleaseRead();
WNNotification* pNotification = WNSafeAlloc(WNNotification);
pNotification->Retain();
pNotification->muNotificationId = uNotificationId;
if(pNotificationData)
pNotification->mpNotificationData = pNotificationData->Retain();
pNotification->mpNotificationCenter = this;
pList->PostNotification(pNotification, pSender);
pNotification->Release();
return true;
}
bool WNNotificationCenter::PostNotification( WNNotification* pNotification, void* pSender /*= NULL*/ )
{
mpReadWriteLocker->LockRead();
unsigned int uNotificationId = pNotification->muNotificationId;
WNNotificationObserverList* pList = mppNotificationObserverList[uNotificationId];
if (!pList)
{
mpReadWriteLocker->ReleaseRead();
return false;
}
if (!pList->ListCount())
{
mpReadWriteLocker->ReleaseRead();
return true;
}
if (!uNotificationId || (uNotificationId >= muNextNotificationId))
{
mpReadWriteLocker->ReleaseRead();
return false;
}
mpReadWriteLocker->ReleaseRead();
pNotification->Retain();
pNotification->mpNotificationCenter = this;
pList->PostNotification(pNotification, pSender);
pNotification->Release();
return true;
}
/*utf8解析行 Don't remove or modify this first line!*/
#ifdef __WINOS__
#include "stdafx.h"
#endif
#include "WNObject.h"
#include "WNCreticalSection.h"
#include "stdio.h"
#define InitRefCount 0x3FFFFFFF
WNObject::WNObject()
:miRetainCount(InitRefCount)
,mbIsAllocOnHeap(false)
,miDelayReleaseCount(0)
,mpDelegate(NULL)
,mpLoker(NULL)
,mbIsOwnLocker(false)
,mpThis(NULL)
,mpTypeFn(NULL)
{
}
WNObject::~WNObject()
{
ResetSafeLocker();
}
void WNObject::ResetRefInfo()
{
miRetainCount = InitRefCount;
miDelayReleaseCount = 0;
}
void WNObject::ResetRefInfoAndDelegate( WNObjectDelegate* pDelegate /*= NULL*/ )
{
ResetRefInfo();
mpDelegate = pDelegate;
}
void WNObject::SetSafeLocker( WNCreticalSection* pLocker /*= NULL*/ )
{
ResetSafeLocker();
if (pLocker)
{
mpLoker = pLocker;
}
else
{
mpLoker = new WNCreticalSection;
mbIsOwnLocker = true;
}
}
WNCreticalSection* WNObject::GetSafeLocker()
{
return mpLoker;
}
void WNObject::ResetSafeLocker()
{
if (mpLoker)
{
if (mbIsOwnLocker)
{
delete mpLoker;
}
mpLoker = NULL;
mbIsOwnLocker = false;
}
}
WNObject* WNObject::Retain()
{
WNCreticalSectionAutoLocker locker(mpLoker);
if (miRetainCount == InitRefCount)
{
miRetainCount = 1;
}
else
{
miRetainCount++;
}
return this;
}
WNSmartPtr<WNObject*> WNObject::AutoRelease()
{
WNCreticalSectionAutoLocker locker(mpLoker);
return WNSmartPtr<WNObject*>(this->DelayRelease());
}
WNObject* WNObject::Release( bool bClearDelayRelease /*= true*/ )
{
if (bClearDelayRelease)
{
WNCreticalSectionAutoLocker locker(mpLoker);
int iRetainCount = 0;
int iDelayReleaseCount = 0;
int iOldRefCount = 0;
int iNewRefCount = 0;
bool bIsChangeZero = false;
iRetainCount = miRetainCount;
if (iRetainCount == InitRefCount)
{
iRetainCount = 1;
}
iDelayReleaseCount = miDelayReleaseCount;
iOldRefCount = iRetainCount - iDelayReleaseCount;
if (iOldRefCount < 0)
{
printf("error 0 WNObject %p, RefCount is %d", this, iOldRefCount);
iOldRefCount = 0;
return NULL;
}
else if (!iOldRefCount)
{
if (iDelayReleaseCount)
{
iNewRefCount = 0;
bIsChangeZero = true;
printf("warning 0 WNObject %p, RefCount is %d", this, iOldRefCount);
}
else
{
printf("error 1 WNObject %p, RefCount is %d", this, iOldRefCount);
return NULL;
}
}
else
{
iNewRefCount = iOldRefCount - 1;
if (!iNewRefCount)
{
bIsChangeZero = true;
}
}
if (!bIsChangeZero)
{
miRetainCount = iNewRefCount;
miDelayReleaseCount = 0;
return this;
}
else
{
//need delete or free by mpDelegate
WNObject* pObject = this;
if (mpDelegate)
{
if (!mpDelegate->OnWNObjectRetainCountIsZero(this))
{
//freed by mpDelegate
pObject = NULL;
}
}
if (pObject)
{
if (mbIsAllocOnHeap)
{
ResetSafeLocker();
locker.mpLocker = NULL;
WNObjectTypeFnBase* pTypeFn = this->mpTypeFn;
void* pThis = this->mpThis;
if (pTypeFn && pThis)
{
pTypeFn->DoDestroy(pThis);
}
else
{
delete this;
}
}
}
return NULL;
}
}
else
{
WNCreticalSectionAutoLocker locker(mpLoker);
miRetainCount--;
return this;
}
}
WNObject* WNObject::DelayRelease()
{
WNCreticalSectionAutoLocker locker(mpLoker);
if (miRetainCount == InitRefCount)
{
miRetainCount = 1;
miDelayReleaseCount = 1;
}
else if (miRetainCount)
{
miDelayReleaseCount++;
if (miDelayReleaseCount > miRetainCount)
{
miDelayReleaseCount = miRetainCount;
}
}
else
{
miRetainCount = 1;
miDelayReleaseCount = 1;
}
return this;
}
WNObject* WNObject::ClearDelayRelease( bool bOlnySetZero /*= FALSE*/ )
{
WNCreticalSectionAutoLocker locker(mpLoker);
if (miRetainCount == InitRefCount)
{
//初始化状态
miDelayReleaseCount = 0;
if (mpDelegate)
{
if (!mpDelegate->OnWNObjectRetainCountIsZero(this))
{
return this;
}
}
return NULL;
}
int iOldRetainCount = miRetainCount;
if (!bOlnySetZero)
{
miRetainCount -= miDelayReleaseCount;
}
miDelayReleaseCount = 0;
if (!miRetainCount && (miRetainCount != iOldRetainCount))
{
if (mpDelegate)
{
if (!mpDelegate->OnWNObjectRetainCountIsZero(this))
{
return this;
}
}
return NULL;
}
return this;
}
//void _doRelease( WNObject** ppObj )
//{
// if (*ppObj)
// {
// (*ppObj)->Release();
// *ppObj = NULL;
// }
//}
//
//void _doDelayRelease( WNObject** ppObj )
//{
// if (*ppObj)
// {
// (*ppObj)->DelayRelease();
// *ppObj = NULL;
// }
//}
/*utf8解析行 Don't remove or modify this first line!*/
#ifdef __WINOS__
#include "stdafx.h"
#endif
#include "WNReadWriteLocker.h"
#include "WNCreticalSection.h"
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
long getCurrentTime()
{
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
WNReadWriteLocker::WNReadWriteLocker()
:m_dwReadCount(0)
,m_dwWriteCount(0)
,m_bWriting(false)
{
mpLocker = new WNCreticalSection;
}
WNReadWriteLocker::~WNReadWriteLocker()
{
delete mpLocker;
mpLocker = 0;
}
bool WNReadWriteLocker::LockRead(unsigned long dwTimeOut /* = 0 */)
{
if (!dwTimeOut)
{
//超时为零,等待直到设置读状态成功
while (!InternalLockRead())
{
usleep(1000);
}
return true;
}
else
{
//超时为非零,等待直到设置读状态成功或者超时
unsigned long dwStart = getCurrentTime();
if (!InternalLockRead())
{
usleep(1000);
}
else
{
return true;
}
while (!InternalLockRead())
{
if (getCurrentTime() - dwStart > dwTimeOut)
{
return false;
}
usleep(1000);
}
return true;
}
}
bool WNReadWriteLocker::LockWrite(unsigned long dwTimeOut /* = 0 */)
{
mpLocker->Lock();
m_dwWriteCount++;
long dlTimeout = dwTimeOut;
mpLocker->Unlock();
if (!dwTimeOut)
{
//超时为零,等待直到设置写状态成功
while (!InternalLockWrite())
{
usleep(1000);
}
return true;
}
else
{
//超时为非零,等待直到设置写状态成功或者超时
long dwStart = getCurrentTime();
if (!InternalLockWrite())
{
usleep(1000);
}
else
{
return true;
}
while (!InternalLockWrite())
{
if (getCurrentTime() - dwStart > dlTimeout)
{
mpLocker->Lock();
m_dwWriteCount--;
mpLocker->Unlock();
return false;
}
usleep(1000);
}
return true;
}
}
bool WNReadWriteLocker::ReleaseRead()
{
mpLocker->Lock();
m_dwReadCount--;
mpLocker->Unlock();
return true;
}
bool WNReadWriteLocker::ReleaseWrite()
{
mpLocker->Lock();
m_dwWriteCount--;
m_bWriting = false;
mpLocker->Unlock();
return true;
}
bool WNReadWriteLocker::InternalLockRead()
{
mpLocker->Lock();
if (!m_dwWriteCount)
{
m_dwReadCount++;
mpLocker->Unlock();
return true;
}
else
{
mpLocker->Unlock();
return false;
}
}
bool WNReadWriteLocker::InternalLockWrite()
{
mpLocker->Lock();
if (m_dwReadCount)
{
mpLocker->Unlock();
return false;
}
else if (m_bWriting)
{
mpLocker->Unlock();
return false;
}
else
{
m_bWriting = true;
mpLocker->Unlock();
return true;
}
}
/*utf8解析行 Don't remove or modify this first line!*/
//#include "StdAfx.h"
#include "WNSocketObserver.h"
WNSocketObserverTarget::WNSocketObserverTarget()
:mSocket(INVALID_SOCKET)
,mSocketState(SS_None)
,mObserverName("")
,mpLocker(NULL)
,mlLockRef(0)
,mdwLockedThreadId(0)
,mpObserverTargetDelegate(NULL)
,miObserverErrorCode(0)
,mLockedThreadId(0)
{
CreateLocker();
}
WNSocketObserverTarget::~WNSocketObserverTarget()
{
DestroyLocker();
}
void WNSocketObserverTarget::CreateLocker()
{
if (!mpLocker)
{
mpLocker = new WNCreticalSection();
}
}
void WNSocketObserverTarget::DestroyLocker()
{
if (mpLocker)
{
delete mpLocker;
mpLocker = NULL;
}
}
bool WNSocketObserverTarget::TryLock()
{
if (mpLocker)
{
if(true == mpLocker->TryLock())
{
mLockedThreadId = pthread_self();
mlLockRef++;
}else{
return false;
}
}
else
{
//没有初始化锁,默认返回TRUE表示可以操作
return true;
}
return true;
}
bool WNSocketObserverTarget::Lock()
{
if (mpLocker)
{
if (mpLocker->Lock())
{
mlLockRef++;
return true;
}
else
{
return false;
}
}
return true;
}
bool WNSocketObserverTarget::Unlock()
{
if(mpLocker)
{
if(pthread_self() == mLockedThreadId)
{
mlLockRef--;
if (!mlLockRef)
{
mLockedThreadId = 0;
}
}
mpLocker->Unlock();
}
return true;
}
/*utf8解析行 Don't remove or modify this first line!*/
#include "WNSocketObserverManager.h"
#include <cstring>
#include <string>
using namespace std;
WNSocketObserverManager& GetObserverManagerRef()
{
static WNSocketObserverManager gObserverManager;
return gObserverManager;
}
WNCLoopList<IWNSocketObserver*>& GetObserverListRef()
{
static WNCLoopList<IWNSocketObserver*> gObserverList;
return gObserverList;
}
#define mObserverList \
GetObserverListRef()
#define mObserverManager GetObserverManagerRef()
//对socket进行初始化
WNSocketObserverManager::WNSocketObserverManager()
{
}
bool WNSocketObserverManager::RegisterObserver( IWNSocketObserver* observer )
{
for (mObserverList.MoveBegin(); mObserverList.NotHead(); mObserverList.MoveNext())
{
if (!std::strcmp(mObserverList.CurrentData()->GetServerName(), observer->GetServerName()))
{
//查找到相同的server,退出函数
return true;
}
}
//添加至server列表
mObserverList.AppendNode(observer);
return true;
}
IWNSocketObserver* WNSocketObserverManager::GetObserverByName( const char* lpName )
{
WNSocketObserverList::PNode pNode = NULL;
for (pNode = mObserverList.Begin(); pNode != mObserverList.Head(); pNode = pNode->nextNode)
{
if (!::strcmp(pNode->data->GetServerName(), lpName))
{
//查找到相同的server,退出函数
return pNode->data;
}
}
//没有找到指定名称的server
return NULL;
}
WNSocketObserverList* WNSocketObserverManager::GetObserverList()
{
return &mObserverList;
}
bool WNSocketObserverManager::AddSocket( WNSocketObserverTarget* socketInfo )
{
if (socketInfo->mObserverName == "")
{
//没有指定observer的名称
//用列表中的第一个observer
if (mObserverList.ListCount())
{
socketInfo->mObserverName = mObserverList.BeginData()->GetServerName();
}
else
{
//列表中没有observer
return false;
}
}
IWNSocketObserver* pObserver = GetObserverByName(socketInfo->mObserverName.c_str());
if (pObserver)
{
pObserver->AddSocket(socketInfo);
}
else
{
//没有找到指定的observer
return false;
}
return true;
}
bool WNSocketObserverManager::RemoveSocket( WNSocketObserverTarget* socketInfo )
{
WNSocketObserverList::PNode pNode = NULL;
for (pNode = mObserverList.Begin(); pNode != mObserverList.Head(); pNode = pNode->nextNode)
{
pNode->data->RemoveSocket(socketInfo);
}
return true;
}
/*utf8解析行 Don't remove or modify this first line!*/
#include "WNSocketSelectObserver.h"
#include "WNSocketObserverManager.h"
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
WNSocketSelectObserver mWNSocketSelectObserver;
WNSocketSelectObserver::WNSocketSelectObserver()
:mdwThreadId(-1)
,mThreadHandle(0)
,mbIsWorking(false)
,mbExitThread(false)
,mpOperateLocker(0)
{
CreateLocker();
signal(SIGPIPE,SIG_IGN);
WNSocketObserverManager::RegisterObserver(this);
//if (this == &mWNSocketSelectObserver)
//{
// printf("enter mWNSocketSelectObserver WNSocketSelectObserver::WNSocketSelectObserver\n");
//}
//else
//{
// printf("enter WNSocketSelectObserver::WNSocketSelectObserver\n");
//}
}
WNSocketSelectObserver::~WNSocketSelectObserver()
{
//if (this == &mWNSocketSelectObserver)
//{
// printf("enter mWNSocketSelectObserver WNSocketSelectObserver::~WNSocketSelectObserver\n");
//}
//else
//{
// printf("enter WNSocketSelectObserver::~WNSocketSelectObserver\n");
//}
StopServer();
DestroyLocker();
//if (this == &mWNSocketSelectObserver)
//{
// printf("exit mWNSocketSelectObserver WNSocketSelectObserver::~WNSocketSelectObserver\n");
//}
//else
//{
// printf("exit WNSocketSelectObserver::~WNSocketSelectObserver\n");
//}
}
bool WNSocketSelectObserver::AddSocket(WNSocketObserverTarget* socketInfo)
{
Lock();
bool bRet = InternalAddSocket(socketInfo);
Unlock();
return bRet;
}
bool WNSocketSelectObserver::RemoveSocket( WNSocketObserverTarget* socketInfo )
{
Lock();
bool bRet = InternalRemoveSocket(socketInfo);
Unlock();
return bRet;
}
bool WNSocketSelectObserver::StartServer()
{
Lock();
bool bRet = InternalStartServer();
Unlock();
return bRet;
}
bool WNSocketSelectObserver::StopServer()
{
Lock();
bool bRet = InternalStopServer();
Unlock();
return bRet;
}
const char* WNSocketSelectObserver::GetServerName()
{
return "WNSocketSelectObserver";
}
void* WNSocketSelectObserver::SelectThreadProc(void* lpParameter)
{
WNSocketSelectObserver* pObserver = (WNSocketSelectObserver*)lpParameter;
if (pObserver)
{
pObserver->InternalSelectThreadProc();
}
else
{
return 0;
}
return 0;
}
long WNSocketSelectObserver::InternalSelectThreadProc()
{
//设置当前状态为正在工作
mbIsWorking = true;
WNSocketObserverTargetList::PNode pSocketNode = NULL;
fd_set sockReadSet;
FD_ZERO(&sockReadSet);
timeval timeOut = { 0, 0 };
int iSelectRet = 0;
int iSelectLoopCount = 0;
int iSelectEventCount = 0;
WNSocketObserverTargetDelegate* pTargetDelegate = NULL;
while (!mbExitThread)
{
//sleep(5);
//检查socket状态
if (!TryLock())
{
continue;
}
iSelectEventCount = 0;
for (pSocketNode = mTargetList.Begin(); pSocketNode != mTargetList.Head(); pSocketNode = pSocketNode->nextNode)
{
if (!pSocketNode->data->mpObserverTargetDelegate)
{
//没有托管,不进行读检查
//Sleep(5);
continue;
}
//if (pSocketNode->data->TryLock())
{
//尝试锁定socket操作成功
//首先设置读socket集合
FD_ZERO(&sockReadSet);
FD_SET(pSocketNode->data->mSocket, &sockReadSet);
iSelectRet = select(pSocketNode->data->mSocket + 1, &sockReadSet, NULL, NULL, &timeOut);
if (!iSelectRet)
{
//没有socket状态改变
//struct sockaddr_in addr;
//int iSize = sizeof(addr);
//getsockname(pSocketNode->data->mSocket, (struct sockaddr*)&addr, (socklen_t*)&iSize);
//char* paddr = inet_ntoa(((struct sockaddr_in*)&addr)->sin_addr);
//unsigned int uPort = ntohs(((struct sockaddr_in *)&addr)->sin_port);
goto CONTINUE_NEXT_SELECT;
}
else if (iSelectRet != -1)
{
//有读的内容
//首先停止下一次的select
pTargetDelegate = pSocketNode->data->mpObserverTargetDelegate;
pSocketNode->data->mpObserverTargetDelegate = NULL;
pTargetDelegate->OnObserverRead(this);
iSelectEventCount++;
}
else
{
//select错误
//首先停止下一次的select
pTargetDelegate = pSocketNode->data->mpObserverTargetDelegate;
pSocketNode->data->mpObserverTargetDelegate = NULL;
pSocketNode->data->miObserverErrorCode = -1;//(int)errno;//::WSAGetLastError();
pTargetDelegate->OnObserverError(this);
iSelectEventCount++;
}
CONTINUE_NEXT_SELECT:
;
//pSocketNode->data->Unlock();
}
}
Unlock();
if (!iSelectEventCount)
{
//没有事件发生,记录没有事件发生的轮询次数
iSelectLoopCount++;
if (iSelectLoopCount == 1)
{
//10次轮询都没有事件发生,检测消息队列
// while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
// {
// ::TranslateMessage(&msg);
// ::DispatchMessage(&msg);
// }
//线程进入睡眠状态
::usleep(5000);
//没有事件发生的轮询次数归零
iSelectLoopCount = 0;
}
}
else
{
//有事件发生,没有事件发生的轮询次数归零
iSelectLoopCount = 0;
}
//sleep(5);
}
//设置当前状态为没有工作
mbIsWorking = false;
return 0;
}
bool WNSocketSelectObserver::InternalStartServer()
{
//if (!mdwThreadId)
{
//mThreadHandle = ::CreateThread(NULL, 0, &WNSocketSelectObserver::SelectThreadProc, this, 0, &mdwThreadId);
pthread_create(&mdwThreadId, NULL, &WNSocketSelectObserver::SelectThreadProc, (void *)this);
pthread_detach(mdwThreadId);
}
while (!IsWorking())
{
::usleep(500);
}
return true;
}
bool WNSocketSelectObserver::InternalStopServer()
{
//printf("enter WNSocketSelectObserver::InternalStopServer()\n");
if (-1 != mdwThreadId)
{
//printf("-1 != mdwThreadId(%d)\n", (int)pthread_self());
mbExitThread = true;
unsigned long dwExitCode;
unsigned long dwThreadExitTime = 0;
//printf("while (IsWorking())\n");
while (IsWorking())
{
::usleep(5 * 1000);
}
mbExitThread = false;
mdwThreadId = -1;
}
//printf("exit WNSocketSelectObserver::InternalStopServer()\n");
return true;
}
bool WNSocketSelectObserver::InternalAddSocket( WNSocketObserverTarget* socketInfo )
{
if (mTargetList.FindData(socketInfo))
{
return true;
}
if (!mTargetList.AppendNode(socketInfo))
{
return false;
}
if (!mbIsWorking)
{
//开启服务
InternalStartServer();
}
return true;
}
bool WNSocketSelectObserver::InternalRemoveSocket( WNSocketObserverTarget* socketInfo )
{
WNSocketObserverTargetList::PNode pNode = NULL;
pNode = mTargetList.FindData(socketInfo);
if (!pNode)
{
return false;
}
mTargetList.RemoveNode(pNode);
if (!mTargetList.ListCount())
{
//没有需要监控的socket
//停止服务
InternalStopServer();
}
return true;
}
void WNSocketSelectObserver::CreateLocker()
{
mpOperateLocker = new WNCreticalSection;
}
void WNSocketSelectObserver::DestroyLocker()
{
if (mpOperateLocker)
{
delete mpOperateLocker;
mpOperateLocker = NULL;
}
}
bool WNSocketSelectObserver::TryLock()
{
if (mpOperateLocker)
{
return mpOperateLocker->TryLock();
}
else
{
return false;
}
}
bool WNSocketSelectObserver::Lock()
{
if (mpOperateLocker)
{
mpOperateLocker->Lock();
}
return false;
}
bool WNSocketSelectObserver::Unlock()
{
if (mpOperateLocker)
{
mpOperateLocker->Unlock();
}
return false;
}
bool WNSocketSelectObserver::IsWorking()
{
return mbIsWorking;
}
/*utf8解析行 Don't remove or modify this first line!*/
#include "WNTimer.h"
#include <functional>
WNTimer::WNTimer()
:muTimerId(0)
,muFireTimes(0)
{
mTimerProc.SetCallBackMemberFunc(this, &WNTimer::InternalTimerProc);
//std::tr1::bind(this, &WNTimer::InternalTimerProc);
//function<void,int> f = bind(&WNTimer::InternalTimerProc,this);
}
WNTimer::~WNTimer()
{
StopTimer();
}
void WNTimer::StartTimer( unsigned int uInterval )
{
if (!uInterval)
{
return;
}
muInterval = uInterval;
if (muTimerId)
{
StopTimer();
}
else
{
//只有在没有开启计时器的时候重置触发次数
muFireTimes = 0;
}
//muTimerId = ::SetTimer(0, 0, muInterval, mTimerProc);
}
void WNTimer::StopTimer()
{
bool bRet ;//= ::KillTimer(0, muTimerId);
if (bRet)
{
muTimerId = 0;
return;
}
else
{
long dwError = 0;
//dwError = GetLastError();
return;
}
}
void WNTimer::Fire()
{
if (mpStdFunc)
{
muFireTimes++;
mpStdFunc(this, muFireTimes);
}
}
void WNTimer::InternalTimerProc( int i )
{
Fire();
}
/*utf8解析行 Don't remove or modify this first line!*/
#include "WNWorkThread.h"
#include <stdlib.h>
#include <sstream>
//#include "WNMsg.h"
using namespace std;
WNWorkThread* mpDefaultMainThread = NULL; //默认的主线程
WNWorkThread mDefaultMainThreadCreator; //用于在构造函数中创建默认的主线程
//如果存在多个模块,使用第一个作为默认的主线程
#define NT_WNWorkThreadGetCurrentThread "NT_WNWorkThreadGetCurrentThread"
unsigned int muGetCurrentThreadNotification = 0;
class WNGetCurrentThreadNotification : public WNNotification
{
public:
WNGetCurrentThreadNotification()
:mpCurrentThread(NULL)
{
mThreadId = pthread_self();
//得到获得当前线程的通知id
if (!muGetCurrentThreadNotification)
{
muGetCurrentThreadNotification = WNNotificationCenter::DefaultCenter()->RegisterNotification(NT_WNWorkThreadGetCurrentThread);
}
muNotificationId = muGetCurrentThreadNotification;
}
public:
WNWorkThread* mpCurrentThread;
pthread_t mThreadId;
};
WNThreadObserverInfoItem::WNThreadObserverInfoItem()
:mpObserver(0)
,mpSender(0)
{
}
WNThreadObserverInfo::WNThreadObserverInfo()
:muNotificationId(0)
,mpCenter(0)
{
}
WNWorkThread::WNWorkThread(void)
:mpThreadDelegate(NULL)
,mbExitOutThread(false)
,mbExitInThread(false)
,mThreadId(0)
,mThreadHandle(0)
,muLastThreadExitCode(0)
,mbIsThreadRunning(false)
,mResetFlag(TRF_ResetMember)
,mpThreadDestroyFn(NULL)
{
//if (this == &mDefaultMainThreadCreator)
//{
// printf("enter DefaultMainThread WNWorkThread::WNWorkThread\n");
//}
//else
//{
// printf("enter WNWorkThread::WNWorkThread\n");
//}
if (this == &mDefaultMainThreadCreator)
{
//判断是否已经存在默认的主线程
//通过环境变量保证系统中只存在一个主线程
ostringstream streamKey;
streamKey << "WNMainThread_P" << getpid();
ostringstream streamValue;
char* pchValue = getenv(streamKey.str().c_str());
if (!pchValue)
{
//创建默认的主线程
mpDefaultMainThread = this;
//在环境变量中写入
streamValue << (long)mpDefaultMainThread;
setenv(streamKey.str().c_str(),streamValue.str().c_str(),1);
mThreadId = pthread_self();
}
else
{
//设置默认的主线程
mpDefaultMainThread = (WNWorkThread*)(void*)atol(streamValue.str().c_str());
}
}
}
WNWorkThread::~WNWorkThread(void)
{
//if (this == &mDefaultMainThreadCreator)
//{
// printf("enter DefaultMainThread WNWorkThread::~WNWorkThread\n");
//}
//else
//{
// printf("enter WNWorkThread::~WNWorkThread\n");
//}
EndWork();
ClearMessageQueue();
//if (this == &mDefaultMainThreadCreator)
//{
// printf("exit DefaultMainThread WNWorkThread::~WNWorkThread\n");
//}
//else
//{
// printf("exit WNWorkThread::~WNWorkThread\n");
//}
}
void WNWorkThread::Sleep(unsigned int uTimeout, unsigned uMultiplier /*= 1000*/)
{
unsigned int uTmp = uTimeout * uMultiplier;
if (uTmp >= 1000000)
{
sleep(uTmp / 1000000);
usleep(uTmp % 1000000);
}
else
{
usleep(uTmp);
}
}
unsigned int WNWorkThread::GetTickCount()
{
static timeval firstTime = { 0, 0 };
if (!firstTime.tv_sec && !firstTime.tv_usec)
{
gettimeofday(&firstTime,NULL);
}
timeval nowTime = { 0, 0 };
gettimeofday(&nowTime, NULL);
if (nowTime.tv_usec < firstTime.tv_usec)
{
return (nowTime.tv_sec - 1 - firstTime.tv_sec) * 1000 + (nowTime.tv_usec + 1000000 - firstTime.tv_usec) / 1000;
}
else
{
return (nowTime.tv_sec - firstTime.tv_sec) * 1000 + (nowTime.tv_usec - firstTime.tv_usec) / 1000;
}
}
void WNWorkThread::DoEvents(WNWorkThread *pThread /*= NULL*/)
{
if (!pThread)
{
pThread = WNWorkThread::GetCurrentThread();
}
if (!pThread)
{
return;
}
while (pThread->ProcessMessageInQueue())
{
}
}
void WNWorkThread::DoEvents(unsigned int uTimeOut , WNWorkThread *pThread /*= NULL*/)
{
unsigned int uStartTime = WNWorkThread::GetTickCount();
if (!pThread)
{
pThread = WNWorkThread::GetCurrentThread();
}
if (!pThread)
{
return;
}
while (true)
{
while (pThread->ProcessMessageInQueue())
{
}
if (WNWorkThread::GetTickCount() - uStartTime >= uTimeOut)
{
break;
}
}
}
void WNWorkThread::DoEventsAndSleep(unsigned int uSleepTime, WNWorkThread *pThread /*= NULL*/)
{
if (!pThread)
{
pThread = WNWorkThread::GetCurrentThread();
}
if (!pThread)
{
return;
}
while (pThread->ProcessMessageInQueue())
{
}
if (uSleepTime)
{
WNWorkThread::Sleep(uSleepTime);
}
}
void WNWorkThread::DoEventsAndSleep( unsigned int uTimeOut, unsigned int uSleepTime, WNWorkThread *pThread /*= NULL*/ )
{
unsigned int uStartTime = WNWorkThread::GetTickCount();
if (!pThread)
{
pThread = WNWorkThread::GetCurrentThread();
}
if (!pThread)
{
return;
}
while (true)
{
while (pThread->ProcessMessageInQueue())
{
}
if (WNWorkThread::GetTickCount() - uStartTime >= uTimeOut)
{
break;
}
else if (uSleepTime)
{
WNWorkThread::Sleep(uSleepTime);
}
}
}
void* WNWorkThread::InternalThreadMain( void* lpParam )
{
unsigned int dwRet = 0;
WNWorkThread* pThread = (WNWorkThread*)lpParam;
pThread->StartObserveNotification(NT_WNWorkThreadGetCurrentThread);
pThread->mbIsThreadRunning = true;
pThread->ClearMessageQueue();
if (pThread->mpThreadDelegate)
{
if (pThread->mpThreadDelegate->OnWorkThreadStart(pThread) == WN_WORK_THREAD_EXIT)
{
goto WNWorkThread_InternalThreadMain_Exit;
}
}
dwRet = pThread->ThreadMain();
pThread->ClearMessageQueue();
WNWorkThread_InternalThreadMain_Exit:
bool bExitInThread = false;
ThreadResetFlag trfFlag = TRF_ResetMember;
bExitInThread = pThread->mbExitInThread;
if (pThread->mpThreadDelegate)
{
dwRet = pThread->mpThreadDelegate->OnWorkThreadProcEnd(pThread);
}
pThread->muLastThreadExitCode = dwRet;
trfFlag = pThread->mResetFlag;
pThread->DoReset();
pThread->StopObserveNotification(NT_WNWorkThreadGetCurrentThread);
bool bIsMainThread = pThread->IsMainThread();
if (trfFlag == TRF_DeleteInstance)
{
while (pThread->mbExitOutThread)
{
WNWorkThread::Sleep(1);
}
pThread->mbExitOutThread = false;
pThread->mbExitInThread = false;
WNWorkThread::WNThreadDestroyFn pDestroyFn = pThread->mpThreadDestroyFn;
if (pDestroyFn)
{
pDestroyFn(pThread);
}
else
{
delete pThread;
}
pThread = 0;
}
else
{
pThread->mbExitOutThread = false;
pThread->mbExitInThread = false;
}
if (!bIsMainThread)
{
DoExitThread(dwRet);
}
return (void*)(unsigned int*)dwRet;
}
void WNWorkThread::StartWork()
{
if (IsThreadRunning())
{
return;
}
if (IsMainThread())
{
//在主线程中调用
WNWorkThread::InternalThreadMain(this);
}
else
{
CreateThread();
}
}
void WNWorkThread::EndWork(unsigned int dwTimeOut /* = 500 */)
{
if (!IsThreadRunning())
{
return;
}
if (IsCurrentThread())
{
//EndWork函数在线程内被调用
mbExitInThread = true;
return;
}
else
{
//EndWork函数在线程外被调用
void* hThreadHandle = 0;
mbExitOutThread = true;
hThreadHandle = mThreadHandle;
while (!WaitThreadEnd(dwTimeOut))
{
//等待直到线程函数正常结束
}
mbExitOutThread = false;
// //由于线程函数结束后线程无法正常退出
// //因此使用系统调用判断线程是否正常退出
// //此过程只在线程外关闭线程时使用
// DWORD dwExitCode = 0;
// DWORD dwThreadExitTime = 0;
// while (::GetExitCodeThread(hThreadHandle, &dwExitCode))
// {
// if (dwExitCode == STILL_ACTIVE)
// {
// ::Sleep(1);
// if (!dwThreadExitTime)
// {
// dwThreadExitTime = ::GetTickCount();
// }
// if (::GetTickCount() - dwThreadExitTime >= dwTimeOut)
// {
// //强制退出线程
// WNWorkThread::DoTerminateThread(hThreadHandle, 0);
// break;
// }
// }
// else
// {
// break;
// }
// }
}
}
bool WNWorkThread::CreateThread()
{
pthread_t idThread;
int err = pthread_create(&idThread, NULL, &WNWorkThread::InternalThreadMain, this);
if ( 0 != err )
{
printf("can't create ntid_joinable thread:%s\n", strerror(err));
return false;
}
mThreadHandle = this;
mThreadId = idThread;
return true;
}
unsigned int WNWorkThread::ThreadMain()
{
unsigned int dwStep = 0;
unsigned int uSleepTime = 0;
while (!mbExitOutThread && !mbExitInThread)
{
if (mpThreadDelegate)
{
if (WN_WORK_THREAD_EXIT == mpThreadDelegate->OnWorkThreadProc(this, dwStep))
{
mbExitInThread = true;
}
while (true)
{
if (!ProcessMessageInQueue())
{
uSleepTime = mpThreadDelegate->OnWorkThreadNeedSleep(this);
if (uSleepTime)
{
WNWorkThread::Sleep(uSleepTime);
}
break;
}
}
}
else
{
if (WN_WORK_THREAD_EXIT == ThreadProc(dwStep))
{
mbExitInThread = true;
}
}
//DoCheckAndInvoke();
}
return 0;
}
bool WNWorkThread::ThreadProc(unsigned int uStep )
{
DoEventsAndSleep(1);
return true;
}
bool WNWorkThread::IsMainThread()
{
return (this == mpDefaultMainThread)?true:false;
}
bool WNWorkThread::IsThreadRunning()
{
return mbIsThreadRunning?((mThreadHandle && mThreadId)?true:false):false;
}
bool WNWorkThread::IsCurrentThread()
{
if (IsThreadRunning())
{
pthread_t idThread = pthread_self();
return pthread_equal(idThread, mThreadId)?true:false;
}
else
{
return false;
}
}
WNWorkThread* WNWorkThread::GetCurrentThread()
{
WNGetCurrentThreadNotification notification;
notification.muNotificationId = muGetCurrentThreadNotification;
WNNotificationCenter::DefaultCenter()->PostNotification(&notification);
return notification.mpCurrentThread;
}
WNWorkThread* WNWorkThread::GetMainThread()
{
return mpDefaultMainThread;
}
unsigned int WNWorkThread::AddObserve4Notification(WNNotificationObserver* pObserver, const char* lpNotificationName, void* pSender /*= NULL*/, WNNotificationCenter* pNotificationCenter /*= NULL*/)
{
if (!pNotificationCenter)
{
pNotificationCenter = WNNotificationCenter::DefaultCenter();
}
mObserverListLocker.Lock();
//由线程本身去注册接收消息
unsigned int uNotificationId = StartObserveNotification(lpNotificationName, 0, pNotificationCenter);
WNThreadObserverInfo* pInfo = NULL;
for (mObserverInfoList.MoveBegin(); mObserverInfoList.NotHead(); mObserverInfoList.MoveNext())
{
pInfo = &(mObserverInfoList.CurrentData());
if ((pInfo->mpCenter == pNotificationCenter) && (pInfo->muNotificationId == uNotificationId))
{
//已找到对应的消息中心以及消息
break;
}
else
{
pInfo = NULL;
}
}
if (!pInfo)
{
//未找到对应的消息中心以及消息
//添加对应消息中心以及消息
WNThreadObserverInfoList::PNode pNode = new WNThreadObserverInfoList::Node;
pNode->data.mpCenter = pNotificationCenter;
pNode->data.muNotificationId = uNotificationId;
pInfo = &(pNode->data);
mObserverInfoList.AppendNode(pNode);
}
//在pInfo中查找是否pObserver已存在
WNThreadObserverInfoItem* pInfoItem = NULL;
for (pInfo->mObserverList.MoveBegin();pInfo->mObserverList.NotHead();pInfo->mObserverList.MoveNext())
{
pInfoItem = &(pInfo->mObserverList.CurrentData());
if (pInfoItem->mpObserver == pObserver)
{
//已找到对应的观察者
break;
}
else
{
pInfoItem = NULL;
}
}
if (!pInfoItem)
{
//未找到对应的观察者
//添加对应的观察者
WNThreadObserverInfoItemList::PNode pNode = new WNThreadObserverInfoItemList::Node;
pInfoItem = &(pNode->data);
pInfo->mObserverList.AppendNode(pNode);
}
//设置观察者
pInfoItem->mpObserver = pObserver;
//设置发送者
pInfoItem->mpSender = pSender;
mObserverListLocker.Unlock();
return uNotificationId;
}
void WNWorkThread::RemoveObserve4Notification(WNNotificationObserver* pObserver, const char* lpNotificationName /*= NULL*/, void* pSender /*= NULL*/, WNNotificationCenter* pNotificationCenter /*= NULL*/)
{
if (!pNotificationCenter)
{
pNotificationCenter = WNNotificationCenter::DefaultCenter();
}
if (lpNotificationName)
{
//指定了消息名称
unsigned int uNotificationId = pNotificationCenter->GetNotificationIdByName(lpNotificationName);
if (!uNotificationId)
{
//没有对应消息,直接返回
return;
}
mObserverListLocker.Lock();
WNThreadObserverInfo* pInfo = NULL;
for (mObserverInfoList.MoveBegin(); mObserverInfoList.NotHead(); mObserverInfoList.MoveNext())
{
pInfo = &(mObserverInfoList.CurrentData());
if ((pInfo->mpCenter == pNotificationCenter) && (pInfo->muNotificationId == uNotificationId))
{
//已找到对应的消息中心以及消息
break;
}
else
{
pInfo = NULL;
}
}
if (!pInfo)
{
//未找到对应的消息中心以及消息
//直接返回
mObserverListLocker.Unlock();
return;
}
//已找到对应的消息中心以及消息pInfo
//从pInfo中移除与pObserver以及pSender相符合的项
WNThreadObserverInfoItem* pInfoItem = NULL;
WNThreadObserverInfoItemList::PNode pNode = NULL;
for (pNode = pInfo->mObserverList.Begin(); pNode != pInfo->mObserverList.Head();)
{
pInfoItem = &(pNode->data);
pNode = pNode->nextNode;
if ((pInfoItem->mpObserver == pObserver) && (pInfoItem->mpSender == pSender))
{
//找到相符合的项
pInfo->mObserverList.RemoveNode(pNode->prevNode);
}
}
if (!pInfo->mObserverList.ListCount())
{
//没有需要转发的消息
//停止监听pInfo所对应的消息
StopObserveNotification(pInfo->mpCenter->GetNotificationNameById(pInfo->muNotificationId), 0, pInfo->mpCenter);
//移除节点
mObserverInfoList.RemoveNode((WNThreadObserverInfoList::PNode)pInfo);
}
mObserverListLocker.Unlock();
}
else
{
//未指定消息名称
mObserverListLocker.Lock();
WNThreadObserverInfo* pInfo = NULL;
WNThreadObserverInfoList::PNode pInfoNode = NULL;
WNThreadObserverInfoItem* pInfoItem = NULL;
WNThreadObserverInfoItemList::PNode pItemNode = NULL;
//遍历消息转发映射表
for (pInfoNode = mObserverInfoList.Begin(); pInfoNode != mObserverInfoList.Head();)
{
pInfoNode = pInfoNode->nextNode;
pInfo = &(mObserverInfoList.CurrentData());
//遍历每个消息的项列表
for (pItemNode = pInfo->mObserverList.Begin(); pItemNode != pInfo->mObserverList.Head();)
{
pInfoItem = &(pItemNode->data);
pItemNode = pItemNode->nextNode;
if ((pInfoItem->mpObserver == pObserver) && (pInfoItem->mpSender == pSender))
{
//移除项
pInfo->mObserverList.RemoveNode(pItemNode->prevNode);
}
}
if (!pInfo->mObserverList.ListCount())
{
//没有需要转发的消息
//停止监听pInfo所对应的消息
StopObserveNotification(pInfo->mpCenter->GetNotificationNameById(pInfo->muNotificationId), 0, pInfo->mpCenter);
//移除节点
mObserverInfoList.RemoveNode(pInfoNode->prevNode);
}
}
mObserverListLocker.Unlock();
}
}
bool WNWorkThread::PostThreadMessage(WNNotification *pNotification)
{
mMsgQueueLocker.Lock();
if (!IsThreadRunning())
{
mMsgQueueLocker.Unlock();
return false;
}
WNNotification* pMsg = NULL;
if (pNotification->mbIsAllocOnHeap)
{
//堆上分配的内存,直接Retain
pMsg = (WNNotification*)pNotification->Retain();
}
else
{
//栈上分配的内存,需要拷贝
pMsg = WNSafeAlloc(WNNotification);
pMsg->muNotificationId = pNotification->muNotificationId;
pMsg->mpNotificationSender = pNotification->mpNotificationSender;
if (pNotification->mpNotificationData)
{
pMsg->mpNotificationData = pNotification->Retain();
}
pMsg->mpNotificationCenter = pNotification->mpNotificationCenter;
for (unsigned int i = 0; i < pMsg->muParamsCount; i++)
{
pMsg->mParams[i] = pNotification->mParams[i];
}
pMsg->Retain();
}
WNCLoopList<WNNotification*>::PNode pNode = new WNCLoopList<WNNotification*>::Node;
pNode->data = pMsg;
mMsgQueue.AppendNode(pNode);
mMsgQueueLocker.Unlock();
return true;
}
bool WNWorkThread::ProcessMessageInQueue()
{
if (!mMsgQueue.ListCount())
{
return false;
}
if (!IsThreadRunning())
{
return false;
}
mMsgQueueLocker.Lock();
WNCLoopList<WNNotification*>::PNode pDetachedNode = NULL;
pDetachedNode = mMsgQueue.DetachNode(mMsgQueue.Begin());
WNNotification* pNotification = pDetachedNode->data;
WNThreadObserverInfo* pObserverInfo = NULL;
WNThreadObserverInfoItem* pObserverInfoItem = NULL;
mMsgQueueLocker.Unlock();
mObserverListLocker.Lock();
for (mObserverInfoList.MoveBegin(); mObserverInfoList.NotHead(); mObserverInfoList.MoveNext())
{
pObserverInfo = &(mObserverInfoList.CurrentData());
if ((pNotification->muNotificationId == pObserverInfo->muNotificationId)
&& (pNotification->mpNotificationCenter == pObserverInfo->mpCenter))
{
for (pObserverInfo->mObserverList.MoveBegin(); pObserverInfo->mObserverList.NotHead(); pObserverInfo->mObserverList.MoveNext())
{
pObserverInfoItem = &(pObserverInfo->mObserverList.CurrentData());
if (pNotification->mpNotificationSender == pObserverInfoItem->mpSender)
{
pObserverInfoItem->mpObserver->OnReceiveNotification(pNotification, this);
}
}
break;
}
}
doRelease(pDetachedNode->data->mpNotificationData);
doRelease(pDetachedNode->data);
delete pDetachedNode;
mObserverListLocker.Unlock();
return true;
}
void WNWorkThread::ClearMessageQueue()
{
mMsgQueueLocker.Lock();
if (!mMsgQueue.ListCount())
{
mMsgQueueLocker.Unlock();
return;
}
WNCLoopList<WNNotification*>::PNode pNode = NULL;
WNCLoopList<WNNotification*>::PNode pDetachedNode = NULL;
for (pNode = mMsgQueue.Begin(); pNode != mMsgQueue.Head();)
{
pNode = pNode->nextNode;
pDetachedNode = mMsgQueue.DetachNode(pNode->prevNode);
doRelease(pDetachedNode->data);
delete pDetachedNode;
}
mMsgQueueLocker.Unlock();
}
void WNWorkThread::OnReceiveNotification( WNNotification* pNotification )
{
if (!IsThreadRunning())
{
return;
}
if (pNotification->muNotificationId == muGetCurrentThreadNotification)
{
WNGetCurrentThreadNotification* pNotificationData = (WNGetCurrentThreadNotification*)pNotification;
if (pNotificationData->mThreadId == mThreadId)
{
pNotificationData->mpCurrentThread = this;
}
}
else
{
PostThreadMessage(pNotification);
}
}
void WNWorkThread::DoReset()
{
if (mThreadId)
{
mThreadId = 0;
}
if (mThreadHandle)
{
mThreadHandle = 0;
}
mbIsThreadRunning = false;
}
bool WNWorkThread::WaitThreadEnd( unsigned int dwTimeOut /*= 500*/ )
{
unsigned int dwStartTime = WNWorkThread::GetTickCount();
while (IsThreadRunning())
{
if (WNWorkThread::GetTickCount() - dwStartTime > dwTimeOut)
{
return false;
}
else
{
WNWorkThread::Sleep(1);
}
}
return true;
}
bool WNWorkThread::DoTerminateThread( WNThreadId hThreadHandle, unsigned int uExitCode /*= 0 */ )
{
// if (hThreadHandle)
// {
// return ::TerminateThread(hThreadHandle, uExitCode)?true:false;
// }
// else
// {
// return true;
// }
return false;
}
void WNWorkThread::DoExitThread( unsigned int uExitCode /*= 0*/ )
{
pthread_detach(pthread_self());
pthread_exit(NULL);
// ::ExitThread(uExitCode);
}
/*utf8解析行 Don't remove or modify this first line!*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include "cfgFile.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define MAX_FILE_SIZE 1024*16
#define LEFT_BRACE '['
#define RIGHT_BRACE ']'
static int load_ini_file(const char *file, char *buf,int *file_size)
{
FILE *in = NULL;
int i=0;
*file_size =0;
assert(file !=NULL);
assert(buf !=NULL);
in = fopen(file,"r");
if( NULL == in) {
return 0;
}
buf[i]=fgetc(in);
while( buf[i]!= (char)EOF) {
i++;
assert( i < MAX_FILE_SIZE );
buf[i]=fgetc(in);
}
buf[i]='\0';
*file_size = i;
fclose(in);
return 1;
}
static int newline(char c)
{
return ('\n' == c || '\r' == c )? 1 : 0;
}
static int end_of_string(char c)
{
return '\0'==c? 1 : 0;
}
static int left_barce(char c)
{
return LEFT_BRACE == c? 1 : 0;
}
static int isright_brace(char c )
{
return RIGHT_BRACE == c? 1 : 0;
}
static int parse_file(const char *section, const char *key, const char *buf,int *sec_s,int *sec_e, int *key_s,int *key_e, int *value_s, int *value_e)
{
const char *p = buf;
int i=0;
assert(buf!=NULL);
assert(section != NULL && strlen(section));
assert(key != NULL && strlen(key));
*sec_e = *sec_s = *key_e = *key_s = *value_s = *value_e = -1;
while( !end_of_string(p[i]) )
{
//find the section
if( ( 0==i || newline(p[i-1]) ) && left_barce(p[i]) )
{
int section_start=i+1;
//find the ']'
do
{
i++;
}
while( !isright_brace(p[i]) && !end_of_string(p[i]));
if( 0 == strncmp(p+section_start,section, i-section_start))
{
int newline_start=0;
i++;
//Skip over space char after ']'
while(isspace(p[i]))
{
i++;
}
//find the section
*sec_s = section_start;
*sec_e = i;
while( ! (newline(p[i-1]) && left_barce(p[i])) && !end_of_string(p[i]) )
{
int j = 0;
//get a new line
newline_start = i;
while( !newline(p[i]) && !end_of_string(p[i]) )
{
i++;
}
//now i is equal to end of the line
j = newline_start;
if(';' != p[j]) //skip over comment
{
while(j < i && p[j]!='=')
{
j++;
if('=' == p[j])
{
if(strncmp(key,p+newline_start,j-newline_start)==0)
{
//find the key ok
*key_s = newline_start;
*key_e = j-1;
*value_s = j+1;
*value_e = i;
return 1;
}
}
}
}
i++;
}
}
}
else
{
i++;
}
}
return 0;
}
int read_profile_string( char *section, char *key, char *value, int size, char *default_value, const char *file)
{
char buf[MAX_FILE_SIZE]={0};
int file_size;
int sec_s,sec_e,key_s,key_e, value_s, value_e;
//check parameters
assert(section != NULL && strlen(section));
assert(key != NULL && strlen(key));
assert(value != NULL);
assert(size > 0);
assert(file !=NULL &&strlen(key));
if(!load_ini_file(file,buf,&file_size))
{
if(default_value!=NULL)
{
strncpy(value,default_value, size);
}
return 0;
}
if(!parse_file(section,key,buf,&sec_s,&sec_e,&key_s,&key_e,&value_s,&value_e))
{
if(default_value!=NULL)
{
strncpy(value,default_value, size);
}
return 0; //not find the key
}
else
{
int cpcount = value_e -value_s;
if( size-1 < cpcount)
{
cpcount = size-1;
}
memset(value, 0, size);
memcpy(value,buf+value_s, cpcount );
value[cpcount] = '\0';
return 1;
}
}
int read_profile_int( char *section, char *key,int default_value, const char *file)
{
char value[32] = {0};
if(!read_profile_string(section,key,value, sizeof(value),NULL,file))
{
return default_value;
}
else
{
return atoi(value);
}
}
int write_profile_string(char *section, char *key, char *value, const char *file)
{
char buf[MAX_FILE_SIZE]={0};
char w_buf[MAX_FILE_SIZE]={0};
int sec_s,sec_e,key_s,key_e, value_s, value_e;
int value_len = (int)strlen(value);
int file_size;
FILE *out;
//check parameters
assert(section != NULL && strlen(section));
assert(key != NULL && strlen(key));
assert(value != NULL);
assert(file !=NULL &&strlen(key));
if(!load_ini_file(file,buf,&file_size))
{
sec_s = -1;
}
else
{
parse_file(section,key,buf,&sec_s,&sec_e,&key_s,&key_e,&value_s,&value_e);
}
if( -1 == sec_s)
{
if(0==file_size)
{
sprintf(w_buf+file_size,"[%s]\n%s=%s\n",section,key,value);
}
else
{
//not find the section, then add the new section at end of the file
memcpy(w_buf,buf,file_size);
sprintf(w_buf+file_size,"\n[%s]\n%s=%s\n",section,key,value);
}
}
else if(-1 == key_s)
{
//not find the key, then add the new key=value at end of the section
memcpy(w_buf,buf,sec_e);
sprintf(w_buf+sec_e,"%s=%s\n",key,value);
sprintf(w_buf+sec_e+strlen(key)+strlen(value)+2,buf+sec_e, file_size - sec_e);
}
else
{
//update value with new value
memcpy(w_buf,buf,value_s);
memcpy(w_buf+value_s,value, value_len);
memcpy(w_buf+value_s+value_len, buf+value_e, file_size - value_e);
}
out = fopen(file,"w");
if(NULL == out)
{
return 0;
}
if(-1 == fputs(w_buf,out) )
{
fclose(out);
return 0;
}
fclose(out);
return 1;
}
#ifdef __cplusplus
}; //end of extern "C" {
#endif
#include <jni.h>
#include <string.h>
#include "BaseSerialPort.h"
#include "TTSManager.h"
//#include <hash_map>
//using namespace std;
#define MOD_LOG_TAG "libgtsdev.so"
#define _GTS_LOG_
#ifdef _GTS_LOG_
#include <android/log.h>
#define LOG (fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, MOD_LOG_TAG, fmt, ##args)
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, MOD_LOG_TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR,MOD_LOG_TAG, fmt, ##args)
#else
#define LOG (...)
#define LOGI(...)
#define LOGE(...)
#endif
JNIEnv * g_cbEnv = NULL;
JavaVM * g_jvm = NULL;
jclass g_cbJNIInterface = NULL;
jmethodID g_cbOnRecvCardNumber = NULL;
jmethodID g_cbOnRecvRelayVoltage = NULL;
char* jstringTostring(JNIEnv* env, jstring jstr)
{
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0)
{
rtn = new char[alen + 1];
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return rtn;
}
//注意:当字符串为空时,也会返回一个空字符串
void split(std::string& s, std::string& delim,std::vector< std::string >* ret)
{
size_t last = 0;
size_t index=s.find_first_of(delim,last);
while (index!=std::string::npos)
{
ret->push_back(s.substr(last,index-last));
last=index+1;
index=s.find_first_of(delim,last);
}
if (index-last>0)
{
ret->push_back(s.substr(last,index-last));
}
}
void * CbOnRecvCardNumber(int type, int num)
{
if (NULL == g_jvm || NULL == g_cbJNIInterface || NULL == g_cbOnRecvCardNumber)
{
return NULL;
}
if (NULL == g_cbEnv)
{
g_jvm->AttachCurrentThread(&g_cbEnv, NULL);
if (NULL == g_cbEnv)
{
return NULL;
}
}
g_cbEnv->CallStaticVoidMethod(g_cbJNIInterface, g_cbOnRecvCardNumber, type, num);
g_jvm->DetachCurrentThread();
g_cbEnv = NULL;
return NULL;
}
void * CbOnRecvRelayVoltage(int part_integer, int part_decimal1, int part_decimal2)
{
if (NULL == g_jvm || NULL == g_cbJNIInterface || NULL == g_cbOnRecvRelayVoltage)
{
return NULL;
}
if (NULL == g_cbEnv)
{
g_jvm->AttachCurrentThread(&g_cbEnv, NULL);
if (NULL == g_cbEnv)
{
return NULL;
}
}
g_cbEnv->CallStaticVoidMethod(g_cbJNIInterface, g_cbOnRecvRelayVoltage, part_integer, part_decimal1, part_decimal2);
g_jvm->DetachCurrentThread();
g_cbEnv = NULL;
return NULL;
}
/*
int GetTimems()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (int)tv.tv_sec * 1000 + tv.tv_usec/1000;
}*/
class DeviceStateRecver : public WNNotificationObserver
{
public:
DeviceStateRecver()
:m_pFarReader(NULL)
,m_pNearReader(NULL)
,m_pVoltageReader(NULL){}
virtual ~DeviceStateRecver(){}
virtual void OnReceiveNotification(WNNotification* pNotification);
//type为0时表示同时开始远程和近程读卡器,1表示仅开启远程读卡器,2表示仅开启近程读卡器
void Start(int type)
{
StartObserveNotification("GTS_CardNumber");
StartObserveNotification("GTS_RelayVoltage");
if(m_pFarReader == NULL && (type == 0 || type == 1))
{
m_pFarReader = new BaseSerialPort();
m_pFarReader->Start(2, 9600, FarReader);
}
if(m_pNearReader == NULL && (type == 0 || type == 2))
{
m_pNearReader = new BaseSerialPort();
m_pNearReader->Start(1, 9600, NearReader);
}
if(m_pVoltageReader == NULL)
{
m_pVoltageReader = new BaseSerialPort();
m_pVoltageReader->Start(5, 9600, RelayVoltage);
}
};
void Stop()
{
if(m_pFarReader != NULL)
{
m_pFarReader->Stop();
delete m_pFarReader;
m_pFarReader = NULL;
}
if(m_pNearReader != NULL)
{
m_pNearReader->Stop();
delete m_pNearReader;
m_pNearReader = NULL;
}
if(m_pVoltageReader != NULL)
{
m_pVoltageReader->Stop();
delete m_pVoltageReader;
m_pVoltageReader = NULL;
}
StopObserveNotification("GTS_RelayVoltage");
StopObserveNotification("GTS_CardNumber");
};
private:
BaseSerialPort * m_pFarReader;
BaseSerialPort * m_pNearReader;
BaseSerialPort * m_pVoltageReader;//电压读取模块
//hash_map<int, int> m_cardList;
};
void DeviceStateRecver::OnReceiveNotification(WNNotification* pNotification)
{
if (pNotification->IsNotification("GTS_CardNumber"))
{
CbOnRecvCardNumber(pNotification->mParams[0], pNotification->mParams[1]);
/* if(m_cardList.find(pNotification->mParams[1]) != m_cardList.end())
{
}
else
{
m_cardList.find(pNotification->mParams[1]) = GetTimems();
}
*/
}
else if(pNotification->IsNotification("GTS_RelayVoltage"))
{
CbOnRecvRelayVoltage(pNotification->mParams[0], pNotification->mParams[1], pNotification->mParams[2]);
}
}
DeviceStateRecver * g_pStateRecver = NULL;
TTSManager * g_pTTS = NULL;
bool g_bTTSInit = false;
static jint NativeInit(JNIEnv* env, jclass clazz)
{
if(g_pTTS == NULL)
{
g_pTTS = new TTSManager;
g_bTTSInit = g_pTTS->InitSoundMap();
if(!g_bTTSInit)
{
LOGE("InitSoundMap failed\n");
//return 1;
}
}
if (NULL == g_cbJNIInterface)
{
g_cbJNIInterface = env->FindClass("com/smart/gts/JNIInterface");
if (NULL == g_cbJNIInterface)
{
LOGE("NativeInit, g_cbJNIInterface is null \n");
return 1;
}
g_cbOnRecvCardNumber = env->GetStaticMethodID(g_cbJNIInterface, "onRecvCardNumber","(II)V");
if (NULL == g_cbOnRecvCardNumber)
{
LOGE("NativeInit, g_cbOnRecvCardNumber is null \n");
return 1;
}
g_cbOnRecvRelayVoltage = env->GetStaticMethodID(g_cbJNIInterface, "onRecvRelayVoltage","(III)V");
if (NULL == g_cbOnRecvRelayVoltage)
{
LOGE("NativeInit, g_cbOnRecvRelayVoltage is null \n");
return 1;
}
env->GetJavaVM(&g_jvm);
if (NULL == g_jvm)
{
g_cbJNIInterface = NULL;
g_cbOnRecvCardNumber = NULL;
g_cbOnRecvRelayVoltage = NULL;
LOGE("NativeInit, g_jvm is null\n");
return 0;
}
}
return 0;
}
static jint NativeUninit(JNIEnv* env, jclass clazz)
{
g_cbJNIInterface = NULL;
if(g_pTTS != NULL)
{
g_pTTS->UninitSoundMap();
delete g_pTTS;
g_pTTS = NULL;
}
return 0;
}
static jint Start(JNIEnv* env, jclass clazz, jint type)
{
if(g_pStateRecver == NULL)
{
g_pStateRecver = new DeviceStateRecver();
g_pStateRecver->Start(type);
}
return 0;
}
static jint Stop(JNIEnv* env, jclass clazz)
{
if(g_pStateRecver != NULL)
{
g_pStateRecver->Stop();
delete g_pStateRecver;
g_pStateRecver = NULL;
}
return 0;
}
static jint PlayWelcome(JNIEnv* env, jclass clazz)
{
if(g_pTTS && g_bTTSInit)
{
return g_pTTS->PlayWelcome();
}
return 0;
}
static jint PlayNoInfoAtStart(JNIEnv* env, jclass clazz)
{
if(g_pTTS && g_bTTSInit)
{
return g_pTTS->PlayNoInfoAtStart();
}
return 0;
}
static jint PlayNoInfoAtThisPoint(JNIEnv* env, jclass clazz)
{
if(g_pTTS && g_bTTSInit)
{
return g_pTTS->PlayNoInfoAtThisPoint();
}
return 0;
}
static jint PlayRankingInfo(JNIEnv* env, jclass clazz, jint level, jint timeIntPart, jstring timeDecPart)
{
if(g_pTTS && g_bTTSInit)
{
string strDecPart(jstringTostring(env, timeDecPart));
return g_pTTS->PlayRankingInfo(level, timeIntPart, strDecPart.data());
}
return 0;
}
static jint PlayNoUserInfo(JNIEnv* env, jclass clazz)
{
if(g_pTTS && g_bTTSInit)
{
return g_pTTS->PlayNoUserInfo();
}
return 0;
}
//为四组,分别表示个人运动信息中的四个可能带小数的数字
static jint PlayUserInfo(JNIEnv* env, jclass clazz, jintArray intPartArr, jstring decPart)
{
if(g_pTTS && g_bTTSInit)
{
jint * iarr = env->GetIntArrayElements(intPartArr, false);
if(iarr == NULL)
{
return 0; /* exception occurred */
}
int intPart[4];
for(int i = 0; i < 4; i++)
{
intPart[i] = iarr[i];
}
env->ReleaseIntArrayElements(intPartArr, iarr, 0);
string strDecPart(jstringTostring(env, decPart));
string s = ";";
std::vector< std::string > strVector;
split(strDecPart, s, &strVector);
char * p0 = new char[strVector[0].size() + 1];
char * p1 = new char[strVector[1].size() + 1];
char * p2 = new char[strVector[2].size() + 1];
char * p3 = new char[strVector[3].size() + 1];
memcpy(p0, strVector[0].data(), strVector[0].size());
memcpy(p1, strVector[1].data(), strVector[1].size());
memcpy(p2, strVector[2].data(), strVector[2].size());
memcpy(p3, strVector[3].data(), strVector[3].size());
p0[strVector[0].size() + 1] = '\0';
p1[strVector[1].size() + 1] = '\0';
p2[strVector[2].size() + 1] = '\0';
p3[strVector[3].size() + 1] = '\0';
char * p[] = {p0, p1, p2, p3};
int ret = g_pTTS->PlayUserInfo(intPart, p);
delete[] p0;
delete[] p1;
delete[] p2;
delete[] p3;
return ret;
}
return 0;
}
static jint PlaySetStart(JNIEnv* env, jclass clazz)
{
if(g_pTTS && g_bTTSInit)
{
return g_pTTS->PlaySetStart();
}
return 0;
}
static jint PlayUserDistance(JNIEnv* env, jclass clazz, jint intPart, jstring decPart)
{
if(g_pTTS && g_bTTSInit)
{
string strDecPart(jstringTostring(env, decPart));
return g_pTTS->PlayUserDistance(intPart, strDecPart.data());
}
return 0;
}
static jint PlayNoMatchThisCard(JNIEnv* env, jclass clazz)
{
if(g_pTTS && g_bTTSInit)
{
return g_pTTS->PlayNoMatchThisCard();
}
return 0;
}
static jint TTSReset(JNIEnv* env, jclass clazz)
{
if(g_pTTS && g_bTTSInit)
{
return g_pTTS->Reset();
}
return 0;
}
///////////=======================
static const char* classPathName = "com/smart/gts/JNIInterface";
static JNINativeMethod methods[] = {
{"NativeInit", "()I", (void*)NativeInit },
{"NativeUninit", "()I", (void*)NativeUninit },
{"Start", "(I)I", (void*)Start },
{"Stop", "()I", (void*)Stop },
{"PlayWelcome", "()I", (void*)PlayWelcome },
{"PlayNoInfoAtStart", "()I", (void*)PlayNoInfoAtStart },
{"PlayNoInfoAtThisPoint", "()I", (void*)PlayNoInfoAtThisPoint },
{"PlayNoUserInfo", "()I", (void*)PlayNoUserInfo },
{"PlaySetStart", "()I", (void*)PlaySetStart },
{"PlayRankingInfo", "(IILjava/lang/String;)I", (void*)PlayRankingInfo},
{"PlayUserDistance", "(ILjava/lang/String;)I", (void*)PlayUserDistance},
{"PlayUserInfo", "([ILjava/lang/String;)I", (void*)PlayUserInfo},
{"PlayNoMatchThisCard", "()I", (void*)PlayNoMatchThisCard },
{"TTSReset", "()I", (void*)TTSReset }
};
/*
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL) {
ALOGE("Native registration unable to find class '%s'", className);
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
ALOGE("RegisterNatives failed for '%s'", className);
return JNI_FALSE;
}
return JNI_TRUE;
}
/*
* Register native methods for all classes we know about.
*
* returns JNI_TRUE on success.
*/
static int registerNatives(JNIEnv* env)
{
if (!registerNativeMethods(env, classPathName,
methods, sizeof(methods) / sizeof(methods[0]))) {
return JNI_FALSE;
}
return JNI_TRUE;
}
/*
* This is called by the VM when the shared library is first loaded.
*/
typedef union {
JNIEnv* env;
void* venv;
} UnionJNIEnvToVoid;
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
UnionJNIEnvToVoid uenv;
uenv.venv = NULL;
jint result = -1;
JNIEnv* env = NULL;
ALOGI("JNI_OnLoad");
if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("ERROR: GetEnv failed");
goto bail;
}
env = uenv.env;
if (registerNatives(env) != JNI_TRUE) {
ALOGE("ERROR: registerNatives failed");
goto bail;
}
result = JNI_VERSION_1_4;
bail:
return result;
}
#include "TTSManager.h"
int main(int argc, char* argv[])
{
TTSManager tts;
if(!tts.InitSoundMap())
{
printf("InitSoundMap failed\n");
}
printf("before PlayWelcome\n");
tts.PlayWelcome();
printf("after PlayWelcome\n");
char c;
while((c = getchar()) != 'q')
{
if(c == '1')
{
tts.PlayRankingInfo(21304, 12132, "27");
}
else if(c == '2')
{
//1289.30 1.2 803 978.56
int intPart[4] = {1289, 1, 803, 978};
char * decPart[4] = {"30", "2", "0", "56"};
tts.PlayUserInfo(intPart, decPart);
}
else if(c == '3')
{
tts.PlayNoInfoAtStart();
}
else if(c == '4')
{
tts.PlayNoInfoAtThisPoint();
}
else if(c == '5')
{
tts.PlayNoUserInfo();
}
else if(c == '6')
{
tts.PlaySetStart();
}
else if(c == '7')
{
tts.PlayUserDistance(5001, "88");
}
getchar();
}
printf("exit while loop\n");
tts.UninitSoundMap();
return 0;
FILE * fpWel = fopen("pcm/welcome.pcm", "rb");
FILE * fpBt2 = fopen("pcm/bt2.pcm", "rb");
/*获取文件的长度*/
fseek(fpWel, 0, SEEK_END);
long lenWel = ftell(fpWel);
fseek(fpBt2, 0, SEEK_END);
long lenBt2 = ftell(fpBt2);
int space = 8000;
int len = lenWel + lenBt2 + space;
fseek(fpWel, 0, SEEK_SET);
fseek(fpBt2, 0, SEEK_SET);
char * buf = new char[len];
memset(buf, 0, len);
fread(buf, 1, lenWel, fpWel);
fread(buf + lenWel + space, 1, lenBt2, fpBt2);
FILE * fp = fopen("out.pcm", "wb");
fwrite(buf, 1, len, fp);
fclose(fpWel);
fclose(fpBt2);
fclose(fp);
return 0;
}
#include "PcmPlayer.h"
#define CHANNEL_MASK_USE_CHANNEL_ORDER 0
PcmPlayer::PcmPlayer()
:mAudioTrack(NULL)
,m_pBufMgr(NULL)
,m_bStart(false)
{
}
PcmPlayer::~PcmPlayer()
{
}
void PcmPlayer::Reset()
{
if(m_pBufMgr != NULL)
{
m_pBufMgr->Reset();
}
}
bool PcmPlayer::Start()
{
m_pBufMgr = new WNMemoryPool(1024 * 1024);//(64 * 1024);
int32_t numChannels = 1, channelMask = 0;
// playing to an AudioTrack, set up mask if necessary
audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?
audio_channel_out_mask_from_count(numChannels) : channelMask;
if (0 == audioMask)
{
return false;
}
mAudioTrack = new AudioTrack(
AUDIO_STREAM_MUSIC, 16000, AUDIO_FORMAT_PCM_16_BIT, audioMask,
0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
//mAudioTrack = new AudioTrack(
// AUDIO_STREAM_MUSIC, 8000, AUDIO_FORMAT_PCM_16_BIT, audioMask,
// 0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
status_t err;
if ((err = mAudioTrack->initCheck()) != OK)
{
mAudioTrack.clear();
return false;
}
int64_t mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
size_t mFrameSize = mAudioTrack->frameSize();
mAudioTrack->start();
m_bStart = true;
return true;
}
void PcmPlayer::Stop()
{
printf("enter PcmPlayer::stop\n");
m_bStart = false;
if(mAudioTrack != NULL)
{
mAudioTrack->stop();
mAudioTrack = NULL;
}
if (m_pBufMgr != NULL)
{
delete m_pBufMgr;
m_pBufMgr = NULL;
}
printf("exit PcmPlayer::stop\n");
}
// static
void PcmPlayer::AudioCallback(int event, void *user, void *info) {
static_cast<PcmPlayer *>(user)->AudioCallback(event, info);
}
void PcmPlayer::AudioCallback(int event, void *info) {
switch (event) {
case AudioTrack::EVENT_MORE_DATA:
{
AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
size_t numBytesWritten = FillBuffer(buffer->raw, buffer->size);
buffer->size = numBytesWritten;
}
break;
case AudioTrack::EVENT_STREAM_END:
//mReachedEOS = true;
//notifyAudioEOS();
printf("ReachedEOS...\n");
break;
}
}
bool PcmPlayer::AddData(unsigned char * data, int len)
{
if(data != NULL && m_pBufMgr != NULL)
{
m_pBufMgr->Write(data, len);
}
return true;
}
size_t PcmPlayer::FillBuffer(void *data, size_t size)
{
return m_pBufMgr->Read((unsigned char*)data, size);
}
\ No newline at end of file
#ifndef _WN_PCMPLAYER_H
#define _WN_PCMPLAYER_H
#include <media/AudioTrack.h>
#include "WNMemoryPool.h"
using namespace android;
class PcmPlayer
{
public:
PcmPlayer();
~PcmPlayer();
bool Start();
void Stop();
bool AddData(unsigned char * data, int len);
void Reset();
private:
static void AudioCallback(int event, void *user, void *info);
void AudioCallback(int event, void *info);
size_t FillBuffer(void *data, size_t size);
sp<AudioTrack> mAudioTrack;
WNMemoryPool * m_pBufMgr;
bool m_bStart;
};
#endif //_WN_PCMPLAYER_H
\ No newline at end of file
#include "TTSManager.h"
const int DIAN = 11;
const int MI = 12;
//const int KMH = 13;
const int WELCOME = 14;
const int JJPM1 = 15;//您在当前中继点的排名为第
const int JJPM2 = 16;//名,距离第1名
const int JJPM3 = 17;//分钟
const int GRXX1 = 18;//您当前已登山里程
const int GRXX2 = 19;//米;登山时间
const int GRXX3 = 20;//小时,剩余里程
const int GRXX4 = 21;//米,平均速度
const int GRXX5 = 22;//米每小时
const int NOINFO_START = 23;//当前中继点为赛事起点,暂时没有排名信息
const int NOINFO_CUR = 24;//您在当前点暂时没有排名信息
const int NOUSERINFO = 25;//获取不到您的运动信息
const int SET_START = 26;//您已设置当前中继点为登山起点
const int DISTANCE = 27;//您的登山里程为
const int NO_MATCH = 28;//该卡当前无赛事
TTSManager::TTSManager()
:m_pNumBuf(NULL)
{
}
TTSManager::~TTSManager()
{
}
bool TTSManager::ReadPcmFile(int num)
{
char szFile[128];
FILE * fp = NULL;
memset(szFile, 0, 128);
sprintf(szFile, "/mnt/sdcard/GTSFiles/Sound/%d.pcm", num);
fp = fopen(szFile, "rb");
if(fp == NULL)
{
LOGE("open %s failed\n", szFile);
return false;
}
NumData * pNum = new NumData;
fseek(fp, 0, SEEK_END);
pNum->iLen = ftell(fp);
fseek(fp, 0, SEEK_SET);
pNum->pData = new char[pNum->iLen];
fread(pNum->pData, 1, pNum->iLen, fp);
fclose(fp);
m_numMap.insert(pair<int, NumData*>(num, pNum));
return true;
}
bool TTSManager::InitSoundMap()
{
m_pNumBuf = new char[1024 * 1024];
for(int i = 0; i < 29; i++)
{
if(!ReadPcmFile(i))
{
return false;
}
}
if(!ReadPcmFile(10000)) return false;
if(!ReadPcmFile(1000)) return false;
if(!ReadPcmFile(100)) return false;
if(!ReadPcmFile(10)) return false;
m_player.Start();
return true;
}
void TTSManager::UninitSoundMap()
{
NumData * pNum = NULL;
hash_map<int, NumData*>::iterator it = m_numMap.begin();
while(it != m_numMap.end())//遍历
{
pNum = it++->second;
if(pNum != NULL)
{
if(pNum->pData != NULL)
{
delete[] pNum->pData;
pNum->pData = NULL;
}
delete pNum;
}
}
m_numMap.clear();
if(m_pNumBuf != NULL)
{
delete[] m_pNumBuf;
m_pNumBuf = NULL;
}
m_player.Stop();
}
int TTSManager::CheckNumber(int& num, int mul, int pre/* = 0*/)
{
int ret = -1;
if(num >= mul)
{
ret = num / mul;
if(ret > 0)
{
num -= mul * ret;
}
}
if(ret < 0 && pre > 0)
{
ret = 0;
}
return ret;
}
int TTSManager::CopyPcmBuf(int num, char * pBuf)
{
int iSpaceLen = 4000;
NumData * pNum = NULL;
hash_map<int, NumData*>::iterator it = m_numMap.find(num);
if(it != m_numMap.end())
{
int len = 0;
pNum = it->second;
memcpy(pBuf + len, pNum->pData, pNum->iLen);
len += pNum->iLen;
memset(pBuf + len, 0, iSpaceLen);
len += iSpaceLen;
return len;
}
return 0;
}
int TTSManager::CreateNumberData(int intPart, const char* decPart, char * pBuf)
{
LOGE("CreateNumberData, intPart = %d, decPart = %s", intPart, decPart);
int iPos = 0;
int iTemp = 0;
if(intPart < 0)
{
return 0;
}
else if(intPart > 0)
{
int temp = intPart;
int w = CheckNumber(temp, 10000);
int q = CheckNumber(temp, 1000, w);
int b = CheckNumber(temp, 100, q);
int s = CheckNumber(temp, 10, b);
int g = CheckNumber(temp, 1, s);
//LOGE("%d, %d, %d, %d, %d\n", w, q, b, s, g);
if(w > 0)
{
iTemp = CopyPcmBuf(w, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
iTemp = CopyPcmBuf(10000, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
}
if((w > 0 && q >= 0) || (w <= 0 && q > 0))
{
iTemp = CopyPcmBuf(q, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
if(q > 0)
{
iTemp = CopyPcmBuf(1000, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
}
}
if((q > 0 && b >= 0) || (q <= 0 && b > 0))
{
iTemp = CopyPcmBuf(b, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
if(b > 0)
{
iTemp = CopyPcmBuf(100, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
}
}
if((b > 0 && s >= 0) || (b <= 0 && s > 0))
{
iTemp = CopyPcmBuf(s, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
if(s > 0)
{
iTemp = CopyPcmBuf(10, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
}
}
if((s > 0 && g >= 0) || (s <= 0 && g > 0))
{
iTemp = CopyPcmBuf(g, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
}
}
else if(intPart == 0)
{
iTemp = CopyPcmBuf(intPart, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
}
iTemp = atoi(decPart);
if(iTemp > 0)
{
iTemp = CopyPcmBuf(DIAN, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
int x = -1;
char c;
int counts = strlen(decPart);
for(int i = 0; i < counts; i++)
{
c = decPart[i];
x = atoi(&c);
iTemp = CopyPcmBuf(x, pBuf + iPos);
if(iTemp <= 0)
{
return 0;
}
iPos += iTemp;
}
}
return iPos;
}
int TTSManager::PlayWelcome()
{
return PlaySoundById(WELCOME);
}
int TTSManager::PlayRankingInfo(int level, int timeIntPart, const char * timeDecPart)
{
int iLen = 0;
int iTemp = 0;
iTemp = CopyPcmBuf(JJPM1, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CreateNumberData(level, "0", m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
memset(m_pNumBuf + iLen, 0, 8000);
iLen += 8000;
iTemp = CopyPcmBuf(JJPM2, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CreateNumberData(timeIntPart, timeDecPart, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CopyPcmBuf(JJPM3, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
m_player.Reset();
m_player.AddData((unsigned char*)m_pNumBuf, iLen);
return 1;
}
int TTSManager::PlaySoundById(int soundid)
{
int iLen = 0;
int iTemp = 0;
iTemp = CopyPcmBuf(soundid, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
m_player.Reset();
m_player.AddData((unsigned char*)m_pNumBuf, iLen);
return 1;
}
int TTSManager::PlayNoInfoAtStart()
{
return PlaySoundById(NOINFO_START);
}
int TTSManager::PlayNoInfoAtThisPoint()
{
return PlaySoundById(NOINFO_CUR);
}
int TTSManager::PlayNoUserInfo()
{
return PlaySoundById(NOUSERINFO);
}
//参数为四组,分别表示个人运动信息中的四个可能带小数的数字
int TTSManager::PlayUserInfo(int * intPart, char * decPart[])
{
int iLen = 0;
int iTemp = 0;
iTemp = CopyPcmBuf(GRXX1, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CreateNumberData(intPart[0], decPart[0], m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
//memset(m_pNumBuf + iLen, 0, 8000);
//iLen += 8000;
iTemp = CopyPcmBuf(GRXX2, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CreateNumberData(intPart[1], decPart[1], m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CopyPcmBuf(GRXX3, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CreateNumberData(intPart[2], decPart[2], m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CopyPcmBuf(GRXX4, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CreateNumberData(intPart[3], decPart[3], m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CopyPcmBuf(GRXX5, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
m_player.Reset();
m_player.AddData((unsigned char*)m_pNumBuf, iLen);
return 1;
}
int TTSManager::PlaySetStart()
{
return PlaySoundById(SET_START);
}
int TTSManager::PlayUserDistance(int intPart, const char * decPart)
{
int iLen = 0;
int iTemp = 0;
iTemp = CopyPcmBuf(DISTANCE, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
iTemp = CreateNumberData(intPart, decPart, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
memset(m_pNumBuf + iLen, 0, 8000);
iLen += 8000;
iTemp = CopyPcmBuf(MI, m_pNumBuf + iLen);
if(iTemp <= 0)
{
return 0;
}
iLen += iTemp;
m_player.Reset();
m_player.AddData((unsigned char*)m_pNumBuf, iLen);
return 1;
}
int TTSManager::PlayNoMatchThisCard()
{
return PlaySoundById(NO_MATCH);
}
int TTSManager::Reset()
{
m_player.Reset();
return 1;
}
#ifndef _DT_TTSMANAGER_H_
#define _DT_TTSMANAGER_H_
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "PcmPlayer.h"
#include <hash_map>
using namespace std;
struct NumData
{
int iLen;
char * pData;
};
class TTSManager{
public:
TTSManager();
~TTSManager();
bool InitSoundMap();
void UninitSoundMap();
int CreateNumberData(int intPart, const char * decPart, char * pBuf);
int PlayWelcome();
int PlayNoInfoAtStart();
int PlayNoInfoAtThisPoint();
int PlayRankingInfo(int level, int timeIntPart, const char * timeDecPart);
int PlayNoUserInfo();
int PlayUserInfo(int * intPart, char * decPart[]);//为四组,分别表示个人运动信息中的四个可能带小数的数字
int PlaySetStart();
int PlayUserDistance(int intPart, const char * decPart);
int PlayNoMatchThisCard();
int Reset();
private:
bool ReadPcmFile(int num);
int CopyPcmBuf(int num, char * pBuf);
int CheckNumber(int & num, int mul, int pre = 0);
int PlaySoundById(int soundid);
char * m_pNumBuf;
hash_map<int, NumData*> m_numMap;
PcmPlayer m_player;
};
#endif //
\ No newline at end of file
#include "WNMemoryPool.h"
#include <string.h>
WNMemoryPool::WNMemoryPool(int size)
:m_iBufSize(size)
,m_iWriteId(0)
,m_iReadId(0)
{
m_pBuf = new unsigned char[size];
memset(m_pBuf, 0, size);
pthread_mutex_init(&m_mtx, NULL);
}
WNMemoryPool::~WNMemoryPool()
{
pthread_mutex_destroy(&m_mtx);
delete []m_pBuf;
m_pBuf = NULL;
}
void WNMemoryPool::Reset()
{
pthread_mutex_lock(&m_mtx);
m_iWriteId = 0;
m_iReadId = 0;
pthread_mutex_unlock(&m_mtx);
}
int WNMemoryPool::Write(unsigned char * data, int writelen)
{
pthread_mutex_lock(&m_mtx);
int buf_unused_len = 0;
if (m_iWriteId >= m_iReadId)
{
buf_unused_len = m_iBufSize - m_iWriteId + m_iReadId;
}
else
{
buf_unused_len = m_iReadId - m_iWriteId;
}
if (buf_unused_len >= writelen)
{
if (m_iWriteId >= m_iReadId)
{
int temp = m_iBufSize - m_iWriteId;//计算右边的可用长度
if (temp >= writelen)
{
memcpy(m_pBuf + m_iWriteId, data, writelen);
m_iWriteId += writelen;
}
else
{
memcpy(m_pBuf + m_iWriteId, data, temp);
memcpy(m_pBuf, data + temp, writelen - temp);
m_iWriteId = writelen - temp;
}
}
else
{
memcpy(m_pBuf + m_iWriteId, data, writelen);
m_iWriteId += writelen;
}
pthread_mutex_unlock(&m_mtx);
return writelen;
}
else
{
LOGE("memory pool for audio is not enought, datalen: %d, buf_unused_len: %d", writelen, buf_unused_len);
}
// 空间不够,直接丢掉
pthread_mutex_unlock(&m_mtx);
return 0;
}
int WNMemoryPool::Read(unsigned char * pOutData, int iRequestLen)
{
pthread_mutex_lock(&m_mtx);
int valid_data_len = 0;
if (m_iWriteId >= m_iReadId)
{
valid_data_len = m_iWriteId - m_iReadId;
}
else
{
valid_data_len = m_iBufSize - m_iReadId + m_iWriteId;
}
if (valid_data_len >= iRequestLen)
{
if (m_iWriteId >= m_iReadId)
{
memcpy(pOutData, m_pBuf + m_iReadId, iRequestLen);
m_iReadId += iRequestLen;
}
else
{
int temp = m_iBufSize - m_iReadId ;
if (temp >= iRequestLen)
{
memcpy(pOutData, m_pBuf + m_iReadId, iRequestLen);
m_iReadId += iRequestLen;
}
else
{
memcpy(pOutData, m_pBuf + m_iReadId, temp);
memcpy(pOutData + temp, m_pBuf, iRequestLen - temp);
m_iReadId = iRequestLen - temp;
}
}
pthread_mutex_unlock(&m_mtx);
return iRequestLen;
}
pthread_mutex_unlock(&m_mtx);
return 0;
}
\ No newline at end of file
#ifndef _WN_MEMORYPOOL_H
#define _WN_MEMORYPOOL_H
#include <pthread.h>
#include "Common.h"
class WNMemoryPool
{
public:
WNMemoryPool(int size);
~WNMemoryPool();
int Write(unsigned char * pInData, int iInLen);
int Read(unsigned char * pOutData, int iRequestLen);
void Reset();
private:
pthread_mutex_t m_mtx;
unsigned char * m_pBuf;
int m_iBufSize;
int m_iWriteId;
int m_iReadId;
};
#endif //_WN_MEMORYPOOL_H
\ No newline at end of file
[Project]
Manager=KDevGenericManager
Name=libgtsdev
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment