hsearch_r函数
inthsearch_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 returnwith 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操作。