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