/*
 * This program demonstrates the use of function pointers
 * to provide type-specific functionalities to a generic
 * function.
 *
 * The quicksort function implements the quicksort algorithm
 * with a custom comparator function as well as a custom
 * data type size.
 *
 * The custom comparator is a function pointer parameter.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void swap(size_t size, void *x, void *y){
	void *tmp = malloc(size);
	memcpy(tmp,x,size);
	memcpy(x,y,size);
	memcpy(y,tmp,size);
	free(tmp);
}

void quicksort(void *array, size_t size, 
               int left, int right, 
               void *(*cmp)(void *, void *)){
	void *pivot = array+(left*size);
	int last=left;
	void *l;
	int i;
	if (left>=right) return;
	for(l=array+((left+1)*size); 
	    l<=(void *)(array+(right*size)); 
			l+=size) {
		if (((int)(*cmp)(l, array+(left*size)))<0) {
			swap(size,l,pivot+size);
			pivot+=size;
			last++;
		}
	}
	swap(size,array+(left*size),pivot);
	quicksort(array,size,left,last-1,cmp);
	quicksort(array,size,last+1,right,cmp);
}

int chrcmp(char *a, char *b){
	if (*a<*b) return -1;
	else if (*a==*b) return 0;
	else return 1;
}

int intcmp(int *a, int *b){
	return *b-*a;
}


int main(int argc, char **argv){
	int i;
	int array[8] = { 2, 5, 3, 2, 1, 4, 0, 7 };
	char *string;
	if (argc>1) {		
		quicksort((void **)argv[1], sizeof(char), 
		          0, strlen(argv[1])-1, 
		          (void *(*)(void *, void *)) (chrcmp));
		printf("%s\n", argv[1]);
	}
	quicksort((void **)array, sizeof(int), 0, 7, 
	          (void *(*)(void *, void *)) (intcmp));
	for(i=0; i<8; i++){
		printf("%d", array[i]);
	}
	printf("\n");
}
