|
|
|
#include "datatypes.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
ArrayList new_arlst(int num_elems) {
|
|
|
|
ArrayList new_list;
|
|
|
|
new_list.free = NULL;
|
|
|
|
new_list.size = 0;
|
|
|
|
new_list.capacity = num_elems;
|
|
|
|
new_list.items = calloc(num_elems, sizeof(void *));
|
|
|
|
|
|
|
|
return new_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArrayList new_arlst_wfree(int num_elems, void (*nfree)(void *ptr)) {
|
|
|
|
ArrayList new_list = new_arlst(num_elems);
|
|
|
|
new_list.free = nfree;
|
|
|
|
return new_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArrayList new_arlst_using_array(void **array, int length) {
|
|
|
|
ArrayList l = new_arlst(length);
|
|
|
|
free(l.items);
|
|
|
|
l.items = array;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArrayList new_arlst_using_array_wfree(void **array, int length,
|
|
|
|
void (*f)(void *)) {
|
|
|
|
ArrayList l = new_arlst_using_array(array, length);
|
|
|
|
l.free = f;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArrayList new_arlst_from_array(void *array, size_t elem_size, int length) {
|
|
|
|
ArrayList l = new_arlst(length);
|
|
|
|
l.free = free;
|
|
|
|
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
void *item = calloc(1, elem_size);
|
|
|
|
void *start = array + i * elem_size;
|
|
|
|
memmove(item, start, elem_size);
|
|
|
|
arlst_add(&l, item);
|
|
|
|
}
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *arlst_get(ArrayList *l, int id) {
|
|
|
|
// out of bounds
|
|
|
|
if (id < 0 || id >= l->size) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return l->items[id];
|
|
|
|
}
|
|
|
|
|
|
|
|
void * arlst_del(ArrayList *l, int id) {
|
|
|
|
void *item = arlst_get(l, id);
|
|
|
|
|
|
|
|
if (!item) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
l->size--;
|
|
|
|
// move elements backward
|
|
|
|
for (int i = id; i < l->size; i++) {
|
|
|
|
l->items[i] = l->items[i+1];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// shrink capacity if neccessary
|
|
|
|
if (D_SHRINK_THRESHOLD != 0
|
|
|
|
|| l->size < (100 / D_SHRINK_THRESHOLD) * l->capacity) {
|
|
|
|
|
|
|
|
size_t new_size = l-> size + (l->capacity * (100 / D_SHRINK_THRESHOLD) *
|
|
|
|
100 / D_GROW_AMOUNT);
|
|
|
|
|
|
|
|
// l->items = reallocarray(l->items, new_size, sizeof(void *));
|
|
|
|
l->items = realloc(l->items, new_size * sizeof(void *));
|
|
|
|
}
|
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
int arlst_add(ArrayList *l, void *item) {
|
|
|
|
int item_index = l->size;
|
|
|
|
|
|
|
|
// grow if neccessary
|
|
|
|
if (l->size == l->capacity) {
|
|
|
|
size_t new_size = l->capacity + (100 / D_GROW_AMOUNT) * l->capacity;
|
|
|
|
l->capacity = new_size;
|
|
|
|
//l->items = (void **)reallocarray(l->items, new_size, sizeof(void *));
|
|
|
|
l->items = (void **)realloc(l->items, new_size * sizeof(void *));
|
|
|
|
}
|
|
|
|
|
|
|
|
l->items[item_index] = item;
|
|
|
|
l->size++;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void * arlst_pop(ArrayList *l) {
|
|
|
|
l->size--;
|
|
|
|
return l->items[l->size];
|
|
|
|
}
|
|
|
|
|
|
|
|
int arlst_push(ArrayList *l, void *item) {
|
|
|
|
return arlst_add(l, item);
|
|
|
|
}
|
|
|
|
|
|
|
|
int arlst_destroy(ArrayList *l) {
|
|
|
|
if (l->free != NULL) {
|
|
|
|
for (int i = 0; i < l->size; i++) {
|
|
|
|
l->free(l->items[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(l->items);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ListFiFo new_fifo(int start_size) {
|
|
|
|
ListFiFo l;
|
|
|
|
memset(&l, 0, sizeof(ListFiFo));
|
|
|
|
l.inner = new_arlst(start_size);
|
|
|
|
l.size = &l.inner.size;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *fifo_get(ListFiFo *l) {
|
|
|
|
if (l->fifo_head >= l->inner.size) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *value = arlst_get(&l->inner, l->fifo_head);
|
|
|
|
|
|
|
|
if (value != NULL) {
|
|
|
|
l->fifo_head++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (l->fifo_head == l->inner.capacity
|
|
|
|
|| (l->fifo_head == l->inner.size
|
|
|
|
&& l->inner.size >= D_MAX_QUEUE_LEN)) {
|
|
|
|
// start rewriting from the beginning
|
|
|
|
l->inner.size = 0;
|
|
|
|
l->fifo_head = 0;
|
|
|
|
// memset(l->inner.items, 0, sizeof(void *) * l->inner.capacity);
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* It is up to the caller to free any data stored */
|
|
|
|
int fifo_add(ListFiFo *l, void *i) {
|
|
|
|
if (l->inner.size >= D_MAX_QUEUE_LEN) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return arlst_add(&l->inner, i);
|
|
|
|
}
|
|
|
|
|