diff options
-rw-r--r-- | source/blender/blenlib/BLI_linklist.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_linklist.c | 71 |
2 files changed, 73 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h index 2ca363ee780..8dbf7b4a908 100644 --- a/source/blender/blenlib/BLI_linklist.h +++ b/source/blender/blenlib/BLI_linklist.h @@ -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); 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 @@ -87,6 +87,77 @@ void BLI_linklist_reverse(LinkNode **listp) } /** + * 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. */ void BLI_linklist_prepend_nlink(LinkNode **listp, void *ptr, LinkNode *nlink) |