转载出处:http://my.oschina.net/xhan/blog/308325
hash.c 代码分析
Lua 中最重要的一个数据结构及相关操作。
主要看下几个对外的接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
新建一个关联数组,入参是关联数组的大小。
新建一个关联数组。
设置大小。
打标记。
新建指针数组。
void lua_hashdelete (Hash *h);
释放关联数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
在关联数组中查看指定项是否存在,如果存在,返回它的指针。
如果不存在,新建一个结点,也同样返回它的指针。
返回关联引用在关联数组中的头。
跟据关联数组的头,查看引用在关联数组中是否存在:
如果不存在,新建一个结点,设置其引用为传入的参数,同时设置其值为空,把新建的结点插入到表头。
如果存在,直接返回它的值。
来看看 head 和 present 的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
关联数组分为两个部分,数值部分和引用部分。
数值部分的下标是通过数值的大小和关联数组的大小取余得到的。
而引用部分目前只支持字符串类型。
字符串部分是通过一个算法得到它的散列值的。
具体算法是把字符串的 ASCII 码左移 8 位后相加之和与关联数组的大小取余。
再看 present 的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
通过数组和下标找到相应的链表,在链表中查找是否有指定的值。如果有,返回结点,如果没有,返回空。
void lua_hashmark (Hash *h)
标记关联数组中所有的结点。
再看看 lua_next 的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
|
在 Lua 脚本中调用 next 时调用的就是它。作用是数组遍历。
给定一个数组和引用,返回数组中给定引用的下一个结点。
如果给的是一个空值,返回数组的头一个结点。
否则返回数组中该值的下一个非空结点。
这里返回了两个值到 Lua 的脚本中。
看下自带的一个用到它的测试程序(array.lua):
a = @() i=0 while i<10 do a[i] = i*i i=i+1 end r,v = next(a,nil) while r ~= nil do print ("array["..r.."] = "..v) r,v = next(a,r) end
这个程序会打印出以下:
array[0] = 0
array[1] = 1
array[2] = 4
array[3] = 9
array[4] = 16
array[5] = 25
array[6] = 36
array[7] = 49
array[8] = 64
array[9] = 81