Blender  V2.93
BLI_linklist.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * Support for linked lists.
19  */
20 
29 #include <stdlib.h>
30 
31 #include "MEM_guardedalloc.h"
32 
33 #include "BLI_linklist.h"
34 #include "BLI_memarena.h"
35 #include "BLI_mempool.h"
36 #include "BLI_utildefines.h"
37 
38 #include "BLI_strict_flags.h"
39 
40 int BLI_linklist_count(const LinkNode *list)
41 {
42  int len;
43 
44  for (len = 0; list; list = list->next) {
45  len++;
46  }
47 
48  return len;
49 }
50 
51 int BLI_linklist_index(const LinkNode *list, void *ptr)
52 {
53  int index;
54 
55  for (index = 0; list; list = list->next, index++) {
56  if (list->link == ptr) {
57  return index;
58  }
59  }
60 
61  return -1;
62 }
63 
65 {
66  int i;
67 
68  for (i = 0; list; list = list->next, i++) {
69  if (i == index) {
70  return list;
71  }
72  }
73 
74  return NULL;
75 }
76 
78 {
79  if (list) {
80  while (list->next) {
81  list = list->next;
82  }
83  }
84  return list;
85 }
86 
88 {
89  LinkNode *rhead = NULL, *cur = *listp;
90 
91  while (cur) {
92  LinkNode *next = cur->next;
93 
94  cur->next = rhead;
95  rhead = cur;
96 
97  cur = next;
98  }
99 
100  *listp = rhead;
101 }
102 
107 void BLI_linklist_move_item(LinkNode **listp, int curr_index, int new_index)
108 {
109  LinkNode *lnk, *lnk_psrc = NULL, *lnk_pdst = NULL;
110  int i;
111 
112  if (new_index == curr_index) {
113  return;
114  }
115 
116  if (new_index < curr_index) {
117  for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) {
118  if (i == new_index - 1) {
119  lnk_pdst = lnk;
120  }
121  else if (i == curr_index - 1) {
122  lnk_psrc = lnk;
123  break;
124  }
125  }
126 
127  if (!(lnk_psrc && lnk_psrc->next && (!lnk_pdst || lnk_pdst->next))) {
128  /* Invalid indices, abort. */
129  return;
130  }
131 
132  lnk = lnk_psrc->next;
133  lnk_psrc->next = lnk->next;
134  if (lnk_pdst) {
135  lnk->next = lnk_pdst->next;
136  lnk_pdst->next = lnk;
137  }
138  else {
139  /* destination is first element of the list... */
140  lnk->next = *listp;
141  *listp = lnk;
142  }
143  }
144  else {
145  for (lnk = *listp, i = 0; lnk; lnk = lnk->next, i++) {
146  if (i == new_index) {
147  lnk_pdst = lnk;
148  break;
149  }
150  if (i == curr_index - 1) {
151  lnk_psrc = lnk;
152  }
153  }
154 
155  if (!(lnk_pdst && (!lnk_psrc || lnk_psrc->next))) {
156  /* Invalid indices, abort. */
157  return;
158  }
159 
160  if (lnk_psrc) {
161  lnk = lnk_psrc->next;
162  lnk_psrc->next = lnk->next;
163  }
164  else {
165  /* source is first element of the list... */
166  lnk = *listp;
167  *listp = lnk->next;
168  }
169  lnk->next = lnk_pdst->next;
170  lnk_pdst->next = lnk;
171  }
172 }
173 
177 void BLI_linklist_prepend_nlink(LinkNode **listp, void *ptr, LinkNode *nlink)
178 {
179  nlink->link = ptr;
180  nlink->next = *listp;
181  *listp = nlink;
182 }
183 
184 void BLI_linklist_prepend(LinkNode **listp, void *ptr)
185 {
186  LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__);
187  BLI_linklist_prepend_nlink(listp, ptr, nlink);
188 }
189 
191 {
192  LinkNode *nlink = BLI_memarena_alloc(ma, sizeof(*nlink));
193  BLI_linklist_prepend_nlink(listp, ptr, nlink);
194 }
195 
196 void BLI_linklist_prepend_pool(LinkNode **listp, void *ptr, BLI_mempool *mempool)
197 {
198  LinkNode *nlink = BLI_mempool_alloc(mempool);
199  BLI_linklist_prepend_nlink(listp, ptr, nlink);
200 }
201 
205 void BLI_linklist_append_nlink(LinkNodePair *list_pair, void *ptr, LinkNode *nlink)
206 {
207  nlink->link = ptr;
208  nlink->next = NULL;
209 
210  if (list_pair->list) {
211  BLI_assert((list_pair->last_node != NULL) && (list_pair->last_node->next == NULL));
212  list_pair->last_node->next = nlink;
213  }
214  else {
215  BLI_assert(list_pair->last_node == NULL);
216  list_pair->list = nlink;
217  }
218 
219  list_pair->last_node = nlink;
220 }
221 
222 void BLI_linklist_append(LinkNodePair *list_pair, void *ptr)
223 {
224  LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__);
225  BLI_linklist_append_nlink(list_pair, ptr, nlink);
226 }
227 
229 {
230  LinkNode *nlink = BLI_memarena_alloc(ma, sizeof(*nlink));
231  BLI_linklist_append_nlink(list_pair, ptr, nlink);
232 }
233 
234 void BLI_linklist_append_pool(LinkNodePair *list_pair, void *ptr, BLI_mempool *mempool)
235 {
236  LinkNode *nlink = BLI_mempool_alloc(mempool);
237  BLI_linklist_append_nlink(list_pair, ptr, nlink);
238 }
239 
240 void *BLI_linklist_pop(struct LinkNode **listp)
241 {
242  /* intentionally no NULL check */
243  void *link = (*listp)->link;
244  void *next = (*listp)->next;
245 
246  MEM_freeN(*listp);
247 
248  *listp = next;
249  return link;
250 }
251 
252 void *BLI_linklist_pop_pool(struct LinkNode **listp, struct BLI_mempool *mempool)
253 {
254  /* intentionally no NULL check */
255  void *link = (*listp)->link;
256  void *next = (*listp)->next;
257 
258  BLI_mempool_free(mempool, (*listp));
259 
260  *listp = next;
261  return link;
262 }
263 
265 {
266  LinkNode *nlink = MEM_mallocN(sizeof(*nlink), __func__);
267  LinkNode *node = *listp;
268 
269  nlink->link = ptr;
270 
271  if (node) {
272  nlink->next = node->next;
273  node->next = nlink;
274  }
275  else {
276  nlink->next = NULL;
277  *listp = nlink;
278  }
279 }
280 
282 {
283  while (list) {
284  LinkNode *next = list->next;
285 
286  if (freefunc) {
287  freefunc(list->link);
288  }
289  MEM_freeN(list);
290 
291  list = next;
292  }
293 }
294 
295 void BLI_linklist_free_pool(LinkNode *list, LinkNodeFreeFP freefunc, struct BLI_mempool *mempool)
296 {
297  while (list) {
298  LinkNode *next = list->next;
299 
300  if (freefunc) {
301  freefunc(list->link);
302  }
303  BLI_mempool_free(mempool, list);
304 
305  list = next;
306  }
307 }
308 
310 {
311  while (list) {
312  LinkNode *next = list->next;
313 
314  MEM_freeN(list->link);
315  MEM_freeN(list);
316 
317  list = next;
318  }
319 }
320 
321 void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata)
322 {
323  for (; list; list = list->next) {
324  applyfunc(list->link, userdata);
325  }
326 }
327 
328 /* -------------------------------------------------------------------- */
329 /* Sort */
330 #define SORT_IMPL_LINKTYPE LinkNode
331 #define SORT_IMPL_LINKTYPE_DATA link
332 
333 /* regular call */
334 #define SORT_IMPL_FUNC linklist_sort_fn
335 #include "list_sort_impl.h"
336 #undef SORT_IMPL_FUNC
337 
338 /* re-entrant call */
339 #define SORT_IMPL_USE_THUNK
340 #define SORT_IMPL_FUNC linklist_sort_fn_r
341 #include "list_sort_impl.h"
342 #undef SORT_IMPL_FUNC
343 #undef SORT_IMPL_USE_THUNK
344 
345 #undef SORT_IMPL_LINKTYPE
346 #undef SORT_IMPL_LINKTYPE_DATA
347 
348 LinkNode *BLI_linklist_sort(LinkNode *list, int (*cmp)(const void *, const void *))
349 {
350  if (list && list->next) {
351  list = linklist_sort_fn(list, cmp);
352  }
353  return list;
354 }
355 
357  int (*cmp)(void *, const void *, const void *),
358  void *thunk)
359 {
360  if (list && list->next) {
361  list = linklist_sort_fn_r(list, cmp, thunk);
362  }
363  return list;
364 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:131
void BLI_mempool_free(BLI_mempool *pool, void *addr) ATTR_NONNULL(1
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_mempool.c:334
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
Read Guarded memory(de)allocation.
OperationNode * node
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong * next
LinkNode * last_node
Definition: BLI_linklist.h:50
LinkNode * list
Definition: BLI_linklist.h:50
void * link
Definition: BLI_linklist.h:40
struct LinkNode * next
Definition: BLI_linklist.h:39
uint len
PointerRNA * ptr
Definition: wm_files.c:3157