diff options
author | Russell Belfer <rb@github.com> | 2013-03-08 16:39:57 -0800 |
---|---|---|
committer | Russell Belfer <rb@github.com> | 2013-03-08 16:39:57 -0800 |
commit | e40f1c2d23c3758968df94a17831ec5432ae6988 (patch) | |
tree | a634eb49add884f11c576b6a956b8b9e1d87357b /src/util.c | |
parent | 9bea03ce776ed864b0556815d94d71d300ac1da3 (diff) | |
download | libgit2-e40f1c2d23c3758968df94a17831ec5432ae6988.tar.gz |
Make tree iterator handle icase equivalence
There is a serious bug in the previous tree iterator implementation.
If case insensitivity resulted in member elements being equivalent
to one another, and those member elements were trees, then the
children of the colliding elements would be processed in sequence
instead of in a single flattened list. This meant that the tree
iterator was not truly acting like a case-insensitive list.
This completely reworks the tree iterator to manage lists with
case insensitive equivalence classes and advance through the items
in a unified manner in a single sorted frame.
It is possible that at a future date we might want to update this
to separate the case insensitive and case sensitive tree iterators
so that the case sensitive one could be a minimal amount of code
and the insensitive one would always know what it needed to do
without checking flags.
But there would be so much shared code between the two, that I'm
not sure it that's a win. For now, this gets what we need.
More tests are needed, though.
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/util.c b/src/util.c index 059108ece..561288f72 100644 --- a/src/util.c +++ b/src/util.c @@ -607,3 +607,33 @@ size_t git__unescape(char *str) return (pos - str); } + +#if defined(GIT_WIN32) || defined(BSD) +typedef struct { + git__qsort_r_cmp cmp; + void *payload; +} git__qsort_r_glue; + +static int GIT_STDLIB_CALL git__qsort_r_glue_cmp( + void *payload, const void *a, const void *b) +{ + git__qsort_r_glue *glue = payload; + return glue->cmp(a, b, glue->payload); +} +#endif + +void git__qsort_r( + void *els, size_t nel, size_t elsize, git__qsort_r_cmp cmp, void *payload) +{ +#if defined(GIT_WIN32) + git__qsort_r_glue glue = { cmp, payload }; + qsort_s(els, nel, elsize, git__qsort_r_glue_cmp, &glue); +#else +#if defined(BSD) + git__qsort_r_glue glue = { cmp, payload }; + qsort_r(els, nel, elsize, &glue, git__qsort_r_glue_cmp); +#else + qsort_r(els, nel, elsize, cmp, payload); +#endif +#endif +} |