Welcome to mirror list, hosted at ThFree Co, Russian Federation.

BLI_listbase.h « blenlib « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9322fa4c85b122b514229a47eef3750dfd90cac1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright 2001-2002 NaN Holding BV. All rights reserved. */

#pragma once

/** \file
 * \ingroup bli
 */

#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
#include "DNA_listBase.h"
// struct ListBase;
// struct LinkData;

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Returns the position of \a vlink within \a listbase, numbering from 0, or -1 if not found.
 */
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT
    ATTR_NONNULL(1);
/**
 * Returns the 0-based index of the first element of listbase which contains the specified
 * null-terminated string at the specified offset, or -1 if not found.
 */
int BLI_findstringindex(const struct ListBase *listbase,
                        const char *id,
                        int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);

/**
 * Return a ListBase representing the entire list the given Link is in.
 */
ListBase BLI_listbase_from_link(struct Link *some_link);

/* Find forwards. */

/**
 * Returns the nth element of \a listbase, numbering from 0.
 */
void *BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT
    ATTR_NONNULL(1);

/**
 * Returns the nth element after \a link, numbering from 0.
 */
void *BLI_findlinkfrom(struct Link *start, int number) ATTR_WARN_UNUSED_RESULT;

/**
 * Finds the first element of \a listbase which contains the null-terminated
 * string \a id at the specified offset, returning NULL if not found.
 */
