mirror of
https://gitlab.com/klmp200/LO41.git
synced 2024-11-23 17:23:21 +00:00
230 lines
5.0 KiB
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;
|
|
}
|
|
|