2012-08-04 10:54:37 +00:00
|
|
|
/*
|
2013-04-06 20:27:08 +00:00
|
|
|
Copyright (c) 2013 Ubergames
|
2012-08-04 10:54:37 +00:00
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
|
this software and associated documentation files (the "Software"), to deal in
|
|
|
|
the Software without restriction, including without limitation the rights to
|
|
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
|
|
of the Software, and to permit persons to whom the Software is furnished to do
|
|
|
|
so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
|
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "list.h"
|
|
|
|
#include <string.h>
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
list_p create_list() {
|
|
|
|
list_p list = (list_p)malloc(sizeof(struct list));
|
|
|
|
|
|
|
|
if(list == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
list->length = 0;
|
|
|
|
list->first = NULL;
|
|
|
|
list->last = NULL;
|
|
|
|
list->destructor = free;
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
list_iter_p list_iterator(list_p list, char init) {
|
2012-08-04 10:54:37 +00:00
|
|
|
list_iter_p iter = (list_iter_p)malloc(sizeof(struct list_iter));
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
if(iter == NULL) {
|
|
|
|
return NULL;
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
if(init == LIST_FRONT) {
|
|
|
|
iter->current = list->first;
|
|
|
|
} else if(init == LIST_BACK) {
|
2012-08-04 10:54:37 +00:00
|
|
|
iter->current = list->last;
|
2013-04-06 20:27:08 +00:00
|
|
|
} else { // asume front
|
|
|
|
iter->current = list->first;
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2012-11-11 12:53:08 +00:00
|
|
|
iter->list = list;
|
2012-08-04 10:54:37 +00:00
|
|
|
iter->started = 0;
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
return iter;
|
|
|
|
}
|
|
|
|
|
2013-04-06 20:42:06 +00:00
|
|
|
int list_add(list_p list, void* data, dataType_t type, size_t size, char end) {
|
2012-08-04 10:54:37 +00:00
|
|
|
lnode_p node = (lnode_p)malloc(sizeof(struct linked_node));
|
|
|
|
|
2013-04-06 22:06:08 +00:00
|
|
|
node->cont = (container_p)malloc(sizeof(container));
|
2013-04-06 20:27:08 +00:00
|
|
|
if(node->cont == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
2013-04-06 20:42:06 +00:00
|
|
|
node->cont->type = type;
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
node->cont->data = malloc(size);
|
|
|
|
if(node->cont->data == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
memcpy(node->cont->data, data, size);
|
|
|
|
|
|
|
|
if(list->first == NULL) {
|
2012-08-04 10:54:37 +00:00
|
|
|
node->prev = NULL;
|
|
|
|
node->next = NULL;
|
|
|
|
list->first = node;
|
|
|
|
list->last = node;
|
2013-04-06 20:42:06 +00:00
|
|
|
} else if(end == LIST_BACK) {
|
|
|
|
list->last->next = node;
|
|
|
|
node->prev = list->last;
|
|
|
|
node->next = NULL;
|
|
|
|
list->last = node;
|
|
|
|
} else if(end == LIST_FRONT) {
|
|
|
|
list->first->prev = node;
|
|
|
|
node->next = list->first;
|
|
|
|
node->prev = NULL;
|
|
|
|
list->first = node;
|
|
|
|
} else { // assume back
|
2012-08-04 10:54:37 +00:00
|
|
|
list->last->next = node;
|
|
|
|
node->prev = list->last;
|
|
|
|
node->next = NULL;
|
|
|
|
list->last = node;
|
|
|
|
}
|
|
|
|
list->length++;
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
return list->length;
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
|
|
|
|
2013-04-06 20:42:06 +00:00
|
|
|
int list_append(list_p list, void* data, dataType_t type, size_t size) {
|
|
|
|
return list_add(list, data, type, size, LIST_BACK);
|
|
|
|
}
|
|
|
|
|
|
|
|
int list_prepend(list_p list, void* data, dataType_t type, size_t size) {
|
|
|
|
return list_add(list, data, type, size, LIST_FRONT);
|
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
container_p list_current(list_iter_p iter){
|
|
|
|
if(iter->started && iter->current != NULL) {
|
|
|
|
return iter->current->cont;
|
|
|
|
}
|
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
container_p list_next(list_iter_p iter) {
|
|
|
|
if(!iter->started && iter->current != NULL) {
|
|
|
|
iter->started = 1;
|
|
|
|
return iter->current->cont;
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
if(iter->current != NULL) {
|
2012-08-04 10:54:37 +00:00
|
|
|
iter->current = iter->current->next;
|
|
|
|
return list_current(iter);
|
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
container_p list_cycl_next(list_iter_p iter) {
|
|
|
|
if(!iter->started && iter->current != NULL) {
|
|
|
|
iter->started = 1;
|
|
|
|
return iter->current->cont;
|
2012-11-11 12:53:08 +00:00
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
if(iter->current != NULL) {
|
2012-11-11 12:53:08 +00:00
|
|
|
iter->current = iter->current->next;
|
|
|
|
if(iter->current == NULL) {
|
|
|
|
iter->current = iter->list->first;
|
|
|
|
}
|
|
|
|
return list_current(iter);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
container_p list_prev(list_iter_p iter) {
|
|
|
|
if(!iter->started&&iter->current!=NULL) {
|
|
|
|
iter->started = 1;
|
|
|
|
return iter->current->cont;
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
if(iter->current!=NULL) {
|
2012-08-04 10:54:37 +00:00
|
|
|
iter->current = iter->current->prev;
|
|
|
|
return list_current(iter);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
container_p list_cycl_prev(list_iter_p iter){
|
|
|
|
if(!iter->started && iter->current != NULL) {
|
|
|
|
iter->started =1 ;
|
|
|
|
return iter->current->cont;
|
2012-11-11 12:53:08 +00:00
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
if(iter->current!=NULL) {
|
2012-11-11 12:53:08 +00:00
|
|
|
iter->current = iter->current->prev;
|
|
|
|
if(iter->current == NULL) {
|
|
|
|
iter->current = iter->list->last;
|
|
|
|
}
|
|
|
|
return list_current(iter);
|
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2012-11-11 12:53:08 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
container_p list_first(list_p list) {
|
|
|
|
return list->first->cont;
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
container_p list_last(list_p list) {
|
|
|
|
return list->last->cont;
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
container_p list_pop(list_p list) {
|
|
|
|
container_p cont;
|
2012-08-04 10:54:37 +00:00
|
|
|
lnode_p last = list->last;
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
if(last == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
list->last = last->prev;
|
2013-04-06 20:27:08 +00:00
|
|
|
cont = last->cont;
|
|
|
|
|
2013-02-13 10:57:18 +00:00
|
|
|
if(last->prev != NULL) {
|
|
|
|
last->prev->next = NULL;
|
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
free(last);
|
2013-02-13 10:57:18 +00:00
|
|
|
list->length--;
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2013-02-13 10:57:18 +00:00
|
|
|
if(list->length == 0) {
|
|
|
|
list->last = list->first = NULL;
|
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
return cont;
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
container_p list_poll(list_p list){
|
|
|
|
container_p cont;
|
2012-08-04 10:54:37 +00:00
|
|
|
lnode_p first = list->first;
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
if(first == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
list->first = first->next;
|
2013-04-06 20:27:08 +00:00
|
|
|
cont = first->cont;
|
|
|
|
|
2013-02-13 10:57:18 +00:00
|
|
|
if(first->next != NULL) {
|
|
|
|
first->next->prev = NULL;
|
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
free(first);
|
2013-02-13 10:57:18 +00:00
|
|
|
list->length--;
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2013-02-13 10:57:18 +00:00
|
|
|
if(list->length == 0) {
|
|
|
|
list->last = list->first = NULL;
|
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|
|
|
|
return cont;
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
void list_remove(list_p list, char end) {
|
|
|
|
container_p cont;
|
|
|
|
void (*destructor)(void*) = list->destructor;
|
|
|
|
|
|
|
|
if(end == LIST_FRONT) {
|
|
|
|
cont = list_poll(list);
|
|
|
|
} else if (end == LIST_BACK) {
|
|
|
|
cont = list_pop(list);
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cont != NULL) {
|
|
|
|
if(cont->data != NULL) {
|
|
|
|
destructor(cont->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(cont);
|
|
|
|
}
|
2012-08-04 10:54:37 +00:00
|
|
|
}
|
|
|
|
|
2013-04-06 20:27:08 +00:00
|
|
|
void destroy_list(list_p list) {
|
2012-08-04 10:54:37 +00:00
|
|
|
lnode_p cur = list->first;
|
|
|
|
lnode_p next;
|
2013-04-06 20:27:08 +00:00
|
|
|
|
2012-08-04 10:54:37 +00:00
|
|
|
while(cur!=NULL){
|
|
|
|
next = cur->next;
|
2012-11-12 20:33:22 +00:00
|
|
|
if(list->destructor != NULL) { // only destroy data if there is a destructor set
|
2013-04-06 20:27:08 +00:00
|
|
|
list->destructor(cur->cont->data);
|
|
|
|
free(cur->cont);
|
2012-11-12 20:33:22 +00:00
|
|
|
}
|
2012-08-04 10:54:37 +00:00
|
|
|
free(cur);
|
|
|
|
cur = next;
|
|
|
|
}
|
|
|
|
free(list);
|
2012-11-11 12:53:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void destroy_iterator(list_iter_p iter) {
|
2013-04-06 20:27:08 +00:00
|
|
|
if(iter == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2012-11-11 12:53:08 +00:00
|
|
|
|
|
|
|
free(iter);
|
2013-02-13 10:57:18 +00:00
|
|
|
}
|
2013-04-06 20:27:08 +00:00
|
|
|
|