Files
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

553 lines
9.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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