Skip to content

Commit

Permalink
Merge branch 'ew/hashmap'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gitster committed Oct 15, 2019
2 parents d0ce4d9 + e2b5038 commit 5efabc7
Show file tree
Hide file tree
Showing 31 changed files with 667 additions and 381 deletions.
24 changes: 13 additions & 11 deletions attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,22 @@ static struct attr_hashmap g_attr_hashmap;

/* The container for objects stored in "struct attr_hashmap" */
struct attr_hash_entry {
struct hashmap_entry ent; /* must be the first member! */
struct hashmap_entry ent;
const char *key; /* the key; memory should be owned by value */
size_t keylen; /* length of the key */
void *value; /* the stored value */
};

/* attr_hashmap comparison function */
static int attr_hash_entry_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct attr_hash_entry *a = entry;
const struct attr_hash_entry *b = entry_or_key;
const struct attr_hash_entry *a, *b;

a = container_of(eptr, const struct attr_hash_entry, ent);
b = container_of(entry_or_key, const struct attr_hash_entry, ent);
return (a->keylen != b->keylen) || strncmp(a->key, b->key, a->keylen);
}

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

hashmap_entry_init(&k, memhash(key, keylen));
hashmap_entry_init(&k.ent, memhash(key, keylen));
k.key = key;
k.keylen = keylen;
e = hashmap_get(&map->map, &k, NULL);
e = hashmap_get_entry(&map->map, &k, ent, NULL);

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

e = xmalloc(sizeof(struct attr_hash_entry));
hashmap_entry_init(e, memhash(key, keylen));
hashmap_entry_init(&e->ent, memhash(key, keylen));
e->key = key;
e->keylen = keylen;
e->value = value;

hashmap_add(&map->map, e);
hashmap_add(&map->map, &e->ent);
}

