name-hash.c: use new hash map implementation for directories
Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Karsten Blees committed
Nov 14, 2013 at 20:20 UTC
e05881a4577cedca4d7456b3cb1f8bbd6f480df2
2 files changed
+20
-60
cache.h
+2
-1
@@ -4,6 +4,7 @@
4
#include "git-compat-util.h"
5
#include "strbuf.h"
6
#include "hash.h"
7
+#include "hashmap.h"
8
#include "advice.h"
9
#include "gettext.h"
10
#include "convert.h"
@@ -278,7 +279,7 @@ struct index_state {
279
unsigned name_hash_initialized : 1,
280
initialized : 1;
281
struct hash_table name_hash;
281
- struct hash_table dir_hash;
282
+ struct hashmap dir_hash;
283
};
284
285
extern struct index_state the_index;
name-hash.c
+18
-59
@@ -8,49 +8,28 @@
8
#define NO_THE_INDEX_COMPATIBILITY_MACROS
9
#include "cache.h"
10
11
-/*
12
- * This removes bit 5 if bit 6 is set.
13
- *
14
- * That will make US-ASCII characters hash to their upper-case
15
- * equivalent. We could easily do this one whole word at a time,
16
- * but that's for future worries.
17
- */
18
-static inline unsigned char icase_hash(unsigned char c)
19
-{
20
- return c & ~((c & 0x40) >> 1);
21
-}
22
-
23
-static unsigned int hash_name(const char *name, int namelen)
24
-{
25
- unsigned int hash = 0x123;
26
-
27
- while (namelen--) {
28
- unsigned char c = *name++;
29
- c = icase_hash(c);
30
- hash = hash*101 + c;
31
- }
32
- return hash;
33
-}
34
-
11
struct dir_entry {
36
- struct dir_entry *next;
12
+ struct hashmap_entry ent;
13
struct dir_entry *parent;
14
struct cache_entry *ce;
15
int nr;
16
unsigned int namelen;
17
};
18
19
+static int dir_entry_cmp(const struct dir_entry *e1,
20
+ const struct dir_entry *e2, const char *name)
21
+{
22
+ return e1->namelen != e2->namelen || strncasecmp(e1->ce->name,
23
+ name ? name : e2->ce->name, e1->namelen);
24
+}
25
+
26
static struct dir_entry *find_dir_entry(struct index_state *istate,
27
const char *name, unsigned int namelen)
28
{
46
- unsigned int hash = hash_name(name, namelen);
47
- struct dir_entry *dir;
48
-
49
- for (dir = lookup_hash(hash, &istate->dir_hash); dir; dir = dir->next)
50
- if (dir->namelen == namelen &&
51
- !strncasecmp(dir->ce->name, name, namelen))
52
- return dir;
53
- return NULL;
29
+ struct dir_entry key;
30
+ hashmap_entry_init(&key, memihash(name, namelen));
31
+ key.namelen = namelen;
32
+ return hashmap_get(&istate->dir_hash, &key, name);
33
}
34
35
static struct dir_entry *hash_dir_entry(struct index_state *istate,
@@ -84,18 +63,11 @@ static struct dir_entry *hash_dir_entry(struct index_state *istate,
63
dir = find_dir_entry(istate, ce->name, namelen);
64
if (!dir) {
65
/* not found, create it and add to hash table */
87
- void **pdir;
88
- unsigned int hash = hash_name(ce->name, namelen);
89
-
66
dir = xcalloc(1, sizeof(struct dir_entry));
67
+ hashmap_entry_init(dir, memihash(ce->name, namelen));
68
dir->namelen = namelen;
69
dir->ce = ce;
93
-
94
- pdir = insert_hash(hash, dir, &istate->dir_hash);
95
- if (pdir) {
96
- dir->next = *pdir;
97
- *pdir = dir;
98
- }
70
+ hashmap_add(&istate->dir_hash, dir);
71
72
/* recursively add missing parent directories */
73
dir->parent = hash_dir_entry(istate, ce, namelen);
@@ -134,7 +106,7 @@ static void hash_index_entry(struct index_state *istate, struct cache_entry *ce)
106
return;
107
ce->ce_flags |= CE_HASHED;
108
ce->next = NULL;
137
- hash = hash_name(ce->name, ce_namelen(ce));
109
+ hash = memihash(ce->name, ce_namelen(ce));
110
pos = insert_hash(hash, ce, &istate->name_hash);
111
if (pos) {
112
ce->next = *pos;
@@ -153,6 +125,7 @@ static void lazy_init_name_hash(struct index_state *istate)
125
return;
126
if (istate->cache_nr)
127
preallocate_hash(&istate->name_hash, istate->cache_nr);
128
+ hashmap_init(&istate->dir_hash, (hashmap_cmp_fn) dir_entry_cmp, 0);
129
for (nr = 0; nr < istate->cache_nr; nr++)
130
hash_index_entry(istate, istate->cache[nr]);
131
istate->name_hash_initialized = 1;
@@ -247,7 +220,7 @@ struct cache_entry *index_dir_exists(struct index_state *istate, const char *nam
220
221
struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int icase)
222
{
250
- unsigned int hash = hash_name(name, namelen);
223
+ unsigned int hash = memihash(name, namelen);
224
struct cache_entry *ce;
225
226
lazy_init_name_hash(istate);
@@ -270,26 +243,12 @@ struct cache_entry *index_name_exists(struct index_state *istate, const char *na
243
return index_file_exists(istate, name, namelen, icase);
244
}
245
273
-static int free_dir_entry(void *entry, void *unused)
274
-{
275
- struct dir_entry *dir = entry;
276
- while (dir) {
277
- struct dir_entry *next = dir->next;
278
- free(dir);
279
- dir = next;
280
- }
281
- return 0;
282
-}
283
-
246
void free_name_hash(struct index_state *istate)
247
{
248
if (!istate->name_hash_initialized)
249
return;
250
istate->name_hash_initialized = 0;
289
- if (ignore_case)
290
- /* free directory entries */
291
- for_each_hash(&istate->dir_hash, free_dir_entry, NULL);
251
252
free_hash(&istate->name_hash);
294
- free_hash(&istate->dir_hash);
253
+ hashmap_free(&istate->dir_hash, 1);
254
}