BLI_listbase: add `BLI_swaplinks` which swaps given links' positions in given list.
authorBastien Montagne <montagne29@wanadoo.fr>
Tue, 21 Oct 2014 09:56:46 +0000 (11:56 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Tue, 21 Oct 2014 10:07:24 +0000 (12:07 +0200)
Can be much simpler and quicker than using remlink/insert functions.

source/blender/blenlib/BLI_listbase.h
source/blender/blenlib/intern/listbase.c

index fb388977ddfa2b54fb8fb766f0dc0c70795e34e0..fec0522159605ecae6398f120c3cce7f30e92aaa 100644 (file)
@@ -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);
index d9cf8971246a17b45549ae21b93afff9cd3daf4a..6d61a046094cbc9355b03ec7035ea65d7968c185 100644 (file)
@@ -129,6 +129,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.
  */