目录
一、概述
二、 symOpen 创建
1.返回值
2.输入值
3.示例:
三、symEnter 插入
四、symLookup查找
五、symClose 释放
一、概述
哈希表,又叫散列表。在用GoAhead 实现WebServer时,其中的哈希工具可以实现对大量数据的快速检索,如查重等。
主要用到的函数有4个:
extern sym_fd_t symOpen(int hash_size);
extern void symClose(sym_fd_t sd);
extern sym_t *symLookup(sym_fd_t sd, char_t *name);
extern sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg);主要访问数据有2个:
static sym_tabent_t **sym; /* List of symbol tables */
static int symMax; /* One past the max symbol table */
下面分别介绍其功能和用法,示例都是GoAhead 原码。
二、 symOpen 创建
每创建一个哈希表就要调用一次symOpen,并给symMax加1。
1.返回值
类型是sym_fd_t ,实际上是一个整型数。创建的哈希表的指针会放在数组sym里,对应数组sym中的索引即symOpen返回的值,从0开始排序。失败则返回-1。
如果创建了多个表,它们会被依次放到数组sym中。symMax即创建的哈希表总个数。如果创建的哈希表被symClose释放了,索引也会被释放给下一个创建的哈希表。
如GoAhead 启动后会依次注册以下哈希表:
MimeList,对应索引 websMime=0;
PageList 的 aspList,对应索引websAspFunctions=1;
PageList 的 formList,对应索引formSymtab=2;
.......
2.输入值
hash_size用于指定表的大小,基于效率的考虑,这个大小最好不要小于原表的二分之一。symOpen内部实际会调整为一个小于等于hash_size的质数。所以我会选择原表大小的四分之三作为输入值,这样即使调整到一个较小的质数也不会小于原值的二分之一。
3.示例:
formSymtab = symOpen(WEBS_SYM_INIT);
三、symEnter 插入
这里不是顺序插入,而是根据传入的name和 哈希表大小计算出索引,以便于后面查找时能根据name 快速定位。name重复的,后来会覆盖先来的。如果不想覆盖,可以先调用symLookup 检查是否name 已经创建过了。
返回值 是创建的这一条目的指针。
输入值 sd即创建时返回的索引。
输入值 name 是个字符串,可以理解为是表项的key。
输入值 v 要特别注意,可以通过valueInteger 、valueString指定类型。
如:
symEnter(formSymtab, name, valueInteger((int) fn), (int) NULL);
或
symEnter(lanSymtab, buf, valueString(val, VALUE_ALLOCATE), (int)NULL);
其中valueString 还需要明确字符串是否需要创建,通常是需要的。
输入值 arg 通常是NULL.
四、symLookup查找
根据指定的哈希表索引sd 和 条目索引 name可以查找对应的哈希条目,远比逐个对比原表快得多。
找不到就返回NULL, 找到了就返回对应条目的指针。
示例:sp = symLookup(formSymtab, formName);
五、symClose 释放
如果哈希表不用了,就需要尽快释放,以免占用内存。上文中提到了索引0-2的哈希表由于一直要用,所以会在webs被关闭时才close(见 websCloseServer)。
对于需要多次覆盖的哈希表,需要在每次创建前判断,如果存在就先close再open。
示例:
void websLanguageUnload(void)
{
if(lanSymtab != -1)
{
symClose(lanSymtab);
lanSymtab = -1;
}
}
int websLanguageLoad(char_t *path)
{
...
if(lanSymtab == -1)
{
lanSymtab = symOpen(LANGUAGE_HASHSIZE);
}
else
{
websLanguageUnload();
lanSymtab = symOpen(LANGUAGE_HASHSIZE);
}
...
}