lstring
lstring实现了Lua对于字符串的管理.
字符串对象的结构体声明在lobject中. Lua中的字符串可以是C语言的'\0'结尾的连续字符数组, 也可以单纯是一块连续内存的内容, 包含任何字节内容.
#define LUA_TSTRING 4
/* Variant tags for strings */
#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */
#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */
在Lua中, 字符串根据长度LUAI_MAXSHORTLEN( 默认40) 区分长短字符串, 分为LUA_TLNGSTR和LUA_TSHRSTR. 对短字符串进行hash后, 保存起来, 进行复用.
数据结构
/*
** Header for string value; string bytes follow the end of this structure
** (aligned according to 'UTString'; see next).
*/
typedef struct TString {
CommonHeader;
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
lu_byte shrlen; /* length for short strings */
unsigned int hash;
union {
size_t lnglen; /* length for long strings */
struct TString *hnext; /* linked list for hash table */
} u;
} TString;
- CommonHeader
- extra: luaX_init中使用到这个, 用来表示是关键字类别.
- shrlen: 短字符串的长度
- hash: hash值
- u.lnglen: 长字符串的长度
- u.hnext: 如果出现hash碰撞, 则将碰撞内容链接到链表内
/*
** Ensures that address after this type is always fully aligned.
*/
typedef union UTString {
L_Umaxalign dummy; /* ensures maximum alignment for strings */
TString tsv;
} UTString;
将TString进行内存对齐. L_Umaxalign默认是一个union, 内容和部分union Value一致.
lua_State和global_State
在lua_State的l_G中引用了这个lua_State所属的global_State. 在global_State中有几个被用到的域
TString *strcache[STRCACHE_SIZE][1]; /* cache for strings in API */
strcache是长字符串的hash表, 默认长字符串使用地址对strcache的大小取余来获取存取地址. 可以通过luaS_clearcache来清空.都是以
'\0'结尾的字符串.
TString *memerrmsg; /* memory-error message */
memerrmsg是在luaS_init的时候没设置成MEMERRMSG("not enough memory"). 在luaS_init中调用了luaC_fix将这个字符串强制标记为不可被GC回收. 也是所有短字符串的默认值. rehash后
stringtable strt; /* hash table for strings */
strt保存hash过的短字符串. 用luaS_remove从中删除字符串对象,
API
luaS_eqlngstr比较长字符串, assert同类型, 先看是否指向同一对象, 在比较长度是否相等, 最后利用字符串长度, 用memcmp比较内存内容.luaS_hash计算字符串的hash值. 对于长度小于2^LUAI_HASHLIMIT的字符串, 每字节都参加计算hash(LUAI_HASHLIMIT默认为5). 长度大于32的字符串, 从末尾开始, 每(l >> LUAI_HASHLIMIT) + 1参加计算hash值.-
如果长度一样, 但是参加计算的字符也是一样的, 就会增加hash碰撞
luaS_resize拓展L->l_G->strt并将拓展部分置NULL. 如果newsize小于strt的长度, 那么就会截取.-
所以必须保证, 截取的时候, 截取位置之后没有hash.
luaS_clearcache: 如果g->strcache[i][0]为white, 则将里面的指向g->memerrmsg-
为什么不置为
NULL, 而要置为一个不可回收的字符串呢? luaS_init利用luaS_resize初始化L->l_G->strt为MINSTRTABSIZE(128)个元素. 将g->memerrmsg置为MEMERRMSG("not enough memory") , 并使其不可被GC回收. 初始化g->strcache的每个元素指向g->memerrmsg.createstrobj创建字符串对象. 调用到了luaC_newobj, 等看到GC的时候再返回看这个函数.luaS_remove将TString从L->l_G->strt中移除, 这个TString需要已经计算出hash值.internshrstr检查短字符串是否在strt内, 如果存在, 则复用, 否则检查是否需要rehash, 最后, 创建新的短字符串对象, 并放入strt中.luaS_newlstr创建字符串对象. 对短字符串进行internshrstr, 对长字符串, 字节创建对象. 长字符串对象的hash是他的长度, 末尾会添加'\0'luaS_new创建或复用'\0'结尾的字符串, 首先在L->l_G->strcache内用地址作为hash键值查找, 看是否有内容相同的'\0'结尾的字符串. 有则复用, 没有则利用luaS_newlstr创建长字符串对象.luaS_newudata和创建userdata相关
本文介绍了Lua中字符串lstring的实现,包括数据结构和API。Lua字符串分为短字符串和长字符串,短字符串通过hash复用。数据结构包含CommonHeader、shrlen、hash等字段,API包括字符串比较、hash计算、字符串创建等功能。文章详细讨论了字符串的内存管理及hash碰撞处理策略。
1853

被折叠的 条评论
为什么被折叠?



