115 lines
2.7 KiB
C
115 lines
2.7 KiB
C
// vim: set ts=4 sw=4 tw=80 et:
|
|
#include "./collections.h"
|
|
|
|
size_t dl_list_length(const dl_list_t* self) {
|
|
size_t length = 0;
|
|
dl_node_t* i = self->first;
|
|
|
|
while (i != NULL) {
|
|
length++;
|
|
i = i->next;
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
dl_node_t* dl_list_ith(const dl_list_t* self, const size_t position) {
|
|
size_t found;
|
|
dl_node_t* elem = dl_list_ith_or_last(self, position, &found);
|
|
return found != position ? NULL : elem;
|
|
}
|
|
|
|
dl_node_t* dl_list_ith_or_last(const dl_list_t* self, const size_t position,
|
|
size_t* returned) {
|
|
dl_node_t* to_reach = self->first;
|
|
size_t i;
|
|
for (i = 0; i < position && to_reach->next != NULL; i++) {
|
|
to_reach = to_reach->next;
|
|
}
|
|
*returned = i;
|
|
return to_reach;
|
|
}
|
|
|
|
inline dl_node_t* dl_list_alloc_node(void* element) {
|
|
dl_node_t* node = malloc(sizeof(node));
|
|
node->element = element;
|
|
node->next = NULL;
|
|
node->prev = NULL;
|
|
}
|
|
|
|
inline void dl_list_free_node(dl_node_t* node) {
|
|
if (node->element != NULL) {
|
|
free(node->element);
|
|
}
|
|
free(node);
|
|
}
|
|
|
|
inline void dl_list_init(dl_list_t* self) {
|
|
self->first = NULL;
|
|
}
|
|
|
|
inline void dl_list_destroy(dl_list_t* self) {
|
|
while(self->first != NULL) {
|
|
free(dl_list_remove(self, 0));
|
|
}
|
|
}
|
|
|
|
size_t dl_list_copy_slice(const dl_list_t* self, dl_list_t* destination,
|
|
const size_t from, const size_t to) {
|
|
if (from >= to) {
|
|
return 0;
|
|
}
|
|
dl_list_destroy(destination);
|
|
size_t start, i;
|
|
dl_node_t* to_copy = dl_list_ith_or_last(self, to, &start);
|
|
if (to_copy == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
for(i = start; i > from; i--) {
|
|
dl_node_t* copied = malloc(sizeof(dl_node_t));
|
|
memcpy(copied, self, sizeof(dl_node_t));
|
|
dl_list_insert(destination, 0, copied);
|
|
}
|
|
|
|
return start - from;
|
|
}
|
|
|
|
int dl_list_insert(dl_list_t* self, const size_t position, dl_node_t* node) {
|
|
if (position == 0) {
|
|
node->next = self->first;
|
|
node->prev = NULL;
|
|
self->first = node;
|
|
return 0;
|
|
}
|
|
|
|
dl_node_t* to_reach = dl_list_ith(self, position - 1);
|
|
|
|
if (to_reach == NULL) {
|
|
return 2;
|
|
}
|
|
|
|
to_reach->next->prev = node;
|
|
node->next = to_reach->next;
|
|
node->prev = to_reach;
|
|
to_reach->next = node;
|
|
return 0;
|
|
}
|
|
|
|
dl_node_t* dl_list_remove(dl_list_t* self, const size_t position) {
|
|
if(position == 0) {
|
|
dl_node_t* to_remove = self->first;
|
|
self->first = to_remove->next;
|
|
return to_remove;
|
|
}
|
|
|
|
dl_node_t* to_reach = dl_list_ith(self, position - 1);
|
|
if (to_reach == NULL || to_reach->next == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
dl_node_t* to_remove = to_reach->next;
|
|
to_reach->next = to_reach->next->next;
|
|
to_reach->next->prev = to_reach;
|
|
return to_remove;
|
|
}
|