ClangFormat: apply to source, most of intern
[blender.git] / source / blender / blenlib / BLI_array.h
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) 2008 Blender Foundation.
17  * All rights reserved.
18  */
19
20 #ifndef __BLI_ARRAY_H__
21 #define __BLI_ARRAY_H__
22
23 /** \file
24  * \ingroup bli
25  * \brief A (mainly) macro array library.
26  */
27
28 /* -------------------------------------------------------------------- */
29 /** \name Internal defines
30  * \{ */
31
32 /** this returns the entire size of the array, including any buffering. */
33 #define _bli_array_totalsize_dynamic(arr) \
34   (((arr) == NULL) ? 0 : MEM_allocN_len(arr) / sizeof(*(arr)))
35
36 #define _bli_array_totalsize_static(arr) (sizeof(_##arr##_static) / sizeof(*(arr)))
37
38 #define _bli_array_totalsize(arr) \
39   ((size_t)(((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ? \
40                 _bli_array_totalsize_static(arr) : \
41                 _bli_array_totalsize_dynamic(arr)))
42
43 /** \} */
44
45 /** BLI_array.c
46  *
47  * Doing the realloc in a macro isn't so simple,
48  * so use a function the macros can use.
49  */
50 void _bli_array_grow_func(void **arr_p,
51                           const void *arr_static,
52                           const int sizeof_arr_p,
53                           const int arr_len,
54                           const int num,
55                           const char *alloc_str);
56
57 /* -------------------------------------------------------------------- */
58 /** \name Public defines
59  * \{ */
60
61 /** use ``sizeof(*(arr))`` to ensure the array exists and is an array */
62 #define BLI_array_declare(arr) \
63   int _##arr##_len = ((void)(sizeof(*(arr))), 0); \
64   void *_##arr##_static = NULL
65
66 /**
67  * this will use stack space, up to maxstatic array elements, before
68  * switching to dynamic heap allocation */
69 #define BLI_array_staticdeclare(arr, maxstatic) \
70   int _##arr##_len = 0; \
71   char _##arr##_static[maxstatic * sizeof(*(arr))]
72
73 /** returns the logical size of the array, not including buffering. */
74 #define BLI_array_len(arr) ((void)0, _##arr##_len)
75
76 /**
77  * Grow the array by a fixed number of items.
78  *
79  * Allow for a large 'num' value when the new size is more than double
80  * to allocate the exact sized array. */
81 #define BLI_array_reserve(arr, num) \
82   (void)((((void *)(arr) == NULL) && \
83           ((void *)(_##arr##_static) != \
84            NULL) && /* don't add _##arr##_len below because it must be zero */ \
85           (_bli_array_totalsize_static(arr) >= \
86            _##arr##_len + (num))) ? /* we have an empty array and a static var big enough */ \
87              (void)(arr = (void *)_##arr##_static) : /* use existing static array or allocate */ \
88              (LIKELY(_bli_array_totalsize(arr) >= _##arr##_len + (num)) ? \
89                   (void)0 /* do nothing */ : \
90                   _bli_array_grow_func((void **)&(arr), \
91                                        _##arr##_static, \
92                                        sizeof(*(arr)), \
93                                        _##arr##_len, \
94                                        num, \
95                                        "BLI_array." #arr)))
96
97 /** returns length of array */
98 #define BLI_array_grow_items(arr, num) (BLI_array_reserve(arr, num), (_##arr##_len += num))
99
100 #define BLI_array_grow_one(arr) BLI_array_grow_items(arr, 1)
101
102 /** appends an item to the array. */
103 #define BLI_array_append(arr, item) \
104   ((void)BLI_array_grow_one(arr), (void)(arr[_##arr##_len - 1] = item))
105
106 /**
107  * appends an item to the array and returns a pointer to the item in the array.
108  * item is not a pointer, but actual data value.*/
109 #define BLI_array_append_r(arr, item) \
110   ((void)BLI_array_grow_one(arr), (void)(arr[_##arr##_len - 1] = item), (&arr[_##arr##_len - 1]))
111
112 /** appends (grows) & returns a pointer to the uninitialized memory */
113 #define BLI_array_append_ret(arr) (BLI_array_reserve(arr, 1), &arr[(_##arr##_len++)])
114
115 #define BLI_array_free(arr) \
116   { \
117     if (arr && (char *)arr != _##arr##_static) { \
118       BLI_array_fake_user(arr); \
119       MEM_freeN(arr); \
120     } \
121   } \
122   ((void)0)
123
124 #define BLI_array_pop(arr) ((arr && _##arr##_len) ? arr[--_##arr##_len] : NULL)
125
126 /**
127  * Resets the logical size of an array to zero, but doesn't
128  * free the memory. */
129 #define BLI_array_clear(arr) \
130   { \
131     _##arr##_len = 0; \
132   } \
133   ((void)0)
134
135 /**
136  * Set the length of the array, doesn't actually increase the allocated array
137  * size.  don't use this unless you know what you're doing. */
138 #define BLI_array_len_set(arr, len) \
139   { \
140     _##arr##_len = (len); \
141   } \
142   ((void)0)
143
144 /** only to prevent unused warnings */
145 #define BLI_array_fake_user(arr) ((void)_##arr##_len, (void)_##arr##_static)
146
147 /** \} */
148
149 /* -------------------------------------------------------------------- */
150 /** \name Generic Array Utils
151  * other useful defines
152  * (unrelated to the main array macros)
153  *
154  * \{ */
155
156 /**
157  * not part of the 'API' but handy funcs,
158  * same purpose as #BLI_array_staticdeclare()
159  * but use when the max size is known ahead of time */
160 #define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr) \
161   char _##arr##_static[maxstatic * sizeof(*(arr))]; \
162   const bool _##arr##_is_static = ((void *)_##arr##_static) != \
163                                   (arr = ((realsize) <= maxstatic) ? \
164                                              (void *)_##arr##_static : \
165                                              MEM_mallocN(sizeof(*(arr)) * (realsize), allocstr))
166
167 #define BLI_array_fixedstack_free(arr) \
168   if (_##arr##_is_static) { \
169     MEM_freeN(arr); \
170   } \
171   ((void)0)
172
173 /** \} */
174
175 #endif /* __BLI_ARRAY_H__ */