Skip to content

Commit 5efabc7

Browse files
committed
Merge branch 'ew/hashmap'
Code clean-up of the hashmap API, both users and implementation. * ew/hashmap: hashmap_entry: remove first member requirement from docs hashmap: remove type arg from hashmap_{get,put,remove}_entry OFFSETOF_VAR macro to simplify hashmap iterators hashmap: introduce hashmap_free_entries hashmap: hashmap_{put,remove} return hashmap_entry * hashmap: use *_entry APIs for iteration hashmap_cmp_fn takes hashmap_entry params hashmap_get{,_from_hash} return "struct hashmap_entry *" hashmap: use *_entry APIs to wrap container_of hashmap_get_next returns "struct hashmap_entry *" introduce container_of macro hashmap_put takes "struct hashmap_entry *" hashmap_remove takes "const struct hashmap_entry *" hashmap_get takes "const struct hashmap_entry *" hashmap_add takes "struct hashmap_entry *" hashmap_get_next takes "const struct hashmap_entry *" hashmap_entry_init takes "struct hashmap_entry *" packfile: use hashmap_entry in delta_base_cache_entry coccicheck: detect hashmap_entry.hash assignment diff: use hashmap_entry_init on moved_entry.ent
2 parents d0ce4d9 + e2b5038 commit 5efabc7

31 files changed

+667
-381
lines changed

attr.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,22 @@ static struct attr_hashmap g_attr_hashmap;
6262

6363
/* The container for objects stored in "struct attr_hashmap" */
6464
struct attr_hash_entry {
65-
struct hashmap_entry ent; /* must be the first member! */
65+
struct hashmap_entry ent;
6666
const char *key; /* the key; memory should be owned by value */
6767
size_t keylen; /* length of the key */
6868
void *value; /* the stored value */
6969
};
7070

7171
/* attr_hashmap comparison function */
7272
static int attr_hash_entry_cmp(const void *unused_cmp_data,
73-
const void *entry,
74-
const void *entry_or_key,
73+
const struct hashmap_entry *eptr,
74+
const struct hashmap_entry *entry_or_key,
7575
const void *unused_keydata)
7676
{
77-
const struct attr_hash_entry *a = entry;
78-
const struct attr_hash_entry *b = entry_or_key;
77+
const struct attr_hash_entry *a, *b;
78+
79+
a = container_of(eptr, const struct attr_hash_entry, ent);
80+
b = container_of(entry_or_key, const struct attr_hash_entry, ent);
7981
return (a->keylen != b->keylen) || strncmp(a->key, b->key, a->keylen);
8082
}
8183

@@ -98,10 +100,10 @@ static void *attr_hashmap_get(struct attr_hashmap *map,
98100
if (!map->map.tablesize)
99101
attr_hashmap_init(map);
100102

101-
hashmap_entry_init(&k, memhash(key, keylen));
103+
hashmap_entry_init(&k.ent, memhash(key, keylen));
102104
k.key = key;
103105
k.keylen = keylen;
104-
e = hashmap_get(&map->map, &k, NULL);
106+
e = hashmap_get_entry(&map->map, &k, ent, NULL);
105107

106108
return e ? e->value : NULL;
107109
}
@@ -117,12 +119,12 @@ static void attr_hashmap_add(struct attr_hashmap *map,
117119
attr_hashmap_init(map);
118120

119121
e = xmalloc(sizeof(struct attr_hash_entry));
120-
hashmap_entry_init(e, memhash(key, keylen));
122+
hashmap_entry_init(&e->ent, memhash(key, keylen));
121123
e->key = key;
122124
e->keylen = keylen;
123125
e->value = value;
124126

125-
hashmap_add(&map->map, e);
127+
hashmap_add(&map->map, &e->ent);
126128
}
127129

