imlib/collections: Add support for moving items between lists.

This commit is contained in:
Kwabena W. Agyeman 2024-06-19 18:11:51 -07:00
parent 8ea5273324
commit 13ab81c0ee
2 changed files with 77 additions and 89 deletions

View File

@ -211,106 +211,91 @@ size_t list_size(list_t *ptr) {
return ptr->size; return ptr->size;
} }
void list_push_front(list_t *ptr, void *data) { static void list_link(list_t *dst, list_lnk_t *insert_before, list_lnk_t *lnk) {
list_lnk_t *tmp = (list_lnk_t *) xalloc(sizeof(list_lnk_t) + ptr->data_len); if (!dst->size) {
memcpy(tmp->data, data, ptr->data_len); lnk->next = NULL;
lnk->prev = NULL;
if (ptr->size++) { dst->head = lnk;
tmp->next = ptr->head; dst->tail = lnk;
tmp->prev = NULL; } else if (dst->head == insert_before) {
ptr->head->prev = tmp; lnk->next = insert_before;
ptr->head = tmp; lnk->prev = NULL;
insert_before->prev = lnk;
dst->head = lnk;
} else if (!insert_before) {
lnk->next = NULL;
lnk->prev = dst->tail;
dst->tail->next = lnk;
dst->tail = lnk;
} else { } else {
tmp->next = NULL; lnk->next = insert_before;
tmp->prev = NULL; lnk->prev = insert_before->prev;
ptr->head = tmp; insert_before->prev->next = lnk;
ptr->tail = tmp; insert_before->prev = lnk;
} }
dst->size += 1;
} }
void list_push_back(list_t *ptr, void *data) { static void list_unlink(list_t *src, list_lnk_t *lnk) {
list_lnk_t *tmp = (list_lnk_t *) xalloc(sizeof(list_lnk_t) + ptr->data_len); if (src->head == lnk) {
memcpy(tmp->data, data, ptr->data_len); if (lnk->next) {
lnk->next->prev = NULL;
if (ptr->size++) { }
tmp->next = NULL; src->head = lnk->next;
tmp->prev = ptr->tail; } else if (src->tail == lnk) {
ptr->tail->next = tmp; if (lnk->prev) {
ptr->tail = tmp; lnk->prev->next = NULL;
}
src->tail = lnk->prev;
} else { } else {
tmp->next = NULL; lnk->prev->next = lnk->next;
tmp->prev = NULL; lnk->next->prev = lnk->prev;
ptr->head = tmp;
ptr->tail = tmp;
}
}
void list_pop_front(list_t *ptr, void *data) {
list_lnk_t *tmp = ptr->head;
if (data) {
memcpy(data, tmp->data, ptr->data_len);
} }
if (tmp->next) { src->size -= 1;
tmp->next->prev = NULL;
}
ptr->head = tmp->next;
ptr->size -= 1;
xfree(tmp);
}
void list_pop_back(list_t *ptr, void *data) {
list_lnk_t *tmp = ptr->tail;
if (data) {
memcpy(data, tmp->data, ptr->data_len);
}
tmp->prev->next = NULL;
ptr->tail = tmp->prev;
ptr->size -= 1;
xfree(tmp);
}
void list_get(list_t *ptr, list_lnk_t *lnk, void *data) {
memcpy(data, lnk->data, ptr->data_len);
}
void list_set(list_t *ptr, list_lnk_t *lnk, void *data) {
memcpy(lnk->data, data, ptr->data_len);
} }
void list_insert(list_t *ptr, list_lnk_t *lnk, void *data) { void list_insert(list_t *ptr, list_lnk_t *lnk, void *data) {
if (ptr->head == lnk) { list_lnk_t *tmp = (list_lnk_t *) xalloc(sizeof(list_lnk_t) + ptr->data_len);
list_push_front(ptr, data); memcpy(tmp->data, data, ptr->data_len);
} else if (!lnk) { list_link(ptr, lnk, tmp);
list_push_back(ptr, data); }
} else {
list_lnk_t *tmp = (list_lnk_t *) xalloc(sizeof(list_lnk_t) + ptr->data_len);
memcpy(tmp->data, data, ptr->data_len);
tmp->next = lnk; void list_push_front(list_t *ptr, void *data) {
tmp->prev = lnk->prev; list_insert(ptr, ptr->head, data);
lnk->prev->next = tmp; }
lnk->prev = tmp;
ptr->size += 1; void list_push_back(list_t *ptr, void *data) {
} list_insert(ptr, NULL, data);
} }
void list_remove(list_t *ptr, list_lnk_t *lnk, void *data) { void list_remove(list_t *ptr, list_lnk_t *lnk, void *data) {
if (ptr->head == lnk) { if (data) {
list_pop_front(ptr, data); memcpy(data, lnk->data, ptr->data_len);
} else if (ptr->tail == lnk) {
list_pop_back(ptr, data);
} else {
if (data) {
memcpy(data, lnk->data, ptr->data_len);
}
lnk->prev->next = lnk->next;
lnk->next->prev = lnk->prev;
ptr->size -= 1;
xfree(lnk);
} }
list_unlink(ptr, lnk);
xfree(lnk);
}
void list_pop_front(list_t *ptr, void *data) {
list_remove(ptr, ptr->head, data);
}
void list_pop_back(list_t *ptr, void *data) {
list_remove(ptr, ptr->tail, data);
}
void list_move(list_t *dst, list_t *src, list_lnk_t *before, list_lnk_t *lnk) {
list_unlink(src, lnk);
list_link(dst, before, lnk);
}
void list_move_front(list_t *dst, list_t *src, list_lnk_t *lnk) {
list_move(dst, src, dst->head, lnk);
}
void list_move_back(list_t *dst, list_t *src, list_lnk_t *lnk) {
list_move(dst, src, NULL, lnk);
} }

View File

@ -88,12 +88,15 @@ void list_copy(list_t *dst, list_t *src);
void list_free(list_t *ptr); void list_free(list_t *ptr);
void list_clear(list_t *ptr); void list_clear(list_t *ptr);
size_t list_size(list_t *ptr); size_t list_size(list_t *ptr);
void list_insert(list_t *ptr, list_lnk_t *lnk, void *data);
void list_push_front(list_t *ptr, void *data); void list_push_front(list_t *ptr, void *data);
void list_push_back(list_t *ptr, void *data); void list_push_back(list_t *ptr, void *data);
void list_remove(list_t *ptr, list_lnk_t *lnk, void *data);
void list_pop_front(list_t *ptr, void *data); void list_pop_front(list_t *ptr, void *data);
void list_pop_back(list_t *ptr, void *data); void list_pop_back(list_t *ptr, void *data);
void list_insert(list_t *ptr, list_lnk_t *lnk, void *data); void list_move(list_t *dst, list_t *src, list_lnk_t *before, list_lnk_t *lnk);
void list_remove(list_t *ptr, list_lnk_t *lnk, void *data); void list_move_front(list_t *dst, list_t *src, list_lnk_t *lnk);
void list_move_back(list_t *dst, list_t *src, list_lnk_t *lnk);
#define list_for_each(iterator, list) \ #define list_for_each(iterator, list) \
for (list_lnk_t *iterator = list->head; iterator != NULL; iterator = iterator->next) for (list_lnk_t *iterator = list->head; iterator != NULL; iterator = iterator->next)
#define list_get_data(iterator) ((void *) iterator->data) #define list_get_data(iterator) ((void *) iterator->data)