hsearch_r函数
int
hsearch_r (item, action, retval, htab)
ENTRY item;
ACTION action;
ENTRY **retval;
struct hsearch_data *htab;
{
unsigned int hval;
unsigned int count;
unsigned int len = strlen (item.key);
unsigned int idx;
/** Compute an value for the given string. Perhaps use a better method. */
hval = len;
count = len;
while (count-- > 0)
{
hval <<= 4;
hval += item.key[count];
}
/** First hash function: simply take the modul but prevent zero. */
idx = hval % htab->size + 1;
if (htab->table[idx].used)
{
/** Further action might be required according to the action value. */
if (htab->table[idx].used == hval
&& strcmp (item.key, htab->table[idx].entry.key) == 0)
{
*retval = &htab->table[idx].entry;
return 1;
}
/** Second hash function, as suggested in [Knuth] */
unsigned int hval2 = 1 + hval % (htab->size - 2);
unsigned int first_idx = idx;
do
{
/** Because SIZE is prime this guarantees to step through all
available indeces. */
if (idx <= hval2)
idx = htab->size + idx - hval2;
else
idx -= hval2;
/** If we visited all entries leave the loop unsuccessfully. */
if (idx == first_idx)
break;
/** If entry is found use it. */
if (htab->table[idx].used == hval
&& strcmp (item.key, htab->table[idx].entry.key) == 0)
{
*retval = &htab->table[idx].entry;
return 1;
}
}
while (htab->table[idx].used);
}
/** An empty bucket has been found. */
if (action == ENTER)
{
/** If table is full and another entry should be entered return
with error. */
if (htab->filled == htab->size)
{
__set_errno (ENOMEM);
*retval = NULL;
return 0;
}
htab->table[idx].used = hval;
htab->table[idx].entry = item;
++htab->filled;
*retval = &htab->table[idx].entry;
return 1;
}
__set_errno (ESRCH);
*retval = NULL;
return 0;
}
函数执行的时候不论action为什么,先查找,若是命中则返回有的,若是没有命中节点且action为ENTER则进行hash_add操作。