From bc218cf4d24f1cb4653950be84129ff9039b4e65 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 10 Feb 2015 17:28:55 +0100 Subject: BLI_linklist: Add a new helper to move an item (identified by its current index) to a new position in the list. --- source/blender/blenlib/intern/BLI_linklist.c | 71 ++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'source/blender/blenlib/intern/BLI_linklist.c') diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c index 6b79cf97e86..391f3ef7702 100644 --- a/source/blender/blenlib/intern/BLI_linklist.c +++ b/source/blender/blenlib/intern/BLI_linklist.c @@ -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. */ -- cgit v1.2.3