Lua5.1 源码注释(一) table.c
2017-07-25 20:02
295 查看
从今天起,我要注释完lua 的所有源码,现在发布第一篇,我要坚持,坚持,坚持完成这个注释工作,哈哈。
本来第一篇打算一周内就可以完成的,妈蛋,注释了一个月才完成。
现在,发布第一个文件,table.c,
本来第一篇打算一周内就可以完成的,妈蛋,注释了一个月才完成。
现在,发布第一个文件,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类型的源码实现
- Lua 5.3 源码分析(六) 字符串 Table
- Lua中table类型源码分析
- LUA源码分析三:table分析(1)
- Lua5.2.3源码阅读--Table(ipairs,pairs)
- LUA源码分析三:table分析(1)
- LUA源码分析三:table分析(1)
- 5.1之前, 全局变量存储在_G这个table中, 这样的操作:5.3 lua_setupvalue
- 使用vs2010编译lua5.1源码生成lua.lib
- lua table 源码分析
- (3) Lua源码系列----table的设计与实现
- Lua源码揭秘(三)一个比较简单的table库扩展
- Lua源码分析-table
- lua源码注释1【转】
- Lua5.2.3源码阅读(2)-Table
- Lua5.2.3源码阅读(3)-Table(ipairs,pairs)
- Lua5.2.3源码阅读(2)-Table
- Lua中table类型的源码实现
- 关于lua 5.1源码分析与相关有用摘要
- lua与C/C++交互table(lua_gettble)