-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathxpower-hash.c
100 lines (88 loc) · 2.78 KB
/
xpower-hash.c
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
** Copyright (C) 2011 XXX all rights reserved.
**
** This file defines Dispatcher Training Simulator (DTS)
** hash and only used for internal.
**
** Created by [email protected] on 01/11/2011
**
*/
#include "xpower-hash.h"
#include "xpower-config.h"
/*
* look up a hash entry in the hash table. return the pointer to
* the existing entry, or the empty slot if none existed. the caller
* need check it.
*/
static struct _xhash_entry *_xlookup_hash_entry(unsigned int hash, const struct _xhash *table){
register unsigned int size = table->size, next = hash % size;
struct _xhash_entry *bucket = table->bucket;
while (bucket[next].index){
if (bucket[next].hash == hash)
break;
next++;
if (next >= size)
next = 0;
}
return bucket + next;
}
/*
* insert a new hash entry pointer into the table. if that hash entry already
* existed, return the pointer to the existing entry, otherwise return NULL
*/
static struct _xhash_entry *_xinsert_hash_entry(unsigned int hash, unsigned int index, struct _xhash *table){
struct _xhash_entry *entry = _xlookup_hash_entry(hash,table);
if (!entry->index){
entry->hash = hash;
entry->index = index;
table->next++;
return NULL;
}
return entry;
}
/*
* increase the hash table size, the new size got from the following format:
* new_size = (((old_size)+16)*3/2)
*/
static void _xgrow_hash(struct _xhash *table){
unsigned int old_size = table->size, new_size;
struct _xhash_entry *old_bucket = table->bucket, *new_bucket;
new_size = (((old_size)+16)*3/2);
new_bucket = (struct _xhash_entry *)_xcalloc(sizeof(struct _xhash_entry), new_size);
_xmem_copy(old_bucket, new_bucket, old_size *sizeof(struct _xhash_entry));
table->size = new_size;
table->bucket = new_bucket;
_xfree(old_bucket);
}
/*!
* look up the hash table to find the entry with hash value,return the
* index field of that entry or 0 if not found
*/
int _xlookup_hash(unsigned int hash, const struct _xhash *table){
struct _xhash_entry *entry;
if (!table->bucket)
return 0;
entry = _xlookup_hash_entry(hash,table);
return entry->hash == hash ? entry->index : 0;
}
/*!
* insert a new entry into the hash table, return 0 if success or
* old index already existed.
*/
int _xinsert_hash(unsigned int hash, unsigned int index, struct _xhash *table){
struct _xhash_entry *entry;
unsigned int next = table->next;
if (next >= table->size/2)
_xgrow_hash(table);
entry = _xinsert_hash_entry(hash,index,table);
return entry ? entry->index : 0;
}
/*!
* deallocate the hash table
*/
void _xfree_hash(struct _xhash *table){
_xfree(table->bucket);
table->bucket = NULL;
table->size = 0;
table->next = 0;
}