#ifndef ARRAY_HEADER
#define ARRAY_HEADER

struct array;
typedef struct array Array;

#define array_new(x) array_new_(x,__FILE__,__LINE__)
Array *array_new_(int initialSize, char *file, int line);

void array_setup(Array *a, int (*cmp)(void **, void **), void (*free)(void **));
/* 
 * The comparrison function must accept 2 (object **)'s it should 
 * then use the value of them for the comparrison, example:
 * 
 * struct A {
 *   char *val;
 * };
 *
 * int cmp(A **a, A **b) {
 *   return strcmp( (*a)->val, (*b)->val );
 * }
 *
 */
void array_setup_compare(Array *a, int (*cmp)(void **, void **));
/*
 * The free function should accept an (object **) it should
 * free the object and set it to NULL, example:
 *
 * void free(A **a) {
 *   free((*a)->val);
 *   free(*a);
 *   *a = NULL;
 * }
 *
 */
void array_setup_free(Array *a, void (*free)(void **));

/* defaults */
int a_strcmp(void **a, void **b);
int a_strcmpnc(void **a, void **b);
int a_memcmp(void **a, void **b);
void a_free(void **a);

void array_clear(Array *a);
#define array_free(a) array_free_(a,__FILE__,__LINE__)
void array_free_(Array **a, char *file, int line);

typedef enum {
	ARRAY_DEFAULT	= 0x0,
	ARRAY_SORTED	= 0x1,
	ARRAY_NODUPS	= 0x2
} ARRAY_MODE;

void array_mode(Array *a, ARRAY_MODE mode);
void array_block(Array *a, int block);

int array_items(Array *a);

int array_add(Array *a, void *item);
#define array_add_i(a,p,i) array_add_i_(a,p,i,__FILE__,__LINE__)
int array_add_i_(Array *a, void *item, int index, char *file, int line); //does not obey NODUPS

int array_del(Array *a, void *item);
int array_del_i(Array *a, int index);

void *array_get(Array *a, int index);
int array_find(Array *a, void *item);

void array_sort(Array *a);
void array_reverse(Array *a);

#endif