struct all_attrs_item {
Expand Down Expand Up @@ -161,12 +163,12 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check)
if (size != check->all_attrs_nr) {
struct attr_hash_entry *e;
struct hashmap_iter iter;
hashmap_iter_init(&map->map, &iter);

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

while ((e = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(&map->map, &iter, e,
ent /* member name */) {
const struct git_attr *a = e->value;
check->all_attrs[a->attr_nr].attr = a;
}
Expand Down
25 changes: 14 additions & 11 deletions blame.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,22 +417,23 @@ static void get_fingerprint(struct fingerprint *result,
/* Ignore whitespace pairs */
if (hash == 0)
continue;
hashmap_entry_init(entry, hash);
hashmap_entry_init(&entry->entry, hash);

found_entry = hashmap_get(&result->map, entry, NULL);
found_entry = hashmap_get_entry(&result->map, entry,
/* member name */ entry, NULL);
if (found_entry) {
found_entry->count += 1;
} else {
entry->count = 1;
hashmap_add(&result->map, entry);
hashmap_add(&result->map, &entry->entry);
++entry;
}
}
}

static void free_fingerprint(struct fingerprint *f)
{
hashmap_free(&f->map, 0);
hashmap_free(&f->map);
free(f->entries);
}

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

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

while ((entry_b = hashmap_iter_next(&iter))) {
if ((entry_a = hashmap_get(&a->map, entry_b, NULL))) {
hashmap_for_each_entry(&b->map, &iter, entry_b,
entry /* member name */) {
entry_a = hashmap_get_entry(&a->map, entry_b, entry, NULL);
if (entry_a) {
intersection += entry_a->count < entry_b->count ?
entry_a->count : entry_b->count;
}
Expand All @@ -470,10 +471,12 @@ static void fingerprint_subtract(struct fingerprint *a, struct fingerprint *b)

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

while ((entry_b = hashmap_iter_next(&iter))) {
if ((entry_a = hashmap_get(&a->map, entry_b, NULL))) {
hashmap_for_each_entry(&b->map, &iter, entry_b,
entry /* member name */) {
entry_a = hashmap_get_entry(&a->map, entry_b, entry, NULL);
if (entry_a) {
if (entry_a->count <= entry_b->count)
hashmap_remove(&a->map, entry_b, NULL);
hashmap_remove(&a->map, &entry_b->entry, NULL);
else
entry_a->count -= entry_b->count;
}
Expand Down
21 changes: 12 additions & 9 deletions builtin/describe.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,22 @@ static const char *prio_names[] = {
};

static int commit_name_neq(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *peeled)
{
const struct commit_name *cn1 = entry;
const struct commit_name *cn2 = entry_or_key;
const struct commit_name *cn1, *cn2;

cn1 = container_of(eptr, const struct commit_name, entry);
cn2 = container_of(entry_or_key, const struct commit_name, entry);

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

static inline struct commit_name *find_commit_name(const struct object_id *peeled)
{
return hashmap_get_from_hash(&names, oidhash(peeled), peeled);
return hashmap_get_entry_from_hash(&names, oidhash(peeled), peeled,
struct commit_name, entry);
}

static int replace_name(struct commit_name *e,
Expand Down Expand Up @@ -122,8 +125,8 @@ static void add_to_known_names(const char *path,
if (!e) {
e = xmalloc(sizeof(struct commit_name));
oidcpy(&e->peeled, peeled);
hashmap_entry_init(e, oidhash(peeled));
hashmap_add(&names, e);
hashmap_entry_init(&e->entry, oidhash(peeled));
hashmap_add(&names, &e->entry);
e->path = NULL;
}
e->tag = tag;
Expand Down Expand Up @@ -329,8 +332,8 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
struct commit_name *n;

init_commit_names(&commit_names);
n = hashmap_iter_first(&names, &iter);
for (; n; n = hashmap_iter_next(&iter)) {
hashmap_for_each_entry(&names, &iter, n,
entry /* member name */) {
c = lookup_commit_reference_gently(the_repository,
&n->peeled, 1);
if (c)
Expand Down
56 changes: 32 additions & 24 deletions builtin/difftool.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,15 @@ struct working_tree_entry {
};

static int working_tree_entry_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct working_tree_entry *a = entry;
const struct working_tree_entry *b = entry_or_key;
const struct working_tree_entry *a, *b;

a = container_of(eptr, const struct working_tree_entry, entry);
b = container_of(entry_or_key, const struct working_tree_entry, entry);

return strcmp(a->path, b->path);
}

Expand All @@ -145,12 +148,14 @@ struct pair_entry {
};

static int pair_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct pair_entry *a = entry;
const struct pair_entry *b = entry_or_key;
const struct pair_entry *a, *b;

a = container_of(eptr, const struct pair_entry, entry);
b = container_of(entry_or_key, const struct pair_entry, entry);

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

FLEX_ALLOC_STR(e, path, path);
hashmap_entry_init(e, strhash(path));
existing = hashmap_get(map, e, NULL);
hashmap_entry_init(&e->entry, strhash(path));
existing = hashmap_get_entry(map, e, entry, NULL);
if (existing) {
free(e);
e = existing;
} else {
e->left[0] = e->right[0] = '\0';
hashmap_add(map, e);
hashmap_add(map, &e->entry);
}
strlcpy(is_right ? e->right : e->left, content, PATH_MAX);
}
Expand All @@ -179,12 +184,14 @@ struct path_entry {
};

static int path_entry_cmp(const void *unused_cmp_data,
const void *entry,
const void *entry_or_key,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *key)
{
const struct path_entry *a = entry;
const struct path_entry *b = entry_or_key;
const struct path_entry *a, *b;

a = container_of(eptr, const struct path_entry, entry);
b = container_of(entry_or_key, const struct path_entry, entry);

return strcmp(a->path, key ? key : b->path);
}
Expand Down Expand Up @@ -234,8 +241,8 @@ static void changed_files(struct hashmap *result, const char *index_path,
while (!strbuf_getline_nul(&buf, fp)) {
struct path_entry *entry;
FLEX_ALLOC_STR(entry, path, buf.buf);
hashmap_entry_init(entry, strhash(buf.buf));
hashmap_add(result, entry);
hashmap_entry_init(&entry->entry, strhash(buf.buf));
hashmap_add(result, &entry->entry);
}
fclose(fp);
if (finish_command(&diff_files))
Expand Down Expand Up @@ -461,12 +468,13 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,

/* Avoid duplicate working_tree entries */
FLEX_ALLOC_STR(entry, path, dst_path);
hashmap_entry_init(entry, strhash(dst_path));
if (hashmap_get(&working_tree_dups, entry, NULL)) {
hashmap_entry_init(&entry->entry, strhash(dst_path));
if (hashmap_get(&working_tree_dups, &entry->entry,
NULL)) {
free(entry);
continue;
}
hashmap_add(&working_tree_dups, entry);
hashmap_add(&working_tree_dups, &entry->entry);

if (!use_wt_file(workdir, dst_path, &roid)) {
if (checkout_path(rmode, &roid, dst_path,
Expand Down Expand Up @@ -530,8 +538,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
* temporary file to both the left and right directories to show the
* change in the recorded SHA1 for the submodule.
*/
hashmap_iter_init(&submodules, &iter);
while ((entry = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(&submodules, &iter, entry,
entry /* member name */) {
if (*entry->left) {
add_path(&ldir, ldir_len, entry->path);
ensure_leading_directories(ldir.buf);
Expand All @@ -549,8 +557,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
* shows only the link itself, not the contents of the link target.
* This loop replicates that behavior.
*/
hashmap_iter_init(&symlinks2, &iter);
while ((entry = hashmap_iter_next(&iter))) {
hashmap_for_each_entry(&symlinks2, &iter, entry,
entry /* member name */) {
if (*entry->left) {
add_path(&ldir, ldir_len, entry->path);
ensure_leading_directories(ldir.buf);
Expand Down
15 changes: 10 additions & 5 deletions builtin/fast-export.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,15 @@ struct anonymized_entry {
};

static int anonymized_entry_cmp(const void *unused_cmp_data,
const void *va, const void *vb,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
const void *unused_keydata)
{
const struct anonymized_entry *a = va, *b = vb;
const struct anonymized_entry *a, *b;

a = container_of(eptr, const struct anonymized_entry, hash);
b = container_of(entry_or_key, const struct anonymized_entry, hash);

return a->orig_len != b->orig_len ||
memcmp(a->orig, b->orig, a->orig_len);
}
Expand All @@ -149,10 +154,10 @@ static const void *anonymize_mem(struct hashmap *map,
if (!map->cmpfn)
hashmap_init(map, anonymized_entry_cmp, NULL, 0);

hashmap_entry_init(&key, memhash(orig, *len));
hashmap_entry_init(&key.hash, memhash(orig, *len));
key.orig = orig;
key.orig_len = *len;
ret = hashmap_get(map, &key, NULL);
ret = hashmap_get_entry(map, &key, hash, NULL);

if (!ret) {
ret = xmalloc(sizeof(*ret));
Expand All @@ -161,7 +166,7 @@ static const void *anonymize_mem(struct hashmap *map,
ret->orig_len = *len;
ret->anon = generate(orig, len);
ret->anon_len = *len;
hashmap_put(map, ret);
hashmap_put(map, &ret->hash);
}

*len = ret->anon_len;
Expand Down
Loading

0 comments on commit 5efabc7

Please sign in to comment.