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

Lua5.1 源码注释(一) table.c

2017-07-25 20:02 295 查看
从今天起,我要注释完lua 的所有源码,现在发布第一篇,我要坚持,坚持,坚持完成这个注释工作,哈哈。  
本来第一篇打算一周内就可以完成的,妈蛋,注释了一个月才完成。

现在,发布第一个文件,table.c,

/*
** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/

/*
** Implementation of tables (aka arrays, objects, or hash tables).
** Tables keep its elements in two parts: an array part and a hash part.
** Non-negative integer keys are all candidates to be kept in the array
** part. The actual size of the array is the largest `n' such that at
** least half the slots between 0 and n are in use.
** Hash uses a mix of chained scatter table with Brent's variation.
** A main invariant of these tables is that, if an element is not
** in its main position (i.e. the `original' position that its hash gives
** to it), then the colliding element is in its own main position.
** Hence even when the load factor reaches 100%, performance remains good.
*/

#include <math.h>
#include <string.h>

#define ltable_c
#define LUA_CORE

#include "lua.h"

#include "ldebug.h"
#include "ldo.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "ltable.h"

/*
** max size of array part is 2^MAXBITS
*/
#if LUAI_BITSINT > 26
#define MAXBITS		26
#else
#define MAXBITS		(LUAI_BITSINT-2)
#endif

#define MAXASIZE	(1 << MAXBITS)

#define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))

#define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)
#define hashboolean(t,p)        hashpow2(t, p)

/*
** for some types, it is better to avoid modulus by power of 2, as
** they tend to have many 2 factors.
*/
#define hashmod(t,n)	(gnode(t, ((n) % ((sizenode(t)-1)|1))))//n对sizenode取模

#define hashpointer(t,p)	hashmod(t, IntPoint(p))

/*
** number of ints inside a lua_Number
*/
#define numints		cast_int(sizeof(lua_Number)/sizeof(int))

#define dummynode		(&dummynode_)

static const Node dummynode_ = { //这是一个静态的空node,key是空的,value也是空的,用来表示所有没有被分配空间的table
{{NULL}, LUA_TNIL},  /* value */
{{{NULL}, LUA_TNIL, NULL}}  /* key */
};

/*
** hash for lua_Numbers
*/
static Node *hashnum (const Table *t, lua_Number n) { //这个函数找出数字n的hash node,lua_Number事实上是double
unsigned int a[numints];//numints  通常是4
int i;
if (luai_numeq(n, 0))  /* avoid problems with -0 */ //这里是和
return gnode(t, 0);//假如是0的话,直接返回hash node的第一个
memcpy(a, &n, sizeof(a));//字节复制n的数据到a上面
for (i = 1; i < numints; i++) a[0] += a[i];//所谓hash,其实就是一字节一字节加起来放到a[0],这种做法的hash分布可能不太理想,不过效率较快
return hashmod(t, a[0]);//a[0]就是hash值,返回这个hash节点的node
}

/*
** returns the `main' position of an element in a table (that is, the index
** of its hash value)
*/
static Node *mainposition (const Table *t, const TValue *key) {
switch (ttype(key)) {//找出key的类型
case LUA_TNUMBER:
return hashnum(t, nvalue(key));//是number hash
case LUA_TSTRING:
return hashstr(t, rawtsvalue(key));//string hash
case LUA_TBOOLEAN:
return hashboolean(t, bvalue(key));//布尔hash
case LUA_TLIGHTUSERDATA:
return hashpointer(t, pvalue(key));//指针hash
default:
return hashpointer(t, gcvalue(key));//默认的也是指针hash
}
}

/*
** returns the index for `key' if `key' is an appropriate key to live in
** the array part of the table, -1 otherwise.
*/
static int arrayindex (const TValue *key) {//候如key值可以放在 table的数值部分的话,就返回key的下标,否则返回-1
if (ttisnumber(key)) {//首先,key必须是number
lua_Number n = nvalue(key);//获得number的实际数值
int k;
lua_number2int(k, n);//将这个number转换成int,并且赋值给k
if (luai_numeq(cast_num(k), n))//假如转换后的k和原值是一样的,说明没有精度损失,n本身就是uint,返回它即可
return k;
}
return -1;  /* `key' did not match some condition */
}

