diff --git a/userspace/libraries/LibC/include/stdlib.h b/userspace/libraries/LibC/include/stdlib.h index aecf2854..b5c920b8 100644 --- a/userspace/libraries/LibC/include/stdlib.h +++ b/userspace/libraries/LibC/include/stdlib.h @@ -84,6 +84,7 @@ int posix_openpt(int oflag); char* ptsname(int fildes); int putenv(char* string); 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_r(unsigned* seed); long random(void); diff --git a/userspace/libraries/LibC/stdlib.cpp b/userspace/libraries/LibC/stdlib.cpp index 188f6421..d69fb6cd 100644 --- a/userspace/libraries/LibC/stdlib.cpp +++ b/userspace/libraries/LibC/stdlib.cpp @@ -566,7 +566,8 @@ struct qsort_pair uint8_t* gt; }; -static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*)) +template +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; @@ -576,7 +577,7 @@ static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width, 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) { @@ -602,13 +603,14 @@ static qsort_pair qsort_partition(uint8_t* pbegin, uint8_t* pend, size_t width, return { lt, gt }; } -static void qsort_impl(uint8_t* pbegin, uint8_t* pend, size_t width, int (*compar)(const void*, const void*)) +template +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) return; - auto [lt, gt] = qsort_partition(pbegin, pend, width, compar); - qsort_impl(pbegin, lt, width, compar); - qsort_impl(gt, pend, width, compar); + auto [lt, gt] = qsort_partition(pbegin, pend, width, compar, args...); + qsort_impl(pbegin, lt, width, compar, args...); + qsort_impl(gt, pend, width, compar, args...); } 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); } +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(base); + qsort_impl(pbegin, pbegin + nel * width, width, compar, arg); +} + // Constants and algorithm from https://en.wikipedia.org/wiki/Permuted_congruential_generator static constexpr uint64_t s_rand_multiplier = 6364136223846793005;