196 lines
5.1 KiB
C
196 lines
5.1 KiB
C
#include <odweta/list.h>
|
|
#include <odweta/vector.h>
|
|
#include <odweta/util.h>
|
|
#include <odweta/string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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);
|
|
}
|
|
}
|