Lua 5.3 源码分析(六) 字符串 Table

Lua 5.3 源码分析 (六) 表 Table

typedef union TKey {
  struct {
    TValuefields;
    int next;  /* for chaining (offset for next node) */
  } nk;
  TValue tvk;
} TKey;


/* copy a value into a key without messing up field 'next' */
#define setnodekey(L,key,obj) \
    { TKey *k_=(key); const TValue *io_=(obj); \
      k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \
      (void)L; checkliveness(G(L),io_); }


typedef struct Node {
  TValue i_val;
  TKey i_key;
} Node;


typedef struct Table {
  CommonHeader;
  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */
  lu_byte lsizenode;  /* log2 of size of 'node' array */
  unsigned int sizearray;  /* size of 'array' array */
  TValue *array;  /* array part */
  Node *node;
  Node *lastfree;  /* any free position is before this position */
  struct Table *metatable;
  GCObject *gclist;
} Table;

table 的存储分为 数组部分和哈希表部分。
数组部分索引从1开始。
nil 是唯一不能做哈希键值的类型。
\# 对table 取长度时,也被定义为 整数下表有关,而不是整个table 的长度。

Table *luaH_new (lua_State *L) {
  GCObject *o = luaC_newobj(L, LUA_TTABLE, sizeof(Table));
  Table *t = gco2t(o);
  t->metatable = NULL;
  t->flags = cast_byte(~0);
  t->array = NULL;
  t->sizearray = 0;
  setnodevector(L, t, 0);
  return t;
}


void luaH_free (lua_State *L, Table *t) {
  if (!isdummy(t->node))
    luaM_freearray(L, t->node, cast(size_t, sizenode(t)));
  luaM_freearray(L, t->array, t->sizearray);
  luaM_free(L, t);
}

用isdummy 判断 哈希表部分是否为空表,当哈希表部分为空时,在析构函数中只需要释放 数组部分占用内存。

数组部分

Table 的数组部分被存储在TValue *array 中, int sizearray 存储着数组长度。

哈希表部分

Table 的哈希表部分被存储在 Node *node , lu_byte lsizenode 存储着哈希表的大小。由于哈希表的大小一定是 2 的整数次幂,所以这里的 lsizenode 表示的是 次幂数,而不是实际大小 (2^lsizenode)。

定义了一个不可写的空哈希表:dummynode , setnodevector 函数用来初始化哈希表部分 , 当 size 参数为0 时,说明是一个空表被初始化,则node 域指向这个dummynode 节点。

#define dummynode       (&dummynode_)

#define isdummy(n)      ((n) == dummynode)

static const Node dummynode_ = {
  {NILCONSTANT},  /* value */
  {
  {NILCONSTANT, 0}}  /* key */
};

表的增删改查

删除

表没有删除操作,使用将对应的键位赋值为nil。

读取

使用 luaH_newkey 负责在哈希表中创建一个不存在的键位,不影响数组部分。

TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
  Node *mp;
  TValue aux;
  if (ttisnil(key))
      luaG_runerror(L, "table index is nil");
  else if (ttisfloat(key)) {
    lua_Number n
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值