2010-10-27 19:51:49 +02:00
|
|
|
/*
|
2011-03-05 13:44:21 +01:00
|
|
|
* This software is licensed under the terms of the MIT-License
|
2017-02-11 04:52:08 +01:00
|
|
|
* See COPYING for further information.
|
2011-03-05 13:44:21 +01:00
|
|
|
* ---
|
2018-01-04 18:14:31 +01:00
|
|
|
* Copyright (c) 2011-2018, Lukas Weber <laochailan@web.de>.
|
|
|
|
* Copyright (c) 2012-2018, Andrei Alexeyev <akari@alienslab.net>.
|
2010-10-27 19:51:49 +02:00
|
|
|
*/
|
|
|
|
|
2017-11-25 20:45:11 +01:00
|
|
|
#include "taisei.h"
|
|
|
|
|
2010-10-27 19:51:49 +02:00
|
|
|
#include <stdlib.h>
|
2010-11-28 12:54:13 +01:00
|
|
|
#include <stdio.h>
|
2010-10-27 19:51:49 +02:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
#define LIST_NO_MACROS
|
|
|
|
|
|
|
|
#include "list.h"
|
|
|
|
#include "global.h"
|
2011-05-13 19:03:02 +02:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
List* list_insert(List **dest, List *elem) {
|
2017-09-29 21:03:49 +02:00
|
|
|
assert(dest != NULL);
|
2017-11-21 15:45:01 +01:00
|
|
|
assert(elem != NULL);
|
2017-09-29 21:03:49 +02:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
elem->prev = *dest;
|
2012-08-17 16:20:05 +02:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
if(*dest != NULL) {
|
|
|
|
elem->next = (*dest)->next;
|
2012-08-17 16:20:05 +02:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
if((*dest)->next) {
|
|
|
|
(*dest)->next->prev = elem;
|
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
(*dest)->next = elem;
|
2012-08-17 15:59:31 +02:00
|
|
|
} else {
|
2017-11-21 15:45:01 +01:00
|
|
|
elem->next = NULL;
|
|
|
|
*dest = elem;
|
|
|
|
}
|
|
|
|
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
|
|
|
List* list_push(List **dest, List *elem) {
|
|
|
|
assert(dest != NULL);
|
|
|
|
assert(elem != NULL);
|
|
|
|
|
|
|
|
if(*dest) {
|
|
|
|
(*dest)->prev = elem;
|
2012-08-17 15:37:09 +02:00
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
elem->next = *dest;
|
|
|
|
elem->prev = NULL;
|
|
|
|
|
|
|
|
*dest = elem;
|
|
|
|
return elem;
|
2010-10-27 19:51:49 +02:00
|
|
|
}
|
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
List* list_append(List **dest, List *elem) {
|
2017-10-03 17:25:38 +02:00
|
|
|
assert(dest != NULL);
|
2017-11-21 15:45:01 +01:00
|
|
|
assert(elem != NULL);
|
2017-10-03 17:25:38 +02:00
|
|
|
|
|
|
|
if(*dest == NULL) {
|
2017-11-21 15:45:01 +01:00
|
|
|
return list_insert(dest, elem);
|
2017-10-03 17:25:38 +02:00
|
|
|
}
|
|
|
|
|
2017-11-23 16:27:41 +01:00
|
|
|
List *end = *dest;
|
|
|
|
for(List *e = (*dest)->next; e; e = e->next) {
|
2017-10-03 17:25:38 +02:00
|
|
|
end = e;
|
|
|
|
}
|
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
return list_insert(&end, elem);
|
2017-10-03 17:25:38 +02:00
|
|
|
}
|
|
|
|
|
2018-01-09 20:52:20 +01:00
|
|
|
__attribute__((hot))
|
|
|
|
static List* list_insert_at_priority(List **list_head, List *elem, int prio, ListPriorityFunc prio_func, bool head) {
|
2017-09-29 21:03:49 +02:00
|
|
|
assert(list_head != NULL);
|
2017-11-21 15:45:01 +01:00
|
|
|
assert(elem != NULL);
|
2017-09-29 21:03:49 +02:00
|
|
|
assert(prio_func != NULL);
|
|
|
|
|
|
|
|
if(!*list_head) {
|
2017-11-21 15:45:01 +01:00
|
|
|
elem->prev = elem->next = NULL;
|
2017-09-29 21:03:49 +02:00
|
|
|
*list_head = elem;
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
|
|
|
List *dest = *list_head;
|
2017-11-23 16:27:41 +01:00
|
|
|
int dest_prio = prio_func(dest);
|
|
|
|
int candidate_prio = dest_prio;
|
2017-09-29 21:03:49 +02:00
|
|
|
|
2018-01-09 20:52:20 +01:00
|
|
|
if(head) {
|
|
|
|
for(List *e = dest->next; e && (candidate_prio = prio_func(e)) < prio; e = e->next) {
|
|
|
|
dest = e;
|
|
|
|
dest_prio = candidate_prio;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for(List *e = dest->next; e && (candidate_prio = prio_func(e)) <= prio; e = e->next) {
|
|
|
|
dest = e;
|
|
|
|
dest_prio = candidate_prio;
|
|
|
|
}
|
2017-09-29 21:03:49 +02:00
|
|
|
}
|
|
|
|
|
2017-11-23 16:27:41 +01:00
|
|
|
if(dest == *list_head && dest_prio > prio) {
|
2017-09-29 21:03:49 +02:00
|
|
|
elem->next = dest;
|
|
|
|
elem->prev = dest->prev;
|
|
|
|
|
|
|
|
if(elem->prev) {
|
|
|
|
elem->prev->next = elem;
|
|
|
|
}
|
|
|
|
|
|
|
|
dest->prev = elem;
|
|
|
|
*list_head = elem;
|
|
|
|
} else {
|
|
|
|
elem->prev = dest;
|
|
|
|
elem->next = dest->next;
|
|
|
|
|
|
|
|
if(dest->next) {
|
|
|
|
dest->next->prev = elem;
|
|
|
|
}
|
|
|
|
|
|
|
|
dest->next = elem;
|
|
|
|
}
|
|
|
|
|
|
|
|
return elem;
|
|
|
|
}
|
|
|
|
|
2018-01-09 20:52:20 +01:00
|
|
|
List* list_insert_at_priority_head(List **dest, List *elem, int prio, ListPriorityFunc prio_func){
|
|
|
|
return list_insert_at_priority(dest, elem, prio, prio_func, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
List* list_insert_at_priority_tail(List **dest, List *elem, int prio, ListPriorityFunc prio_func){
|
|
|
|
return list_insert_at_priority(dest, elem, prio, prio_func, false);
|
|
|
|
}
|
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
List* list_unlink(List **dest, List *elem) {
|
|
|
|
if(elem->prev != NULL) {
|
|
|
|
elem->prev->next = elem->next;
|
|
|
|
}
|
2017-03-02 11:23:30 +01:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
if(elem->next != NULL) {
|
|
|
|
elem->next->prev = elem->prev;
|
|
|
|
}
|
2017-09-29 21:03:49 +02:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
if(*dest == elem) {
|
|
|
|
*dest = elem->next;
|
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
return elem;
|
2010-10-27 19:51:49 +02:00
|
|
|
}
|
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
List* list_pop(List **dest) {
|
2017-12-13 20:05:12 +01:00
|
|
|
if(*dest == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
return list_unlink(dest, *dest);
|
2010-11-14 13:24:56 +01:00
|
|
|
}
|
2011-05-13 19:03:02 +02:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
void* list_foreach(List **dest, ListForeachCallback callback, void *arg) {
|
|
|
|
List *e = *dest;
|
2017-02-28 18:16:38 +01:00
|
|
|
|
|
|
|
while(e != 0) {
|
2017-11-21 15:45:01 +01:00
|
|
|
void *ret;
|
|
|
|
List *tmp = e;
|
|
|
|
e = e->next;
|
2017-02-28 18:16:38 +01:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
if((ret = callback(dest, tmp, arg)) != NULL) {
|
|
|
|
return ret;
|
2011-05-13 19:03:02 +02:00
|
|
|
}
|
|
|
|
}
|
2017-02-11 04:52:08 +01:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
return NULL;
|
2011-05-13 19:03:02 +02:00
|
|
|
}
|
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
void* list_callback_free_element(List **dest, List *elem, void *arg) {
|
|
|
|
list_unlink(dest, elem);
|
|
|
|
free(elem);
|
|
|
|
return NULL;
|
2011-05-13 19:03:02 +02:00
|
|
|
}
|
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
void list_free_all(List **dest) {
|
|
|
|
list_foreach(dest, list_callback_free_element, NULL);
|
2017-02-23 11:43:45 +01:00
|
|
|
}
|
2017-02-28 15:38:02 +01:00
|
|
|
|
2017-11-21 15:45:01 +01:00
|
|
|
ListContainer* list_wrap_container(void *data) {
|
|
|
|
ListContainer *c = calloc(1, sizeof(ListContainer));
|
|
|
|
c->data = data;
|
|
|
|
return c;
|
2017-02-28 15:38:02 +01:00
|
|
|
}
|