Re: [PATCH 15/16] commit-reach: make can_all_from_reach... linear
- From
Derrick Stolee <stolee@gmail.com>
- Date
- Oct 15, 2018, 15:31 UTC
- Message-ID
- <0cd89b69-4b65-f961-a025-c74851f8c999@gmail.com>
- In-Reply-To
- <c141fb44-904f-e8b6-119f-7d2d6bcfd81a@web.de>
On 10/14/2018 10:29 AM, René Scharfe wrote:
Show 31 quoted lines
> It still has some repetition, converted code is a bit longer than the > current one, and I don't know how to build a Coccinelle rule that would > do that conversion. > > Looked for a possibility to at least leave QSORT call-sites alone by > enhancing that macro, but didn't find any. Found a few websites > showing off mindblowing macros, thouhg, this one in particular: > > https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms > > Anyway, drove the generative approach a bit further, and came up with > the new DEFINE_SORT below. I'm unsure about the name; perhaps it should > be called DEFINE_SORT_BY_COMPARE_FUNCTION_BODY, but that's a bit long. > It handles casts and const attributes behind the scenes and avoids > repetition, but looks a bit weird, as it is placed where a function > signature would go. > > Apart from that the macro is simple and doesn't use any tricks or > added checks. It just sets up boilerplate functions to offer type-safe > sorting. > > diffcore-rename.c and refs/packed-backend.c receive special treatment in > the patch because their compare functions are used outside of sorting as > well. I made them take typed pointers nevertheless and used them from > DEFINE_SORT; the wrapper generated by that macro is supposed to be > private. Given that such reuse is rare and I think we don't need a way > to make it public. > > What do y'all think about this direction? > > ---
[snip]
Show 23 quoted lines
> diff --git a/git-compat-util.h b/git-compat-util.h
> index 5f2e90932f..491230fc57 100644
> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -1066,6 +1066,21 @@ static inline void sane_qsort(void *base, size_t nmemb, size_t size,
> qsort(base, nmemb, size, compar);
> }
>
> +#define DECLARE_SORT(scope, name, elemtype) \
> +scope void name(elemtype, size_t)
> +
> +#define DEFINE_SORT(scope, name, elemtype, one, two) \
> +static int name##_compare(const elemtype, const elemtype); \
> +static int name##_compare_void(const void *a, const void *b) \
> +{ \
> + return name##_compare(a, b); \
> +} \
> +scope void name(elemtype base, size_t nmemb) \
> +{ \
> + QSORT(base, nmemb, name##_compare_void); \
> +} \
> +static int name##_compare(const elemtype one, const elemtype two)
> +Since you were worried about the "private" name of the compare function, maybe split this macro into two: DEFINE_COMPARE and DEFINE_SORT. Then, if someone wants direct access to the compare function, they could use the DEFINE_COMPARE to ensure the typing is correct, and use QSORT as normal with name##_compare_void.
As I think about this, I think this is less of a problem than is worth this split. The commit-slab definitions generate a lot of methods using the "name##" convention, so perhaps we should just trust developers using the macros to look up the macro definition or similar examples. In that sense, including a conversion that consumes the compare function directly can be a signpost for future callers.
I would say that maybe the times where you need to do something special should be pulled out into their own patches, so we can call attention to them directly.
[snip]
Show 22 quoted lines
> diff --git a/midx.c b/midx.c
> index 713d6f9dde..4407db7949 100644
> --- a/midx.c
> +++ b/midx.c
> @@ -419,10 +419,8 @@ struct pack_pair {
> char *pack_name;
> };
>
> -static int pack_pair_compare(const void *_a, const void *_b)
> +DEFINE_SORT(static, sort_by_pack_name, struct pack_pair *, a, b)
> {
> - struct pack_pair *a = (struct pack_pair *)_a;
> - struct pack_pair *b = (struct pack_pair *)_b;
> return strcmp(a->pack_name, b->pack_name);
> }
>
> @@ -438,7 +436,7 @@ static void sort_packs_by_name(char **pack_names, uint32_t nr_packs, uint32_t *p
> pairs[i].pack_name = pack_names[i];
> }
>
> - QSORT(pairs, nr_packs, pack_pair_compare);
> + sort_by_pack_name(pairs, nr_packs);I like this "sort_by_" convention..
Show 21 quoted lines
>
> for (i = 0; i < nr_packs; i++) {
> pack_names[i] = pairs[i].pack_name;
> @@ -455,10 +453,8 @@ struct pack_midx_entry {
> uint64_t offset;
> };
>
> -static int midx_oid_compare(const void *_a, const void *_b)
> +DEFINE_SORT(static, sort_midx, struct pack_midx_entry *, a, b)
> {
> - const struct pack_midx_entry *a = (const struct pack_midx_entry *)_a;
> - const struct pack_midx_entry *b = (const struct pack_midx_entry *)_b;
> int cmp = oidcmp(&a->oid, &b->oid);
>
> if (cmp)
> @@ -573,7 +569,7 @@ static struct pack_midx_entry *get_sorted_entries(struct multi_pack_index *m,
> }
> }
>
> - QSORT(entries_by_fanout, nr_fanout, midx_oid_compare);
> + sort_midx(entries_by_fanout, nr_fanout);...but it isn't followed here. Perhaps "sort_by_oid"?
Thanks, -Stolee