/*
** returns the index of a `key' for table traversals. First goes all
** elements in the array part, then elements in the hash part. The
** beginning of a traversal is signalled by -1.
*/
//遍历table,返回key对应的下标,首先遍历数组部分,然后遍历hash部分,-1表示遍历开始
static int findindex (lua_State *L, Table *t, StkId key) {
int i;
if (ttisnil(key)) return -1;  /* first iteration */ //key是一个空值的话,返回-1
i = arrayindex(key);//找出key在数组中的index,如果不存在,arrayindex是会返回-1的
if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */
return i-1;  /* yes; that's the index (corrected to C) */ //如果key在数组中存在,则返回它在数组中的c数组下标
else {
Node *n = mainposition(t, key); //在数组中不存在,开始在hash中找 key对应的hash node N
do {  /* check whether `key' is somewhere in the chain */
/* key may be dead already, but it is ok to use it in `next' */
if (luaO_rawequalObj(key2tval(n), key) ||
(ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&
gcvalue(gkey(n)) == gcvalue(key))) {//检查key值是不是在hash的链表中, key == n则说明它在hash表中,或者key已经被回收了, 那么检查一下xxxxx
i = cast_int(n - gnode(t, 0));  /* key index in hash table */ //
/* hash elements are numbered after array ones */
return i + t->sizearray;//i是hash node的位置,要加上数组的长度
}
else n = gnext(n);//找node指向的下个node
} while (n);
luaG_runerror(L, "invalid key to " LUA_QL("next"));  /* key not found */ //找不到这个key
return 0;  /* to avoid warnings */
}
}

int luaH_next (lua_State *L, Table *t, StkId key) { //找出key对应的下一个元素,并把它的值放在key里面
int i = findindex(L, t, key);  /* find original element */ //找出key在table中的索引
for (i++; i < t->sizearray; i++) {  /* try first array part */ //假如是在数组中
if (!ttisnil(&t->array[i])) {  /* a non-nil value? */ //遍历数组,一直找到下一个非空值为止
setnvalue(key, cast_num(i+1));//将key的值变成number,并赋i+1
setobj2s(L, key+1, &t->array[i]);//一是将array[i]的值赋给key+1指向的值
return 1;
}
}
for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */  //候如前面没有找到,就从hash里面找,i重置
if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */ //找出hash 中的i对应的值,是否为空,如果不是
setobj2s(L, key, key2tval(gnode(t, i)));//将i对应该的hash node的键值放在 key里面
setobj2s(L, key+1, gval(gnode(t, i))); //将i对应该的 hash node的 value值放在key +1
return 1;
}
}
return 0;  /* no more elements */
}

/*
** {=============================================================
** Rehash
** ==============================================================
*/

static int computesizes (int nums[], int *narray) { //计算size  //nums所有的值加起来得出的总值,和narray的值是一样大小的
int i;
int twotoi;  /* 2^i */
int a = 0;  /* number of elements smaller than 2^i */
int na = 0;  /* number of elements to go to array part */
int n = 0;  /* optimal size for array part */
for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
if (nums[i] > 0) {
a += nums[i];//a一直累加
if (a > twotoi/2) {  /* more than half elements present? */
n = twotoi;  /* optimal size (till now) */
na = a;  /* all elements smaller than n will go to array part */
}
}
if (a == *narray) break;  /* all elements already counted */ //直到a累加到上限,退出
}
*narray = n;
lua_assert(*narray/2 <= na && na <= *narray);//na的值应该大于narray的一半,小于narray,否则报错
return na;
}

static int countint (const TValue *key, int *nums) {//找出key在table中的索引,并将 nums下标为索引log2()的值自增1
int k = arrayindex(key);//找出key 在数组部分 的位置
if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */
nums[ceillog2(k)]++;  /* count as such */  //取这个位置的log2
return 1;
}
else
return 0;
}

