BLI_linklist: Add a new helper to move an item (identified by its current index) to a new position in the list.

This commit is contained in:
Bastien Montagne 2015-02-10 17:28:55 +01:00
parent a9c5d0ba51
commit bc218cf4d2
2 changed files with 73 additions and 0 deletions

View File

@ -54,6 +54,8 @@ struct LinkNode *BLI_linklist_find(struct LinkNode *list, int index);
void BLI_linklist_reverse(struct LinkNode **listp);
void BLI_linklist_move_item(struct LinkNode **listp, int curr_index, int new_index);
void BLI_linklist_prepend_nlink(struct LinkNode **listp, void *ptr, struct LinkNode *nlink);
void BLI_linklist_prepend(struct LinkNode **listp, void *ptr);
void BLI_linklist_prepend_arena(struct LinkNode **listp, void *ptr, struct MemArena *ma);

View File

@ -86,6 +86,77 @@ void BLI_linklist_reverse(LinkNode **listp)
*listp = rhead;
}
/**
* Move an item from its current position to a new one inside a single-linked list.
* Note *listp may be modified.
*/
void BLI_linklist_move_item(LinkNode **listp, int curr_index, int new_index)
{
LinkNode *lnk, *lnk_psrc = NULL, *lnk_pdst = NULL;
int i;
if (new_index == curr_index) {
return;
}
if (new_index < curr_index) {
for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) {
if (i == new_index - 1) {
lnk_pdst = lnk;
}
else if (i == curr_index - 1) {
lnk_psrc = lnk;
break;
}
}
if (!(lnk_psrc && lnk_psrc->next && (!lnk_pdst || lnk_pdst->next))) {
/* Invalid indices, abort. */
return;
}
lnk = lnk_psrc->next;
lnk_psrc->next = lnk->next;
if (lnk_pdst) {
lnk->next = lnk_pdst->next;
lnk_pdst->next = lnk;
}
else {
/* destination is first element of the list... */
lnk->next = *listp;
*listp = lnk;
}
}
else {
for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) {
if (i == new_index) {
lnk_pdst = lnk;
break;
}
else if (i == curr_index - 1) {
lnk_psrc = lnk;
}
}
if (!(lnk_pdst && (!lnk_psrc || lnk_psrc->next))) {
/* Invalid indices, abort. */
return;
}
if (lnk_psrc) {
lnk = lnk_psrc->next;
lnk_psrc->next = lnk->next;
}
else {
/* source is first element of the list... */
lnk = *listp;
*listp = lnk->next;
}
lnk->next = lnk_pdst->next;
lnk_pdst->next = lnk;
}
}
/**
* A version of prepend that takes the allocated link.
*/