diff --git a/libc/Makefile b/libc/Makefile
index 922b3f6a..34d40281 100644
--- a/libc/Makefile
+++ b/libc/Makefile
@@ -171,6 +171,7 @@ stdlib/mblen.o \
stdlib/mbstowcs.o \
stdlib/mbtowc.o \
stdlib/qsort.o \
+stdlib/qsort_r.o \
stdlib/strtod.o \
stdlib/strtof.o \
stdlib/strtold.o \
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 6d039f21..f2d38f3a 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -106,6 +106,7 @@ int mkstemp(char*);
char* mktemp(char* templ);
int on_exit(void (*function)(int, void*), void* arg);
void qsort(void*, size_t, size_t, int (*)(const void*, const void*));
+void qsort_r(void*, size_t, size_t, int (*)(const void*, const void*, void*), void*);
int rand(void);
void* realloc(void*, size_t);
char* realpath(const char* __restrict, char* __restrict);
diff --git a/libc/stdlib/qsort.cpp b/libc/stdlib/qsort.cpp
index 9390443f..6421d576 100644
--- a/libc/stdlib/qsort.cpp
+++ b/libc/stdlib/qsort.cpp
@@ -1,6 +1,6 @@
/*******************************************************************************
- Copyright(C) Jonas 'Sortie' Termansen 2012.
+ Copyright(C) Jonas 'Sortie' Termansen 2012, 2014.
This file is part of the Sortix C Library.
@@ -18,7 +18,7 @@
along with the Sortix C Library. If not, see .
stdlib/qsort.cpp
- Utility functions related to sorting and sorted data.
+ Sort an array.
*******************************************************************************/
@@ -26,36 +26,16 @@
#include
#include
-// TODO: This is an ugly hack!
-static void memswap(uint8_t* a, uint8_t* b, size_t size)
+static int compare_wrapper(const void* a, const void* b, void* arg)
{
- uint8_t* tmp = (uint8_t*) malloc(size);
- if ( !tmp ) { abort(); }
- memcpy(tmp, a, size);
- memcpy(a, b, size);
- memcpy(b, tmp, size);
- free(tmp);
+ return ((int (*)(const void*, const void*)) arg)(a, b);
}
-// TODO: This is just a quick and dirty insertion sort. It'd be nice to have a
-// good old quick sort here soon. Combined with the slow memswap above, this
-// results in a very slow sorting algorithm.
-extern "C" void qsort(void* base, size_t nmemb, size_t size,
- int (* compare)(const void*, const void*))
+extern "C"
+void qsort(void* base_ptr,
+ size_t num_elements,
+ size_t element_size,
+ int (*compare)(const void*, const void*))
{
- uint8_t* buf = (uint8_t*) base;
- for ( size_t i = 0; i < nmemb; i++ )
- {
- for ( size_t c = i; c; c-- )
- {
- size_t currentoff = c * size;
- uint8_t* current = buf + currentoff;
- size_t p = c-1;
- size_t prevoff = p * size;
- uint8_t* prev = buf + prevoff;
- int cmp = compare(prev, current);
- if ( cmp <= 0 ) { break; }
- memswap(prev, current, size);
- }
- }
+ qsort_r(base_ptr, num_elements, element_size, compare_wrapper, (void*) compare);
}
diff --git a/libc/stdlib/qsort_r.cpp b/libc/stdlib/qsort_r.cpp
new file mode 100644
index 00000000..a3ee4f97
--- /dev/null
+++ b/libc/stdlib/qsort_r.cpp
@@ -0,0 +1,64 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012, 2014.
+
+ This file is part of the Sortix C Library.
+
+ The Sortix C Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or (at your
+ option) any later version.
+
+ The Sortix C Library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with the Sortix C Library. If not, see .
+
+ stdlib/qsort_r.cpp
+ Sort an array.
+
+*******************************************************************************/
+
+#include
+#include
+#include
+
+static void memswap(uint8_t* a, uint8_t* b, size_t size)
+{
+ uint8_t tmp;
+ for ( size_t i = 0; i < size; i++ )
+ {
+ tmp = a[i];
+ a[i] = b[i];
+ b[i] = tmp;
+ }
+}
+
+// TODO: This is just a quick and dirty insertion sort. It'd be nice to have a
+// good old quick sort here soon.
+extern "C"
+void qsort_r(void* base_ptr,
+ size_t num_elements,
+ size_t element_size,
+ int (*compare)(const void*, const void*, void*),
+ void* arg)
+{
+ uint8_t* base = (uint8_t*) base_ptr;
+ for ( size_t i = 0; i < num_elements; i++ )
+ {
+ for ( size_t c = i; c; c-- )
+ {
+ size_t currentoff = c * element_size;
+ uint8_t* current = base + currentoff;
+ size_t p = c-1;
+ size_t prevoff = p * element_size;
+ uint8_t* prev = base + prevoff;
+ int cmp = compare(prev, current, arg);
+ if ( cmp <= 0 ) { break; }
+ memswap(prev, current, element_size);
+ }
+ }
+}