一、创建一个table(lapi.c, line:666)
LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
Table *t;
lua_lock(L);
luaC_checkGC(L);
t = luaH_new(L);
sethvalue(L, L->top, t);
api_incr_top(L);
if (narray > 0 || nrec > 0)
luaH_resize(L, t, narray, nrec);
lua_unlock(L);
}
1.luaH_new: 创建一个table(ltable.c, line:368)
Table *luaH_new (lua_State *L) {
Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h;
t->metatable = NULL;
t->flags = cast_byte(~0);
t->array = NULL;
t->sizearray = 0;
setnodevector(L, t, 0);
return t;
}
初始化下面几个重要属性
1.t->array = NULL; /*数组为空*/
2.t->sizearray = 0; /*数组长度为0*/
3.t->node = cast(Node *, dummynode); /* use common `dummynode' */
4.t->lsizenode = cast_byte(lsize); /*hash 节点链表长度为0 */
5.t->lastfree = gnode(t, size); /* all positions are free */
2.luaH_resize(ltable.c, line:304): 根据narray和nrec的长度来决定是否要resize
a.resize分两部分:array和hash部分
array部分:
如果需要扩大,则在最后部分增加空节点;
如果需要减少,把超出新的总量部分的不为空的节点插入到hash部分里,再减少数量。
hash部分:
把先保存一下旧的节点列表头指针,设置hash列表部分的大小后,重新把旧的节目插入到hash部分。
注意:
调用luaM_reallocvector时,实际调用的是void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize)
frealloc是初始化是在lua_State *L = lua_newstate(l_alloc, NULL),l_alloc为frealloc最后调用分配的地方
1.会创建一个大小为nsize的数据块,而不管osize是什么。
2.如果nsize为0,则释放这个数据块
3.如果osize和nsize都为0,则什么都不做
void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
int i;
int oldasize = t->sizearray;
int oldhsize = t->lsizenode;
Node *nold = t->node; /* save old hash ... */
if (nasize > oldasize) /* array part must grow? */
setarrayvector(L, t, nasize);
/* create new hash part with appropriate size */
setnodevector(L, t, nhsize);
if (nasize < oldasize) { /* array part must shrink? */
t->sizearray = nasize;
/* re-insert elements from vanishing