#include #include #include #include #include #include #include #define init_error_exit(l) fprintf(stderr, "could not init list\n"); free(l); exit(EXIT_FAILURE) list_t *list_new() { list_t *self = (list_t *)malloc(sizeof(list_t)); if (self == NULL) { init_error_exit(self); } self->data = (vector_t *)vector_new(VECTOR); if (self->data == NULL) { init_error_exit(self); } self->size = 0; self->capacity = 1; return self; } void list_push(list_t *self, type_e type, void *element) { vector_t *new_vec = vector_new(type); vector_push(new_vec, element); vector_push((vector_t *)self->data, new_vec); self->size += 1; if (self->size == self->capacity) { self->capacity *= 2; } } void _list_print_recursive(list_t *self, int depth) { printf("["); int i; for (i = 0; i < self->size; i++) { vector_t *ith_vec = (vector_t *)vector_get_at((vector_t *)self->data, i); switch (ith_vec->type) { case INT: printf("%d", *((int *)vector_get_at(ith_vec, 0))); break; case FLOAT: printf("%f", *((float *)vector_get_at(ith_vec, 0))); break; case CHAR: printf("'%c'", *((char *)vector_get_at(ith_vec, 0))); break; case VECTOR: _vector_print_recursive(ith_vec->data, 0); break; case LIST: _list_print_recursive(ith_vec->data, 0); break; case BOOL: printf("%s", (*((bool_t *)vector_get_at(ith_vec, 0)) == FALSE) ? "false" : "true"); break; case STRING: string_print((string_t *)vector_get_at(ith_vec, 0)); break; } if (i < self->size - 1) { printf(", "); } } printf("]"); if (depth != 0) { printf("\n"); } } void list_show(list_t *self) { printf("["); int i; for (i = 0; i < self->size; i++) { vector_t *ith_vec = (vector_t *)vector_get_at((vector_t *)self->data, i); switch (ith_vec->type) { case INT: printf("%d", *((int *)vector_get_at(ith_vec, 0))); break; case FLOAT: printf("%f", *((float *)vector_get_at(ith_vec, 0))); break; case CHAR: printf("'%c'", *((char *)vector_get_at(ith_vec, 0))); break; case VECTOR: _vector_print_recursive(ith_vec->data, 0); break; case LIST: _list_print_recursive(ith_vec->data, 0); break; case BOOL: printf("%s", (*((bool_t *)vector_get_at(ith_vec, 0)) == FALSE) ? "false" : "true"); break; case STRING: string_print((string_t *)vector_get_at(ith_vec, 0)); break; } if (i < self->size - 1) { printf(", "); } } printf("]\n"); } void list_cleanup(list_t *self) { vector_cleanup((vector_t *)self->data); free(self); } void *list_pop(list_t *self) { if (self->size != 0) { vector_t *first_ptr = (vector_t *)vector_pop((vector_t *)self->data); void *ptr = vector_pop(first_ptr); self->size -= 1; if (self->size <= self->capacity / 2) self->capacity /= 2; if (self->capacity == 0) self->capacity = 1; return ptr; } else { // cannot pop when there is no value in the list return NULL; } } void list_insert_at(list_t *self, int index, type_e type, void *element) { if (self->size == 0) { list_push(self, type, element); } else { vector_t* new_vec = vector_new(type); vector_push(new_vec, element); vector_insert_at((vector_t *)self->data, index, new_vec); self->size += 1; if (self->size == self->capacity) { self->capacity *= 2; } } } void list_remove_at(list_t *self, int index) { vector_remove_at(self->data, index); self->size -= 1; if (self->size == self->capacity) { self->capacity /= 2; } } void list_set_at(list_t *self, int index, type_e type, void *element) { if (self->size == 0) { list_push(self, type, element); } else if (index < self->size && index >= 0) { list_remove_at(self, index); if (index == self->size) { self->data->size += 1; if (self->data->size == self->data->capacity) { self->data->capacity *= 2; } } list_insert_at(self, index, type, element); } } void *list_get_at(list_t *self, int index) { if (self->size == 0) { //fprintf(stderr, "list is empty\n"); return NULL; } else if (index >= self->size || index < 0) { //fprintf(stderr, "index out of range\n"); return NULL; } else { return vector_get_at((vector_t *)vector_get_at(self->data, index), 0); } }