libc: Add qsort (with a test!!)

This commit is contained in:
apio 2022-11-06 17:16:08 +01:00
parent 44815b08c7
commit 1025248cc7
4 changed files with 95 additions and 4 deletions

View File

@ -113,7 +113,8 @@ extern "C"
/* Runs a shell command. */
int system(const char* command);
void qsort(void*, size_t, size_t, int (*)(const void*, const void*)); // Not implemented.
/* Sorts the array pointed to by base of nmemb items of the specified size using the comparison function compar. */
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
void* bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*)); // Not implemented.

View File

@ -77,6 +77,51 @@ template <typename Arg, typename Struct> static inline Struct common_div(Arg a,
return result;
}
static void qswap(void* ptr1, void* ptr2, size_t size)
{
char* x = (char*)ptr1;
char* y = (char*)ptr2;
while (size--)
{
char t = *x;
*x = *y;
*y = t;
x += 1;
y += 1;
}
}
static size_t partition(void* base, size_t start, size_t end, size_t size, int (*compar)(const void*, const void*))
{
auto atindex = [&base, &size](size_t index) { return (void*)((char*)base + (index * size)); };
void* pivot = atindex(end);
size_t i = (start - 1);
for (size_t j = start; j <= end - 1; j++)
{
if (compar(atindex(j), pivot) < 0)
{
i++;
qswap(atindex(i), atindex(j), size);
}
}
qswap(atindex(i + 1), pivot, size);
return i + 1;
}
static void quicksort(void* base, size_t start, size_t end, size_t size, int (*compar)(const void*, const void*))
{
if (start < end)
{
size_t pivot = partition(base, start, end, size, compar);
quicksort(base, start, pivot - 1, size, compar);
quicksort(base, pivot + 1, end, size, compar);
}
}
extern "C"
{
__lc_noreturn void abort()
@ -175,9 +220,9 @@ extern "C"
return status;
}
void qsort(void*, size_t, size_t, int (*)(const void*, const void*))
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*))
{
NOT_IMPLEMENTED("qsort");
quicksort(base, 0, nmemb - 1, size, compar);
}
void* bsearch(const void*, const void*, size_t, size_t, int (*)(const void*, const void*))

View File

@ -25,6 +25,7 @@ DEFINE_TEST(srand);
DEFINE_TEST(malloc);
DEFINE_TEST(calloc);
DEFINE_TEST(mktemp);
DEFINE_TEST(qsort);
int main()
{
@ -53,4 +54,5 @@ int main()
RUN_TEST(malloc);
RUN_TEST(calloc);
RUN_TEST(mktemp);
RUN_TEST(qsort);
}

View File

@ -164,3 +164,46 @@ DEFINE_TEST(mktemp)
TEST_SUCCESS();
}
static int compare_char(const void* p1, const void* p2)
{
const char* c1 = (const char*)p1;
const char* c2 = (const char*)p2;
if (*c1 < *c2) return -1;
if (*c1 > *c2) return 1;
return 0;
}
static int compare_int(const void* p1, const void* p2)
{
const int* c1 = (const int*)p1;
const int* c2 = (const int*)p2;
if (*c1 < *c2) return -1;
if (*c1 > *c2) return 1;
return 0;
}
DEFINE_TEST(qsort)
{
START_TEST(qsort);
char unsorted[] = "elacbkdjf";
const char sorted[] = "abcdefjkl";
qsort(unsorted, 9, sizeof(char), compare_char);
int rc = memcmp(sorted, unsorted, 9);
EXPECT_EQ(rc, 0);
int unsorted2[] = {1500, 45, 3, 11, 41, 90, 6, 32, 5, 76};
const int sorted2[] = {3, 5, 6, 11, 32, 41, 45, 76, 90, 1500};
qsort(unsorted2, 10, sizeof(int), compare_int);
rc = memcmp(unsorted2, sorted2, 10);
EXPECT_EQ(rc, 0);
TEST_SUCCESS();
}