static int numusearray (const Table *t, int *nums) { //统计数组中的非空元素个数
int lg;
int ttlg;  /* 2^lg */
int ause = 0;  /* summation of `nums' */
int i = 1;  /* count to traverse all array keys */
for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) {  /* for each slice */ //[1]={1-2},[2]={3-4},3={5-8},[4]={9-16},[5]={17-64)}...这样分组,从头到尾遍历非nil的元素,统计每个分组的个数,并返回总个数.
int lc = 0;  /* counter */
int lim = ttlg;
if (lim > t->sizearray) { //最后组不免2的n次幂时,以实现长度为准
lim = t->sizearray;  /* adjust upper limit */
if (i > lim)
break;  /* no more elements to count */ //上一轮已经没有数据了,开始新一轮时i>lim会退出
}
/* count elements in range (2^(lg-1), 2^lg] */
for (; i <= lim; i++) {//执行一轮统计,找出这一轮所有非空的元素
if (!ttisnil(&t->array[i-1]))
lc++;
}
nums[lg] += lc;
ause += lc;
}
return ause; //返回总数
}

static int numusehash (const Table *t, int *nums, int *pnasize) {
int totaluse = 0;  /* total number of elements */
int ause = 0;  /* summation of `nums' */
int i = sizenode(t);//找出hash的长度
while (i--) {
Node *n = &t->node[i];
if (!ttisnil(gval(n))) {
ause += countint(key2tval(n), nums);//找出key值所在的位置index,并将nums[log(index)]自加1,找到就返回1,找不到返回0
totaluse++;//总数加1
}
}
*pnasize += ause;//对应的数组总长度+1
return totaluse;//返回所有非空数量
}

static void setarrayvector (lua_State *L, Table *t, int size) {//重新分配table的数组内存
int i;
luaM_reallocvector(L, t->array, t->sizearray, size, TValue);//释放旧的内存,然后分配新的内存,因为是数组部分,所以不担心内存回收的问题,直接都释放了,话说这个东西真的不进行数据复制的,会不会太狠了?
for (i=t->sizearray; i<size; i++)//为什么后面的数据要设置为nil,前面的就不管了?luaM_reallocvector好像真的没有内存复制啊
setnilvalue(&t->array[i]);//设置nil
t->sizearray = size;//设置size
}

static void setnodevector (lua_State *L, Table *t, int size) { //设置hash表
int lsize;
if (size == 0) {  /* no elements to hash part? */ //假如新的长度是0
t->node = cast(Node *, dummynode);  /* use common `dummynode' */ //则将node指向空值
lsize = 0;//size设置为0
}
else {
int i;
lsize = ceillog2(size); //否则,lsize=size的log2,并向上取整
if (lsize > MAXBITS) //超出了最大容量
luaG_runerror(L, "table overflow");//报错
size = twoto(lsize);//将size变成lsize的平方
t->node = luaM_newvector(L, size, Node);// 分配一个新的长度的node
for (i=0; i<size; i++) {//初始化node
Node *n = gnode(t, i);
gnext(n) = NULL;//next指针清空
setnilvalue(gkey(n));//key 清空
setnilvalue(gval(n));//value清空
}
}
t->lsizenode = cast_byte(lsize);//新的size
t->lastfree = gnode(t, size);  /* all positions are free */ //所有的node都是可用的
}

static void resize (lua_State *L, Table *t, int nasize, int nhsize) { //重新分配size,nasize新数组长度,nhsize新hash表长度
int i;
int oldasize = t->sizearray;//旧数组长度
int oldhsize = t->lsizenode;//旧hash长度
Node *nold = t->node;  /* save old hash ... * /   //保存旧的hash表数据
if (nasize > oldasize)  /* array part must grow? */
setarrayvector(L, t, nasize); //假如新的数组长度旧的数级长度长,则配置新的数组
/* create new hash part with appropriate size */
setnodevector(L, t, nhsize);  //分配新的hash表
if (nasize < oldasize) {  /* array part must shrink? */
t->sizearray = nasize;//假如旧的数组长长比新的数组长度短,则收缩
/* re-insert elements from vanishing slice */
for (i=nasize; i<oldasize; i++) {//将收缩后的数据根据下标放入到hash表中
if (!ttisnil(&t->array[i])) //假如数组数据非空
setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);//将数据放入到key=i+1的hash里面,为什么i+1?因为lua的下标比c的下标大1
}
/* shrink array */
luaM_reallocvector(L, t->array, oldasize, nasize, TValue);//收缩数组同存空间
}
/* re-insert elements from hash part */
for (i = twoto(oldhsize) - 1; i >= 0; i--) {//遍历hash数据
Node *old = nold+i;//找出node
if (!ttisnil(gval(old)))//如果node的value非空,则将数据复制到新的hash表中
setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));//复制旧值到新node中
}
if (nold != dummynode)//释放非空的旧hash表数据
luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */
}

