ex34 darray bits
This commit is contained in:
parent
312c68e248
commit
64dfc0cb6f
116
lcthw-remnants-2/liblcthw/src/lcthw/darray.c
Normal file
116
lcthw-remnants-2/liblcthw/src/lcthw/darray.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include <lcthw/darray.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
DArray *DArray_create(size_t element_size, size_t initial_max)
|
||||||
|
{
|
||||||
|
DArray *array = malloc(sizeof(DArray));
|
||||||
|
check_mem(array);
|
||||||
|
array->max = initial_max;
|
||||||
|
check(array->max > 0, "You must set an initial_max > 0.");
|
||||||
|
|
||||||
|
array->contents = calloc(initial_max, sizeof(void *));
|
||||||
|
check_mem(array->contents);
|
||||||
|
|
||||||
|
array->end = 0;
|
||||||
|
array->element_size = element_size;
|
||||||
|
array->expand_rate = DEFAULT_EXPAND_RATE;
|
||||||
|
|
||||||
|
return array;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if(array) free(array);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DArray_clear(DArray *array)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
if(array->element_size > 0) {
|
||||||
|
for(i = 0; i < array->max; i++) {
|
||||||
|
if(array->contents[i] != NULL) {
|
||||||
|
free(array->contents[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int DArray_resize(DArray *array, size_t newsize)
|
||||||
|
{
|
||||||
|
array->max = newsize;
|
||||||
|
check(array->max > 0, "The newsize must be > 0.");
|
||||||
|
|
||||||
|
void *contents = realloc(array->contents, array->max * sizeof(void *));
|
||||||
|
|
||||||
|
check_mem(contents);
|
||||||
|
|
||||||
|
array->contents = contents;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DArray_expand(DArray *array)
|
||||||
|
{
|
||||||
|
size_t old_max = array->max;
|
||||||
|
check(DArray_resize(array, array->max + array->expand_rate) == 0,
|
||||||
|
"Failed to expand array to new size: %d",
|
||||||
|
array->max + (int)array->expand_rate);
|
||||||
|
|
||||||
|
memset(array->contents + old_max, 0, array->expand_rate + 1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DArray_contract(DArray *array)
|
||||||
|
{
|
||||||
|
int new_size = array->end < (int)array->expand_rate ? (int)array->expand_rate : array->end;
|
||||||
|
|
||||||
|
return DArray_resize(array, new_size + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DArray_destroy(DArray *array)
|
||||||
|
{
|
||||||
|
if(array) {
|
||||||
|
if(array->contents) free(array->contents);
|
||||||
|
free(array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DArray_clear_destroy(DArray *array)
|
||||||
|
{
|
||||||
|
DArray_clear(array);
|
||||||
|
DArray_destroy(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DArray_push(DArray *array, void *el)
|
||||||
|
{
|
||||||
|
array->contents[array->end] = el;
|
||||||
|
array->end++;
|
||||||
|
|
||||||
|
if(DArray_end(array) >= DArray_max(array)) {
|
||||||
|
return DArray_expand(array);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *DArray_pop(DArray *array)
|
||||||
|
{
|
||||||
|
check(array->end - 1 >= 0, "Attempt to pop from empty array.");
|
||||||
|
|
||||||
|
void *el = DArray_remove(array, array->end - 1);
|
||||||
|
array->end--;
|
||||||
|
|
||||||
|
if(DArray_end(array) > (int)array->expand_rate && DArray_end(array) % array->expand_rate) {
|
||||||
|
DArray_contract(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
return el;
|
||||||
|
error:
|
||||||
|
return NULL;
|
||||||
|
}
|
78
lcthw-remnants-2/liblcthw/src/lcthw/darray.h
Normal file
78
lcthw-remnants-2/liblcthw/src/lcthw/darray.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#ifndef lcthw_DArray_h
|
||||||
|
#define lcthw_DArray_h
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <lcthw/dbg.h>
|
||||||
|
|
||||||
|
typedef struct DArray {
|
||||||
|
int end;
|
||||||
|
int max;
|
||||||
|
size_t element_size;
|
||||||
|
size_t expand_rate;
|
||||||
|
void **contents;
|
||||||
|
} DArray;
|
||||||
|
|
||||||
|
DArray *DArray_create(size_t element_size, size_t initial_max);
|
||||||
|
|
||||||
|
void DArray_destroy(DArray *array);
|
||||||
|
|
||||||
|
void DArray_clear(DArray *array);
|
||||||
|
|
||||||
|
int DArray_expand(DArray *array);
|
||||||
|
|
||||||
|
int DArray_contract(DArray *array);
|
||||||
|
|
||||||
|
int DArray_push(DArray *array, void *el);
|
||||||
|
|
||||||
|
void *DArray_pop(DArray *array);
|
||||||
|
|
||||||
|
void DArray_clear_destroy(DArray *array);
|
||||||
|
|
||||||
|
#define DArray_last(A) ((A)->contents[(A)->end - 1])
|
||||||
|
#define DArray_first(A) ((A)->contents[0])
|
||||||
|
#define DArray_end(A) ((A)->end)
|
||||||
|
#define DArray_count(A) DArray_end(A)
|
||||||
|
#define DArray_max(A) ((A)->max)
|
||||||
|
|
||||||
|
#define DEFAULT_EXPAND_RATE 300
|
||||||
|
|
||||||
|
|
||||||
|
static inline void DArray_set(DArray *array, int i, void *el)
|
||||||
|
{
|
||||||
|
check(i < array->max, "darray attempt to set past max");
|
||||||
|
if(i > array->end) array->end = i;
|
||||||
|
array->contents[i] = el;
|
||||||
|
error:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *DArray_get(DArray *array, int i)
|
||||||
|
{
|
||||||
|
check(i < array->max, "darray attempt to get past max");
|
||||||
|
return array->contents[i];
|
||||||
|
error:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *DArray_remove(DArray *array, int i)
|
||||||
|
{
|
||||||
|
void *el = array->contents[i];
|
||||||
|
|
||||||
|
array->contents[i] = NULL;
|
||||||
|
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *DArray_new(DArray *array)
|
||||||
|
{
|
||||||
|
check(array->element_size > 0, "Can't use DArray_new on 0 size darrays.");
|
||||||
|
|
||||||
|
return calloc(1, array->element_size);
|
||||||
|
|
||||||
|
error:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DArray_free(E) free((E))
|
||||||
|
|
||||||
|
#endif
|
124
lcthw-remnants-2/liblcthw/tests/lcthw/darray_tests.c
Normal file
124
lcthw-remnants-2/liblcthw/tests/lcthw/darray_tests.c
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#include "../minunit.h"
|
||||||
|
#include <lcthw/darray.h>
|
||||||
|
|
||||||
|
static DArray *array = NULL;
|
||||||
|
static int *val1 = NULL;
|
||||||
|
static int *val2 = NULL;
|
||||||
|
|
||||||
|
char *test_create()
|
||||||
|
{
|
||||||
|
array = DArray_create(sizeof(int), 100);
|
||||||
|
mu_assert(array != NULL, "DArray_create failed.");
|
||||||
|
mu_assert(array->contents != NULL, "contents are wrong in darray");
|
||||||
|
mu_assert(array->end == 0, "end isn't at the right spot");
|
||||||
|
mu_assert(array->element_size == sizeof(int), "element size is wrong.");
|
||||||
|
mu_assert(array->max == 100, "wrong max length on initial size");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *test_destroy()
|
||||||
|
{
|
||||||
|
DArray_destroy(array);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *test_new()
|
||||||
|
{
|
||||||
|
val1 = DArray_new(array);
|
||||||
|
mu_assert(val1 != NULL, "failed to make a new element");
|
||||||
|
|
||||||
|
val2 = DArray_new(array);
|
||||||
|
mu_assert(val2 != NULL, "failed to make a new element");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *test_set()
|
||||||
|
{
|
||||||
|
DArray_set(array, 0, val1);
|
||||||
|
DArray_set(array, 1, val2);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *test_get()
|
||||||
|
{
|
||||||
|
mu_assert(DArray_get(array, 0) == val1, "Wrong first value.");
|
||||||
|
mu_assert(DArray_get(array, 1) == val2, "Wrong second value.");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *test_remove()
|
||||||
|
{
|
||||||
|
int *val_check = DArray_remove(array, 0);
|
||||||
|
mu_assert(val_check != NULL, "Should not get NULL.");
|
||||||
|
mu_assert(*val_check == *val1, "Should get the first value.");
|
||||||
|
mu_assert(DArray_get(array, 0) == NULL, "Should be gone.");
|
||||||
|
DArray_free(val_check);
|
||||||
|
|
||||||
|
val_check = DArray_remove(array, 1);
|
||||||
|
mu_assert(val_check != NULL, "Should not get NULL.");
|
||||||
|
mu_assert(*val_check == *val2, "Should get the second value.");
|
||||||
|
mu_assert(DArray_get(array, 1) == NULL, "Should be gone.");
|
||||||
|
DArray_free(val_check);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *test_expand_contract()
|
||||||
|
{
|
||||||
|
int old_max = array->max;
|
||||||
|
DArray_expand(array);
|
||||||
|
mu_assert((unsigned int)array->max == old_max + array->expand_rate, "Wrong size after expand.");
|
||||||
|
|
||||||
|
DArray_contract(array);
|
||||||
|
mu_assert((unsigned int)array->max == array->expand_rate + 1, "Should stay at the expand_rate at least.");
|
||||||
|
|
||||||
|
DArray_contract(array);
|
||||||
|
mu_assert((unsigned int)array->max == array->expand_rate + 1, "Should stay at the expand_rate at least.");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *test_push_pop()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for(i = 0; i < 1000; i++) {
|
||||||
|
int *val = DArray_new(array);
|
||||||
|
*val = i * 333;
|
||||||
|
DArray_push(array, val);;
|
||||||
|
}
|
||||||
|
|
||||||
|
mu_assert(array->max == 1201, "Wrong max size.");
|
||||||
|
|
||||||
|
for(i = 999; i >= 0; i--) {
|
||||||
|
int *val = DArray_pop(array);
|
||||||
|
mu_assert(val != NULL, "Shouldn't get a NULL.");
|
||||||
|
mu_assert(*val == i * 333, "Wrong value.");
|
||||||
|
DArray_free(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *all_tests()
|
||||||
|
{
|
||||||
|
mu_suite_start();
|
||||||
|
|
||||||
|
mu_run_test(test_create);
|
||||||
|
mu_run_test(test_new);
|
||||||
|
mu_run_test(test_set);
|
||||||
|
mu_run_test(test_get);
|
||||||
|
mu_run_test(test_remove);
|
||||||
|
mu_run_test(test_expand_contract);
|
||||||
|
mu_run_test(test_push_pop);
|
||||||
|
mu_run_test(test_destroy);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
RUN_TESTS(all_tests);
|
Loading…
Reference in New Issue
Block a user