1 #ifndef CGPERF_HASH_TABLE_C
2 #define CGPERF_HASH_TABLE_C
9 #include "hash-table.h"
11 /*------------------------------------------------------------------------------------------------*/
12 #include "namespace/hash-table.h"
13 #include "namespace/keyword.h"
14 #include "namespace/hash.h"
15 /*------------------------------------------------------------------------------------------------*/
18 * We make the size of the hash table a power of 2. This allows for two optimizations: It eliminates
19 * the modulo instruction, and allows for an easy secondary hashing function.
21 static struct Hash_Table
*ht_new(u32 size
, bool ignore_length
)
26 t
= calloc(1, sizeof(*t
));
27 t
->ignore_length
= ignore_length
;
29 /* there need to be enough spare entries */
30 size
= size
* (u32
)ht_size_factor
;
32 /* find smallest power of 2 that is >= size */
34 if ((size
>> 16) > 0) {
38 if ((size
>> 8) > 0) {
42 if ((size
>> 4) > 0) {
46 if ((size
>> 2) > 0) {
50 if ((size
>> 1) > 0) {
57 t
->table
= calloc(t
->size
, sizeof(*(t
->table
)));
61 static void ht_del(struct Hash_Table
*t
)
68 * Attempts to insert ITEM in the table. If there is already an equal entry in it, returns it.
69 * Otherwise inserts ITEM and returns NULL.
71 static struct Keyword
*ht_insert(struct Hash_Table
*t
, struct Keyword
*item
)
77 hash_val
= hashpjw((u8
*)item
->selchars
, item
->selchars_length
* sizeof(u32
));
78 probe
= hash_val
& (t
->size
- 1);
79 increment
= (((hash_val
>> t
->log_size
) ^ (t
->ignore_length
? 0 : item
->allchars_length
))
82 * note that because _size is a power of 2 and increment is odd, we have
83 * gcd(increment,_size) = 1, which guarantees that we'll find an empty entry during the loop
86 if (t
->table
[probe
] == 0)
88 if (ht_equal(t
, t
->table
[probe
], item
))
89 return t
->table
[probe
];
91 probe
= (probe
+ increment
) & (t
->size
- 1);
93 t
->table
[probe
] = item
;
97 static bool ht_equal(struct Hash_Table
*t
, struct Keyword
*item1
, struct Keyword
*item2
)
99 return item1
->selchars_length
== item2
->selchars_length
100 && memcmp(item1
->selchars
, item2
->selchars
, item1
->selchars_length
* sizeof(u32
))
102 && (t
->ignore_length
|| item1
->allchars_length
== item2
->allchars_length
);
105 static void ht_dump(struct Hash_Table
*t
)
118 if (t
->table
[i
] != 0)
119 if (field_width
< t
->table
[i
]->selchars_length
)
120 field_width
= t
->table
[i
]->selchars_length
;
124 fprintf(stderr
, "\ndumping the hash table\ntotal available table slots = %d, total bytes = %d, total collisions = %d\nlocation, %*s, keyword\n", t
->size
, t
->size
* (u32
)(sizeof(*(t
->table
))), t
->collisions
, field_width
, "keysig");
130 if (t
->table
[i
] != 0) {
133 fprintf(stderr
, "%8d, ", i
);
134 if (field_width
> t
->table
[i
]->selchars_length
)
135 fprintf(stderr
, "%*s", field_width
- t
->table
[i
]->selchars_length
, "");
138 if (j
>= t
->table
[i
]->selchars_length
)
140 putc(t
->table
[i
]->selchars
[j
], stderr
);
143 fprintf(stderr
, ", %.*s\n", t
->table
[i
]->allchars_length
, t
->table
[i
]->allchars
);
147 fprintf(stderr
, "\nend dumping hash table\n\n");
149 /*------------------------------------------------------------------------------------------------*/
151 #include "namespace/hash-table.h"
152 #include "namespace/keyword.h"
153 #include "namespace/hash.h"
155 /*------------------------------------------------------------------------------------------------*/