void luaH_resizearray (lua_State *L, Table *t, int nasize) {//重新分配数组数据
int nsize = (t->node == dummynode) ? 0 : sizenode(t);//hash表的长度,如果table是空的话,则设置为0,如果是非空的话,则设置为table的hash长度
resize(L, t, nasize, nsize);//重新分配空间
}

static void rehash (lua_State *L, Table *t, const TValue *ek) {//重新分配hash数据
int nasize, na;
int nums[MAXBITS+1];  /* nums[i] = number of keys between 2^(i-1) and 2^i */ //定义一个nusm数组,用来记录 2^(i-1) and 2^i 之间已经使用了的数据数量
int i;
int totaluse;
for (i=0; i<=MAXBITS; i++) nums[i] = 0;  /* reset counts */ //清空nums
nasize = numusearray(t, nums);  /* count keys in array part */ // //计算数组已经使用了的个数
totaluse = nasize;  /* all those keys are integer keys */
totaluse += numusehash(t, nums, &nasize);  /* count keys in hash part */ //计算hash中已经使用了的个数
/* count extra key */
nasize += countint(ek, nums); //计算额外的数据,ek假如可以放到array中的话,nums对应的位置+1,countint返回1,否则返回0
totaluse++;//totaluse无论ek可以放在数组还是hash,它都会加1
/* compute new size for array part */
na = computesizes(nums, &nasize); //计算新的数组的长度
/* resize the table to new computed sizes */
resize(L, t, nasize, totaluse - na); //重新分配空间,//为什么会这样重新分配?totaluse - na即是hash部分的长度是用已经分配了的长度来决定?
}

/*
** }=============================================================
*/

Table *luaH_new (lua_State *L, int narray, int nhash) {//分配一个新的table
Table *t = luaM_new(L, Table);//首先,分配table的空间
luaC_link(L, obj2gco(t), LUA_TTABLE);//这是什么鬼?将table放入到gc里面吗?应该是的
t->metatable = NULL;//元表是空
t->flags = cast_byte(~0);//flags是1,即是使用中?
/* temporary values (kept only if some malloc fails) */
t->array = NULL;//数组指针是空
t->sizearray = 0;//数组长度是空
t->lsizenode = 0;//hash长度是空
t->node = cast(Node *, dummynode);//node指向空
setarrayvector(L, t, narray);//分配数组空间
setnodevector(L, t, nhash);//分配hash空间
return t;
}

void luaH_free (lua_State *L, Table *t) {//释放table的内存
if (t->node != dummynode)//假如node 表不是空
luaM_freearray(L, t->node, sizenode(t), Node); //释放node 表
luaM_freearray(L, t->array, t->sizearray, TValue);//释放数组表
luaM_free(L, t);//释放table占的内存
}

static Node *getfreepos (Table *t) {	//找出一个空的node
while (t->lastfree-- > t->node) {		//向前找,直到第一个为止
if (ttisnil(gkey(t->lastfree)))		//假如当前的lastfree是空的话,
return t->lastfree;				//则返回这个lastfree
}
return NULL;  /* could not find a free place */
}

