flite里的基础数据结构,最常见的是cst_val.这个结构设计的很巧妙.
有如下特点
有关cons,可以参考本文最后的一个小介绍.
一个优雅的union体,能文能武.既可以当基础类型使用,也可以当作复合类型使用
typedef struct cst_val_struct {
union
{
cst_val_cons cc;
cst_val_atom a;
} c;
} cst_val;
堆类型
typedef struct cst_val_cons_struct {
struct cst_val_struct *car;
struct cst_val_struct *cdr;
} cst_val_cons;
栈类型
typedef struct cst_val_atom_struct {
#ifdef WORDS_BIGENDIAN
short ref_count;
short type; /* order is here important */
#else
#if (defined(__x86_64__) || defined(_M_X64))
int type; /* order is here important */
int ref_count;
#else
short type; /* order is here important */
short ref_count;
#endif
#endif
union
{
#if (defined(__x86_64__) || defined(_M_X64))
double fval;
long long ival;
void *vval;
#else
float fval;
int ival;
void *vval;
#endif
} v;
} cst_val_atom;
常用的宏定义
/* Only CONS can be an even number */
#define CST_VAL_TYPE_CONS 0
#define CST_VAL_TYPE_INT 1
#define CST_VAL_TYPE_FLOAT 3
#define CST_VAL_TYPE_STRING 5
#define CST_VAL_TYPE_FIRST_FREE 7
#define CST_VAL_TYPE_MAX 54
#define CST_VAL_STRING_LVAL(X) ((X)->c.a.v.vval)
#define CST_VAL_TYPE(X) ((X)->c.a.type)
#define CST_VAL_INT(X) ((X)->c.a.v.ival)
#define CST_VAL_FLOAT(X) ((X)->c.a.v.fval)
#define CST_VAL_STRING(X) ((const char *)(CST_VAL_STRING_LVAL(X)))
#define CST_VAL_VOID(X) ((X)->c.a.v.vval)
#define CST_VAL_CAR(X) ((X)->c.cc.car)
#define CST_VAL_CDR(X) ((X)->c.cc.cdr)
#define CST_VAL_REFCOUNT(X) ((X)->c.a.ref_count)
常用的基础类型转换
cst_val *int_val(int i)
{
cst_val *v = new_val();
CST_VAL_TYPE(v) = CST_VAL_TYPE_INT;
CST_VAL_INT(v) = i;
return v;
}
cst_val *float_val(float f)
{
cst_val *v = new_val();
CST_VAL_TYPE(v) = CST_VAL_TYPE_FLOAT;
CST_VAL_FLOAT(v) = f;
return v;
}
cst_val *string_val(const char *s)
{
cst_val *v = new_val();
CST_VAL_TYPE(v) = CST_VAL_TYPE_STRING;
/* would be nice to note if this is a deletable string or not */
CST_VAL_STRING_LVAL(v) = cst_strdup(s);
return v;
}
int val_int(const cst_val *v)
{
if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_INT))
return CST_VAL_INT(v);
else if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_FLOAT))
return (int)CST_VAL_FLOAT(v);
else if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING))
return atoi(CST_VAL_STRING(v));
else
{
cst_errmsg("VAL: tried to access int in %d typed val\n",
(v ? CST_VAL_TYPE(v) : -1));
cst_error();
}
return 0;
}
float val_float(const cst_val *v)
{
if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_INT))
return (float)CST_VAL_INT(v);
else if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_FLOAT))
return CST_VAL_FLOAT(v);
else if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING))
return cst_atof(CST_VAL_STRING(v));
else
{
cst_errmsg("VAL: tried to access float in %d typed val\n",
(v ? CST_VAL_TYPE(v) : -1));
cst_error();
}
return 0;
}
const char *val_string(const cst_val *v)
{
if (v && (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING))
return CST_VAL_STRING(v);
else
{
cst_errmsg("VAL: tried to access string in %d typed val\n",
(v ? CST_VAL_TYPE(v) : -1));
cst_error();
}
return 0;
}
const cst_val *val_car(const cst_val *v)
{
if (v && cst_val_consp(v))
return CST_VAL_CAR(v);
else
{
cst_errmsg("VAL: tried to access car in %d typed val\n",
(v ? CST_VAL_TYPE(v) : -1));
cst_error();
}
return 0;
}
const cst_val *val_cdr(const cst_val *v)
{
if (v && cst_val_consp(v))
return CST_VAL_CDR(v);
else
{
cst_errmsg("VAL: tried to access cdr in %d typed val\n",
(v ? CST_VAL_TYPE(v) : -1));
cst_error();
}
return 0;
}
void *val_generic(const cst_val *v, int type, const char *stype)
{ /* a generic access function that checks the expected type */
if (v && CST_VAL_TYPE(v) == type)
return CST_VAL_VOID(v);
else
{
cst_errmsg("VAL: tried to access %s in %d type val\n",
stype,
(v ? CST_VAL_TYPE(v) : -1));
cst_error();
}
return NULL;
}
void *val_void(const cst_val *v)
{
/* The scary, do anything function, this shouldn't be called by mortals */
if ((v == NULL) ||
(CST_VAL_TYPE(v) == CST_VAL_TYPE_CONS) ||
(CST_VAL_TYPE(v) == CST_VAL_TYPE_INT) ||
(CST_VAL_TYPE(v) == CST_VAL_TYPE_FLOAT))
{
cst_errmsg("VAL: tried to access void in %d typed val\n",
(v ? CST_VAL_TYPE(v) : -1));
cst_error();
return NULL;
}
else
return CST_VAL_VOID(v);
}
cons类型与cst_val转换
cst_val *cons_val(const cst_val *a, const cst_val *b)
{
cst_val *v = new_val();
CST_VAL_CAR(v)=((!a || cst_val_consp(a)) ?
(cst_val *)(void *)a:val_inc_refcount(a));
CST_VAL_CDR(v)=((!b || cst_val_consp(b)) ?
(cst_val *)(void *)b:val_inc_refcount(b));
return v;
}
const cst_val *val_car(const cst_val *v)
{
if (v && cst_val_consp(v))
return CST_VAL_CAR(v);
else
{
cst_errmsg("VAL: tried to access car in %d typed val\n",
(v ? CST_VAL_TYPE(v) : -1));
cst_error();
}
return 0;
}
const cst_val *val_cdr(const cst_val *v)
{
if (v && cst_val_consp(v))
return CST_VAL_CDR(v);
else
{
cst_errmsg("VAL: tried to access cdr in %d typed val\n",
(v ? CST_VAL_TYPE(v) : -1));
cst_error();
}
return 0;
}
const cst_val *set_cdr(cst_val *v1, const cst_val *v2)
{
/* destructive set cdr, be careful you have a pointer to current cdr */
if (!cst_val_consp(v1))
{
cst_errmsg("VAL: tried to set cdr of non-consp cell\n");
cst_error();
return NULL;
}
else
{
if (CST_VAL_CDR(v1))
{
val_dec_refcount(CST_VAL_CDR(v1));
val_inc_refcount(v1);
}
CST_VAL_CDR(v1) = (cst_val *)v2;
}
return v1;
}
const cst_val *set_car(cst_val *v1, const cst_val *v2)
{
/* destructive set car, be careful you have a pointer to current car */
if (!cst_val_consp(v1))
{
cst_errmsg("VAL: tried to set car of non-consp cell\n");
cst_error();
return NULL;
}
else
{
val_dec_refcount(CST_VAL_CAR(v1));
val_inc_refcount(v1);
CST_VAL_CAR(v1) = (cst_val *)v2;
}
return v1;
}
atomic类型使用
cst_val* val1 = int_val(1);
printf("%lld\n", CST_VAL_INT(val1));
cst_val* val2 = string_val("this is test");
printf("%s\n", CST_VAL_STRING(val2));
delete_val(val1);
delete_val(val2);
cons类型使用
cst_val* val1 = int_val(1);
cst_val* val2 = string_val("this is test");
cst_val* con1 = cons_val(val1, val2);
const cst_val* tmp1 = val_car(con1);
printf("%lld\n", CST_VAL_INT(tmp1));
const cst_val* tmp2 = val_cdr(con1);
printf("%s\n", CST_VAL_STRING(tmp2));
// delete_val(val1);
// delete_val(val2);
delete_val(con1);
这三个名词是LISP语音的, cons是construct的简写,是指从堆上分配内存的类型
car,发音/kɑːr/ 是"Contents of the Address part of the Register"的缩写,而cdr,发音/ˈkʌdər/,是"Contents of the Decrement Register"的缩写.
car从cons中取出第一个指针;cdr从cons中取出第二个.
更多历史故事,请参考CAR and CDR