LO41/List/List.c

230 lines
5.0 KiB
C

//
// Created by Antoine Bartuccio on 22/05/2018.
//
#include "List.h"
GETTER(List, Element*, head)
GETTER(List, Element*, tail)
GETTER(List, int, size)
void set_custom_free_List(THIS(List), void (*custom_free)(void *)){
this->custom_free = custom_free;
}
Element * get_element_List(THIS(List), int index){
Element * current = NULL;
int i;
if (index < this->size){
if (index == this->size - 1)
current = this->tail;
else if (index == 0)
current = this->head;
else if (index <= (this->size - 1) / 2){
i = 0;
current = this->head;
while (i < index){
current = current->next;
i++;
}
} else {
i = this->size - 1;
current = this->tail;
while (i > index){
current = current->previous;
i--;
}
}
} else {
OUTSIDE_BOUNDS;
}
return current;
}
void * get_element_data_List(THIS(List), int index){
Element * el = this->get_element(this, index);
if (el != NULL)
return el->data;
return NULL;
}
void * get_head_data_List(THIS(List)){
if (this->head != NULL)
return this->head->data;
return NULL;
}
void * get_tail_data_List(THIS(List)){
if (this->tail != NULL)
return this->tail->data;
return NULL;
}
void _free__List(THIS(List)){
this->clear(this);
free(this);
}
void clear_custom_List(THIS(List), void (*custom_free)(void *)){
Element *current = this->head;
Element *to_delete = NULL;
while (current != NULL){
to_delete = current;
current = current->next;
to_delete->list = NULL;
to_delete->data_free = custom_free;
DELETE(to_delete);
}
this->head = NULL;
this->tail = NULL;
this->size = 0;
}
void clear_List(THIS(List)){
this->clear_custom(this, free);
}
void insert_tail_List(THIS(List), void * data, size_t data_size){
/* Create a new element */
Element *new_element = NEW(Element, data, data_size, this);
new_element->data_free = this->custom_free;
if (this->tail == NULL){
this->head = new_element;
this->tail = new_element;
} else {
new_element->previous = this->tail;
this->tail->next = new_element;
this->tail = new_element;
}
}
void insert_head_List(THIS(List), void * data, size_t data_size){
/* Create a new element */
Element *new_element = NEW(Element, data, data_size, this);
new_element->data_free = this->custom_free;
if (this->head != NULL)
this->head->previous = new_element;
else
this->tail = new_element;
new_element->next = this->head;
this->head = new_element;
}
void insert_inside_List(THIS(List), void * data, size_t data_size, int index){
Element *new_element = NULL;
Element *old_element = NULL;
if (index == 0)
this->insert_head(this, data, data_size);
else if (index == this->size)
this->insert_tail(this, data, data_size);
else if (index < this->size){
new_element = NEW(Element, data, data_size, this);
new_element->data_free = this->custom_free;
old_element = this->get_element(this, index);
new_element->previous = old_element->previous;
new_element->next = old_element;
old_element->previous->next = new_element;
old_element->previous = new_element;
} else {
OUTSIDE_BOUNDS;
}
}
/**
* Remove element with specified data in the list
* @param this THIS(List)
* @param data_to_remove pointer to data you want to remove
* @param compare a compare function, return true or false and takes two void * pointers
* @return true or false, depending on if the element was found in the list
*/
int remove_inside_List(THIS(List), void * data_to_remove, int (*compare)(void*, void*)){
Element* temp_element = this->head;
while(temp_element != NULL){
if(compare(data_to_remove, temp_element->data)){
if(temp_element == this->head){
this->remove_head(this);
}else if (temp_element == this->tail){
this->remove_tail(this);
}else{
if(temp_element->previous != NULL)
temp_element->previous->next = temp_element->next;
if(temp_element->next != NULL)
temp_element->next->previous = temp_element->previous;
DELETE(temp_element);
}
return 1;
}
temp_element = temp_element->next;
}
return 0;
}
/**
* Check if data_to_find exist in list
* @param this THIS(List)
* @param data_to_find pointer to data you want to find inside
* @param compare a compare function, return true or false and takes two void * pointers
* @return true or false if the element is within the list or not
*/
int contains_List(THIS(List), void * data_to_find, int (*compare)(void *, void *)){
Element * current = this->head;
while (current != NULL){
if (compare(data_to_find, current->data)){
return 1;
}
current = current->next;
}
return 0;
}
void remove_head_List(THIS(List)){
DELETE(this->head);
}
void remove_tail_List(THIS(List)){
DELETE(this->tail);
}
List *_init_List(){
List *l = (List*) malloc_or_die(sizeof(List));
l->size = 0;
l->head = NULL;
l->tail = NULL;
l->custom_free = free;
LINK_ALL(List, l,
get_head,
get_tail,
get_size,
get_head_data,
get_tail_data,
get_element,
get_element_data,
set_custom_free,
remove_inside,
insert_inside,
insert_tail,
insert_head,
clear_custom,
clear,
remove_head,
remove_tail,
contains
)
return l;
}