/*
** inserts a new key into a hash table; first, check whether key's main
** position is free. If not, check whether colliding node is in its main
** position or not: if it is not, move colliding node to an empty place and
** put new key in its main position; otherwise (colliding node is in its main
** position), new key goes to an empty position.
*/
/*插入一个新key到hash 表中,首先,检查key对应的main position是否是空的,如果不是,
则检查冲突的node是不是main position,如果不是,就应该将冲突的node移到一个新的空位置,
将新key放到main position。如果冲突的点就已经是main position,则将新key放到一个空白点*/
static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp = mainposition(t, key);
if (!ttisnil(gval(mp)) || mp == dummynode) { //mp的值不是空或者mp是空
Node *othern;
Node *n = getfreepos(t);  /* get a free place */ //找出一个空点
if (n == NULL) {  /* cannot find a free place? *///假如找不到,即是没有空间了,要重新分配
rehash(L, t, key);  /* grow table */
return luaH_set(L, t, key);  /* re-insert key into grown table */ //然后返回新分配空间后的点
}
lua_assert(n != dummynode);
othern = mainposition(t, key2tval(mp));// 通常key2tval(mp)的值就是ke,这里面不用key,重新取一次
if (othern != mp) {  /* is colliding node out of its main position? */ //假如有mp.key取出来的值不等于mp,这就尴尬了,说明是冲突的点
/* yes; move colliding node into free position */
while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */ //other-> ...->pre->mainposition,遍历,找出pre点
gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */ //将pre 点的next指针赋成n点
*n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */ //将mp的数据放进n时面
gnext(mp) = NULL;  /* now `mp' is free */ //然后清空mp的next指针
setnilvalue(gval(mp));//再新空mp的值

else {  /* colliding node is in its own main position */  //假如冲突node本来就应该放在mp上面
/* new node will go into free position */
gnext(n) = gnext(mp);  /* chain new position */ // 那么,将n插入到mp->{n}->next 中间
gnext(mp) = n;
mp = n;//将mp赋成n
}
}
gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;//将mp的key值变成key的什,
luaC_barriert(L, t, key);//这是什么鬼,是用来做内存回收的吧
lua_assert(ttisnil(gval(mp)));//断言mp的值必须是空,如果非空,有问题啊
return gval(mp);//返回mp node的value
}

/*
** search function for integers
*/
const TValue *luaH_getnum (Table *t, int key) {//获取key为数值的node的value
/* (1 <= key && key <= t->sizearray) */
if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) //假如key小于数组的长度,直接返回数组的数据
return &t->array[key-1];
else {
lua_Number nk = cast_num(key);//否则,查找hash里面的数据
Node *n = hashnum(t, nk); //找出hash node
do {  /* check whether `key' is somewhere in the chain */
if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) //假如node n的key是数值,并且这个数值和nk相等的话
return gval(n);  /* that's it */ //返回 node的value,
else n = gnext(n);//否则,查找下一个
} while (n);//直到下一个是空为止
return luaO_nilobject;//返回空
}
}

/*
** search function for strings
*/
const TValue *luaH_getstr (Table *t, TString *key) {//返回key为字付串的node的value
Node *n = hashstr(t, key); //将key转换成hash值,并且访问表中对应的 node
do {  /* check whether `key' is somewhere in the chain */
if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)//假如这个node的key是string,并且和参数key相等,则返回node的值
return gval(n);  /* that's it */ //就是它了
else n = gnext(n); //如果不是,则找node的下一个,继续对比
} while (n);
return luaO_nilobject;//找不到,返回nil
}

/*
** main search function
*/
const TValue *luaH_get (Table *t, const TValue *key) { //找出key在table中的value
switch (ttype(key)) {
case LUA_TNIL: return luaO_nilobject; //空key,返回空值
case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));//字符串的key,找hash
case LUA_TNUMBER: {//数值key
int k;
lua_Number n = nvalue(key); //找出key的double值
lua_number2int(k, n);//转成int
if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ //假如double和int值是一样的
return luaH_getnum(t, k);  /* use specialized version */ //luaH_getnum先从array里面查找,如果找不到,就从hash里面查找
/* else go through */
}
default: {
Node *n = mainposition(t, key);//其它的默认情况,先从hash中找出main postion
do {  /* check whether `key' is somewhere in the chain */
if (luaO_rawequalObj(key2tval(n), key))// //然后对比main position和key值是否相等
return gval(n);  /* that's it */ //假如相等则返回,
else n = gnext(n);//假如不等,则通过main position 的next指针找下一个
} while (n);//一直找到空的为止
return luaO_nilobject;// 最后找不到的就返回空
}
}
}

TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { //设置table key,返回一个Tvalue的指针
const TValue *p = luaH_get(t, key);//找出key对应的Tvalue
t->flags = 0; //这是什么鬼?加锁吗?
if (p != luaO_nilobject) //假如p不等于nil,
return cast(TValue *, p);//将p转换成TValue指针,为嘛要转换?前面不用const不就可以了
else {
if (ttisnil(key)) luaG_runerror(L, "table index is nil"); //假如P是nil,则检查key,如果key是nil,则报错
else if (ttisnumber(key) && luai_numisnan(nvalue(key)))//如果key是数值,并且是nan,同样报错.
luaG_runerror(L, "table index is NaN");
return newkey(L, t, key);//否则,插入一个新key
}
}

TValue *luaH_setnum (lua_State *L, Table *t, int key) { //设置key是数值的value,返回value的指针,这样就可以通过修改指针改值
const TValue *p = luaH_getnum(t, key);//找出key对应的value
if (p != luaO_nilobject)//假如是空,则
return cast(TValue *, p);//则直接返回tvalue指针
else {
TValue k;
setnvalue(&k, cast_num(key));//否则,将k转成Tvalue,
return newkey(L, t, &k);//然后插入新node,返回node的value
}
}

TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {//设置key是string的value
const TValue *p = luaH_getstr(t, key);//获得value
if (p != luaO_nilobject)//假如非空
return cast(TValue *, p);//则直接返回tvalue指针
else {//假如是空
TValue k;
setsvalue(L, &k, key);//生成一个新key
return newkey(L, t, &k);//插入node中
}
}

static int unbound_search (Table *t, unsigned int j) {
unsigned int i = j;  /* i is zero or a present index */ //先记录j坐标
j++; //j下一个元素
/* find `i' and `j' such that i is present and j is not */
while (!ttisnil(luaH_getnum(t, j))) {//j对应的元素不是nil的话,要继续找下去
i = j;//记录一下不是nil的j
j *= 2;//j double,晕,又是倍数增长
if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */ //2倍就超长啦,丧尽天良,回复到线性查找 吧
/* table was built with bad purposes: resort to linear search */
i = 1; //从1开始
while (!ttisnil(luaH_getnum(t, i))) i++;//
return i - 1;
}
}
/* now do a binary search between them */
while (j - i > 1) { //j在前面就已经2倍增长了,一直增长到luaH_getnum(t, j)为空时
unsigned int m = (i+j)/2;//折半查找
if (ttisnil(luaH_getnum(t, m))) j = m;//假如中间也是空,则j=m
else i = m;//假如中间不是空,则i=m
}
return i;
}

/*
** Try to find a boundary in table `t'. A `boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
int luaH_getn (Table *t) { //找出table的边界i,这个i指t[i]是非空的,t[i+1]是空的
unsigned int j = t->sizearray;
if (j > 0 && ttisnil(&t->array[j - 1])) {//假如数组最后一个是空,则肯定是在数组里面
/* there is a boundary in the array part: (binary) search for it */
unsigned int i = 0;
while (j - i > 1) {
unsigned int m = (i+j)/2;//居然是用折半查找 的方法,汗
if (ttisnil(&t->array[m - 1])) j = m;//假如中间的是空,则从开始到中间之间找
else i = m;//否则从中间到最后之间找
}
return i;//当中间没有数值时
}
/* else must find a boundary in hash part */ //走到这里,前明前面的数组部分全是满的(其实就是数组最后一个值是非空的而已)
else if (t->node == dummynode)  /* hash part is empty? */ //假如hash部分就是空的话,直接返回数组长度
return j;  /* that is easy... */
else return unbound_search(t, j);//否则,开始调用unbound_search找出,unbound_search也是二分法查找hash 表部份
}

#if defined(LUA_DEBUG)

Node *luaH_mainposition (const Table *t, const TValue *key) {// 返回key值对应的node,只是封装了一下mainposition
return mainposition(t, key);
}

int luaH_isdummy (Node *n) { return n == dummynode; }//判断这个node是不是假的

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lua 源码 table