flite里的基础数据结构,最常见的是cst_val.这个结构设计的很巧妙.

有如下特点

  1. 最基础的数据结构,可以用于存储int,float,string,和其他对象.同样可以存放列表和树.
  2. cst_val结构很巧妙的设计成只占用8字节(也可能是16字节在64位机器上).
  3. cst_val内部分为栈类型(atomic)和堆类型(cons). 其中,堆类型是引用计数的.

有关cons,可以参考本文最后的一个小介绍.

cst_val定义

一个优雅的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_BIGENDIANshort 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;
#elseshort type;  /* order is here important */short ref_count;
#endif
#endifunion {
#if (defined(__x86_64__) || defined(_M_X64))double fval;long long ival;void *vval;
#elsefloat 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);

什么是cons,car,cdr?

这三个名词是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

[flite源码分析一]常用数据结构cst_val相关推荐

  1. Nginx源码分析:核心数据结构ngx_cycle_t与内存池概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 核心数据结构与内存池概述 在Nginx中的核心数据结构就是ngx_cycle_t结构,在初始 ...

  2. mysql源码分析——索引的数据结构

    引子 说几句题外话,在京被困三个月之久,不能回家,所以这个源码分析就中断了.之所以在家搞这个数据库的源码分析,主要是在家环境齐全,公司的电脑老旧不堪.意外事件往往打断正常的习惯和运行轨迹,但这却是正常 ...

  3. 【嵌入式】Libmodbus源码分析(二)-常用接口函数分析

    00. 目录 文章目录 00. 目录 01. modbus常用接口函数概述 02. modbus辅助接口函数 03. modbus功能接口函数 04. modbus数据处理 05. 附录 01. mo ...

  4. JNI实现源码分析【二 数据结构】

    正文 在展开深入讨论之前,先说一下Dalvik中和JNI相关的数据结构,是很有必要的. 在Object.h中定义了很多的数据结构: 0x01: 虚拟机中的对象 我们知道,Java是面向对象的,Java ...

  5. libev源码分析(一)libev数据结构整理

    这里选取的版本为最新版:libev-4.04.libev的代码很简练,除了对高效I/O模型等的封装文件,核心文件就两个:ev.h和ev.c,其中ev.c大概4000行左右.代码大量用到了宏,并且宏还嵌 ...

  6. 鸿蒙轻内核M核源码分析:数据结构之任务就绪队列

    摘要:本文会给读者介绍鸿蒙轻内核M核源码中重要的数据结构,任务基于优先级的就绪队列Priority Queue. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列三 数据结构-任务就绪队列> ...

  7. JNI实现源码分析【三 间接引用表】

    在JNI实现源码分析[二 数据结构]的参数传递一节中,我们提到,JNI为了安全性的考虑使用了形如jobject的结构来传递参数.而jobject被表述为指针,但又不是直接指向Object的指针那么jo ...

  8. pppoe协议和pppd源码分析

    原文链接:http://blog.chinaunix.net/uid-26675482-id-4133784.html pppoe协议简介 (一)发现(Discovery)阶段 在发现(Discove ...

  9. 【esp32-adf】按键服务源码分析

    一.adc按键 二.源码分析 2.1 数据结构 设备集合 typedef struct esp_periph_sets {EventGroupHandle_t state_event_bits;xSe ...

最新文章

  1. 函数参数---动态参数
  2. ffmpeg为AVPacket添加解码头信息
  3. python爬取学校题库_pyhton 网络爬取软考题库保持txt
  4. custom Idp sapdev 申请用户
  5. Java数组的十大方法
  6. ios越狱系统UIGestureRecognizer事件截获问题
  7. mysql视图表怎么设置约束_MySQL一一sql的视图、索引、约束
  8. 腾讯也有“神盾局”?秀出“技术肌肉”就靠TA了……
  9. hdu 1507 Largest Rectangle in a Histogram 动态规划计算最大面积
  10. 三菱PLC编程软件操作快捷键汇总
  11. AD20导出Gerber教程
  12. LoadRunner教程(12)-LoadRunner IP欺骗
  13. 微博情感分析 mysql_利用500万条微博语料对微博评论进行情感分析
  14. catdog matlab,猫狗收养所 - ranjiewen的个人空间 - OSCHINA - 中文开源技术交流社区
  15. 隐藏百度地图logo
  16. 【深度学习】 Designing Network Design Spaces
  17. 做专业领域领航者 佳能正式推出了Professional Print Layout打印软件
  18. java 从入门到单身狗_java 的23种设计模式 之单身狗和隔壁老王的故事
  19. @Scheduled注解详解
  20. 云服务器和vps主机有什么 区别,到底哪个更好?

热门文章

  1. JS深入--词法作用域、执行上下文与闭包
  2. Java中的多态(for myself)
  3. centos 调整home分区xfs_centos 7.4 磁盘空间不足,扩容根分区 --lvm模式
  4. 高性能Linux服务器运维实战,《高性能Linux服务器构建实战》笔记
  5. 基于 Web 的 Linux 终端 WebTerminal
  6. 基于ggplot2的解剖图和组织模块可视化
  7. COM:微生物促进植物的氮获得
  8. P4报名截止|引爆1.1万亿基因测序市场,精准医学50+殿堂级专家议程大曝光
  9. ggplot2笔记7:定位(分面和坐标系)
  10. 扩增子统计绘图1箱线图:Alpha多样性