128130
struct all_attrs_item {
@@ -161,12 +163,12 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)
161163
if (size != check->all_attrs_nr) {
162164
struct attr_hash_entry *e;
163165
struct hashmap_iter iter;
164-
hashmap_iter_init(&map->map, &iter);
165166

166167
REALLOC_ARRAY(check->all_attrs, size);
167168
check->all_attrs_nr = size;
168169

169-
while ((e = hashmap_iter_next(&iter))) {
170+
hashmap_for_each_entry(&map->map, &iter, e,
171+
ent /* member name */) {
170172
const struct git_attr *a = e->value;
171173
check->all_attrs[a->attr_nr].attr = a;
172174
}

blame.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -417,22 +417,23 @@ static void get_fingerprint(struct fingerprint *result,
417417
/* Ignore whitespace pairs */
418418
if (hash == 0)
419419
continue;
420-
hashmap_entry_init(entry, hash);
420+
hashmap_entry_init(&entry->entry, hash);
421421

422-
found_entry = hashmap_get(&result->map, entry, NULL);
422+
found_entry = hashmap_get_entry(&result->map, entry,
423+
/* member name */ entry, NULL);
423424
if (found_entry) {
424425
found_entry->count += 1;
425426
} else {
426427
entry->count = 1;
427-
hashmap_add(&result->map, entry);
428+
hashmap_add(&result->map, &entry->entry);
428429
++entry;
429430
}
430431
}
431432
}
432433

433434
static void free_fingerprint(struct fingerprint *f)
434435
{
435-
hashmap_free(&f->map, 0);
436+
hashmap_free(&f->map);
436437
free(f->entries);
437438
}
438439

@@ -449,10 +450,10 @@ static int fingerprint_similarity(struct fingerprint *a, struct fingerprint *b)
449450
struct hashmap_iter iter;
450451
const struct fingerprint_entry *entry_a, *entry_b;
451452

452-
hashmap_iter_init(&b->map, &iter);
453-
454-
while ((entry_b = hashmap_iter_next(&iter))) {
455-
if ((entry_a = hashmap_get(&a->map, entry_b, NULL))) {
453+
hashmap_for_each_entry(&b->map, &iter, entry_b,
454+
entry /* member name */) {
455+
entry_a = hashmap_get_entry(&a->map, entry_b, entry, NULL);
456+
if (entry_a) {
456457
intersection += entry_a->count < entry_b->count ?
457458
entry_a->count : entry_b->count;
458459
}
@@ -470,10 +471,12 @@ static void fingerprint_subtract(struct fingerprint *a, struct fingerprint *b)
470471

471472
hashmap_iter_init(&b->map, &iter);
472473

473-
while ((entry_b = hashmap_iter_next(&iter))) {
474-
if ((entry_a = hashmap_get(&a->map, entry_b, NULL))) {
474+
hashmap_for_each_entry(&b->map, &iter, entry_b,
475+
entry /* member name */) {
476+
entry_a = hashmap_get_entry(&a->map, entry_b, entry, NULL);
477+
if (entry_a) {
475478
if (entry_a->count <= entry_b->count)
476-
hashmap_remove(&a->map, entry_b, NULL);
479+
hashmap_remove(&a->map, &entry_b->entry, NULL);
477480
else
478481
entry_a->count -= entry_b->count;
479482
}

builtin/describe.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,22 @@ static const char *prio_names[] = {
6363
};
6464

6565
static int commit_name_neq(const void *unused_cmp_data,
66-
const void *entry,
67-
const void *entry_or_key,
66+
const struct hashmap_entry *eptr,
67+
const struct hashmap_entry *entry_or_key,
6868
const void *peeled)
6969
{
70-
const struct commit_name *cn1 = entry;
71-
const struct commit_name *cn2 = entry_or_key;
70+
const struct commit_name *cn1, *cn2;
71+
72+
cn1 = container_of(eptr, const struct commit_name, entry);
73+
cn2 = container_of(entry_or_key, const struct commit_name, entry);
7274

7375
return !oideq(&cn1->peeled, peeled ? peeled : &cn2->peeled);
7476
}
7577

7678
static inline struct commit_name *find_commit_name(const struct object_id *peeled)
7779
{
78-
return hashmap_get_from_hash(&names, oidhash(peeled), peeled);
80+
return hashmap_get_entry_from_hash(&names, oidhash(peeled), peeled,
81+
struct commit_name, entry);
7982
}
8083

8184
static int replace_name(struct commit_name *e,
@@ -122,8 +125,8 @@ static void add_to_known_names(const char *path,
122125
if (!e) {
123126
e = xmalloc(sizeof(struct commit_name));
124127
oidcpy(&e->peeled, peeled);
125-
hashmap_entry_init(e, oidhash(peeled));
126-
hashmap_add(&names, e);
128+
hashmap_entry_init(&e->entry, oidhash(peeled));
129+
hashmap_add(&names, &e->entry);
127130
e->path = NULL;
128131
}
129132
e->tag = tag;
@@ -329,8 +332,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
329332
struct commit_name *n;
330333

331334
init_commit_names(&commit_names);
332-
n = hashmap_iter_first(&names, &iter);
333-
for (; n; n = hashmap_iter_next(&iter)) {
335+
hashmap_for_each_entry(&names, &iter, n,
336+
entry /* member name */) {
334337
c = lookup_commit_reference_gently(the_repository,
335338
&n->peeled, 1);
336339
if (c)

builtin/difftool.c

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,15 @@ struct working_tree_entry {
125125
};
126126

127127
static int working_tree_entry_cmp(const void *unused_cmp_data,
128-
const void *entry,
129-
const void *entry_or_key,
128+
const struct hashmap_entry *eptr,
129+
const struct hashmap_entry *entry_or_key,
130130
const void *unused_keydata)
131131
{
132-
const struct working_tree_entry *a = entry;
133-
const struct working_tree_entry *b = entry_or_key;
132+
const struct working_tree_entry *a, *b;
133+
134+
a = container_of(eptr, const struct working_tree_entry, entry);
135+
b = container_of(entry_or_key, const struct working_tree_entry, entry);
136+
134137
return strcmp(a->path, b->path);
135138
}
136139

@@ -145,12 +148,14 @@ struct pair_entry {
145148
};
146149

147150
static int pair_cmp(const void *unused_cmp_data,
148-
const void *entry,
149-
const void *entry_or_key,
151+
const struct hashmap_entry *eptr,
152+
const struct hashmap_entry *entry_or_key,
150153
const void *unused_keydata)
151154
{
152-
const struct pair_entry *a = entry;
153-
const struct pair_entry *b = entry_or_key;
155+
const struct pair_entry *a, *b;
156+
157+
a = container_of(eptr, const struct pair_entry, entry);
158+
b = container_of(entry_or_key, const struct pair_entry, entry);
154159

155160
return strcmp(a->path, b->path);
156161
}
@@ -161,14 +166,14 @@ static void add_left_or_right(struct hashmap *map, const char *path,
161166
struct pair_entry *e, *existing;
162167

163168
FLEX_ALLOC_STR(e, path, path);
164-
hashmap_entry_init(e, strhash(path));
165-
existing = hashmap_get(map, e, NULL);
169+
hashmap_entry_init(&e->entry, strhash(path));
170+
existing = hashmap_get_entry(map, e, entry, NULL);
166171
if (existing) {
167172
free(e);
168173
e = existing;
169174
} else {
170175
e->left[0] = e->right[0] = '\0';
171-
hashmap_add(map, e);
176+
hashmap_add(map, &e->entry);
172177
}
173178
strlcpy(is_right ? e->right : e->left, content, PATH_MAX);
174179
}
@@ -179,12 +184,14 @@ struct path_entry {
179184
};
180185

181186
static int path_entry_cmp(const void *unused_cmp_data,
182-
const void *entry,
183-
const void *entry_or_key,
187+
const struct hashmap_entry *eptr,
188+
const struct hashmap_entry *entry_or_key,
184189
const void *key)
185190
{
186-
const struct path_entry *a = entry;
187-
const struct path_entry *b = entry_or_key;
191+
const struct path_entry *a, *b;
192+
193+
a = container_of(eptr, const struct path_entry, entry);
194+
b = container_of(entry_or_key, const struct path_entry, entry);
188195

189196
return strcmp(a->path, key ? key : b->path);
190197
}
@@ -234,8 +241,8 @@ static void changed_files(struct hashmap *result, const char *index_path,
234241
while (!strbuf_getline_nul(&buf, fp)) {
235242
struct path_entry *entry;
236243
FLEX_ALLOC_STR(entry, path, buf.buf);
237-
hashmap_entry_init(entry, strhash(buf.buf));
238-
hashmap_add(result, entry);
244+
hashmap_entry_init(&entry->entry, strhash(buf.buf));
245+
hashmap_add(result, &entry->entry);
239246
}
240247
fclose(fp);
241248
if (finish_command(&diff_files))
@@ -461,12 +468,13 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
461468

462469
/* Avoid duplicate working_tree entries */
463470
FLEX_ALLOC_STR(entry, path, dst_path);
464-
hashmap_entry_init(entry, strhash(dst_path));
465-
if (hashmap_get(&working_tree_dups, entry, NULL)) {
471+
hashmap_entry_init(&entry->entry, strhash(dst_path));
472+
if (hashmap_get(&working_tree_dups, &entry->entry,
473+
NULL)) {
466474
free(entry);
467475
continue;
468476
}
469-
hashmap_add(&working_tree_dups, entry);
477+
hashmap_add(&working_tree_dups, &entry->entry);
470478

471479
if (!use_wt_file(workdir, dst_path, &roid)) {
472480
if (checkout_path(rmode, &roid, dst_path,
@@ -530,8 +538,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
530538
* temporary file to both the left and right directories to show the
531539
* change in the recorded SHA1 for the submodule.
532540
*/
533-
hashmap_iter_init(&submodules, &iter);
534-
while ((entry = hashmap_iter_next(&iter))) {
541+
hashmap_for_each_entry(&submodules, &iter, entry,
542+
entry /* member name */) {
535543
if (*entry->left) {
536544
add_path(&ldir, ldir_len, entry->path);
537545
ensure_leading_directories(ldir.buf);
@@ -549,8 +557,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
549557
* shows only the link itself, not the contents of the link target.
550558
* This loop replicates that behavior.
551559
*/
552-
hashmap_iter_init(&symlinks2, &iter);
553-
while ((entry = hashmap_iter_next(&iter))) {
560+
hashmap_for_each_entry(&symlinks2, &iter, entry,
561+
entry /* member name */) {
554562
if (*entry->left) {
555563
add_path(&ldir, ldir_len, entry->path);
556564
ensure_leading_directories(ldir.buf);

builtin/fast-export.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,15 @@ struct anonymized_entry {
127127
};
128128

129129
static int anonymized_entry_cmp(const void *unused_cmp_data,
130-
const void *va, const void *vb,
130+
const struct hashmap_entry *eptr,
131+
const struct hashmap_entry *entry_or_key,
131132
const void *unused_keydata)
132133
{
133-
const struct anonymized_entry *a = va, *b = vb;
134+
const struct anonymized_entry *a, *b;
135+
136+
a = container_of(eptr, const struct anonymized_entry, hash);
137+
b = container_of(entry_or_key, const struct anonymized_entry, hash);
138+
134139
return a->orig_len != b->orig_len ||
135140
memcmp(a->orig, b->orig, a->orig_len);
136141
}
@@ -149,10 +154,10 @@ static const void *anonymize_mem(struct hashmap *map,
149154
if (!map->cmpfn)
150155
hashmap_init(map, anonymized_entry_cmp, NULL, 0);
151156

152-
hashmap_entry_init(&key, memhash(orig, *len));
157+
hashmap_entry_init(&key.hash, memhash(orig, *len));
153158
key.orig = orig;
154159
key.orig_len = *len;
155-
ret = hashmap_get(map, &key, NULL);
160+
ret = hashmap_get_entry(map, &key, hash, NULL);
156161

157162
if (!ret) {
158163
ret = xmalloc(sizeof(*ret));
@@ -161,7 +166,7 @@ static const void *anonymize_mem(struct hashmap *map,
161166
ret->orig_len = *len;
162167
ret->anon = generate(orig, len);
163168
ret->anon_len = *len;
164-
hashmap_put(map, ret);
169+
hashmap_put(map, &ret->hash);
165170
}
166171

167172
*len = ret->anon_len;

0 commit comments

Comments
 (0)