#ifndef WONKY_ARRAY_C
#define WONKY_ARRAY_C WONKY_ARRAY_C
#include <wonky_array.h>
#define wonky_array_malloc(x) wonky_malloc(x)
#define wonky_array_realloc(x,y) wonky_realloc(x,y)
#define wonky_array_free(x) wonky_free(x)
void* _wonky_arr wonky_arr_alloc(size_t number_of_elements,size_t element_size)
{
struct wonky_array_internals *internals;
if(element_size==0)
return NULL;
/*
allocate one element extra so that wonky_array_last_index
can always give an index for valid memory
*/
internals=wonky_array_malloc(sizeof(struct wonky_array_internals)+element_size*(number_of_elements?number_of_elements:1));
if(internals==NULL)
return NULL;
internals->size=number_of_elements;
internals->capacity=1;
if((element_size*number_of_elements)/element_size!=number_of_elements)
internals->element_size=0;
else
internals->element_size=element_size;
return internals->bytes;
}
void* _wonky_arr wonky_arr_expand(void * _wonky_arr arr,size_t expansion_size)
{
struct wonky_array_internals *internals;
internals=wonky_arr_get_internals(arr);
if(internals->element_size==0 || expansion_size==0) /*check for oom state or no expansion*/
{
return arr;
}else if(internals->size+expansion_size<=internals->size) /*check for size overflow*/
{
internals->element_size=0;/*oom state*/
return arr;
}else
{
if(internals->size+expansion_size<=internals->capacity)
{
internals->size+=expansion_size;
return arr;
}else
{
struct wonky_array_internals *new_internals=NULL;
size_t new_capacity=internals->capacity;
while(new_capacity<internals->size+expansion_size)
{
/*check for overflow*/
if( (new_capacity<<1) > new_capacity &&
(new_capacity<<1)*internals->element_size+sizeof(struct wonky_array_internals)
>
new_capacity*internals->element_size+sizeof(struct wonky_array_internals)
)
{
new_capacity<<=1;
}else
{
internals->element_size=0;/*oom state*/
return arr;
}
}
new_internals=wonky_array_realloc(internals,sizeof(struct wonky_array_internals)+new_capacity*internals->element_size);
if(new_internals==NULL)
{
internals->element_size=0; /*oom state*/
return arr;
}else
{
new_internals->capacity=new_capacity;
new_internals->size+=expansion_size;
return new_internals->bytes;
}
}
}
}
void* _wonky_arr wonky_arr_resize(void * _wonky_arr arr,size_t new_size)
{
struct wonky_array_internals *internals;
internals=wonky_arr_get_internals(arr);
if(new_size>internals->capacity)
{
arr=wonky_arr_expand(arr,new_size-internals->size);
internals=wonky_arr_get_internals(arr);
}
internals->size=new_size;
return arr;
}
void wonky_arr_delete_elements(void * _wonky_arr arr,size_t start_index,size_t number_of_elements)
{
if(arr)
{
struct wonky_array_internals *internals;
internals=wonky_arr_get_internals(arr);
if(start_index<internals->size)
{
if(number_of_elements>internals->size ||
start_index>internals->size-number_of_elements ||
start_index>SIZE_MAX-number_of_elements)
{
internals->size=start_index+1;
return;
}
gmemmove(internals->bytes+start_index*internals->element_size,
internals->bytes+(start_index+number_of_elements)*internals->element_size,
(internals->size-start_index-number_of_elements)*internals->element_size);
internals->size-=number_of_elements;
}
}
}
void wonky_arr_shrink(void * _wonky_arr arr,size_t shrink_size)
{
struct wonky_array_internals *internals;
internals=wonky_arr_get_internals(arr);
if(internals->size<shrink_size)
internals->size=0;
else
internals->size-=shrink_size;
}
void wonky_arr_delete(void * _wonky_arr arr)
{
if(arr)
{
struct wonky_array_internals *internals;
internals=wonky_arr_get_internals(arr);
wonky_array_free(internals);
}
}
size_t wonky_arr_size(void * _wonky_arr arr)
{
return wonky_arr_get_internals(arr)->size;
}
size_t wonky_arr_last_index(void * _wonky_arr arr)
{
struct wonky_array_internals *internals;
internals=wonky_arr_get_internals(arr);
if(internals->size==0)
return 0;
else
return internals->size-1;
}
_Bool wonky_arr_oom(void * _wonky_arr arr)
{
if(arr)
return wonky_arr_get_internals(arr)->element_size==0;
else
return 1;
}
void _wonky_arr * wonky_arr_copy(void * _wonky_arr arr)
{
if(arr)
{
struct wonky_array_internals *internals;
void* ret_arr;
internals=wonky_arr_get_internals(arr);
ret_arr=wonky_arr_alloc(internals->size,internals->element_size);
if(!wonky_arr_oom(ret_arr))
{
gmemmove(ret_arr,internals->bytes,internals->size*internals->element_size);
return ret_arr;
}else
{
return ret_arr;
}
}else
{
return NULL;
}
}
struct wonky_array_internals* wonky_arr_get_internals(void * _wonky_arr arr)
{
return (struct wonky_array_internals*)(arr-offsetof(struct wonky_array_internals,bytes));
}
#endif