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); + } + } +}