Line data Source code
1 : // SPDX-License-Identifier: BSD-2-Clause 2 : // Copyright (C) 2011 Andrea Mazzoleni 3 : 4 : /** \file 5 : * Dynamic array based on segments of exponentially growing size. 6 : * 7 : * This array is able to grow dynamically upon request, without any reallocation. 8 : * 9 : * The grow operation involves an allocation of a new array segment, without reallocating 10 : * the already used memory, and thus **not increasing** the heap fragmentation. 11 : * This also implies that the address of the stored elements never change. 12 : * 13 : * Allocated segments grow in size exponentially. 14 : */ 15 : 16 : #ifndef __TOMMYARRAY_H 17 : #define __TOMMYARRAY_H 18 : 19 : #include "tommytypes.h" 20 : 21 : #include <assert.h> /* for assert */ 22 : 23 : /******************************************************************************/ 24 : /* array */ 25 : 26 : /** 27 : * Initial and minimal size of the array expressed as a power of 2. 28 : * The initial size is 2^TOMMY_ARRAY_BIT. 29 : */ 30 : #define TOMMY_ARRAY_BIT 6 31 : 32 : /** 33 : * Array container type. 34 : * \note Don't use internal fields directly, but access the container only using functions. 35 : */ 36 : typedef struct tommy_array_struct { 37 : void** bucket[TOMMY_SIZE_BIT]; /**< Dynamic array of buckets. */ 38 : tommy_size_t bucket_max; /**< Number of buckets. */ 39 : tommy_size_t count; /**< Number of initialized elements in the array. */ 40 : tommy_uint_t bucket_bit; /**< Bits used in the bit mask. */ 41 : } tommy_array; 42 : 43 : /** 44 : * Initializes the array. 45 : */ 46 : TOMMY_API void tommy_array_init(tommy_array* array); 47 : 48 : /** 49 : * Deinitializes the array. 50 : */ 51 : TOMMY_API void tommy_array_done(tommy_array* array); 52 : 53 : /** 54 : * Grows the size up to the specified value. 55 : * All the new elements in the array are initialized with the 0 value. 56 : */ 57 : TOMMY_API void tommy_array_grow(tommy_array* array, tommy_size_t size); 58 : 59 : /** 60 : * Gets a reference of the element at the specified position. 61 : * You must be sure that space for this position is already 62 : * allocated calling tommy_array_grow(). 63 : */ 64 8946200 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_size_t pos) 65 : { 66 : tommy_uint_t bsr; 67 : 68 8946200 : assert(pos < array->count); 69 : 70 : /* get the highest bit set, in case of all 0, return 0 */ 71 8946200 : bsr = tommy_ilog2(pos | 1); 72 : 73 8946200 : return &array->bucket[bsr][pos]; 74 : } 75 : 76 : /** 77 : * Sets the element at the specified position. 78 : * You must be sure that space for this position is already 79 : * allocated calling tommy_array_grow(). 80 : */ 81 2454 : tommy_inline void tommy_array_set(tommy_array* array, tommy_size_t pos, void* element) 82 : { 83 2454 : *tommy_array_ref(array, pos) = element; 84 2454 : } 85 : 86 : /** 87 : * Gets the element at the specified position. 88 : * You must be sure that space for this position is already 89 : * allocated calling tommy_array_grow(). 90 : */ 91 8943746 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_size_t pos) 92 : { 93 8943746 : return *tommy_array_ref(array, pos); 94 : } 95 : 96 : /** 97 : * Grows and inserts a new element at the end of the array. 98 : */ 99 256 : tommy_inline void tommy_array_insert(tommy_array* array, void* element) 100 : { 101 256 : tommy_size_t pos = array->count; 102 : 103 256 : tommy_array_grow(array, pos + 1); 104 : 105 256 : tommy_array_set(array, pos, element); 106 256 : } 107 : 108 : /** 109 : * Gets the initialized size of the array. 110 : */ 111 1711703 : tommy_inline tommy_size_t tommy_array_size(tommy_array* array) 112 : { 113 1711703 : return array->count; 114 : } 115 : 116 : /** 117 : * Gets the size of allocated memory. 118 : */ 119 : TOMMY_API tommy_size_t tommy_array_memory_usage(tommy_array* array); 120 : 121 : #endif