Blender V2.61 - r43446

BLI_array.h

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017  *
00018  * The Original Code is Copyright (C) 2008 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Joseph Eagar.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00028 /*
00029  * this library needs to be changed to not use macros quite so heavily,
00030  * and to be more of a complete array API.  The way arrays are
00031  * exposed to client code as normal C arrays is very useful though, imho.
00032  * it does require some use of macros, however.
00033  *
00034  * anyway, it's used a bit too heavily to simply rewrite as a
00035  * more "correct" solution without macros entirely.  I originally wrote this
00036  * to be very easy to use, without the normal pain of most array libraries.
00037  * This was especially helpful when it came to the massive refactors necessary
00038  * for bmesh, and really helped to speed the process up. - joeedh
00039  *
00040  * little array macro library.  example of usage:
00041  *
00042  * int *arr = NULL;
00043  * BLI_array_declare(arr);
00044  * int i;
00045  *
00046  * for (i=0; i<10; i++) {
00047  *     BLI_array_growone(arr);
00048  *      arr[i] = something;
00049  * }
00050  * BLI_array_free(arr);
00051  *
00052  * arrays are buffered, using double-buffering (so on each reallocation,
00053  * the array size is doubled).  supposedly this should give good Big Oh
00054  * behaviour, though it may not be the best in practice.
00055  */
00056 
00057 #define BLI_array_declare(arr)                                                \
00058     int   _##arr##_count = 0;                                                 \
00059     void *_##arr##_tmp;                                                       \
00060     void *_##arr##_static = NULL
00061 
00062 /* this will use stack space, up to maxstatic array elements, before
00063  * switching to dynamic heap allocation */
00064 #define BLI_array_staticdeclare(arr, maxstatic)                               \
00065     int   _##arr##_count = 0;                                                 \
00066     void *_##arr##_tmp;                                                       \
00067     char _##arr##_static[maxstatic*sizeof(arr)]
00068 
00069 
00070 /* this returns the entire size of the array, including any buffering. */
00071 #define BLI_array_totalsize_dyn(arr)  (                                       \
00072     ((arr)==NULL) ?                                                           \
00073         0 :                                                                   \
00074         MEM_allocN_len(arr) / sizeof(*arr)                                    \
00075 )
00076 
00077 
00078 #define BLI_array_totalsize(arr)  (                                           \
00079     (size_t)                                                                  \
00080     (((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ?    \
00081         (sizeof(_##arr##_static) / sizeof(*arr)) :                            \
00082         BLI_array_totalsize_dyn(arr))                                         \
00083 )
00084 
00085 
00086 /* this returns the logical size of the array, not including buffering. */
00087 #define BLI_array_count(arr) _##arr##_count
00088 
00089 /* Grow the array by a fixed number of items. zeroes the new elements.
00090  *
00091  * Allow for a large 'num' value when the new size is more then double
00092  * to allocate the exact sized array. */
00093 #define _bli_array_grow_items(arr, num)  (                                    \
00094     (BLI_array_totalsize(arr) >= _##arr##_count + num) ?                      \
00095         (_##arr##_count += num) :                                             \
00096         (                                                                     \
00097             (void) (_##arr##_tmp = MEM_callocN(                               \
00098                     sizeof(*arr) * (num < _##arr##_count ?                    \
00099                                     (_##arr##_count * 2 + 2) :                \
00100                                     (_##arr##_count + num)),                  \
00101                     #arr " " __FILE__ ":" STRINGIFY(__LINE__)                 \
00102                     )                                                         \
00103                     ),                                                        \
00104             (void) (arr && memcpy(_##arr##_tmp,                               \
00105                                   arr,                                        \
00106                                   sizeof(*arr) * _##arr##_count)              \
00107                     ),                                                        \
00108             (void) (arr && ((void *)(arr) != (void*)_##arr##_static ?         \
00109                     (MEM_freeN(arr), arr) :                                   \
00110                     arr)                                                      \
00111                     ),                                                        \
00112             (void) (arr = _##arr##_tmp                                        \
00113                     ),                                                        \
00114             (_##arr##_count += num)                                           \
00115         )                                                                     \
00116 )
00117 
00118 /* grow an array by a specified number of items */
00119 #define BLI_array_growitems(arr, num)  (                                      \
00120     ((void *)(arr)==NULL && (void *)(_##arr##_static) != NULL) ?              \
00121         ((arr= (void*)_##arr##_static), (_##arr##_count += num)) :            \
00122         _bli_array_grow_items(arr, num)                                       \
00123 )
00124 
00125 /* returns length of array */
00126 #define BLI_array_growone(arr)  BLI_array_growitems(arr, 1)
00127 
00128 
00129 /* appends an item to the array. */
00130 #define BLI_array_append(arr, item)  (                                        \
00131     (void) BLI_array_growone(arr),                                            \
00132     (void) (arr[_##arr##_count - 1] = item)                                   \
00133 )
00134 
00135 /* appends an item to the array and returns a pointer to the item in the array.
00136  * item is not a pointer, but actual data value.*/
00137 #define BLI_array_append_r(arr, item)  (                                      \
00138     (void) BLI_array_growone(arr),                                            \
00139     (void) (arr[_##arr##_count - 1] = item),                                  \
00140     (&arr[_##arr##_count - 1])                                                \
00141 )
00142 
00143 #define BLI_array_free(arr)                                                   \
00144     if (arr && (char *)arr != _##arr##_static) {                              \
00145         BLI_array_fake_user(arr);                                             \
00146         MEM_freeN(arr);                                                       \
00147     }
00148 
00149 #define BLI_array_pop(arr)  (                                                 \
00150     (arr&&_##arr##_count) ?                                                   \
00151         arr[--_##arr##_count] :                                               \
00152         0                                                                     \
00153 )
00154 
00155 /* resets the logical size of an array to zero, but doesn't
00156  * free the memory. */
00157 #define BLI_array_empty(arr)                                                  \
00158     _##arr##_count=0
00159 
00160 /* set the count of the array, doesn't actually increase the allocated array
00161  * size.  don't use this unless you know what you're doing. */
00162 #define BLI_array_set_length(arr, count)                                      \
00163     _##arr##_count = (count)
00164 
00165 /* only to prevent unused warnings */
00166 #define BLI_array_fake_user(arr)                                              \
00167     (void)_##arr##_count,                                                     \
00168     (void)_##arr##_tmp,                                                       \
00169     (void)_##arr##_static
00170 
00171 
00172 /* not part of the 'API' but handy funcs,
00173  * same purpose as BLI_array_staticdeclare()
00174  * but use when the max size is known ahead of time */
00175 #define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr)      \
00176     char _##arr##_static[maxstatic*sizeof(*arr)];                             \
00177     const int _##arr##_is_static= ((void *)_##arr##_static) != (              \
00178         arr= (realsize <= maxstatic) ?                                        \
00179             (void *)_##arr##_static :                                         \
00180             MEM_mallocN(sizeof(*arr)*realsize, allocstr)                      \
00181         )                                                                     \
00182 
00183 #define BLI_array_fixedstack_free(arr)                                        \
00184     if (_##arr##_is_static) MEM_freeN(arr)                                    \
00185