LibC: Implement qsort_r

This is not really required by anything but i've seen few ports
optionally use it if available. This was trivial to implement so why not
add it :^)
This commit is contained in:
2026-07-05 01:55:57 +03:00
parent 58c58bcccf
commit 3e16e69602
2 changed files with 17 additions and 6 deletions

View File

@@ -84,6 +84,7 @@ int posix_openpt(int oflag);
char* ptsname(int fildes); char* ptsname(int fildes);
int putenv(char* string); int putenv(char* string);
void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*)); void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*));
void qsort_r(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*, void*), void* arg);
int rand(void); int rand(void);
int rand_r(unsigned* seed); int rand_r(unsigned* seed);
long random(void); long random(void);

View File

@@ -566,7 +566,8 @@ struct qsort_pair
uint8_t* gt; uint8_t* gt;
}; };
static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*)) template<typename... Args>
static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*, Args...), Args... args)
{ {
uint8_t* pivot = pbegin + (pend - pbegin) / width / 2 * width; uint8_t* pivot = pbegin + (pend - pbegin) / width / 2 * width;
@@ -576,7 +577,7 @@ static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width,
while (eq < gt) while (eq < gt)
{ {
const int comp = (eq == pivot) ? 0 : compar(eq, pivot); const int comp = (eq == pivot) ? 0 : compar(eq, pivot, args...);
if (comp < 0) if (comp < 0)
{ {
@@ -602,13 +603,14 @@ static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width,
return { lt, gt }; return { lt, gt };
} }
static void qsort_impl(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*)) template<typename... Args>
static void qsort_impl(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*, Args...), Args... args)
{ {
if (pbegin + width >= pend) if (pbegin + width >= pend)
return; return;
auto [lt, gt] = qsort_partition(pbegin, pend, width, compar); auto [lt, gt] = qsort_partition(pbegin, pend, width, compar, args...);
qsort_impl(pbegin, lt, width, compar); qsort_impl(pbegin, lt, width, compar, args...);
qsort_impl(gt, pend, width, compar); qsort_impl(gt, pend, width, compar, args...);
} }
void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*)) void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*))
@@ -619,6 +621,14 @@ void qsort(void* base, size_t nel, size_t width, int (*compar)(const void*, cons
qsort_impl(pbegin, pbegin + nel * width, width, compar); qsort_impl(pbegin, pbegin + nel * width, width, compar);
} }
void qsort_r(void* base, size_t nel, size_t width, int (*compar)(const void*, const void*, void*), void* arg)
{
if (width == 0 || nel <= 1)
return;
uint8_t* pbegin = static_cast<uint8_t*>(base);
qsort_impl(pbegin, pbegin + nel * width, width, compar, arg);
}
// Constants and algorithm from https://en.wikipedia.org/wiki/Permuted_congruential_generator // Constants and algorithm from https://en.wikipedia.org/wiki/Permuted_congruential_generator
static constexpr uint64_t s_rand_multiplier = 6364136223846793005; static constexpr uint64_t s_rand_multiplier = 6364136223846793005;