lua源码阅读(4)---表
来源:互联网 发布:通信工程预算软件 编辑:程序博客网 时间:2024/05/17 01:49
lua中只有一种数据结构,表,可以可以存储任意类型,只要键不是nil。在Lobject.h中,有表的定义:
typedef struct Table { CommonHeader; //表示存在哪些元方法 lu_byte flags; /* 1<<p means tagmethod(p) is not present */ // log2( node数组大小) lu_byte lsizenode; /* log2 of size of `node' array *///元表 struct Table *metatable; //数组部分 TValue *array; /* array part */// Node数组 Node *node; Node *lastfree; /* any free position is before this position */ GCObject *gclist;//array大小 int sizearray; /* size of `array' array */} Table;lua中的表包含了两部分,一个是数组部分,存储在array指向的数组中,另一个是hash表部分,存储在node指向的数组中。其中Node类型如下:
typedef union TKey { struct { TValuefields; //Value value; int tt struct Node *next; /* for chaining */ } nk; TValue tvk;} TKey;typedef struct Node { TValue i_val; TKey i_key;} Node;Node包含了key和value。
如在lua中 a={3,2,4,x=10},则3,2,4存储在数组部分,x=10存储在hash表部分
在ltable.c中,定义了一些对表的操作的函数。
luaH_set,;uaH_setnum.luaH_strstr是进行新增元素的操作。首先进行查找,如果表中没有改元素,则进行添加的操作,最终调用了newkey函数
static TValue *newkey (lua_State *L, Table *t, const TValue *key) {//计算hash值,得到key所在的hash表中的位置 Node *mp = mainposition(t, key);//如果该位置已经存储了元素 if (!ttisnil(gval(mp)) || mp == dummynode) { 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);//#define key2tval(n)(&(n)->i_key.tvk)othern = mainposition(t, key2tval(mp));if (othern != mp) { /* is colliding node out of its main position? */ /* yes; move colliding node into free position */ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ gnext(mp) = NULL; /* now `mp' is free */ setnilvalue(gval(mp)); } else { /* colliding node is in its own main position */ /* new node will go into free position */ gnext(n) = gnext(mp); /* chain new position */ gnext(mp) = n; mp = n; } } gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; luaC_barriert(L, t, key); lua_assert(ttisnil(gval(mp))); return gval(mp);}
首先根据key 计算位置,如果该位置没有存储,则直接存储,否则,发生了hash冲突,需要找到新的空闲位置,存储,加入到链表中。该链表比较特殊,是通过数组实现的。
结构如图
在hash部分的数组中,每一个位置都有一个指针,用于形成链表。这样,hash值相同的元素存储在数组中后,又形成了一条链表。整个hash部分会形成多条链表。这种用数组实现链表的方式与普通的链地址法有些差异。
理解了table的存储结构,其余的操作也就比较好理解了。
阅读全文
0 0
- lua源码阅读(4)---表
- 阅读Lua源码
- 阅读lua源码顺序
- lua源码阅读(2)---数据类型
- lua源码阅读(3)----字符串
- lua源码阅读(5)-lua_State
- lua源码阅读(6)-函数
- lua源码阅读(7)-指令
- lua源码阅读(8)-虚拟机
- [Lua源码阅读] 理解Lua的object
- LUA源码阅读之词法分析
- LUA 源码阅读笔记(一)
- lua源码阅读(1)----概览
- Lua源码阅读二——lua内存管理
- Lua源码阅读三——lua字符串缓存
- Lua源码阅读四——lua虚拟机指令系统
- Lua源码阅读一——在Windows下编译
- c内核源码阅读准备知识(erlang mudos lua)
- loadView是干嘛用的?
- 安装VM、Centos、SecureCRT 搭建JDK、Mysql、Tomcat、Redis环境
- ArcMap桌面端如何正确加载天地图WMTS服务
- MFC中如何从EDIT控件中获取文字
- 初识Linux之root 超级用户与普通用户切换
- lua源码阅读(4)---表
- JS节点的属性及方法
- java的反射机制
- Android---保存数据工具类
- Spring Cloud Bus
- ArrayBlockingQueue源码讲解
- android对话框外全部透明样式
- Faster-RCNN_TF代码解读8:networks.py
- webpack踩坑之路——图片的路径与打包