void *BLI_findstring(const struct ListBase *listbase,
                     const char *id,
                     int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/**
 * Finds the first element of \a listbase which contains a pointer to the
 * null-terminated string \a id at the specified offset, returning NULL if not found.
 */
void *BLI_findstring_ptr(const struct ListBase *listbase,
                         const char *id,
                         int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/**
 * Finds the first element of listbase which contains the specified pointer value
 * at the specified offset, returning NULL if not found.
 */
void *BLI_findptr(const struct ListBase *listbase,
                  const void *ptr,
                  int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/**
 * Finds the first element of listbase which contains the specified bytes
 * at the specified offset, returning NULL if not found.
 */
void *BLI_listbase_bytes_find(const ListBase *listbase,
                              const void *bytes,
                              size_t bytes_size,
                              int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);
/**
 * Find the first item in the list that matches the given string, or the given index as fallback.
 *
 * \note The string is only used is non-NULL and non-empty.
 *
 * \return The found item, or NULL.
 */
void *BLI_listbase_string_or_index_find(const struct ListBase *listbase,
                                        const char *string,
                                        size_t string_offset,
                                        int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);

/* Find backwards. */

/**
 * Returns the nth-last element of \a listbase, numbering from 0.
 */
void *BLI_rfindlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT
    ATTR_NONNULL(1);
/**
 * Finds the last element of \a listbase which contains the
 * null-terminated string \a id at the specified offset, returning NULL if not found.
 */
void *BLI_rfindstring(const struct ListBase *listbase,
                      const char *id,
                      int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/**
 * Finds the last element of \a listbase which contains a pointer to the
 * null-terminated string \a id at the specified offset, returning NULL if not found.
 */
void *BLI_rfindstring_ptr(const struct ListBase *listbase,
                          const char *id,
                          int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/**
 * Finds the last element of listbase which contains the specified pointer value
 * at the specified offset, returning NULL if not found.
 */
void *BLI_rfindptr(const struct ListBase *listbase,
                   const void *ptr,
                   int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/**
 * Finds the last element of listbase which contains the specified bytes
 * at the specified offset, returning NULL if not found.
 */
void *BLI_listbase_bytes_rfind(const ListBase *listbase,
                               const void *bytes,
                               size_t bytes_size,
                               int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2);

/**
 * Removes and disposes of the entire contents of \a listbase using guardedalloc.
 */
void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1);
/**
 * Appends \a vlink (assumed to begin with a Link) onto listbase.
 */
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
/**
 * Removes \a vlink from \a listbase. Assumes it is linked into there!
 */
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
/**
 * Checks that \a vlink is linked into listbase, removing it from there if so.
 */
bool BLI_remlink_safe(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
/**
 * Removes the head from \a listbase and returns it.
 */
void *BLI_pophead(ListBase *listbase) ATTR_NONNULL(1);
/**
 * Removes the tail from \a listbase and returns it.
 */
void *BLI_poptail(ListBase *listbase) ATTR_NONNULL(1);

/**
 * Prepends \a vlink (assumed to begin with a Link) onto listbase.
 */
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
/**
 * Inserts \a vnewlink immediately preceding \a vnextlink in listbase.
 * Or, if \a vnextlink is NULL, puts \a vnewlink at the end of the list.
 */
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink)
    ATTR_NONNULL(1);
/**
 * Inserts \a vnewlink immediately following \a vprevlink in \a listbase.
 * Or, if \a vprevlink is NULL, puts \a vnewlink at the front of the list.
 */
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink)
    ATTR_NONNULL(1);
/**
 * Insert a link in place of another, without changing its position in the list.
 *
 * Puts `vnewlink` in the position of `vreplacelink`, removing `vreplacelink`.
 * - `vreplacelink` *must* be in the list.
 * - `vnewlink` *must not* be in the list.
 */
void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlink)
    ATTR_NONNULL(1, 2, 3);
/**
 * Sorts the elements of listbase into the order defined by cmp
 * (which should return 1 if its first arg should come after its second arg).
 * This uses insertion sort, so NOT ok for large list.
 */
void BLI_listbase_sort(struct ListBase *listbase, int (*cmp)(const void *, const void *))
    ATTR_NONNULL(1, 2);
void BLI_listbase_sort_r(ListBase *listbase,
                         int (*cmp)(void *, const void *, const void *),
                         void *thunk) ATTR_NONNULL(1, 2);
/**
 * Reinsert \a vlink relative to its current position but offset by \a step. Doesn't move
 * item if new position would exceed list (could optionally move to head/tail).
 *
 * \param step: Absolute value defines step size, sign defines direction. E.g pass -1
 *              to move \a vlink before previous, or 1 to move behind next.
 * \return If position of \a vlink has changed.
 */
bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL();
/**
 * Move the link at the index \a from to the position at index \a to.
 *
 * \return If the move was successful.
 */
bool BLI_listbase_move_index(ListBase *listbase, int from, int to) ATTR_NONNULL();
/**
 * Removes and disposes of the entire contents of listbase using direct free(3).
 */
void BLI_freelist(struct ListBase *listbase) ATTR_NONNULL(1);
/**
 * Returns the number of elements in \a listbase, up until (and including count_max)
 *
 * \note Use to avoid redundant looping.
 */
int BLI_listbase_count_at_most(const struct ListBase *listbase,
                               int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/**
 * Returns the number of elements in \a listbase.
 */
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
/**
 * Removes \a vlink from listbase and disposes of it. Assumes it is linked into there!
 */
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);

/**
 * Swaps \a vlinka and \a vlinkb in the list. Assumes they are both already in the list!
 */
void BLI_listbase_swaplinks(struct ListBase *listbase, void *vlinka, void *vlinkb)
    ATTR_NONNULL(1, 2);
/**
 * Swaps \a vlinka and \a vlinkb from their respective lists.
 * Assumes they are both already in their \a listbasea!
 */
void BLI_listbases_swaplinks(struct ListBase *listbasea,
                             struct ListBase *listbaseb,
                             void *vlinka,
                             void *vlinkb) ATTR_NONNULL(2, 3);

/**
 * Moves the entire contents of \a src onto the end of \a dst.
 */
void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2);
/**
 * Moves the entire contents of \a src at the beginning of \a dst.
 */
void BLI_movelisttolist_reverse(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2);
/**
 * Sets dst to a duplicate of the entire contents of src. dst may be the same as src.
 */
void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1, 2);
void BLI_listbase_reverse(struct ListBase *lb) ATTR_NONNULL(1);
/**
 * \param vlink: Link to make first.
 */
void BLI_listbase_rotate_first(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);
/**
 * \param vlink: Link to make last.
 */
void BLI_listbase_rotate_last(struct ListBase *lb, void *vlink) ATTR_NONNULL(1, 2);

/**
 * Utility functions to avoid first/last references inline all over.
 */
BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
{
  return (lb->first && lb->first == lb->last);
}
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
{
  return (lb->first == (void *)0);
}
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
{
  lb->first = lb->last = (void *)0;
}

/**
 * Equality check for ListBase.
 *
 * This only shallowly compares the ListBase itself (so the first/last
 * pointers), and does not do any equality checks on the list items.
 */
BLI_INLINE bool BLI_listbase_equal(const struct ListBase *a, const struct ListBase *b)
{
  if (a == NULL) {
    return b == NULL;
  }
  if (b == NULL) {
    return false;
  }
  return a->first == b->first && a->last == b->last;
}

/**
 * Create a generic list node containing link to provided data.
 */
struct LinkData *BLI_genericNodeN(void *data);

/**
 * Does a full loop on the list, with any value acting as first
 * (handy for cycling items)
 *
 * \code{.c}
 *
 * LISTBASE_CIRCULAR_FORWARD_BEGIN(listbase, item, item_init)
 * {
 *     ...operate on marker...
 * }
 * LISTBASE_CIRCULAR_FORWARD_END (listbase, item, item_init);
 *
 * \endcode
 */
#define LISTBASE_CIRCULAR_FORWARD_BEGIN(lb, lb_iter, lb_init) \
  if ((lb)->first && (lb_init || (lb_init = (lb)->first))) { \
    lb_iter = lb_init; \
    do {
#define LISTBASE_CIRCULAR_FORWARD_END(lb, lb_iter, lb_init) \
  } \
  while ((lb_iter = (lb_iter)->next ? (lb_iter)->next : (lb)->first), (lb_iter != lb_init)) \
    ; \
  } \
  ((void)0)

#define LISTBASE_CIRCULAR_BACKWARD_BEGIN(type, lb, lb_iter, lb_init) \
  if ((lb)->last && (lb_init || (lb_init = (type)(lb)->last))) { \
    lb_iter = lb_init; \
    do {
#define LISTBASE_CIRCULAR_BACKWARD_END(type, lb, lb_iter, lb_init) \
  } \
  while ((lb_iter = (lb_iter)->prev ? (lb_iter)->prev : (type)(lb)->last), (lb_iter != lb_init)) \
    ; \
  } \
  ((void)0)

#define LISTBASE_FOREACH(type, var, list) \
  for (type var = (type)((list)->first); var != NULL; var = (type)(((Link *)(var))->next))

/**
 * A version of #LISTBASE_FOREACH that supports incrementing an index variable at every step.
 * Including this in the macro helps prevent mistakes where "continue" mistakenly skips the
 * incrementation.
 */
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var) \
  for (type var = (((void)(index_var = 0)), (type)((list)->first)); var != NULL; \
       var = (type)(((Link *)(var))->next), index_var++)

#define LISTBASE_FOREACH_BACKWARD(type, var, list) \
  for (type var = (type)((list)->last); var != NULL; var = (type)(((Link *)(var))->prev))

/**
 * A version of #LISTBASE_FOREACH that supports removing the item we're looping over.
 */
#define LISTBASE_FOREACH_MUTABLE(type, var, list) \
  for (type var = (type)((list)->first), *var##_iter_next; \
       ((var != NULL) ? ((void)(var##_iter_next = (type)(((Link *)(var))->next)), 1) : 0); \
       var = var##_iter_next)

/**
 * A version of #LISTBASE_FOREACH_BACKWARD that supports removing the item we're looping over.
 */
#define LISTBASE_FOREACH_BACKWARD_MUTABLE(type, var, list) \
  for (type var = (type)((list)->last), *var##_iter_prev; \
       ((var != NULL) ? ((void)(var##_iter_prev = (type)(((Link *)(var))->prev)), 1) : 0); \
       var = var##_iter_prev)

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus
BLI_INLINE bool operator==(const ListBase &a, const ListBase &b)
{
  return BLI_listbase_equal(&a, &b);
}
#endif