#pragma once /************************************************************************ C/C++程序中为脚本提供的变量类 变量支持double、char*、以及带有名称的成员值 ************************************************************************/ #include "_osdef.h" #include "ObjectCounter.h" class CCLVariant : public Counter { public: /** 定义变量类型 **/ typedef enum tagVarType { vNil = 0, //无值 vNumber = 1,//数字值 vStr = 2,//字符串值 vStruct = 3,//结构值 }VARTYPE; public: inline operator __int64 () const { if (m_btType == vNumber) return (__int64)m_Data.n; if (m_btType == vStr) { char *e; double d = strtod(m_Data.s.str, &e); if (!e || !*e) return (__int64)d; } return 0; } inline operator double () const { if (m_btType == vNumber) return m_Data.n; if (m_btType == vStr) { char *e; double d = strtod(m_Data.s.str, &e); if (!e || !*e) return d; } return 0; } inline operator const char* () const { if (m_btType == vStr) { return m_Data.s.str; } return NULL; } inline operator const CCLVariant** () const { if (m_btType == vStruct) return (const CCLVariant**)m_Data.a.list; return NULL; } public: /** 比较判断运算符函数集 **/ inline bool operator == (const CCLVariant &var) { char *e; double d; switch(m_btType) { case vNumber: if (var.m_btType == vNumber) { return m_Data.n == var.m_Data.n; } else if (var.m_btType == vStr) { d = strtod(var.m_Data.s.str, &e); if (!e || !*e) return m_Data.n == d; } break; case vStr: if (var.m_btType == vNumber) { d = strtod(m_Data.s.str, &e); if (!e || !*e) return d == var.m_Data.n; } else if (var.m_btType == vStr) return (m_Data.s.len == var.m_Data.s.len) && !strcmp(m_Data.s.str, var.m_Data.s.str); break; } return false; } inline bool operator < (const CCLVariant &var) { char *e; double d; switch(m_btType) { case vNumber: if (var.m_btType == vNumber) { return m_Data.n < var.m_Data.n; } else if (var.m_btType == vStr)//此时不要进行将数字转换为字符而进行strcmp比较,因为进行>运算的时候,lua会将第二个参数传递为第一个参数 { d = strtod(var.m_Data.s.str, &e); if (!e || !*e) return m_Data.n < d; } break; case vStr: if (var.m_btType == vNumber) { d = strtod(m_Data.s.str, &e); if (!e || !*e) return d < var.m_Data.n; } else if (var.m_btType == vStr) return (m_Data.s.len < var.m_Data.s.len) || strcmp(m_Data.s.str, var.m_Data.s.str) < 0; break; } return false; } inline bool operator > (const CCLVariant &var) { return !operator <= (var); } inline bool operator <= (const CCLVariant &var) { char *e; double d; switch(m_btType) { case vNumber: if (var.m_btType == vNumber) { return m_Data.n <= var.m_Data.n; } else if (var.m_btType == vStr)//此时不要进行将数字转换为字符而进行strcmp比较,因为进行>=运算的时候,lua会将第二个参数传递为第一个参数 { d = strtod(var.m_Data.s.str, &e); if (!e || !*e) return m_Data.n <= d; } break; case vStr: if (var.m_btType == vNumber) { d = strtod(m_Data.s.str, &e); if (!e || !*e) return d <= var.m_Data.n; } else if (var.m_btType == vStr) return (m_Data.s.len = (const CCLVariant &var) { return !operator < (var); } public: /** 复制运算符函数集 **/ inline CCLVariant& operator = (double val) { if (m_btType != vNumber && m_btType != vNil) clear(); m_btType = vNumber; m_Data.n = val; return *this; } inline CCLVariant& operator = (const char* val) { if (m_btType == vStr && m_Data.s.str && !strcmp(m_Data.s.str, val)) return *this; clear(); m_btType = vStr; m_Data.s.len = (unsigned int)strlen(val); m_Data.s.str = (char*)malloc(m_Data.s.len + 1); memcpy(m_Data.s.str, val, m_Data.s.len + 1); return *this; } inline CCLVariant& operator = (const CCLVariant& val) { if (&val == this) return *this; if (val.m_btType == vNumber) { operator = (val.m_Data.n); } else if (val.m_btType == vStr) { if (m_btType == vStr && m_Data.s.len == val.m_Data.s.len && m_Data.s.str && val.m_Data.s.str && !strcmp(m_Data.s.str, val.m_Data.s.str)) { return *this; } clear(); m_btType = vStr; m_Data.s.str = (char*)malloc(val.m_Data.s.len + 1); memcpy(m_Data.s.str, val.m_Data.s.str, val.m_Data.s.len + 1); } else if (val.m_btType == vStruct) { clear(); m_btType = vStruct; m_Data.a.list = (CCLVariant**)calloc(val.m_Data.a.len, sizeof(*m_Data.a.list)); for (INT_PTR i=0; i<(INT_PTR)val.m_Data.a.len; ++i) { m_Data.a.list[i] = new CCLVariant(*val.m_Data.a.list[i]); } } return *this; } public: inline CCLVariant* ipair(int idx) { if (m_btType != vStruct) return NULL; CCLVariant *pVar; if(idx <= m_Data.a.len && idx >= 0) { pVar = m_Data.a.list[idx]; return pVar; } return NULL; } /** 取成员值以及设置成员值的函数集 **/ //通过名称获取成员值 inline CCLVariant* get(const char* sName) { if (m_btType != vStruct || !sName) return NULL; DWORD dwName = hashstr(sName); return get(dwName); } //通过数字名称或索引获取成员值 inline CCLVariant* get(DWORD dwName) { if (m_btType != vStruct) return NULL; CCLVariant *pVar; if(m_Data.a.len ) { for (INT_PTR i=m_Data.a.len-1; i>-1; --i) { pVar = m_Data.a.list[i]; if (pVar->m_dwName == dwName) { return pVar; } } } return NULL; } //创建成员值,如果成员已经存在则什么也不做,否则创建按一个值为vNil的成员 inline CCLVariant& set(const char* sName) { if (m_btType != vStruct) clear(); m_btType = vStruct; DWORD dwName = hashstr(sName); CCLVariant *pVar = get(dwName); if (!pVar) { pVar = new CCLVariant(); pVar->m_dwName = dwName; m_Data.a.list = (CCLVariant**)realloc(m_Data.a.list, sizeof(*m_Data.a.list) * (m_Data.a.len+1)); m_Data.a.list[m_Data.a.len] = pVar; m_Data.a.len++; } return *pVar; } //设置一个成员的double值,如果成员值不存在则会自动创建,如果成员值存在则会改变成员值的类型 inline const CCLVariant& set(const char* sName, double val) { CCLVariant &Var = set(sName); Var.operator = (val); return Var; } //设置一个成员的字符串值,如果成员值不存在则会自动创建,如果成员值存在则会改变成员值的类型 inline const CCLVariant& set(const char* sName, const char* val) { CCLVariant &Var = set(sName); Var.operator = (val); return Var; } //设置为空数据结构体 inline const void setToEmptyStruct() { clear(); m_btType = vStruct; } public: //字符串hash函数 inline static unsigned int hashstr(const char* str) { return hashlstr(str, strlen(str)); } //字符串hash函数,需要提供长度 inline static unsigned int hashlstr(const char* str, size_t len) { unsigned int h = (unsigned int)len; size_t step = (len>>5)+1; /* if string is too long, don't hash all its chars */ size_t l1; for (l1=len; l1>=step; l1-=step) /* compute hash */ h = h ^ ((h<<5)+(h>>2)+(unsigned char)str[l1-1]); return h; } public: //获取变量的类型 inline int type() { return m_btType; } /* 获取变量的长度 * 当变量的值类型为数字的时候,返回值为1; * 当变量的值类型为字符串的时候,返回值为字符串长度; * 当变量的值类型为结构化数据的时候,返回一级子成员的数量; * 返回0表示变量没有值 */ inline size_t len() { if (m_btType == vStr) return m_Data.s.len; if (m_btType == vStruct) return m_Data.a.len; if (m_btType == vNumber) return 1; return 0; } //清空变量的值 inline void clear() { if (m_btType == vStr) { free(m_Data.s.str); m_Data.s.str = NULL; m_Data.s.len = 0; } else if (m_btType == vStruct) { if(m_Data.a.len) { for (INT_PTR i=m_Data.a.len-1; i>-1; --i) { delete m_Data.a.list[i]; } } free(m_Data.a.list); m_Data.a.list = NULL; m_Data.a.len = 0; } else if (m_btType == vNumber) { m_Data.n = 0; } m_btType = vNil; } //获取在vStr类型中排除vNil值的成员数量 inline size_t packedlen() { if (vStruct != m_btType || m_Data.a.len ==0 ) { return 0; } size_t result = 0; for (INT_PTR i=m_Data.a.len-1; i>-1; --i) { if (m_Data.a.list[i]->m_btType != vNil) result++; } return result; } /* * Comments: 从数据流中加载变量数据 * Param const char * ptr: 数据流指针 * Param size_t size: 数据流长度 * Param size_t *pCount: 用于保存加载了多少个变量对象 * @Return size_t: 函数返回加载了变量后的内存的新位置 */ inline const char* loadFromMemory(const char* ptr, size_t size, size_t *pCount = NULL) { //内存长度小于5字节,不能读取 if (size < 5) { if (pCount) *pCount = 0; return ptr; } clear(); //读取类型 m_btType = *(unsigned char*)ptr; ptr += sizeof(unsigned char); size -= sizeof(unsigned char); //读取名称 m_dwName = *(unsigned int *)ptr; ptr += sizeof(unsigned int); size -= sizeof(unsigned int); //依据类型读取数据 switch(m_btType) { case vNumber: if (size >= sizeof(m_Data.n)) { m_Data.n = *(double*)ptr; ptr += sizeof(double); size -= sizeof(double); } else m_btType = vNil; break; case vStr: if (size >= sizeof(unsigned int)) { unsigned int len = *(unsigned int*)ptr; ptr += sizeof(unsigned int); size -= sizeof(unsigned int); if (len > 0 && size >= len + 1) { operator = ((const char*)ptr); ptr += len + 1; size -= len + 1; } } else m_btType = vNil; break; case vStruct: if (size >= sizeof(unsigned int)) { unsigned int len = *(unsigned int*)ptr; ptr += sizeof(unsigned int); size -= sizeof(unsigned int); if (len > 0 && size >= 5) { m_Data.a.list = (CCLVariant**)calloc(len, sizeof(*m_Data.a.list)); for (INT_PTR i=0; i<(INT_PTR)len; ++i) { size_t n = 0; m_Data.a.list[i] = new CCLVariant(); ptr = m_Data.a.list[i]->loadFromMemory(ptr, size, &n); if (n <= 0) break; m_Data.a.len++; if (pCount) *pCount += n; } } } else m_btType = vNil; break; } //增加读取的变量数据量 if (pCount && m_btType != vNil) *pCount += 1;//不能用*pCount++,意义不一样的,*pCount++表示 *(pCount++)。 return ptr; } /* * Comments:获取这个对象存储的时候需要多少内存 * @Return size_t:返回需要的内存的数目 */ inline size_t getStoreMemory() { size_t reqSize = 0; //计算存储所需的空间 switch(m_btType) { case vNil: reqSize =0; //nil值没有值,但是数据的长度里还是包含了类型以及名字 break; case vNumber: reqSize = 1 + sizeof(m_dwName) + sizeof(m_Data.n); break; case vStr: reqSize = 1 + sizeof(m_dwName) + sizeof(m_Data.s.len) + ((m_Data.s.len > 0) ? m_Data.s.len + 1 : 0); break; case vStruct: reqSize = 1 + sizeof(m_dwName) + sizeof(m_Data.a.len); if (m_Data.a.len >0)//仅当参数size为0时用于计算保存变量所需的内存字节长度 { for (INT_PTR i=m_Data.a.len-1;i>-1; --i) { reqSize += m_Data.a.list[i]->getStoreMemory(); } } break; } return reqSize; } /* * Comments: 将变量保存到内存中 * Param char * ptr: 内存流指针 * Param size_t size: 内存缓存长度,如果值为0,则函数不会写入变量数据,且返回写入变量所需的内存字节长度 @ Param CCLVariant **pNextSaveVar: 由于内存长度不够而终止写入的变量位置,如果此值输出非空, 则调用者必须增长内存并再次调用输出值的saveToStream函数来保存数据, 否则之间保存的数据将导致读取时出现丢失数据 * @Return size_t: 函数返回向内存中写入了多少字节的数据 * * & 示例代码 & * * char *buff = NULL; * size_t bufsize = 0; * size_t totalsize = 0; * CCLVariant *pContinueVar = &var; * do * { * bufsize += 1024; * buff = realloc(buff, buffsize); * totalsize += pContinueVar->saveToMemory(&buff[totalsize], bufsize - totalsize, &pContinueVar); * } * while (pContinueVar); * */ inline size_t saveToMemory(char *ptr, size_t size, CCLVariant **pNextSaveVar) { size_t reqSize = getStoreMemory(); //获取存储需要的内存的量 size_t saveSize =0; //这个变量写进去多少的内存 //计算存储所需的空间 //没有任何数据可以写入 if (reqSize <= 0) { *pNextSaveVar = NULL; return 0; } else if (size > 0) { //仅在剩余内存空间满足所需空间长度的时候才书写内容 if (size >= reqSize) { if (pNextSaveVar) *pNextSaveVar = NULL; if(m_btType == vNil) //如果是空的话 { return saveSize; } //写入类型 *(unsigned char*)ptr = (unsigned char)m_btType; ptr += sizeof(unsigned char); size -= sizeof(unsigned char); saveSize += sizeof(unsigned char); //写入名称 *(unsigned int*)ptr = m_dwName; ptr += sizeof(unsigned int); size -= sizeof(unsigned int); saveSize += sizeof(unsigned int); //写入数据 switch(m_btType) { case vNumber: //写入值 *(double*)ptr = m_Data.n; ptr += sizeof(double); size -= sizeof(double); saveSize += sizeof(double); break; case vStr: //写入字符串长度 *(unsigned int*)ptr = m_Data.s.len; ptr += sizeof(unsigned int); size -= sizeof(unsigned int); saveSize += sizeof(unsigned int); //写入字符串内容 if (m_Data.s.len > 0) { memcpy(ptr, m_Data.s.str, m_Data.s.len + 1); ptr += m_Data.s.len + 1; size -= m_Data.s.len + 1; saveSize += m_Data.s.len + 1; } break; case vStruct: //写入成员数量 { *(unsigned int*)ptr =(unsigned int)packedlen() ; ptr += sizeof(unsigned int); size -= sizeof(unsigned int); saveSize += sizeof(unsigned int); //循环写入成员内容 if(m_Data.a.len >0) { for (INT_PTR i=m_Data.a.len-1;i>-1; --i) { size_t nb = m_Data.a.list[i]->saveToMemory(ptr, size, pNextSaveVar); //没有写入数据则终止,不能判断写入长度是否大于0,因为nil值不会写入 if(nb >0) { saveSize += nb; ptr += nb; size -= nb; } if (pNextSaveVar && *pNextSaveVar) break; } } } break; } } else { if (pNextSaveVar) *pNextSaveVar = this; saveSize = 0;//没有写入任何数据 } } return saveSize; } private: inline void zd() { m_btType = vNil; m_dwName = 0; m_Data.s.len = 0; m_Data.n = 0; } protected: unsigned int m_btType; //数据类型 unsigned int m_dwName; //哈希名称 union { //整数值 double n; //字符串值 struct { char *str; unsigned int len; }s; //数组值 struct { CCLVariant** list; unsigned int len; }a; } m_Data; public: CCLVariant() { zd(); } CCLVariant(double val) { zd(); m_btType = vNumber; m_Data.n = val; } CCLVariant(const char* val) { zd(); this->operator = (val); } CCLVariant(const CCLVariant& val) { zd(); this->operator = (val); } ~CCLVariant() { clear(); } };