Macro fid_DYNARRAY_DECLARE() declares a new dynamic array type of a given name, storing elements of given type. This new type has several members, where the "public" ones are
dyndata
,allocated
, andoccupied
The actual data is stored in memory pointed to by dyndata
. This is a pointer of the type passed to fid_DYNARRAY_DECLARE(). The number of allocated elements is stored in allocated
. This is the total number of elements of the stored type that the array can store, not the size of the memory block in bytes. If the total size needs to be known in bytes, then this can be obtained by multiplying allocated
with the size of the stored type. The number of elements currently in use is stored in occupied
. The dynamic arrays implemented here do not maintain a free-list, but assume a stack-like organization. That is, the value occupied
is always interpreted in a way that elements 0, 1, ..., occupied-1
are in use, and that elements occupied, occupied+1, ..., allocated-1
are free. This makes the element at index occupied-1
the last used element in the array, which can be accessed easily using macro fid_DYNARRAY_TOPELEM().
DEBUG
defined), then the array structures are augmented with one extra member that is used for additional checks. These checks are only performed in debug mode. An implication is that array structure sizes are different in debug and non-debug modes, so that applications compiled with DEBUG
are binary incompatible with a version of libfid
compiled without DEBUG
(and vice versa). Please keep this in mind when observing strange things happening. Data Structures | |
struct | fid_Arraychar |
Dynamic array of char values. More... | |
struct | fid_Arrayuchar |
Dynamic array of unsigned char values. More... | |
struct | fid_ArrayUint32 |
Dynamic array of fid_Uint32 values. More... | |
struct | fid_ArrayUint64 |
Dynamic array of fid_Uint64 values. More... | |
struct | fid_ArraySint32 |
Dynamic array of fid_Sint32 values. More... | |
struct | fid_ArraySint64 |
Dynamic array of fid_Sint64 values. More... | |
Defines | |
#define | fid_DYNARRAY_SIZECHECK(ARRAY, TYPE) |
Debugging. | |
#define | fid_DYNARRAY_DECLARE(NAME, TYPE) |
Declare a dynamic array. | |
#define | fid_DYNARRAY_INIT(ARRAY, TYPE) |
Initialize a dynamic array. | |
#define | fid_DYNARRAY_FREE(ARRAY, TYPE) |
Free space occupied by a dynamic array. | |
#define | fid_DYNARRAY_PUSH_UNSAFE(ARRAY, TYPE) ++(ARRAY)->occupied |
Append element to dynamic array, without size check. | |
#define | fid_DYNARRAY_POP_ELEM(ARRAY, TYPE, VAL) (VAL)=(ARRAY)->dyndata[--(ARRAY)->occupied] |
Assign last element of dynamic array to some variable, and remove it from the array. | |
#define | fid_DYNARRAY_POP(ARRAY, TYPE) --(ARRAY)->occupied |
Remove last element from dynamic array. | |
#define | fid_DYNARRAY_ENSURE_NFREE(ARRAY, TYPE, N, FAILCODE) |
Make sure that there are at least n free elements in dynamic array. | |
#define | fid_DYNARRAY_ENSURE_NEXT(ARRAY, TYPE, N, FAILCODE) |
Make sure that the next element in a dynamic array can be written to. | |
#define | fid_DYNARRAY_INIT_PREALLOC(ARRAY, TYPE, N, FAILCODE) |
Initialize a dynamic array, pre-allocate some elements. | |
#define | fid_DYNARRAY_APPEND(ARRAY, TYPE, N, VAL, FAILCODE) |
Append a value to a dynamic array. | |
#define | fid_DYNARRAY_APPEND_UNSAFE(ARRAY, TYPE, VAL) |
Append a value to a dynamic array, without size check. | |
#define | fid_DYNARRAY_PUSH(ARRAY, TYPE, N, FAILCODE) |
Append element to dynamic array. | |
#define | fid_DYNARRAY_TOPELEM(ARRAY, TYPE) ((ARRAY)->dyndata[(ARRAY)->occupied-1]) |
Access last/top element in dynamic array. | |
#define | fid_DYNARRAY_SHRINK(ARRAY, TYPE, FAILCODE) |
Reallocate array so that it does not use up more space than necessary. |
#define fid_DYNARRAY_SIZECHECK | ( | ARRAY, | |||
TYPE | ) |
#define fid_DYNARRAY_DECLARE | ( | NAME, | |||
TYPE | ) |
Value:
typedef struct\ {\ size_t occupied; /*!<\brief Number of elements in use. */\ size_t allocated; /*!<\brief Number of elements for which space has * been allocated. */\ TYPE *dyndata; /*!<\brief Pointer to array data. */\ TYPE *prev_dyndata; /*!<\brief Temporary used before calling\ * \c realloc() to prevent leaking memory. */\ } NAME
NAME | The name of the new structure. | |
TYPE | The type of elements to be stored inside the dynamic array. |
#define fid_DYNARRAY_INIT | ( | ARRAY, | |||
TYPE | ) |
Value:
(ARRAY)->occupied=(ARRAY)->allocated=0;\ (ARRAY)->dyndata=(TYPE *)NULL;\ (ARRAY)->prev_dyndata=(TYPE *)NULL
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. |
Definition at line 217 of file arrays.h.
Referenced by fid_projectfile_init().
#define fid_DYNARRAY_FREE | ( | ARRAY, | |||
TYPE | ) |
Value:
fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ if(((ARRAY)->dyndata) != NULL)\ {\ free((ARRAY)->dyndata);\ }
This macro does attempt not iterate over the array's elements and free them. If the array elements need to be freed, maybe because they contain pointers to allocated memory, then you must free them by yourself before calling this macro.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. |
Definition at line 222 of file arrays.h.
Referenced by fid_suffixarray_traverse().
#define fid_DYNARRAY_PUSH_UNSAFE | ( | ARRAY, | |||
TYPE | ) | ++(ARRAY)->occupied |
Append element to dynamic array, without size check.
This macro, like fid_DYNARRAY_PUSH(), does not store anything to the array. It is just a convenience macro that increases the occupied
member of the array. After that, the element at index occupied
is considered free and can be written to. This macro is used to be make the code more readable, and also to emphasize that a simple increment of the occupied
variable is not safe in general.
Use fid_DYNARRAY_PUSH() if the dynamic array may need to be resized. Also check if fid_DYNARRAY_APPEND() or fid_DYNARRAY_APPEND_UNSAFE() are more appropriate for your application.
Never use this macro unless you are absolutely sure that there is enough free space in the array. The debug version may catch an attempt to write beyond array bounds, but the non-debug version will not.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. |
#define fid_DYNARRAY_POP_ELEM | ( | ARRAY, | |||
TYPE, | |||||
VAL | ) | (VAL)=(ARRAY)->dyndata[--(ARRAY)->occupied] |
Assign last element of dynamic array to some variable, and remove it from the array.
This macro is unsafe. If the array is empty, your program will not do the correct thing since it will try to read the non-existent element beyond the lower array boundary. The debug version might catch such a mistake, the non-debug version will not.
Also think if the assignment performed by this macro is correct for your application, or if the use of some copy function would be more approriate, or if you could simply use the array element directly.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. | |
VAL | A variable of type TYPE that the last element of the dynamic array is assigned to. |
#define fid_DYNARRAY_POP | ( | ARRAY, | |||
TYPE | ) | --(ARRAY)->occupied |
Remove last element from dynamic array.
Like fid_DYNARRAY_PUSH_UNSAFE(), this macro is a convenience macro that simply decrements the occupied
member of the passed dynamic array. And like fid_DYNARRAY_POP_ELEM(), it is also unsafe to use it on empty arrays.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. |
Definition at line 235 of file arrays.h.
Referenced by fid_suffixarray_traverse().
#define fid_DYNARRAY_ENSURE_NFREE | ( | ARRAY, | |||
TYPE, | |||||
N, | |||||
FAILCODE | ) |
Value:
fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ if((ARRAY)->occupied+(N) > (ARRAY)->allocated)\ {\ (ARRAY)->allocated=(ARRAY)->occupied+(N);\ (ARRAY)->prev_dyndata=(ARRAY)->dyndata;\ (ARRAY)->dyndata=(TYPE *)realloc((ARRAY)->dyndata,sizeof(TYPE)*(ARRAY)->allocated);\ if((ARRAY)->dyndata == NULL)\ {\ (ARRAY)->dyndata=(ARRAY)->prev_dyndata;\ FAILCODE\ }\ }\ assert((ARRAY)->dyndata != NULL)
If you know that you will store a certain number of elements inside a dynamic array, then this macro can be used to pre-allocate this number of elements. After a successful call of this macro, the next N
elements, starting at index occupied
, can be used safely. This means that macros like fid_DYNARRAY_PUSH_UNSAFE() or fid_DYNARRAY_APPEND_UNSAFE() can be used safely up to N
times in order to access the next N
elements of the array.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. | |
N | The number of elements needed. | |
FAILCODE | When there is not enough memory left, then this code is executed. |
dyndata
pointer will still point to the old memory block, which is left intact. #define fid_DYNARRAY_ENSURE_NEXT | ( | ARRAY, | |||
TYPE, | |||||
N, | |||||
FAILCODE | ) |
Value:
fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ if((ARRAY)->occupied >= (ARRAY)->allocated)\ {\ (ARRAY)->allocated=(ARRAY)->occupied+(N);\ (ARRAY)->prev_dyndata=(ARRAY)->dyndata;\ (ARRAY)->dyndata=(TYPE *)realloc((ARRAY)->dyndata,sizeof(TYPE)*(ARRAY)->allocated);\ if((ARRAY)->dyndata == NULL)\ {\ (ARRAY)->dyndata=(ARRAY)->prev_dyndata;\ FAILCODE\ }\ }\ assert((ARRAY)->dyndata != NULL)
Before writing to the next element in a dynamic array, use this macro to make sure that this next element can actually be used. When running out of space, the macro resizes the dynamic array so that N
more elements can be stored. After a successful call of this macro, the element at index occupied
can safely be written to, and unsafe macros like fid_DYNARRAY_PUSH_UNSAFE() may be used once (in that case, however, you may use fid_DYNARRAY_PUSH() as well).
Use fid_DYNARRAY_ENSURE_NFREE() to pre-allocate a specific number of free elements.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. | |
N | The number of elements to add to the array when running out of space. This value should be an estimate on how many elements are likely to be added while the application is running. The greater this value, the fewer reallocations will happen, which is good for performance, but the more space is likely to be wasted. | |
FAILCODE | When there is not enough memory left, then this code is executed. |
dyndata
pointer will still point to the old memory block, which is left intact. #define fid_DYNARRAY_INIT_PREALLOC | ( | ARRAY, | |||
TYPE, | |||||
N, | |||||
FAILCODE | ) |
Value:
fid_DYNARRAY_INIT(ARRAY,TYPE);\ fid_DYNARRAY_ENSURE_NFREE(ARRAY,TYPE,N,FAILCODE);\ (ARRAY)->occupied=(ARRAY)->allocated
Like fid_DYNARRAY_INIT(), but also make sure that the first N
elements can be written to. The occupied
member is initialized to point beyond the last free element (i.e., set to the same value as allocated
) so as to mark all elements used.
This macro makes using dynamic arrays convenient to use as fixed-size arrays (that may, of course, be enlarged later), when the number of elements, or initial number of elements, is known in advance.
occupied
being smaller than allocated
, like fid_DYNARRAY_APPEND_UNSAFE(), must not be used on pre-allocated arrays initialized by this macro. Using macros like fid_DYNARRAY_APPEND() may not work as expected since they will write after the pre-allocated elements.ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. | |
N | The number of elements to allocate. | |
FAILCODE | When there is not enough memory left, then this code is executed. |
#define fid_DYNARRAY_APPEND | ( | ARRAY, | |||
TYPE, | |||||
N, | |||||
VAL, | |||||
FAILCODE | ) |
Value:
fid_DYNARRAY_ENSURE_NEXT(ARRAY,TYPE,N,FAILCODE);\ (ARRAY)->dyndata[(ARRAY)->occupied++]=(VAL)
This is a shortcut for a call of fid_DYNARRAY_ENSURE_NEXT(), followed by an assignment of a value to the last element of a dynamic array, followed by an increment of occupied
.
The passed value VAL
is stored via assigment. If this is not enough, i.e., you need to call some copy function to make a real copy, then may prefer to use fid_DYNARRAY_PUSH(), which does the same as this macro does, but omits the assigment.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. | |
N | The number of elements to add to the array when running out of space. See fid_DYNARRAY_ENSURE_NEXT(). | |
VAL | The value of type TYPE to be stored. | |
FAILCODE | When there is not enough memory left, then this code is executed. |
dyndata
pointer will still point to the old memory block, which is left intact. #define fid_DYNARRAY_APPEND_UNSAFE | ( | ARRAY, | |||
TYPE, | |||||
VAL | ) |
Value:
fid_DYNARRAY_SIZECHECK(ARRAY,TYPE);\ (ARRAY)->dyndata[(ARRAY)->occupied++]=(VAL)
Just like fid_DYNARRAY_APPEND(), but omit the check if there is enough space left.
Never use this macro unless you are absolutely sure that there is enough free space in the array. The debug version may catch an attempt to write beyond array bounds, but the non-debug version will not.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. space. See fid_DYNARRAY_ENSURE_NEXT(). | |
VAL | The value of type TYPE to be stored. |
#define fid_DYNARRAY_PUSH | ( | ARRAY, | |||
TYPE, | |||||
N, | |||||
FAILCODE | ) |
Value:
fid_DYNARRAY_ENSURE_NEXT(ARRAY,TYPE,N,FAILCODE);\ fid_DYNARRAY_PUSH_UNSAFE(ARRAY,TYPE)
Simpler alternative for fid_DYNARRAY_APPEND() when assignment is not good enough. After a successful call of this macro, you may want to use fid_DYNARRAY_TOPELEM() to initialize the new element.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. | |
N | The number of elements to add to the array when running out of space. See fid_DYNARRAY_ENSURE_NEXT(). | |
FAILCODE | When there is not enough memory left, then this code is executed. |
dyndata
pointer will still point to the old memory block, which is left intact. Definition at line 408 of file arrays.h.
Referenced by fid_suffixarray_traverse().
#define fid_DYNARRAY_TOPELEM | ( | ARRAY, | |||
TYPE | ) | ((ARRAY)->dyndata[(ARRAY)->occupied-1]) |
Access last/top element in dynamic array.
Just a shortcut macro to make the code more readable. It is safe to put a &
in front of this macro to obtain a pointer to the last element. (Bear in mind, however, that this pointer may quickly become invalid when the array needs to be reallocated.)
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. |
Definition at line 423 of file arrays.h.
Referenced by fid_suffixarray_traverse().
#define fid_DYNARRAY_SHRINK | ( | ARRAY, | |||
TYPE, | |||||
FAILCODE | ) |
Value:
if((ARRAY)->occupied > 0)\ {\ if((ARRAY)->allocated > (ARRAY)->occupied)\ {\ (ARRAY)->prev_dyndata=(ARRAY)->dyndata;\ (ARRAY)->dyndata=(TYPE *)realloc((ARRAY)->dyndata,sizeof(TYPE)*(ARRAY)->occupied);\ if((ARRAY)->dyndata != NULL)\ {\ (ARRAY)->allocated=(ARRAY)->occupied;\ }\ else\ {\ (ARRAY)->dyndata=(ARRAY)->prev_dyndata;\ FAILCODE\ }\ }\ }\ else\ {\ fid_DYNARRAY_FREE(ARRAY,TYPE);\ fid_DYNARRAY_INIT(ARRAY,TYPE);\ }
If the array is empty, i.e., occupied
is zero, then the array will be freed and re-initialized.
ARRAY | A pointer to a dynamic array. | |
TYPE | Type of the elements stored inside the dynamic array. | |
FAILCODE | When reallocation failed, then this code is executed. |
dyndata
pointer will still point to the old memory block, which is left intact. This means, it might be safe to ignore a failure, and keep your program running even in case of failure since all data will still be there, and the rest of the dynamic array will remain unchanged.