minor change r53918 was supposed to resolve.
[blender.git] / source / blender / blenlib / BLI_array.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joseph Eagar.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #ifndef __BLI_ARRAY_H__
29 #define __BLI_ARRAY_H__
30
31 /** \file BLI_array.h
32  *  \ingroup bli
33  *  \brief A (mainly) macro array library.
34  */
35
36 /* -------------------------------------------------------------------- */
37 /* internal defines */
38
39 /* this returns the entire size of the array, including any buffering. */
40 #define _bli_array_totalsize_dynamic(arr)  (                                  \
41         ((arr) == NULL) ?                                                         \
42             0 :                                                                   \
43             MEM_allocN_len(arr) / sizeof(*arr)                                    \
44 )
45
46 #define _bli_array_totalsize_static(arr)  \
47         (sizeof(_##arr##_static) / sizeof(*arr))
48
49 #define _bli_array_totalsize(arr)  (                                          \
50         (size_t)                                                                  \
51         (((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ?    \
52             _bli_array_totalsize_static(arr) :                                    \
53             _bli_array_totalsize_dynamic(arr))                                    \
54 )
55
56 /* BLI_array.c
57  *
58  * Doing the realloc in a macro isn't so simple,
59  * so use a function the macros can use.
60  */
61 void _bli_array_grow_func(void **arr_p, const void *arr_static,
62                           const int sizeof_arr_p, const int arr_count, const int num,
63                           const char *alloc_str);
64
65
66 /* -------------------------------------------------------------------- */
67 /* public defines */
68
69 #define BLI_array_declare(arr)                                                \
70         int   _##arr##_count = 0;                                                 \
71         void *_##arr##_static = NULL
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##_count = 0;                                                 \
77         char  _##arr##_static[maxstatic * sizeof(arr)]
78
79 /* this returns the logical size of the array, not including buffering. */
80 #define BLI_array_count(arr) _##arr##_count
81
82 /* Grow the array by a fixed number of items. zeroes the new elements.
83  *
84  * Allow for a large 'num' value when the new size is more then double
85  * to allocate the exact sized array. */
86
87 /* grow an array by a specified number of items */
88 #define BLI_array_grow_items(arr, num)  ((                                    \
89         (((void *)(arr) == NULL) &&                                               \
90          ((void *)(_##arr##_static) != NULL) &&                                   \
91         /* don't add _##arr##_count below because it must be zero */              \
92          (_bli_array_totalsize_static(arr) >= _##arr##_count + num)) ?            \
93         /* we have an empty array and a static var big enough */                  \
94         (arr = (void *)_##arr##_static)                                           \
95             :                                                                     \
96         /* use existing static array or allocate */                               \
97         (LIKELY(_bli_array_totalsize(arr) >= _##arr##_count + num) ?              \
98          (void)0 /* do nothing */ :                                               \
99          _bli_array_grow_func((void **)&(arr), _##arr##_static,                   \
100                                sizeof(*arr), _##arr##_count, num,                 \
101                                "BLI_array." #arr),                                \
102          (void)0)  /* msvc2008 needs this */                                      \
103         ),                                                                        \
104         /* increment the array count, all conditions above are accounted for. */  \
105         (_##arr##_count += num))
106
107 /* returns length of array */
108 #define BLI_array_grow_one(arr)  BLI_array_grow_items(arr, 1)
109
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##_count - 1] = item)                                   \
115 )
116
117 /* appends an item to the array and returns a pointer to the item in the array.
118  * item is not a pointer, but actual data value.*/
119 #define BLI_array_append_r(arr, item)  (                                      \
120         (void) BLI_array_grow_one(arr),                                           \
121         (void) (arr[_##arr##_count - 1] = item),                                  \
122         (&arr[_##arr##_count - 1])                                                \
123 )
124
125 #define BLI_array_reserve(arr, num)                                           \
126         BLI_array_grow_items(arr, num), (void)(_##arr##_count -= (num))
127
128
129 #define BLI_array_free(arr)                                                   \
130         if (arr && (char *)arr != _##arr##_static) {                              \
131             BLI_array_fake_user(arr);                                             \
132             MEM_freeN(arr);                                                       \
133         } (void)0
134
135 #define BLI_array_pop(arr)  (                                                 \
136         (arr && _##arr##_count) ?                                                 \
137             arr[--_##arr##_count] :                                               \
138             NULL                                                                  \
139 )
140
141 /* resets the logical size of an array to zero, but doesn't
142  * free the memory. */
143 #define BLI_array_empty(arr)                                                  \
144         { _##arr##_count = 0; } (void)0
145
146 /* set the count of the array, doesn't actually increase the allocated array
147  * size.  don't use this unless you know what you're doing. */
148 #define BLI_array_length_set(arr, count)                                      \
149         { _##arr##_count = (count); }(void)0
150
151 /* only to prevent unused warnings */
152 #define BLI_array_fake_user(arr)                                              \
153         (void)_##arr##_count,                                                     \
154         (void)_##arr##_static
155
156
157 /* -------------------------------------------------------------------- */
158 /* other useful defines
159  * (unrelated to the main array macros) */
160
161 /* not part of the 'API' but handy funcs,
162  * same purpose as BLI_array_staticdeclare()
163  * but use when the max size is known ahead of time */
164 #define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr)      \
165         char _##arr##_static[maxstatic * sizeof(*(arr))];                         \
166         const int _##arr##_is_static = ((void *)_##arr##_static) != (             \
167             arr = ((realsize) <= maxstatic) ?                                     \
168                 (void *)_##arr##_static :                                         \
169                 MEM_mallocN(sizeof(*(arr)) * (realsize), allocstr)                \
170             )                                                                     \
171
172 #define BLI_array_fixedstack_free(arr)                                        \
173         if (_##arr##_is_static) {                                                 \
174                 MEM_freeN(arr);                                                       \
175         } (void)0
176
177
178 /* alloca */
179 #ifdef _MSC_VER
180 #  define alloca _alloca
181 #endif
182
183 #if defined(__MINGW32__)
184 #  include <malloc.h>  /* mingw needs for alloca() */
185 #endif
186
187 #if defined(__GNUC__) || defined(__clang__)
188 #define BLI_array_alloca(arr, realsize) \
189         (typeof(arr))alloca(sizeof(*arr) * (realsize))
190
191 #define BLI_array_alloca_and_count(arr, realsize) \
192         (typeof(arr))alloca(sizeof(*arr) * (realsize));  \
193         const int _##arr##_count = (realsize)
194
195 #else
196 #define BLI_array_alloca(arr, realsize) \
197         alloca(sizeof(*arr) * (realsize))
198
199 #define BLI_array_alloca_and_count(arr, realsize) \
200         alloca(sizeof(*arr) * (realsize));  \
201         const int _##arr##_count = (realsize)
202 #endif
203
204 #endif  /* __BLI_ARRAY_H__ */