Skip to content

Commit 845a200

Browse files
daor-oticfriedt
authored andcommitted
libc: minimal: qsort remove callback cast in call of qsort_r
Remove the cast of the two parameter compare function used by qsort, to the three parameter callback function used by qsort_r, in order to ensure compatibility with other toolchains, even those off-tree. Fixes #42870 Signed-off-by: Danny Oerndrup <[email protected]>
1 parent 89cc06e commit 845a200

File tree

2 files changed

+54
-20
lines changed

2 files changed

+54
-20
lines changed

lib/libc/minimal/include/stdlib.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ void *bsearch(const void *key, const void *array,
3232

3333
void qsort_r(void *base, size_t nmemb, size_t size,
3434
int (*compar)(const void *, const void *, void *), void *arg);
35+
void qsort(void *base, size_t nmemb, size_t size,
36+
int (*compar)(const void *, const void *));
3537

3638
#define EXIT_SUCCESS 0
3739
#define EXIT_FAILURE 1
@@ -63,14 +65,6 @@ static inline long long llabs(long long __n)
6365
return (__n < 0LL) ? -__n : __n;
6466
}
6567

66-
static inline void qsort(void *base, size_t nmemb, size_t size,
67-
int (*compar)(const void *, const void *))
68-
{
69-
typedef int (*compar3)(const void *, const void *, void *);
70-
71-
qsort_r(base, nmemb, size, (compar3)compar, NULL);
72-
}
73-
7468
#ifdef __cplusplus
7569
}
7670
#endif

lib/libc/minimal/source/stdlib/qsort.c

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66

77
#include <stddef.h>
88
#include <stdint.h>
9+
#include <stdlib.h>
910
#include <sys/types.h>
1011
#include <sys/util.h>
1112

12-
typedef int (*comp3_t)(const void *, const void *, void *);
13-
1413
/*
1514
* Normally parent is defined parent(k) = floor((k-1) / 2) but we can avoid a
1615
* divide by noticing that floor((k-1) / 2) = ((k - 1) >> 1).
@@ -32,7 +31,25 @@ typedef int (*comp3_t)(const void *, const void *, void *);
3231

3332
#define A(k) ((uint8_t *)base + size * (k))
3433

35-
static void sift_down(void *base, int start, int end, size_t size, comp3_t comp, void *comp_arg)
34+
struct qsort_comp {
35+
bool has3;
36+
void *arg;
37+
union {
38+
int (*comp2)(const void *a, const void *b);
39+
int (*comp3)(const void *a, const void *b, void *arg);
40+
};
41+
};
42+
43+
static inline int compare(struct qsort_comp *cmp, void *a, void *b)
44+
{
45+
if (cmp->has3) {
46+
return cmp->comp3(a, b, cmp->arg);
47+
}
48+
49+
return cmp->comp2(a, b);
50+
}
51+
52+
static void sift_down(void *base, int start, int end, size_t size, struct qsort_comp *cmp)
3653
{
3754
int root;
3855
int child;
@@ -42,12 +59,12 @@ static void sift_down(void *base, int start, int end, size_t size, comp3_t comp,
4259
child = left(root);
4360

4461
/* if root < left */
45-
if (comp(A(swap), A(child), comp_arg) < 0) {
62+
if (compare(cmp, A(swap), A(child)) < 0) {
4663
swap = child;
4764
}
4865

4966
/* right exists and min(A(root),A(left)) < A(right) */
50-
if (right(root) < end && comp(A(swap), A(right(root)), comp_arg) < 0) {
67+
if (right(root) < end && compare(cmp, A(swap), A(right(root))) < 0) {
5168
swap = right(root);
5269
}
5370

@@ -59,28 +76,51 @@ static void sift_down(void *base, int start, int end, size_t size, comp3_t comp,
5976
}
6077
}
6178

62-
static void heapify(void *base, int nmemb, size_t size, comp3_t comp, void *comp_arg)
79+
static void heapify(void *base, int nmemb, size_t size, struct qsort_comp *cmp)
6380
{
6481
int start;
6582

6683
for (start = parent(nmemb - 1); start >= 0; --start) {
67-
sift_down(base, start, nmemb, size, comp, comp_arg);
84+
sift_down(base, start, nmemb, size, cmp);
6885
}
6986
}
7087

71-
static void heap_sort(void *base, int nmemb, size_t size, comp3_t comp, void *comp_arg)
88+
static void heap_sort(void *base, int nmemb, size_t size, struct qsort_comp *cmp)
7289
{
7390
int end;
7491

75-
heapify(base, nmemb, size, comp, comp_arg);
92+
heapify(base, nmemb, size, cmp);
7693

7794
for (end = nmemb - 1; end > 0; --end) {
7895
byteswp(A(end), A(0), size);
79-
sift_down(base, 0, end, size, comp, comp_arg);
96+
sift_down(base, 0, end, size, cmp);
8097
}
8198
}
8299

83-
void qsort_r(void *base, size_t nmemb, size_t size, comp3_t comp, void *arg)
100+
void qsort_r(void *base, size_t nmemb, size_t size,
101+
int (*comp3)(const void *a, const void *b, void *arg), void *arg)
84102
{
85-
heap_sort(base, nmemb, size, comp, arg);
103+
struct qsort_comp cmp = {
104+
.has3 = true,
105+
.arg = arg,
106+
{
107+
.comp3 = comp3
108+
}
109+
};
110+
111+
heap_sort(base, nmemb, size, &cmp);
112+
}
113+
114+
void qsort(void *base, size_t nmemb, size_t size,
115+
int (*comp2)(const void *a, const void *b))
116+
{
117+
struct qsort_comp cmp = {
118+
.has3 = false,
119+
.arg = NULL,
120+
{
121+
.comp2 = comp2
122+
}
123+
};
124+
125+
heap_sort(base, nmemb, size, &cmp);
86126
}

0 commit comments

Comments
 (0)