#ifndef _CL_VARIANT_H_ #define _CL_VARIANT_H_ /************************************************************************ * C/C++程序中为脚本提供的变量类 * 变量支持double、char*、以及带有名称的成员值 ************************************************************************/ #include "bzhash.h" class CLVariant { public: /** 定义变量类型 **/ typedef enum tagVarType { vNil = 0, //无值 vNumber = 1,//数字值 vStr = 2,//字符串值 vStruct = 3,//结构值 } VARTYPE; public: /** 类型转换运算符函数集 **/ inline operator int64_t() const { if (type_ == vNumber) return (int64_t)data_.n; if (type_ == vStr) { char* e; double d = strtod(data_.s.str, &e); if (!e || !*e) return (int64_t)d; } return 0; } inline operator double() const { if (type_ == vNumber) return data_.n; if (type_ == vStr) { char* e; double d = strtod(data_.s.str, &e); if (!e || !*e) return d; } return 0; } inline operator const char* () const { if (type_ == vStr) { return data_.s.str; } return NULL; } inline operator const CLVariant** () const { if (type_ == vStruct) return (const CLVariant**)data_.a.list; return NULL; } public: /** 比较判断运算符函数集 **/ inline bool operator == (const CLVariant& var) { switch (type_) { case vNumber: if (var.type_ == vNumber) { return data_.n == var.data_.n; } else if (var.type_ == vStr) { char* e = NULL; double d = strtod(var.data_.s.str, &e); if (!e || !*e) return data_.n == d; } break; case vStr: if (var.type_ == vNumber) { char* e = NULL; double d = strtod(data_.s.str, &e); if (!e || !*e) return d == var.data_.n; } else if (var.type_ == vStr) { return (data_.s.len == var.data_.s.len) && !strcmp(data_.s.str, var.data_.s.str); } break; } return false; } inline bool operator < (const CLVariant& var) { switch (type_) { case vNumber: if (var.type_ == vNumber) { return data_.n < var.data_.n; } else if (var.type_ == vStr)//此时不要进行将数字转换为字符而进行strcmp比较,因为进行>运算的时候,lua会将第二个参数传递为第一个参数 { char* e = NULL; double d = strtod(var.data_.s.str, &e); if (!e || !*e) return data_.n < d; } break; case vStr: if (var.type_ == vNumber) { char* e = NULL; double d = strtod(data_.s.str, &e); if (!e || !*e) return d < var.data_.n; } else if (var.type_ == vStr) return (data_.s.len < var.data_.s.len) || strcmp(data_.s.str, var.data_.s.str) < 0; break; } return false; } inline bool operator > (const CLVariant& var) { return !operator <= (var); } inline bool operator <= (const CLVariant& var) { switch (type_) { case vNumber: if (var.type_ == vNumber) { return data_.n <= var.data_.n; } else if (var.type_ == vStr)//此时不要进行将数字转换为字符而进行strcmp比较,因为进行>=运算的时候,lua会将第二个参数传递为第一个参数 { char* e = NULL; double d = strtod(var.data_.s.str, &e); if (!e || !*e) return data_.n <= d; } break; case vStr: if (var.type_ == vNumber) { char* e = NULL; double d = strtod(data_.s.str, &e); if (!e || !*e) return d <= var.data_.n; } else if (var.type_ == vStr) return (data_.s.len = (const CLVariant& var) { return !operator < (var); } public: /** 复制运算符函数集 **/ inline CLVariant& operator = (double val) { if (type_ != vNumber && type_ != vNil) clear(); type_ = vNumber; data_.n = val; return *this; } inline CLVariant& operator = (const char* val) { if (type_ == vStr && data_.s.str && !strcmp(data_.s.str, val)) return *this; clear(); type_ = vStr; data_.s.len = (unsigned int)strlen(val); data_.s.str = (char*)malloc(data_.s.len + 1); memcpy(data_.s.str, val, data_.s.len + 1); return *this; } inline CLVariant& operator = (const CLVariant& val) { if (&val == this) return *this; if (val.type_ == vNumber) { operator = (val.data_.n); } else if (val.type_ == vStr) { if (type_ == vStr && data_.s.len == val.data_.s.len && data_.s.str && val.data_.s.str && !strcmp(data_.s.str, val.data_.s.str)) { return *this; } clear(); type_ = vStr; data_.s.str = (char*)malloc(val.data_.s.len + 1); memcpy(data_.s.str, val.data_.s.str, val.data_.s.len + 1); } else if (val.type_ == vStruct) { clear(); type_ = vStruct; data_.a.list = (CLVariant**)calloc(val.data_.a.len, sizeof(*data_.a.list)); data_.a.len = val.data_.a.len; for (int i = 0; i < (int)val.data_.a.len; ++i) { data_.a.list[i] = new CLVariant(*val.data_.a.list[i]); } } return *this; } public: /** 取成员值以及设置成员值的函数集 **/ //通过名称获取成员值 inline CLVariant* get(const char* name) { if (type_ != vStruct || !name) return NULL; unsigned int h1 = bzhashstr(name, 1); unsigned int h2 = bzhashstr(name, 2); int64_t namecode = MAKEINT64(h1, h2); return get(namecode); } //通过数字名称或索引获取成员值 inline CLVariant* get(int64_t namecode) { if (type_ != vStruct) return NULL; CLVariant* pVar = NULL; if (data_.a.len && data_.a.list) { int low = 0; int high = data_.a.len - 1; while (low <= high) { int mid = ((unsigned int)(low + high)) >> 1; const CLVariant* mid_item = data_.a.list[mid]; if (mid_item->name_id_ < namecode) low = mid + 1; else if (mid_item->name_id_ > namecode) high = mid - 1; else return data_.a.list[mid]; // key found } } return pVar; } //创建成员值,如果成员已经存在则什么也不做,否则创建按一个值为vNil的成员 inline CLVariant& set(const char* name) { if (type_ != vStruct) clear(); type_ = vStruct; unsigned int h1 = bzhashstr(name, 1); unsigned int h2 = bzhashstr(name, 2); int64_t namecode = MAKEINT64(h1, h2); CLVariant* var = get(namecode); if (!var) { var = new CLVariant(); var->name_id_ = namecode; int low = 0; int high = data_.a.len - 1; while (low <= high) { int mid = ((unsigned)(low + high)) >> 1; const CLVariant* mid_item = data_.a.list[mid]; if (mid_item->name_id_ < var->name_id_) low = mid + 1; else high = mid - 1; } int index = low; data_.a.list = (CLVariant**)realloc(data_.a.list, sizeof(*data_.a.list) * (data_.a.len + 1)); if (index < (int)data_.a.len) { memmove(data_.a.list + index + 1, data_.a.list + index, sizeof(CLVariant*) * (data_.a.len - index)); } data_.a.list[index] = var; data_.a.len++; } return *var; } //设置一个成员的double值,如果成员值不存在则会自动创建,如果成员值存在则会改变成员值的类型 inline const CLVariant& set(const char* name, double val) { CLVariant& Var = set(name); Var.operator = (val); return Var; } //设置一个成员的字符串值,如果成员值不存在则会自动创建,如果成员值存在则会改变成员值的类型 inline const CLVariant& set(const char* name, const char* val) { CLVariant& Var = set(name); Var.operator = (val); return Var; } //设置为空数据结构体 inline const void setToEmptyStruct() { clear(); type_ = vStruct; } public: //获取变量的类型 inline int type() { return type_; } /* 获取变量的长度 * 当变量的值类型为数字的时候,返回值为1; * 当变量的值类型为字符串的时候,返回值为字符串长度; * 当变量的值类型为结构化数据的时候,返回一级子成员的数量; * 返回0表示变量没有值 */ inline size_t len() { if (type_ == vStr) return data_.s.len; if (type_ == vStruct) return data_.a.len; if (type_ == vNumber) return 1; return 0; } //清空变量的值 inline void clear() { if (type_ == vStr) { free(data_.s.str); data_.s.str = NULL; data_.s.len = 0; } else if (type_ == vStruct) { if (data_.a.len) { for (int i = data_.a.len - 1; i > -1; --i) { delete data_.a.list[i]; } } free(data_.a.list); data_.a.list = NULL; data_.a.len = 0; } else if (type_ == vNumber) { data_.n = 0; } type_ = vNil; } //获取在vStr类型中排除vNil值的成员数量 inline size_t packedlen() { if (vStruct != type_ || data_.a.len == 0) { return 0; } size_t result = 0; for (int i = data_.a.len - 1; i > -1; --i) { if (data_.a.list[i]->type_ != vNil) result++; } return result; } /* * Comments: 从数据流中加载变量数据 * Param const char * ptr: 数据流指针 * Param size_t size: 数据流长度 * Param size_t *pCount: 用于保存加载了多少个变量对象 * @Return size_t: 函数返回加载了变量后的内存的新位置 */ const char* loadFromMemory(const char* ptr, size_t& size, size_t* pCount = NULL); /* * Comments: 将变量保存到内存中 * Param char * ptr: 内存流指针 * Param size_t size: 内存缓存长度,如果值为0,则函数不会写入变量数据,且返回写入变量所需的内存字节长度 memory:会作为返回值,表示内存是否足够 */ size_t saveToMemory(char* ptr, size_t size, bool& memory); inline int compareName(CLVariant* v2) { if (name_id_ < v2->name_id_) { return -1; } else if (name_id_ > v2->name_id_) { return 1; } else { return 0; } } private: inline void zd() { type_ = vNil; name_id_ = 0; data_.s.len = 0; data_.n = 0; } public: CLVariant() { zd(); } CLVariant(double val) { zd(); type_ = vNumber; data_.n = val; } CLVariant(const char* val) { zd(); this->operator = (val); } CLVariant(const CLVariant& val) { zd(); this->operator = (val); } ~CLVariant() { clear(); } private: unsigned int type_; //数据类型 int64_t name_id_; //哈希名称 union { //整数值 double n; //字符串值 struct { char* str; unsigned int len; } s; //数组值 struct { CLVariant** list; unsigned int len; } a; } data_; }; #endif