2011-12-28 13:40:14 +00:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2013-09-12 03:02:50 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2011-12-28 13:40:14 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2013-01-19 07:35:55 +00:00
|
|
|
#pragma once
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup bli
|
|
|
|
* \brief A (mainly) macro array library.
|
2011-12-28 13:40:14 +00:00
|
|
|
*/
|
|
|
|
|
2013-01-19 07:35:55 +00:00
|
|
|
/* -------------------------------------------------------------------- */
|
2015-02-14 07:28:15 +11:00
|
|
|
/** \name Internal defines
|
|
|
|
* \{ */
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/** this returns the entire size of the array, including any buffering. */
|
2013-01-19 07:35:55 +00:00
|
|
|
#define _bli_array_totalsize_dynamic(arr) \
|
2013-07-28 17:06:31 +00:00
|
|
|
(((arr) == NULL) ? 0 : MEM_allocN_len(arr) / sizeof(*(arr)))
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
#define _bli_array_totalsize_static(arr) (sizeof(_##arr##_static) / sizeof(*(arr)))
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-19 07:35:55 +00:00
|
|
|
#define _bli_array_totalsize(arr) \
|
2015-02-14 07:28:15 +11:00
|
|
|
((size_t)(((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ? \
|
2012-11-26 04:58:33 +00:00
|
|
|
_bli_array_totalsize_static(arr) : \
|
2013-01-19 07:35:55 +00:00
|
|
|
_bli_array_totalsize_dynamic(arr)))
|
2015-02-14 07:28:15 +11:00
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
2019-11-25 01:14:39 +11:00
|
|
|
/**
|
|
|
|
* BLI_array.c
|
2013-01-19 07:35:55 +00:00
|
|
|
*
|
|
|
|
* Doing the realloc in a macro isn't so simple,
|
|
|
|
* so use a function the macros can use.
|
|
|
|
*/
|
2018-03-15 01:42:44 +11:00
|
|
|
void _bli_array_grow_func(void **arr_p,
|
|
|
|
const void *arr_static,
|
|
|
|
const int sizeof_arr_p,
|
|
|
|
const int arr_len,
|
|
|
|
const int num,
|
|
|
|
const char *alloc_str);
|
2013-01-19 07:35:55 +00:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2015-02-14 07:28:15 +11:00
|
|
|
/** \name Public defines
|
|
|
|
* \{ */
|
|
|
|
|
2021-07-20 22:52:31 +10:00
|
|
|
/** use `sizeof(*(arr))` to ensure the array exists and is an array */
|
2013-01-19 07:35:55 +00:00
|
|
|
#define BLI_array_declare(arr) \
|
2018-03-15 01:42:44 +11:00
|
|
|
int _##arr##_len = ((void)(sizeof(*(arr))), 0); \
|
2013-01-19 07:35:55 +00:00
|
|
|
void *_##arr##_static = NULL
|
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/**
|
|
|
|
* this will use stack space, up to maxstatic array elements, before
|
2013-01-19 07:35:55 +00:00
|
|
|
* switching to dynamic heap allocation */
|
|
|
|
#define BLI_array_staticdeclare(arr, maxstatic) \
|
2018-03-15 01:42:44 +11:00
|
|
|
int _##arr##_len = 0; \
|
2014-06-27 00:20:17 +10:00
|
|
|
char _##arr##_static[maxstatic * sizeof(*(arr))]
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/** returns the logical size of the array, not including buffering. */
|
2018-03-15 01:42:44 +11:00
|
|
|
#define BLI_array_len(arr) ((void)0, _##arr##_len)
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/**
|
|
|
|
* Grow the array by a fixed number of items.
|
2011-12-28 13:40:14 +00:00
|
|
|
*
|
2013-04-07 15:09:06 +00:00
|
|
|
* Allow for a large 'num' value when the new size is more than double
|
2011-12-28 13:40:14 +00:00
|
|
|
* to allocate the exact sized array. */
|
2014-09-28 13:37:13 +10:00
|
|
|
#define BLI_array_reserve(arr, num) \
|
2012-11-26 04:58:33 +00:00
|
|
|
(void)((((void *)(arr) == NULL) && \
|
|
|
|
((void *)(_##arr##_static) != \
|
2018-03-15 01:42:44 +11:00
|
|
|
NULL) && /* don't add _##arr##_len below because it must be zero */ \
|
|
|
|
(_bli_array_totalsize_static(arr) >= \
|
2019-09-05 12:56:34 +10:00
|
|
|
(size_t)(_##arr##_len + \
|
|
|
|
(num)))) ? /* we have an empty array and a static var big enough */ \
|
2012-11-26 04:58:33 +00:00
|
|
|
(void)(arr = (void *)_##arr##_static) : /* use existing static array or allocate */ \
|
2019-08-30 11:25:50 -04:00
|
|
|
(LIKELY(_bli_array_totalsize(arr) >= (size_t)(_##arr##_len + (num))) ? \
|
2013-01-19 07:35:55 +00:00
|
|
|
(void)0 /* do nothing */ : \
|
2013-01-20 11:54:43 +00:00
|
|
|
_bli_array_grow_func((void **)&(arr), \
|
|
|
|
_##arr##_static, \
|
2018-03-15 01:42:44 +11:00
|
|
|
sizeof(*(arr)), \
|
|
|
|
_##arr##_len, \
|
|
|
|
num, \
|
2014-08-14 14:18:37 +10:00
|
|
|
"BLI_array." #arr)))
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/** returns length of array */
|
2018-03-15 01:42:44 +11:00
|
|
|
#define BLI_array_grow_items(arr, num) (BLI_array_reserve(arr, num), (_##arr##_len += num))
|
2014-09-28 13:37:13 +10:00
|
|
|
|
|
|
|
#define BLI_array_grow_one(arr) BLI_array_grow_items(arr, 1)
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/** appends an item to the array. */
|
2011-12-28 13:40:14 +00:00
|
|
|
#define BLI_array_append(arr, item) \
|
2018-03-15 01:42:44 +11:00
|
|
|
((void)BLI_array_grow_one(arr), (void)(arr[_##arr##_len - 1] = item))
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/**
|
2021-06-26 21:35:18 +10:00
|
|
|
* Appends an item to the array and returns a pointer to the item in the array.
|
|
|
|
* item is not a pointer, but actual data value.
|
|
|
|
*/
|
2011-12-28 13:40:14 +00:00
|
|
|
#define BLI_array_append_r(arr, item) \
|
2018-03-15 01:42:44 +11:00
|
|
|
((void)BLI_array_grow_one(arr), (void)(arr[_##arr##_len - 1] = item), (&arr[_##arr##_len - 1]))
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/** appends (grows) & returns a pointer to the uninitialized memory */
|
2018-03-15 01:42:44 +11:00
|
|
|
#define BLI_array_append_ret(arr) (BLI_array_reserve(arr, 1), &arr[(_##arr##_len++)])
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-07-29 08:18:20 +10:00
|
|
|
#define BLI_array_free(arr) \
|
|
|
|
{ \
|
2011-12-28 13:40:14 +00:00
|
|
|
if (arr && (char *)arr != _##arr##_static) { \
|
2017-06-12 13:35:00 +10:00
|
|
|
BLI_array_fake_user(arr); \
|
2020-08-27 15:33:33 +10:00
|
|
|
MEM_freeN((void *)arr); \
|
2017-07-29 08:18:20 +10:00
|
|
|
} \
|
|
|
|
} \
|
|
|
|
((void)0)
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-12-28 13:40:14 +00:00
|
|
|
#define BLI_array_pop(arr) ((arr && _##arr##_len) ? arr[--_##arr##_len] : NULL)
|
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/**
|
2018-03-15 01:42:44 +11:00
|
|
|
* Resets the logical size of an array to zero, but doesn't
|
2011-12-28 13:40:14 +00:00
|
|
|
* free the memory. */
|
2018-02-01 12:06:57 +11:00
|
|
|
#define BLI_array_clear(arr) \
|
2018-03-15 01:42:44 +11:00
|
|
|
{ \
|
|
|
|
_##arr##_len = 0; \
|
|
|
|
} \
|
|
|
|
((void)0)
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/**
|
2018-03-15 01:42:44 +11:00
|
|
|
* Set the length of the array, doesn't actually increase the allocated array
|
2011-12-28 13:40:14 +00:00
|
|
|
* size. don't use this unless you know what you're doing. */
|
2018-03-15 01:42:44 +11:00
|
|
|
#define BLI_array_len_set(arr, len) \
|
|
|
|
{ \
|
|
|
|
_##arr##_len = (len); \
|
|
|
|
} \
|
|
|
|
((void)0)
|
2011-12-28 13:40:14 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/** only to prevent unused warnings */
|
2011-12-28 13:40:14 +00:00
|
|
|
#define BLI_array_fake_user(arr) ((void)_##arr##_len, (void)_##arr##_static)
|
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/** \} */
|
|
|
|
|
2013-01-19 07:35:55 +00:00
|
|
|
/* -------------------------------------------------------------------- */
|
2015-02-14 07:28:15 +11:00
|
|
|
/** \name Generic Array Utils
|
|
|
|
* other useful defines
|
|
|
|
* (unrelated to the main array macros)
|
|
|
|
*
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
/**
|
2021-08-04 10:03:07 +10:00
|
|
|
* Not part of the 'API' but handy functions,
|
2015-02-14 07:28:15 +11:00
|
|
|
* same purpose as #BLI_array_staticdeclare()
|
2011-12-28 13:40:14 +00:00
|
|
|
* but use when the max size is known ahead of time */
|
|
|
|
#define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr) \
|
2012-04-07 12:37:15 +00:00
|
|
|
char _##arr##_static[maxstatic * sizeof(*(arr))]; \
|
2013-07-28 09:05:27 +00:00
|
|
|
const bool _##arr##_is_static = ((void *)_##arr##_static) != \
|
2012-04-07 12:37:15 +00:00
|
|
|
(arr = ((realsize) <= maxstatic) ? \
|
2011-12-28 13:40:14 +00:00
|
|
|
(void *)_##arr##_static : \
|
2012-02-19 03:10:11 +00:00
|
|
|
MEM_mallocN(sizeof(*(arr)) * (realsize), allocstr))
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-08 21:20:10 +00:00
|
|
|
#define BLI_array_fixedstack_free(arr) \
|
|
|
|
if (_##arr##_is_static) { \
|
|
|
|
MEM_freeN(arr); \
|
2018-03-15 01:42:44 +11:00
|
|
|
} \
|
|
|
|
((void)0)
|
2012-12-11 15:10:19 +00:00
|
|
|
|
2015-02-14 07:28:15 +11:00
|
|
|
/** \} */
|