From d22245a2e360d2e708ca37169be8eb5a5899b98d Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Oct 2019 23:30:27 +0000 Subject: hashmap_entry_init takes "struct hashmap_entry *" C compilers do type checking to make life easier for us. So rely on that and update all hashmap_entry_init callers to take "struct hashmap_entry *" to avoid future bugs while improving safety and readability. Signed-off-by: Eric Wong Reviewed-by: Derrick Stolee Signed-off-by: Junio C Hamano --- attr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index 93dc16b59c..a8be7a7b4f 100644 --- a/attr.c +++ b/attr.c @@ -98,7 +98,7 @@ 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); @@ -117,7 +117,7 @@ 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; -- cgit v1.2.3 From b94e5c1df674eb4ec8fdeaaae1ad8df552cb5d70 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Oct 2019 23:30:29 +0000 Subject: hashmap_add takes "struct hashmap_entry *" This is less error-prone than "void *" as the compiler now detects invalid types being passed. Signed-off-by: Eric Wong Reviewed-by: Derrick Stolee Signed-off-by: Junio C Hamano --- attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index a8be7a7b4f..fa26a3e3cb 100644 --- a/attr.c +++ b/attr.c @@ -122,7 +122,7 @@ static void attr_hashmap_add(struct attr_hashmap *map, e->keylen = keylen; e->value = value; - hashmap_add(&map->map, e); + hashmap_add(&map->map, &e->ent); } struct all_attrs_item { -- cgit v1.2.3 From b6c5241606e67b57470e86ccf547d4ab90008a1d Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Oct 2019 23:30:30 +0000 Subject: hashmap_get takes "const struct hashmap_entry *" This is less error-prone than "const void *" as the compiler now detects invalid types being passed. Signed-off-by: Eric Wong Reviewed-by: Derrick Stolee Signed-off-by: Junio C Hamano --- attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index fa26a3e3cb..9bdef61cc3 100644 --- a/attr.c +++ b/attr.c @@ -101,7 +101,7 @@ static void *attr_hashmap_get(struct attr_hashmap *map, hashmap_entry_init(&k.ent, memhash(key, keylen)); k.key = key; k.keylen = keylen; - e = hashmap_get(&map->map, &k, NULL); + e = hashmap_get(&map->map, &k.ent, NULL); return e ? e->value : NULL; } -- cgit v1.2.3 From f23a465132a22860684ac66052cf9a954a18e27d Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Oct 2019 23:30:36 +0000 Subject: hashmap_get{,_from_hash} return "struct hashmap_entry *" Update callers to use hashmap_get_entry, hashmap_get_entry_from_hash or container_of as appropriate. This is another step towards eliminating the requirement of hashmap_entry being the first field in a struct. Signed-off-by: Eric Wong Reviewed-by: Derrick Stolee Signed-off-by: Junio C Hamano --- attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index 9bdef61cc3..4230bee63d 100644 --- a/attr.c +++ b/attr.c @@ -101,7 +101,7 @@ static void *attr_hashmap_get(struct attr_hashmap *map, hashmap_entry_init(&k.ent, memhash(key, keylen)); k.key = key; k.keylen = keylen; - e = hashmap_get(&map->map, &k.ent, NULL); + e = hashmap_get_entry(&map->map, &k, NULL, struct attr_hash_entry, ent); return e ? e->value : NULL; } -- cgit v1.2.3 From 939af16eac1608766273d3971598dbcc4fe09928 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Oct 2019 23:30:37 +0000 Subject: hashmap_cmp_fn takes hashmap_entry params Another step in eliminating the requirement of hashmap_entry being the first member of a struct. Signed-off-by: Eric Wong Reviewed-by: Derrick Stolee Signed-off-by: Junio C Hamano --- attr.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index 4230bee63d..6053481610 100644 --- a/attr.c +++ b/attr.c @@ -70,12 +70,14 @@ struct attr_hash_entry { /* 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); } -- cgit v1.2.3 From 87571c3f71ba41d89eef5202f8589daa26f984ca Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Oct 2019 23:30:38 +0000 Subject: hashmap: use *_entry APIs for iteration Inspired by list_for_each_entry in the Linux kernel. Once again, these are somewhat compromised usability-wise by compilers lacking __typeof__ support. Signed-off-by: Eric Wong Reviewed-by: Derrick Stolee Signed-off-by: Junio C Hamano --- attr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index 6053481610..ca8be46e8e 100644 --- a/attr.c +++ b/attr.c @@ -163,12 +163,13 @@ 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, + struct attr_hash_entry, + ent /* member name */) { const struct git_attr *a = e->value; check->all_attrs[a->attr_nr].attr = a; } -- cgit v1.2.3 From 23dee69f53cf5024ca79e0b707dcb03c63f33bef Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Oct 2019 23:30:41 +0000 Subject: OFFSETOF_VAR macro to simplify hashmap iterators While we cannot rely on a `__typeof__' operator being portable to use with `offsetof'; we can calculate the pointer offset using an existing pointer and the address of a member using pointer arithmetic for compilers without `__typeof__'. This allows us to simplify usage of hashmap iterator macros by not having to specify a type when a pointer of that type is already given. In the future, list iterator macros (e.g. list_for_each_entry) may also be implemented using OFFSETOF_VAR to save hackers the trouble of using container_of/list_entry macros and without relying on non-portable `__typeof__'. v3: use `__typeof__' to avoid clang warnings Signed-off-by: Eric Wong Reviewed-by: Derrick Stolee Signed-off-by: Junio C Hamano --- attr.c | 1 - 1 file changed, 1 deletion(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index ca8be46e8e..9849106627 100644 --- a/attr.c +++ b/attr.c @@ -168,7 +168,6 @@ static void all_attrs_init(struct attr_hashmap *map, struct attr_check *check) check->all_attrs_nr = size; hashmap_for_each_entry(&map->map, &iter, e, - struct attr_hash_entry, ent /* member name */) { const struct git_attr *a = e->value; check->all_attrs[a->attr_nr].attr = a; -- cgit v1.2.3 From 404ab78e39fc74c4eb604b6003642ed264f687a6 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Oct 2019 23:30:42 +0000 Subject: hashmap: remove type arg from hashmap_{get,put,remove}_entry Since these macros already take a `keyvar' pointer of a known type, we can rely on OFFSETOF_VAR to get the correct offset without relying on non-portable `__typeof__' and `offsetof'. Argument order is also rearranged, so `keyvar' and `member' are sequential as they are used as: `keyvar->member' Signed-off-by: Eric Wong Reviewed-by: Derrick Stolee Signed-off-by: Junio C Hamano --- attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index 9849106627..15f0efdf60 100644 --- a/attr.c +++ b/attr.c @@ -103,7 +103,7 @@ static void *attr_hashmap_get(struct attr_hashmap *map, hashmap_entry_init(&k.ent, memhash(key, keylen)); k.key = key; k.keylen = keylen; - e = hashmap_get_entry(&map->map, &k, NULL, struct attr_hash_entry, ent); + e = hashmap_get_entry(&map->map, &k, ent, NULL); return e ? e->value : NULL; } -- cgit v1.2.3 From e2b5038d8793a1d1f92b62dab82acc0d6b7dbcb7 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Oct 2019 23:30:43 +0000 Subject: hashmap_entry: remove first member requirement from docs Comments stating that "struct hashmap_entry" must be the first member in a struct are no longer valid. Suggested-by: Phillip Wood Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- attr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'attr.c') diff --git a/attr.c b/attr.c index 15f0efdf60..e5c951db69 100644 --- a/attr.c +++ b/attr.c @@ -62,7 +62,7 @@ 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 */ -- cgit v1.2.3