2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bli
|
2013-02-22 14:12:55 +00:00
|
|
|
*
|
2018-01-19 21:39:18 +11:00
|
|
|
* Manipulations on double-linked list (#ListBase structs).
|
|
|
|
|
*
|
|
|
|
|
* For single linked lists see 'BLI_linklist.h'
|
2011-02-27 20:37:56 +00:00
|
|
|
*/
|
|
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
#include <stdlib.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <string.h>
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "DNA_listBase.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_listbase.h"
|
|
|
|
|
|
2015-06-11 15:13:06 +10:00
|
|
|
#include "BLI_strict_flags.h"
|
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
void BLI_movelisttolist(ListBase *dst, ListBase *src)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
2019-03-27 13:16:10 +11:00
|
|
|
if (src->first == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
if (dst->first == NULL) {
|
|
|
|
|
dst->first = src->first;
|
|
|
|
|
dst->last = src->last;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-12 15:13:06 +00:00
|
|
|
((Link *)dst->last)->next = src->first;
|
|
|
|
|
((Link *)src->first)->prev = dst->last;
|
|
|
|
|
dst->last = src->last;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
2012-05-12 15:13:06 +00:00
|
|
|
src->first = src->last = NULL;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
|
2018-09-29 16:39:45 +02:00
|
|
|
void BLI_movelisttolist_reverse(ListBase *dst, ListBase *src)
|
|
|
|
|
{
|
2019-03-27 13:16:10 +11:00
|
|
|
if (src->first == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-09-29 16:39:45 +02:00
|
|
|
|
|
|
|
|
if (dst->first == NULL) {
|
|
|
|
|
dst->first = src->first;
|
|
|
|
|
dst->last = src->last;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
((Link *)src->last)->next = dst->first;
|
|
|
|
|
((Link *)dst->first)->prev = src->last;
|
|
|
|
|
dst->first = src->first;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
src->first = src->last = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
void BLI_addhead(ListBase *listbase, void *vlink)
|
|
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = vlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (link == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
|
link->next = listbase->first;
|
|
|
|
|
link->prev = NULL;
|
|
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (listbase->first) {
|
|
|
|
|
((Link *)listbase->first)->prev = link;
|
|
|
|
|
}
|
|
|
|
|
if (listbase->last == NULL) {
|
|
|
|
|
listbase->last = link;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
listbase->first = link;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLI_addtail(ListBase *listbase, void *vlink)
|
|
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = vlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (link == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
|
link->next = NULL;
|
|
|
|
|
link->prev = listbase->last;
|
|
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (listbase->last) {
|
|
|
|
|
((Link *)listbase->last)->next = link;
|
|
|
|
|
}
|
|
|
|
|
if (listbase->first == NULL) {
|
|
|
|
|
listbase->first = link;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
listbase->last = link;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLI_remlink(ListBase *listbase, void *vlink)
|
|
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = vlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (link == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (link->next) {
|
|
|
|
|
link->next->prev = link->prev;
|
|
|
|
|
}
|
|
|
|
|
if (link->prev) {
|
|
|
|
|
link->prev->next = link->next;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (listbase->last == link) {
|
|
|
|
|
listbase->last = link->prev;
|
|
|
|
|
}
|
|
|
|
|
if (listbase->first == link) {
|
|
|
|
|
listbase->first = link->next;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-22 14:12:55 +00:00
|
|
|
bool BLI_remlink_safe(ListBase *listbase, void *vlink)
|
merge own commits into render branch into trunk since 27560
27562, 27570, 27571, 27574, 27576, 27577, 27579, 27590, 27591, 27594, 27595, 27596, 27599, 27605, 27611, 27612, 27613, 27614, 27623
2010-03-20 16:41:01 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (BLI_findindex(listbase, vlink) != -1) {
|
merge own commits into render branch into trunk since 27560
27562, 27570, 27571, 27574, 27576, 27577, 27579, 27590, 27591, 27594, 27595, 27596, 27599, 27605, 27611, 27612, 27613, 27614, 27623
2010-03-20 16:41:01 +00:00
|
|
|
BLI_remlink(listbase, vlink);
|
2013-02-22 14:12:55 +00:00
|
|
|
return true;
|
merge own commits into render branch into trunk since 27560
27562, 27570, 27571, 27574, 27576, 27577, 27579, 27590, 27591, 27594, 27595, 27596, 27599, 27605, 27611, 27612, 27613, 27614, 27623
2010-03-20 16:41:01 +00:00
|
|
|
}
|
2020-08-07 11:23:02 +02:00
|
|
|
|
|
|
|
|
return false;
|
merge own commits into render branch into trunk since 27560
27562, 27570, 27571, 27574, 27576, 27577, 27579, 27590, 27591, 27594, 27595, 27596, 27599, 27605, 27611, 27612, 27613, 27614, 27623
2010-03-20 16:41:01 +00:00
|
|
|
}
|
|
|
|
|
|
2014-10-21 14:06:16 +02:00
|
|
|
void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb)
|
2014-10-21 11:56:46 +02:00
|
|
|
{
|
|
|
|
|
Link *linka = vlinka;
|
|
|
|
|
Link *linkb = vlinkb;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (!linka || !linkb) {
|
2014-10-21 11:56:46 +02:00
|
|
|
return;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-21 11:56:46 +02:00
|
|
|
if (linkb->next == linka) {
|
|
|
|
|
SWAP(Link *, linka, linkb);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-21 11:56:46 +02:00
|
|
|
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);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-10-21 11:56:46 +02:00
|
|
|
/* Update neighbors of linka and linkb. */
|
2019-03-27 13:16:10 +11:00
|
|
|
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;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (listbase->last == linka) {
|
|
|
|
|
listbase->last = linkb;
|
|
|
|
|
}
|
|
|
|
|
else if (listbase->last == linkb) {
|
|
|
|
|
listbase->last = linka;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (listbase->first == linka) {
|
|
|
|
|
listbase->first = linkb;
|
|
|
|
|
}
|
|
|
|
|
else if (listbase->first == linkb) {
|
|
|
|
|
listbase->first = linka;
|
|
|
|
|
}
|
2014-10-21 11:56:46 +02:00
|
|
|
}
|
|
|
|
|
|
2017-11-14 16:10:48 +11:00
|
|
|
void BLI_listbases_swaplinks(ListBase *listbasea, ListBase *listbaseb, void *vlinka, void *vlinkb)
|
|
|
|
|
{
|
|
|
|
|
Link *linka = vlinka;
|
|
|
|
|
Link *linkb = vlinkb;
|
|
|
|
|
Link linkc = {NULL};
|
|
|
|
|
|
|
|
|
|
if (!linka || !linkb) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-18 18:06:56 +10:00
|
|
|
/* The reference to `linkc` assigns NULL, not a dangling pointer so it can be ignored. */
|
|
|
|
|
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 1201 /* gcc12.1+ only */
|
|
|
|
|
# pragma GCC diagnostic push
|
|
|
|
|
# pragma GCC diagnostic ignored "-Wdangling-pointer"
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-11-14 16:10:48 +11:00
|
|
|
/* Temporary link to use as placeholder of the links positions */
|
|
|
|
|
BLI_insertlinkafter(listbasea, linka, &linkc);
|
|
|
|
|
|
2022-05-18 18:06:56 +10:00
|
|
|
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 1201 /* gcc12.1+ only */
|
|
|
|
|
# pragma GCC diagnostic pop
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-11-14 16:10:48 +11:00
|
|
|
/* Bring linka into linkb position */
|
|
|
|
|
BLI_remlink(listbasea, linka);
|
|
|
|
|
BLI_insertlinkafter(listbaseb, linkb, linka);
|
|
|
|
|
|
|
|
|
|
/* Bring linkb into linka position */
|
|
|
|
|
BLI_remlink(listbaseb, linkb);
|
|
|
|
|
BLI_insertlinkafter(listbasea, &linkc, linkb);
|
|
|
|
|
|
|
|
|
|
/* Remove temporary link */
|
|
|
|
|
BLI_remlink(listbasea, &linkc);
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-26 23:37:08 +00:00
|
|
|
void *BLI_pophead(ListBase *listbase)
|
|
|
|
|
{
|
|
|
|
|
Link *link;
|
|
|
|
|
if ((link = listbase->first)) {
|
|
|
|
|
BLI_remlink(listbase, link);
|
|
|
|
|
}
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *BLI_poptail(ListBase *listbase)
|
|
|
|
|
{
|
|
|
|
|
Link *link;
|
|
|
|
|
if ((link = listbase->last)) {
|
|
|
|
|
BLI_remlink(listbase, link);
|
|
|
|
|
}
|
|
|
|
|
return link;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
|
void BLI_freelinkN(ListBase *listbase, void *vlink)
|
|
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = vlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (link == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2012-04-29 15:47:02 +00:00
|
|
|
BLI_remlink(listbase, link);
|
2008-12-20 10:02:00 +00:00
|
|
|
MEM_freeN(link);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-11 15:13:06 +10:00
|
|
|
/**
|
|
|
|
|
* Assigns all #Link.prev pointers from #Link.next
|
|
|
|
|
*/
|
|
|
|
|
static void listbase_double_from_single(Link *iter, ListBase *listbase)
|
|
|
|
|
{
|
|
|
|
|
Link *prev = NULL;
|
|
|
|
|
listbase->first = iter;
|
|
|
|
|
do {
|
|
|
|
|
iter->prev = prev;
|
|
|
|
|
prev = iter;
|
|
|
|
|
} while ((iter = iter->next));
|
|
|
|
|
listbase->last = prev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SORT_IMPL_LINKTYPE Link
|
|
|
|
|
|
|
|
|
|
/* regular call */
|
|
|
|
|
#define SORT_IMPL_FUNC listbase_sort_fn
|
|
|
|
|
#include "list_sort_impl.h"
|
|
|
|
|
#undef SORT_IMPL_FUNC
|
|
|
|
|
|
2019-09-30 17:06:28 +10:00
|
|
|
/* re-entrant call */
|
2015-06-11 15:13:06 +10:00
|
|
|
#define SORT_IMPL_USE_THUNK
|
|
|
|
|
#define SORT_IMPL_FUNC listbase_sort_fn_r
|
|
|
|
|
#include "list_sort_impl.h"
|
|
|
|
|
#undef SORT_IMPL_FUNC
|
|
|
|
|
#undef SORT_IMPL_USE_THUNK
|
|
|
|
|
|
|
|
|
|
#undef SORT_IMPL_LINKTYPE
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2014-11-16 13:57:58 +01:00
|
|
|
void BLI_listbase_sort(ListBase *listbase, int (*cmp)(const void *, const void *))
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
2012-03-06 18:40:15 +00:00
|
|
|
if (listbase->first != listbase->last) {
|
2015-06-11 15:13:06 +10:00
|
|
|
Link *head = listbase->first;
|
|
|
|
|
head = listbase_sort_fn(head, cmp);
|
|
|
|
|
listbase_double_from_single(head, listbase);
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-11 15:07:14 +10:00
|
|
|
void BLI_listbase_sort_r(ListBase *listbase,
|
|
|
|
|
int (*cmp)(void *, const void *, const void *),
|
|
|
|
|
void *thunk)
|
2014-02-13 13:08:05 +11:00
|
|
|
{
|
|
|
|
|
if (listbase->first != listbase->last) {
|
2015-06-11 15:13:06 +10:00
|
|
|
Link *head = listbase->first;
|
|
|
|
|
head = listbase_sort_fn_r(head, cmp, thunk);
|
|
|
|
|
listbase_double_from_single(head, listbase);
|
2014-02-13 13:08:05 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink)
|
|
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *prevlink = vprevlink;
|
|
|
|
|
Link *newlink = vnewlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
|
/* newlink before nextlink */
|
2019-03-27 13:16:10 +11:00
|
|
|
if (newlink == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
|
/* empty list */
|
2012-10-21 05:46:41 +00:00
|
|
|
if (listbase->first == NULL) {
|
2012-05-12 15:13:06 +00:00
|
|
|
listbase->first = newlink;
|
|
|
|
|
listbase->last = newlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
/* insert at head of list */
|
2012-10-21 05:46:41 +00:00
|
|
|
if (prevlink == NULL) {
|
2008-12-20 10:02:00 +00:00
|
|
|
newlink->prev = NULL;
|
|
|
|
|
newlink->next = listbase->first;
|
2013-02-22 14:12:55 +00:00
|
|
|
newlink->next->prev = newlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
listbase->first = newlink;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* at end of list */
|
2013-02-22 14:12:55 +00:00
|
|
|
if (listbase->last == prevlink) {
|
2008-12-20 10:02:00 +00:00
|
|
|
listbase->last = newlink;
|
2013-02-22 14:12:55 +00:00
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
|
newlink->next = prevlink->next;
|
|
|
|
|
newlink->prev = prevlink;
|
|
|
|
|
prevlink->next = newlink;
|
2013-02-22 14:12:55 +00:00
|
|
|
if (newlink->next) {
|
|
|
|
|
newlink->next->prev = newlink;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink)
|
|
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *nextlink = vnextlink;
|
|
|
|
|
Link *newlink = vnewlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
|
/* newlink before nextlink */
|
2019-03-27 13:16:10 +11:00
|
|
|
if (newlink == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
|
|
|
|
/* empty list */
|
2012-10-21 05:46:41 +00:00
|
|
|
if (listbase->first == NULL) {
|
2012-05-12 15:13:06 +00:00
|
|
|
listbase->first = newlink;
|
|
|
|
|
listbase->last = newlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
/* insert at end of list */
|
2012-10-21 05:46:41 +00:00
|
|
|
if (nextlink == NULL) {
|
2012-05-12 15:13:06 +00:00
|
|
|
newlink->prev = listbase->last;
|
|
|
|
|
newlink->next = NULL;
|
|
|
|
|
((Link *)listbase->last)->next = newlink;
|
|
|
|
|
listbase->last = newlink;
|
2008-12-20 10:02:00 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* at beginning of list */
|
2013-02-22 14:12:55 +00:00
|
|
|
if (listbase->first == nextlink) {
|
2008-12-20 10:02:00 +00:00
|
|
|
listbase->first = newlink;
|
2013-02-22 14:12:55 +00:00
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
newlink->next = nextlink;
|
|
|
|
|
newlink->prev = nextlink->prev;
|
|
|
|
|
nextlink->prev = newlink;
|
2013-02-22 14:12:55 +00:00
|
|
|
if (newlink->prev) {
|
|
|
|
|
newlink->prev->next = newlink;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
|
2017-04-09 16:07:09 +10:00
|
|
|
void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlink)
|
|
|
|
|
{
|
|
|
|
|
Link *l_old = vreplacelink;
|
|
|
|
|
Link *l_new = vnewlink;
|
|
|
|
|
|
|
|
|
|
/* update adjacent links */
|
|
|
|
|
if (l_old->next != NULL) {
|
|
|
|
|
l_old->next->prev = l_new;
|
|
|
|
|
}
|
|
|
|
|
if (l_old->prev != NULL) {
|
|
|
|
|
l_old->prev->next = l_new;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set direct links */
|
|
|
|
|
l_new->next = l_old->next;
|
|
|
|
|
l_new->prev = l_old->prev;
|
|
|
|
|
|
|
|
|
|
/* update list */
|
|
|
|
|
if (listbase->first == l_old) {
|
|
|
|
|
listbase->first = l_new;
|
|
|
|
|
}
|
|
|
|
|
if (listbase->last == l_old) {
|
|
|
|
|
listbase->last = l_new;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-18 21:36:34 +02:00
|
|
|
bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step)
|
|
|
|
|
{
|
|
|
|
|
Link *link = vlink;
|
|
|
|
|
Link *hook = link;
|
|
|
|
|
const bool is_up = step < 0;
|
|
|
|
|
|
2016-09-19 10:18:10 +02:00
|
|
|
if (step == 0) {
|
2016-09-18 21:36:34 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
BLI_assert(BLI_findindex(listbase, link) != -1);
|
|
|
|
|
|
|
|
|
|
/* find link to insert before/after */
|
2020-03-06 17:18:10 +01:00
|
|
|
const int abs_step = abs(step);
|
|
|
|
|
for (int i = 0; i < abs_step; i++) {
|
2016-09-18 21:36:34 +02:00
|
|
|
hook = is_up ? hook->prev : hook->next;
|
|
|
|
|
if (!hook) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* reinsert link */
|
|
|
|
|
BLI_remlink(listbase, vlink);
|
|
|
|
|
if (is_up) {
|
|
|
|
|
BLI_insertlinkbefore(listbase, hook, vlink);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_insertlinkafter(listbase, hook, vlink);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-04 22:09:57 +03:00
|
|
|
bool BLI_listbase_move_index(ListBase *listbase, int from, int to)
|
|
|
|
|
{
|
|
|
|
|
if (from == to) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find the link to move. */
|
|
|
|
|
void *link = BLI_findlink(listbase, from);
|
|
|
|
|
|
|
|
|
|
if (!link) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return BLI_listbase_link_move(listbase, link, to - from);
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
void BLI_freelist(ListBase *listbase)
|
|
|
|
|
{
|
|
|
|
|
Link *link, *next;
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
link = listbase->first;
|
2008-12-20 10:02:00 +00:00
|
|
|
while (link) {
|
2012-05-12 15:13:06 +00:00
|
|
|
next = link->next;
|
2008-12-20 10:02:00 +00:00
|
|
|
free(link);
|
2012-05-12 15:13:06 +00:00
|
|
|
link = next;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
2014-05-19 00:24:45 +10:00
|
|
|
|
|
|
|
|
BLI_listbase_clear(listbase);
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BLI_freelistN(ListBase *listbase)
|
|
|
|
|
{
|
|
|
|
|
Link *link, *next;
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
link = listbase->first;
|
2008-12-20 10:02:00 +00:00
|
|
|
while (link) {
|
2012-05-12 15:13:06 +00:00
|
|
|
next = link->next;
|
2008-12-20 10:02:00 +00:00
|
|
|
MEM_freeN(link);
|
2012-05-12 15:13:06 +00:00
|
|
|
link = next;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
2014-05-19 00:24:45 +10:00
|
|
|
|
|
|
|
|
BLI_listbase_clear(listbase);
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
|
2018-04-03 17:05:21 +02:00
|
|
|
int BLI_listbase_count_at_most(const ListBase *listbase, const int count_max)
|
2014-11-16 14:02:18 +01:00
|
|
|
{
|
|
|
|
|
Link *link;
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
for (link = listbase->first; link && count != count_max; link = link->next) {
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
|
2014-11-16 13:57:58 +01:00
|
|
|
int BLI_listbase_count(const ListBase *listbase)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
|
|
|
|
Link *link;
|
|
|
|
|
int count = 0;
|
2014-11-16 14:02:18 +01:00
|
|
|
|
|
|
|
|
for (link = listbase->first; link; link = link->next) {
|
|
|
|
|
count++;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
2014-11-16 14:02:18 +01:00
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
void *BLI_findlink(const ListBase *listbase, int number)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
|
|
|
|
Link *link = NULL;
|
|
|
|
|
|
|
|
|
|
if (number >= 0) {
|
|
|
|
|
link = listbase->first;
|
|
|
|
|
while (link != NULL && number != 0) {
|
|
|
|
|
number--;
|
|
|
|
|
link = link->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-03 22:07:58 +00:00
|
|
|
void *BLI_rfindlink(const ListBase *listbase, int number)
|
|
|
|
|
{
|
|
|
|
|
Link *link = NULL;
|
|
|
|
|
|
|
|
|
|
if (number >= 0) {
|
|
|
|
|
link = listbase->last;
|
|
|
|
|
while (link != NULL && number != 0) {
|
|
|
|
|
number--;
|
|
|
|
|
link = link->prev;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
|
GPencil: Update-on-write using update cache
This implements the update cache described in T95401.
The cache is currently only used for drawing strokes and
sculpting (using the push brush).
**Note: Making use of the cache throughout grease pencil will
have to be done incrementally in other patches. **
The update cache stores what elements have changed in the
original data-block since the last time the eval object
was updated. Additionally, the update cache can store multiple
updates to the data and minimizes the number of elements
that need to be copied.
Elements can be tagged using `BKE_gpencil_tag_full_update` and
`BKE_gpencil_tag_light_update`. A full update means that the element
itself will be copied but also all of the content inside. E.g. when a
layer is tagged for a full update, the layer, all the frames inside the
layer and all the strokes inside the frames will be copied.
A light update means that only the properties of the element are copied
without any of the content. E.g. if a layer is tagged with a light
update, it will copy the layer name, opacity, transform, etc.
When the update cache is in use (e.g. elements have been tagged) then
the depsgraph will not trigger a copy-on-write, but an update-on-write.
This means that the update cache will be used to determine what elements
have changed and then only those elements will be copied over to the
eval object.
If the update cache is empty or the data block was tagged with a full
update, we always fall back to a copy-on-write.
Currently, the update cache is only used by the active depsgraph. This
is because we need to free the update cache after an update-on-write so
it's reset and we need to make sure it is not freed or read by other
depsgraphs.
Co-authored-by: @yann-lty
This patch was contributed by The SPA Studios.
Reviewed By: sergey, antoniov, #dependency_graph, pepeland, mendio
Maniphest Tasks: T95401
Differential Revision: https://developer.blender.org/D13984
2022-02-10 11:34:12 +01:00
|
|
|
void *BLI_findlinkfrom(Link *start, int number)
|
|
|
|
|
{
|
|
|
|
|
Link *link = NULL;
|
|
|
|
|
|
|
|
|
|
if (number >= 0) {
|
|
|
|
|
link = start;
|
|
|
|
|
while (link != NULL && number != 0) {
|
|
|
|
|
number--;
|
|
|
|
|
link = link->next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-15 04:44:10 +00:00
|
|
|
int BLI_findindex(const ListBase *listbase, const void *vlink)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = NULL;
|
|
|
|
|
int number = 0;
|
2013-05-30 19:05:46 +00:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (vlink == NULL) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
link = listbase->first;
|
2008-12-20 10:02:00 +00:00
|
|
|
while (link) {
|
2019-03-27 13:16:10 +11:00
|
|
|
if (link == vlink) {
|
2008-12-20 10:02:00 +00:00
|
|
|
return number;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
number++;
|
2012-05-12 15:13:06 +00:00
|
|
|
link = link->next;
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2008-12-20 10:02:00 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
void *BLI_findstring(const ListBase *listbase, const char *id, const int offset)
|
2009-12-29 15:40:26 +00:00
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = NULL;
|
2009-12-29 15:40:26 +00:00
|
|
|
const char *id_iter;
|
|
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (id == NULL) {
|
2018-07-31 10:22:19 +02:00
|
|
|
return NULL;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
for (link = listbase->first; link; link = link->next) {
|
|
|
|
|
id_iter = ((const char *)link) + offset;
|
2009-12-29 15:47:16 +00:00
|
|
|
|
2015-01-26 16:03:11 +01:00
|
|
|
if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
|
2010-08-13 06:30:04 +00:00
|
|
|
return link;
|
2011-05-02 13:35:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
2010-08-13 06:30:04 +00:00
|
|
|
|
2011-05-02 13:35:04 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
void *BLI_rfindstring(const ListBase *listbase, const char *id, const int offset)
|
|
|
|
|
{
|
2021-12-09 20:01:44 +11:00
|
|
|
/* Same as #BLI_findstring but find reverse. */
|
|
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = NULL;
|
2011-05-02 13:35:04 +00:00
|
|
|
const char *id_iter;
|
|
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
for (link = listbase->last; link; link = link->prev) {
|
|
|
|
|
id_iter = ((const char *)link) + offset;
|
2011-05-02 13:35:04 +00:00
|
|
|
|
2015-01-26 16:03:11 +01:00
|
|
|
if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
|
2011-05-02 13:35:04 +00:00
|
|
|
return link;
|
|
|
|
|
}
|
2010-08-13 06:30:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
void *BLI_findstring_ptr(const ListBase *listbase, const char *id, const int offset)
|
2010-08-13 06:30:04 +00:00
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = NULL;
|
2010-08-13 06:30:04 +00:00
|
|
|
const char *id_iter;
|
|
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
for (link = listbase->first; link; link = link->next) {
|
2010-08-13 06:30:04 +00:00
|
|
|
/* exact copy of BLI_findstring(), except for this line */
|
2012-05-12 15:13:06 +00:00
|
|
|
id_iter = *((const char **)(((const char *)link) + offset));
|
2010-08-13 06:30:04 +00:00
|
|
|
|
2015-01-26 16:03:11 +01:00
|
|
|
if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
|
2009-12-29 15:40:26 +00:00
|
|
|
return link;
|
2011-05-02 13:35:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-12-29 15:40:26 +00:00
|
|
|
|
2011-05-02 13:35:04 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
void *BLI_rfindstring_ptr(const ListBase *listbase, const char *id, const int offset)
|
|
|
|
|
{
|
2021-12-09 20:01:44 +11:00
|
|
|
/* Same as #BLI_findstring_ptr but find reverse. */
|
|
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = NULL;
|
2011-05-02 13:35:04 +00:00
|
|
|
const char *id_iter;
|
|
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
for (link = listbase->last; link; link = link->prev) {
|
2011-05-02 13:35:04 +00:00
|
|
|
/* exact copy of BLI_rfindstring(), except for this line */
|
2012-05-12 15:13:06 +00:00
|
|
|
id_iter = *((const char **)(((const char *)link) + offset));
|
2011-05-02 13:35:04 +00:00
|
|
|
|
2015-01-26 16:03:11 +01:00
|
|
|
if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
|
2011-05-02 13:35:04 +00:00
|
|
|
return link;
|
|
|
|
|
}
|
2009-12-29 15:40:26 +00:00
|
|
|
}
|
|
|
|
|
|
2012-08-18 16:16:13 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *BLI_findptr(const ListBase *listbase, const void *ptr, const int offset)
|
|
|
|
|
{
|
|
|
|
|
Link *link = NULL;
|
|
|
|
|
const void *ptr_iter;
|
|
|
|
|
|
|
|
|
|
for (link = listbase->first; link; link = link->next) {
|
|
|
|
|
/* exact copy of BLI_findstring(), except for this line */
|
2013-02-22 14:12:55 +00:00
|
|
|
ptr_iter = *((const void **)(((const char *)link) + offset));
|
2012-08-18 16:16:13 +00:00
|
|
|
|
|
|
|
|
if (ptr == ptr_iter) {
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset)
|
|
|
|
|
{
|
2021-12-09 20:01:44 +11:00
|
|
|
/* Same as #BLI_findptr but find reverse. */
|
|
|
|
|
|
2012-08-18 16:16:13 +00:00
|
|
|
Link *link = NULL;
|
|
|
|
|
const void *ptr_iter;
|
|
|
|
|
|
|
|
|
|
for (link = listbase->last; link; link = link->prev) {
|
|
|
|
|
/* exact copy of BLI_rfindstring(), except for this line */
|
2013-02-22 14:12:55 +00:00
|
|
|
ptr_iter = *((const void **)(((const char *)link) + offset));
|
2012-08-18 16:16:13 +00:00
|
|
|
|
|
|
|
|
if (ptr == ptr_iter) {
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-29 15:40:26 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-16 12:49:31 +01:00
|
|
|
void *BLI_listbase_bytes_find(const ListBase *listbase,
|
|
|
|
|
const void *bytes,
|
|
|
|
|
const size_t bytes_size,
|
|
|
|
|
const int offset)
|
|
|
|
|
{
|
|
|
|
|
Link *link = NULL;
|
|
|
|
|
const void *ptr_iter;
|
|
|
|
|
|
|
|
|
|
for (link = listbase->first; link; link = link->next) {
|
|
|
|
|
ptr_iter = (const void *)(((const char *)link) + offset);
|
|
|
|
|
|
|
|
|
|
if (memcmp(bytes, ptr_iter, bytes_size) == 0) {
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
void *BLI_listbase_bytes_rfind(const ListBase *listbase,
|
|
|
|
|
const void *bytes,
|
|
|
|
|
const size_t bytes_size,
|
|
|
|
|
const int offset)
|
|
|
|
|
{
|
2021-12-09 20:01:44 +11:00
|
|
|
/* Same as #BLI_listbase_bytes_find but find reverse. */
|
|
|
|
|
|
2017-11-16 12:49:31 +01:00
|
|
|
Link *link = NULL;
|
|
|
|
|
const void *ptr_iter;
|
|
|
|
|
|
|
|
|
|
for (link = listbase->last; link; link = link->prev) {
|
|
|
|
|
ptr_iter = (const void *)(((const char *)link) + offset);
|
|
|
|
|
|
|
|
|
|
if (memcmp(bytes, ptr_iter, bytes_size) == 0) {
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-19 14:39:40 +01:00
|
|
|
void *BLI_listbase_string_or_index_find(const ListBase *listbase,
|
|
|
|
|
const char *string,
|
|
|
|
|
const size_t string_offset,
|
|
|
|
|
const int index)
|
|
|
|
|
{
|
|
|
|
|
Link *link = NULL;
|
|
|
|
|
Link *link_at_index = NULL;
|
|
|
|
|
|
|
|
|
|
int index_iter;
|
|
|
|
|
for (link = listbase->first, index_iter = 0; link; link = link->next, index_iter++) {
|
|
|
|
|
if (string != NULL && string[0] != '\0') {
|
|
|
|
|
const char *string_iter = ((const char *)link) + string_offset;
|
|
|
|
|
|
|
|
|
|
if (string[0] == string_iter[0] && STREQ(string, string_iter)) {
|
|
|
|
|
return link;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (index_iter == index) {
|
|
|
|
|
link_at_index = link;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return link_at_index;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
int BLI_findstringindex(const ListBase *listbase, const char *id, const int offset)
|
2010-02-02 21:43:26 +00:00
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
Link *link = NULL;
|
2010-02-02 21:43:26 +00:00
|
|
|
const char *id_iter;
|
2012-05-12 15:13:06 +00:00
|
|
|
int i = 0;
|
2010-02-02 21:43:26 +00:00
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
link = listbase->first;
|
2010-02-02 21:43:26 +00:00
|
|
|
while (link) {
|
2012-05-12 15:13:06 +00:00
|
|
|
id_iter = ((const char *)link) + offset;
|
2010-02-02 21:43:26 +00:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (id[0] == id_iter[0] && STREQ(id, id_iter)) {
|
2010-02-02 21:43:26 +00:00
|
|
|
return i;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2010-02-02 21:43:26 +00:00
|
|
|
i++;
|
2012-05-12 15:13:06 +00:00
|
|
|
link = link->next;
|
2010-02-02 21:43:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-17 17:31:15 +01:00
|
|
|
ListBase BLI_listbase_from_link(Link *some_link)
|
|
|
|
|
{
|
|
|
|
|
ListBase list = {some_link, some_link};
|
|
|
|
|
if (some_link == NULL) {
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find the first element. */
|
|
|
|
|
while (((Link *)list.first)->prev != NULL) {
|
|
|
|
|
list.first = ((Link *)list.first)->prev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find the last element. */
|
|
|
|
|
while (((Link *)list.last)->next != NULL) {
|
|
|
|
|
list.last = ((Link *)list.last)->next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-21 14:49:34 +00:00
|
|
|
void BLI_duplicatelist(ListBase *dst, const ListBase *src)
|
2008-12-20 10:02:00 +00:00
|
|
|
{
|
2010-12-21 14:49:34 +00:00
|
|
|
struct Link *dst_link, *src_link;
|
|
|
|
|
|
|
|
|
|
/* in this order, to ensure it works if dst == src */
|
2012-05-12 15:13:06 +00:00
|
|
|
src_link = src->first;
|
|
|
|
|
dst->first = dst->last = NULL;
|
2010-12-21 14:49:34 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
while (src_link) {
|
2012-05-12 15:13:06 +00:00
|
|
|
dst_link = MEM_dupallocN(src_link);
|
2010-12-21 14:49:34 +00:00
|
|
|
BLI_addtail(dst, dst_link);
|
|
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
src_link = src_link->next;
|
2010-12-21 14:49:34 +00:00
|
|
|
}
|
2008-12-20 10:02:00 +00:00
|
|
|
}
|
|
|
|
|
|
2014-06-25 19:33:35 +10:00
|
|
|
void BLI_listbase_reverse(ListBase *lb)
|
2013-05-11 12:18:12 +00:00
|
|
|
{
|
|
|
|
|
struct Link *curr = lb->first;
|
|
|
|
|
struct Link *prev = NULL;
|
|
|
|
|
struct Link *next = NULL;
|
2013-05-14 06:58:35 +00:00
|
|
|
while (curr) {
|
2013-05-11 12:18:12 +00:00
|
|
|
next = curr->next;
|
|
|
|
|
curr->next = prev;
|
|
|
|
|
curr->prev = next;
|
|
|
|
|
prev = curr;
|
|
|
|
|
curr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* swap first/last */
|
|
|
|
|
curr = lb->first;
|
|
|
|
|
lb->first = lb->last;
|
|
|
|
|
lb->last = curr;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-30 15:01:16 +10:00
|
|
|
void BLI_listbase_rotate_first(ListBase *lb, void *vlink)
|
2013-05-11 12:18:12 +00:00
|
|
|
{
|
|
|
|
|
/* make circular */
|
2013-09-05 11:40:38 +00:00
|
|
|
((Link *)lb->first)->prev = lb->last;
|
|
|
|
|
((Link *)lb->last)->next = lb->first;
|
2013-05-11 12:18:12 +00:00
|
|
|
|
|
|
|
|
lb->first = vlink;
|
2013-09-05 11:40:38 +00:00
|
|
|
lb->last = ((Link *)vlink)->prev;
|
2013-05-11 12:18:12 +00:00
|
|
|
|
2013-09-05 11:40:38 +00:00
|
|
|
((Link *)lb->first)->prev = NULL;
|
|
|
|
|
((Link *)lb->last)->next = NULL;
|
2013-05-11 12:18:12 +00:00
|
|
|
}
|
|
|
|
|
|
2014-07-30 15:01:16 +10:00
|
|
|
void BLI_listbase_rotate_last(ListBase *lb, void *vlink)
|
2013-09-05 11:40:38 +00:00
|
|
|
{
|
|
|
|
|
/* make circular */
|
|
|
|
|
((Link *)lb->first)->prev = lb->last;
|
|
|
|
|
((Link *)lb->last)->next = lb->first;
|
|
|
|
|
|
|
|
|
|
lb->first = ((Link *)vlink)->next;
|
|
|
|
|
lb->last = vlink;
|
|
|
|
|
|
|
|
|
|
((Link *)lb->first)->prev = NULL;
|
|
|
|
|
((Link *)lb->last)->next = NULL;
|
|
|
|
|
}
|
2013-05-11 12:18:12 +00:00
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
LinkData *BLI_genericNodeN(void *data)
|
2009-09-17 10:14:56 +00:00
|
|
|
{
|
|
|
|
|
LinkData *ld;
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (data == NULL) {
|
2009-09-17 10:14:56 +00:00
|
|
|
return NULL;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2009-09-17 10:14:56 +00:00
|
|
|
/* create new link, and make it hold the given data */
|
2013-05-12 05:54:33 +00:00
|
|
|
ld = MEM_callocN(sizeof(LinkData), __func__);
|
2012-05-12 15:13:06 +00:00
|
|
|
ld->data = data;
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2009-09-17 10:14:56 +00:00
|
|
|
return ld;
|
2018-06-17 16:32:54 +02:00
|
|
|
}
|