You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
1.3 KiB
69 lines
1.3 KiB
#include "../git-compat-util.h" |
|
|
|
/* |
|
* A merge sort implementation, simplified from the qsort implementation |
|
* by Mike Haertel, which is a part of the GNU C Library. |
|
* Added context pointer, safety checks and return value. |
|
*/ |
|
|
|
static void msort_with_tmp(void *b, size_t n, size_t s, |
|
int (*cmp)(const void *, const void *, void *), |
|
char *t, void *ctx) |
|
{ |
|
char *tmp; |
|
char *b1, *b2; |
|
size_t n1, n2; |
|
|
|
if (n <= 1) |
|
return; |
|
|
|
n1 = n / 2; |
|
n2 = n - n1; |
|
b1 = b; |
|
b2 = (char *)b + (n1 * s); |
|
|
|
msort_with_tmp(b1, n1, s, cmp, t, ctx); |
|
msort_with_tmp(b2, n2, s, cmp, t, ctx); |
|
|
|
tmp = t; |
|
|
|
while (n1 > 0 && n2 > 0) { |
|
if (cmp(b1, b2, ctx) <= 0) { |
|
memcpy(tmp, b1, s); |
|
tmp += s; |
|
b1 += s; |
|
--n1; |
|
} else { |
|
memcpy(tmp, b2, s); |
|
tmp += s; |
|
b2 += s; |
|
--n2; |
|
} |
|
} |
|
if (n1 > 0) |
|
memcpy(tmp, b1, n1 * s); |
|
memcpy(b, t, (n - n2) * s); |
|
} |
|
|
|
int git_qsort_s(void *b, size_t n, size_t s, |
|
int (*cmp)(const void *, const void *, void *), void *ctx) |
|
{ |
|
const size_t size = st_mult(n, s); |
|
char buf[1024]; |
|
|
|
if (!n) |
|
return 0; |
|
if (!b || !cmp) |
|
return -1; |
|
|
|
if (size < sizeof(buf)) { |
|
/* The temporary array fits on the small on-stack buffer. */ |
|
msort_with_tmp(b, n, s, cmp, buf, ctx); |
|
} else { |
|
/* It's somewhat large, so malloc it. */ |
|
char *tmp = xmalloc(size); |
|
msort_with_tmp(b, n, s, cmp, tmp, ctx); |
|
free(tmp); |
|
} |
|
return 0; |
|
}
|
|
|