I am making C dynamic array library, kind of. Note that I'm doing it for fun in my free time, so please do not recommend million of existing libraries.
I started implementing sorting. The array is of arbitrary element size, defined as struct:
typedef struct {
//[PRIVATE] Pointer to array data
void *array;
//[READONLY] How many elements are in array
size_t length;
//[PRIVATE] How many elements can further fit in array (allocated memory)
size_t size;
//[PRIVATE] Bytes per element
size_t elm_size;
} Array;
I originally prepared this to start with the sort function:
/** sorts the array using provided comparator method
* if metod not provided, memcmp is used
* Comparator signature
* int my_comparator ( const void * ptr1, const void * ptr2, size_t type_size );
**/
void array_sort(Array* a, int(*comparator)(const void*, const void*, size_t)) {
if(comparator == NULL)
comparator = &memcmp;
// Sorting algorithm should follow
}
However I learned about qsort
:
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
Apparently, I could just pass my internal array to qsort
. I could just call that:
qsort (a->array, a->length, a->elm_size, comparator_callback);
But there's a catch - qsort
's comparator signature reads as:
int (*compar)(const void*,const void*)
While memcmp
's signature is:
int memcmp ( const void * ptr1, const void * ptr2, size_t type_size );
The element size is missing in qsort
's callback, meaning I can no longer have a generic comparator function when NULL
is passed as callback. I could manually generate comparators up to X bytes of element size, but that sounds ugly.
Can I use qsort
(or other sorting built-in) along with memcpy
? Or do I have to chose between built-in comparator and built-in sorting function?
A non-thread-safe way is use private global variable to pass the size.
static size_t compareSize = 0;
int defaultComparator(const void *p1, const void *p2) {
return memcmp(p1, p2, compareSize);
}
void array_sort(Array* a, int(*comparator)(const void*, const void*, size_t)) {
if(comparator == NULL) {
compareSize = a->elm_size;
comparator = &defaultComparator;
}
// Sorting algorithm should follow
}
You can make it thread-safe by make compareSize
thread-local variable (__thread
)