diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenlib/BLI_listbase.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/listbase.c | 38 |
2 files changed, 40 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index fb388977ddf..fec05221596 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -73,6 +73,8 @@ void BLI_freelist(struct ListBase *listbase) ATTR_NONNULL(1); int BLI_countlist(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1); +void BLI_swaplinks(struct ListBase *listbase, void *vlinka, void *vlinkb) ATTR_NONNULL(1, 2); + void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2); void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1, 2); void BLI_listbase_reverse(struct ListBase *lb) ATTR_NONNULL(1); diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index d9cf8971246..6d61a046094 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -130,6 +130,44 @@ bool BLI_remlink_safe(ListBase *listbase, void *vlink) } /** + * Swaps \a vlinka and \a vlinkb in the list. Assumes they are both already in the list! + */ +void BLI_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb) +{ + Link *linka = vlinka; + Link *linkb = vlinkb; + + if (!linka || !linkb) + return; + + if (linkb->next == linka) { + SWAP(Link *, linka, linkb); + } + + if (linka->next == linkb) { + linka->next = linkb->next; + linkb->prev = linka->prev; + linka->prev = linkb; + linkb->next = linka; + } + else { /* Non-contiguous items, we can safely swap. */ + SWAP(Link *, linka->prev, linkb->prev); + SWAP(Link *, linka->next, linkb->next); + } + + /* Update neighbors of linka and linkb. */ + if (linka->prev) linka->prev->next = linka; + if (linka->next) linka->next->prev = linka; + if (linkb->prev) linkb->prev->next = linkb; + if (linkb->next) linkb->next->prev = linkb; + + if (listbase->last == linka) listbase->last = linkb; + else if (listbase->last == linkb) listbase->last = linka; + if (listbase->first == linka) listbase->first = linkb; + else if (listbase->first == linkb) listbase->first = linka; +} + +/** * Removes the head from \a listbase and returns it. */ void *BLI_pophead(ListBase *listbase) |