WONKY



LOG | FILES | OVERVIEW


#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