553 lines
9.8 KiB
C++
553 lines
9.8 KiB
C++
#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 </*这里不能用<=*/ var.data_.s.len) ||
|
||
(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);
|
||
}
|
||
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
|
||
|