您的位置:首页 > 编程语言 > Lua

Lua - lstring

2015-10-30 12:55 756 查看

lstring

lstring
数据结构

lua_State和global_State

API

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
相关
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: