#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
static char *_array_err_str = NULL;
enum {
ARRAY_ERRNO,
ARRAY_NEW,
ARRAY_ONITEM
};
enum {
ARRAY_CTYPE_STRING,
ARRAY_CTYPE_STRING_ALLOCED,
ARRAY_CTYPE_INT32,
ARRAY_CTYPE_UINT32,
ARRAY_CTYPE_FLOAT,
ARRAY_CTYPE_DOUBLE
};
#define ARRAY_CAST_STRING_T (char *)
#define ARRAY_CAST_INT32_T *(int *)
#define ARRAY_CAST_UINT32_T *(unsigned int *)
#define ARRAY_CAST_FLOAT_T *(float *)
#define ARRAY_CAST_DOUBLE_T *(double *)
typedef struct {
unsigned index;
const void *value;
unsigned type;
} array_item_t;
typedef struct {
int status;
int count;
array_item_t *items;
} array_t;
array_t *array_new(void) {
array_t *arr;
if ( NULL == (arr = malloc(sizeof(array_t) + 1)) ) {
errno = ENOMEM;
return NULL;
}
if ( NULL == (arr->items = malloc(sizeof(array_item_t) + 1))) {
errno = ENOMEM;
return NULL;
}
arr->status = ARRAY_NEW;
arr->count = 0;
return arr;
}
int array_geterrno(void) {
if (errno)
return errno;
return -1;
}
bool array_iserror(bool print) {
if (errno && NULL != _array_err_str) {
switch(print) {
case false: break;
case true:
perror((const char *)_array_err_str); break;
}
_array_err_str = NULL;
return true;
}
return false;
}
bool array_addvalue(
array_t *arr, const void *value, int type)
{
array_item_t *items;
unsigned idx = 0;
if (NULL == arr) {
errno = EINVAL;
_array_err_str = "array_addvalue";
return false;
}
if (!arr->status)
return false;
if ( NULL == (items = realloc(arr->items, (sizeof *items)*(arr->count + 1))) ) {
arr->status = ARRAY_ERRNO;
errno = ENOMEM;
return false;
}
idx = arr->count++;
arr->items = items;
arr->items[idx].type = type;
arr->items[idx].value = value;
arr->items[idx].index = idx;
arr->status = ARRAY_ONITEM;
return true;
}
bool array_addstring(
array_t *arr, const char *string, bool allocate)
{
if (NULL == arr) {
errno = EINVAL;
_array_err_str = "array_addstring";
return false;
}
return array_addvalue(arr,
(allocate && NULL != string) ? strdup(string) : string,
(allocate && NULL != string) ? ARRAY_CTYPE_STRING_ALLOCED : ARRAY_CTYPE_STRING);
}
bool array_addnumber(
array_t *arr, void *number, int type)
{
if (NULL == arr) {
errno = EINVAL;
_array_err_str = "array_addnumber";
return false;
}
return array_addvalue(arr, number, type);
}
bool array_show(
array_t *arr)
{
unsigned i = 0;
if (NULL == arr) {
errno = EINVAL;
_array_err_str = "array_show";
return false;
}
if (!arr->status) {
errno = EINVAL;
_array_err_str = "array_show";
return false;
}
do {
switch(arr->items[i].type) {
case ARRAY_CTYPE_STRING:
case ARRAY_CTYPE_STRING_ALLOCED:
if( NULL != arr->items[i].value)
printf("array[%u] = \"%s\" \n",i,
ARRAY_CAST_STRING_T arr->items[i].value);
else
printf("array[%u] = NULL \n",i);
break;
case ARRAY_CTYPE_INT32:
printf("array[%u] = %i \n",i,
ARRAY_CAST_INT32_T arr->items[i].value);
break;
case ARRAY_CTYPE_UINT32:
printf("array[%u] = %u \n",i,
ARRAY_CAST_UINT32_T arr->items[i].value);
break;
case ARRAY_CTYPE_FLOAT:
printf("array[%u] = %f \n",i,
ARRAY_CAST_FLOAT_T arr->items[i].value);
break;
case ARRAY_CTYPE_DOUBLE:
printf("array[%u] = %f \n",i,
ARRAY_CAST_DOUBLE_T arr->items[i].value);
break;
}
} while(++i < arr->count);
if (i)
return true;
return false;
}
const void *array_getvalue(
array_t *arr, unsigned idx)
{
if (NULL == arr) {
errno = EINVAL;
_array_err_str = "array_getvalue";
return false;
}
if ( 2 != arr->status || arr->count < 0)
return NULL;
if ( idx < arr->count && arr >= 0) {
return arr->items[idx].value;
}
return NULL;
}
bool array_delvalue(
array_t *arr, unsigned idx)
{
array_t *cpy;
unsigned i = 0;
if (NULL == arr) {
errno = EINVAL;
_array_err_str = "array_delvalue";
return false;
}
if ( 2 != arr->status || arr->count < 0)
return false;
if ( idx < arr->count && idx >= 0) {
cpy = array_new();
do {
if ( idx != arr->items[i].index)
array_addvalue(cpy,
arr->items[i].value, arr->items[i].type);
} while(++i < arr->count);
free(arr->items);
free(arr);
*arr = *cpy;
return true;
}
return false;
}
int array_getcount(
array_t *arr) {
if (NULL == arr) {
errno = EINVAL;
_array_err_str = "array_getcount";
return 0;
}
if (!arr->count) {
errno = EINVAL;
_array_err_str = "array_getcount";
return 0;
}
return arr->count;
}
bool array_free(
array_t *arr)
{
unsigned i = 0;
if (NULL == arr) {
errno = EINVAL;
_array_err_str = "array_free";
return false;
}
if (!arr->items) {
errno = EINVAL;
_array_err_str = "array_free";
free(arr);
arr = NULL;
return false;
}
if (arr->count) {
do {
if ( arr->items[i].type == ARRAY_CTYPE_STRING_ALLOCED)
free((void *)arr->items[i].value);
} while(++i < arr->count);
}
free(arr->items);
free(arr);
return true;
}
int main(void)
{
array_t *arr;
int int_val;
float float_val, float_val_ret;
double double_val, double_val_ret;
char *string_a = "string_a string_a string_a";
char *string_b = "string_b string_b string_b";
arr = array_new();
int_val = 10;
float_val = 10.567889;
double_val = 1444444448.144449;
array_addnumber(arr,
&int_val, ARRAY_CTYPE_INT32);
array_addnumber(arr,
&float_val, ARRAY_CTYPE_FLOAT);
array_addnumber(arr,
&double_val, ARRAY_CTYPE_DOUBLE);
array_addstring(arr, string_a, false);
array_addstring(arr, string_b, false);
array_addstring(arr, NULL, false);
array_show(arr);
array_delvalue(arr, 3);
array_show(arr);
puts("---");
float_val_ret = ARRAY_CAST_FLOAT_T array_getvalue(arr, 1);
printf("%f \n", float_val);
puts("---");
double_val_ret = ARRAY_CAST_DOUBLE_T array_getvalue(arr, 1);
printf("%f \n", double_val);
puts("---");
return 0;
}