From 9594210f02572681ed581c5197ace4c207db0917 Mon Sep 17 00:00:00 2001 From: JSDurand Date: Mon, 8 Nov 2021 16:37:57 +0800 Subject: initial commit Now the rough framework is established and the grammar class is sort of ready. It remains to write a general input reading mechanism. --- src/list.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 src/list.c (limited to 'src/list.c') diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..8c67a09 --- /dev/null +++ b/src/list.c @@ -0,0 +1,247 @@ +#include "list.h" +#include "util.h" +#include +#include + +struct List_s { + void **array; /* the array of elements */ + NUM len; /* the length of the array */ + NUM capacity; /* the number of pre-allocated bytes + for the array */ +}; + +List * +new_list() +{ + void **array = MYALLOC(void*, LIST_INIT_AMOUNT); + + if (array == NULL) return NULL; + + for (NUM i = 0; i < LIST_INIT_AMOUNT; i++) + *(array+i) = NULL; + + List *list = MYALLOC(List, 1); + + if (list == NULL) return NULL; + + list->array = array; + list->len = 0; + list->capacity = LIST_INIT_AMOUNT; + + return list; +} + +H_ATTR +unsigned char +add_to_list(List *ls, void *element) +{ + if (!(ls->capacity)) { + /* The capacity can be zero only when the list has been destroyed, + in which case adding an element to that list is definitely an + error. */ + eprintf("%s:%d, Adding an element to a destroyed list.\n", + __FILE__, __LINE__); + } + + (ls->len)++; + + if (ls->len >= ls->capacity) { + NUM new_capacity = ((ls->capacity) * 3) >> 1; + + if (new_capacity < ls->capacity + LIST_INIT_AMOUNT) + new_capacity = ls->capacity + LIST_INIT_AMOUNT; + + NUM max_diff = 1 << 20; + if (new_capacity >= ls->capacity + max_diff) + new_capacity = ls->capacity + max_diff; + + void **array = MYALLOC(void *, ls->capacity); + + if (array == NULL) { + ls->len -= 1; + return 1; + } + + for (NUM i = 0; i < ls->capacity; i++) + *(array+i) = *(ls->array+i); + + /* The new_capacity will not be zero, so upon failure it returns + NULL. */ + ls->array = realloc(ls->array, sizeof(void*) * new_capacity); + + if (ls->array == NULL) { + ls->len -= 1; + free(array); + return 1; + } + + for (NUM i = 0; i < ls->capacity; i++) + *(ls->array+i) = *(array+i); + + free(array); + + for (NUM i = ls->capacity; i < new_capacity; i++) + *(ls->array+i) = NULL; + + ls->capacity = new_capacity; + } + + *(ls->array+ls->len-1) = element; + + return 0; +} + +H_ATTR +void * +pop_from_list(List *ls) +{ + if (!(ls->len)) return NULL; + + return *(ls->array+--(ls->len)); +} + +H_ATTR +void +map_list(List *ls, acter f) +{ + for (NUM i = 0; i < ls->len; i++) + f(*(ls->array+i)); +} + +void +print_list(List *ls, printer prt) +{ + printf("printing a list with length = %lu and capacity = %lu\n", + ls->len, ls->capacity); + + map_list(ls, (acter) prt); + + printf("printing terminated\n"); +} + +void * +copy_num(void *p) +{ + NUM *pointer = malloc(sizeof *pointer); + + if (pointer == NULL) return NULL; + + *pointer = *((NUM *) p); + + return pointer; +} + +unsigned char +copy_list(List *dest, List *source, copyer copyf) +{ + unsigned char sign = 0; + + if ((sign = list_assure_size(dest, source->len))) + return sign; + + dest->len = source->len; + + for (NUM i = 0; i < source->len; i++) { + void *pointer = copyf(*(source->array+i)); + if (pointer == NULL) return 1; + *(dest->array+i) = pointer; + } + + return 0; +} + +H_ATTR +void * +list_nth(List *ls, NUM n) +{ + return *(ls->array+n); +} + +H_ATTR +NUM +list_length(List *ls) +{ + return ls->len; +} + +unsigned char +list_assure_size(List *ls, NUM size) +{ + if (ls->capacity >= size) return 0; /* we are good */ + + void **array = MYALLOC(void *, ls->capacity); + + if (array == NULL) return 1; + + for (NUM i = 0; i < ls->capacity; i++) + *(array+i) = *(ls->array+i); + + ls->array = realloc(ls->array, sizeof(void*) * size); + + if (ls->array == NULL) return 1; + + for (NUM i = 0; i < ls->capacity; i++) + *(ls->array+i) = *(array+i); + + free(array); + + for (NUM i = ls->capacity; i < size; i++) + *(ls->array+i) = NULL; + + ls->capacity = size; + + return 0; +} + +unsigned char +list_set_length(List *ls, NUM len) +{ + if (ls->len >= len) return 0; + + NUM *array = MYALLOC(NUM, len - ls->len); + + if (array == NULL) return 1; + + for (NUM i = ls->len; i < len; i++) { + *(array + i - ls->len) = -1; + *(ls->array+i) = array + i - ls->len; + } + + ls->len = len; + + return 0; +} + +void * +list_to_array(List *ls, NUM element_bytes, NUM *num) +{ + /* We shall not use a void pointer here, since standard C does not + allow doing arithmetic on void pointers. So we use a char + pointer here, since the size of char is 1. */ + char *array = malloc(element_bytes * ls->len); + + if (array == NULL) return NULL; + + *num = ls->len; + + for (NUM i = 0; i < *num; i++) + memcpy(array+(element_bytes*i), *(ls->array+i), element_bytes); + + return array; +} + +void +destroy_list(List *ls, unsigned char all_free_p) +{ + if (all_free_p == 1) + for (NUM i = 0; i < ls->len; i++) + free(*(ls->array+i)); + + if (all_free_p == 2) + free(*(ls->array)); + + free(ls->array); + free(ls); + + ls->len = (ls->capacity = 0); +} -- cgit v1.2.3-18-g5258