Line data Source code
1 : /* 2 : * Copyright (c) 2011, Andrea Mazzoleni. All rights reserved. 3 : * 4 : * Redistribution and use in source and binary forms, with or without 5 : * modification, are permitted provided that the following conditions 6 : * are met: 7 : * 8 : * 1. Redistributions of source code must retain the above copyright 9 : * notice, this list of conditions and the following disclaimer. 10 : * 11 : * 2. Redistributions in binary form must reproduce the above copyright 12 : * notice, this list of conditions and the following disclaimer in the 13 : * documentation and/or other materials provided with the distribution. 14 : * 15 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 : * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 : * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 : * POSSIBILITY OF SUCH DAMAGE. 26 : */ 27 : 28 : /** \file 29 : * Dynamic array based on segments of exponential growing size. 30 : * 31 : * This array is able to grow dynamically upon request, without any reallocation. 32 : * 33 : * The grow operation involves an allocation of a new array segment, without reallocating 34 : * the already used memory, and then not increasing the heap fragmentation. 35 : * This also implies that the address of the stored elements never change. 36 : * 37 : * Allocated segments grow in size exponentially. 38 : */ 39 : 40 : #ifndef __TOMMYARRAY_H 41 : #define __TOMMYARRAY_H 42 : 43 : #include "tommytypes.h" 44 : 45 : #include <assert.h> /* for assert */ 46 : 47 : /******************************************************************************/ 48 : /* array */ 49 : 50 : /** 51 : * Initial and minimal size of the array expressed as a power of 2. 52 : * The initial size is 2^TOMMY_ARRAY_BIT. 53 : */ 54 : #define TOMMY_ARRAY_BIT 6 55 : 56 : /** 57 : * Array container type. 58 : * \note Don't use internal fields directly, but access the container only using functions. 59 : */ 60 : typedef struct tommy_array_struct { 61 : void** bucket[TOMMY_SIZE_BIT]; /**< Dynamic array of buckets. */ 62 : tommy_size_t bucket_max; /**< Number of buckets. */ 63 : tommy_size_t count; /**< Number of initialized elements in the array. */ 64 : tommy_uint_t bucket_bit; /**< Bits used in the bit mask. */ 65 : } tommy_array; 66 : 67 : /** 68 : * Initializes the array. 69 : */ 70 : void tommy_array_init(tommy_array* array); 71 : 72 : /** 73 : * Deinitializes the array. 74 : */ 75 : void tommy_array_done(tommy_array* array); 76 : 77 : /** 78 : * Grows the size up to the specified value. 79 : * All the new elements in the array are initialized with the 0 value. 80 : */ 81 : void tommy_array_grow(tommy_array* array, tommy_size_t size); 82 : 83 : /** 84 : * Gets a reference of the element at the specified position. 85 : * You must be sure that space for this position is already 86 : * allocated calling tommy_array_grow(). 87 : */ 88 8302193 : tommy_inline void** tommy_array_ref(tommy_array* array, tommy_size_t pos) 89 : { 90 : tommy_uint_t bsr; 91 : 92 8302193 : assert(pos < array->count); 93 : 94 : /* get the highest bit set, in case of all 0, return 0 */ 95 8302193 : bsr = tommy_ilog2(pos | 1); 96 : 97 8302193 : return &array->bucket[bsr][pos]; 98 : } 99 : 100 : /** 101 : * Sets the element at the specified position. 102 : * You must be sure that space for this position is already 103 : * allocated calling tommy_array_grow(). 104 : */ 105 2221 : tommy_inline void tommy_array_set(tommy_array* array, tommy_size_t pos, void* element) 106 : { 107 2221 : *tommy_array_ref(array, pos) = element; 108 2221 : } 109 : 110 : /** 111 : * Gets the element at the specified position. 112 : * You must be sure that space for this position is already 113 : * allocated calling tommy_array_grow(). 114 : */ 115 8299972 : tommy_inline void* tommy_array_get(tommy_array* array, tommy_size_t pos) 116 : { 117 8299972 : return *tommy_array_ref(array, pos); 118 : } 119 : 120 : /** 121 : * Grows and inserts a new element at the end of the array. 122 : */ 123 256 : tommy_inline void tommy_array_insert(tommy_array* array, void* element) 124 : { 125 256 : tommy_size_t pos = array->count; 126 : 127 256 : tommy_array_grow(array, pos + 1); 128 : 129 256 : tommy_array_set(array, pos, element); 130 256 : } 131 : 132 : /** 133 : * Gets the initialized size of the array. 134 : */ 135 1578231 : tommy_inline tommy_size_t tommy_array_size(tommy_array* array) 136 : { 137 1578231 : return array->count; 138 : } 139 : 140 : /** 141 : * Gets the size of allocated memory. 142 : */ 143 : tommy_size_t tommy_array_memory_usage(tommy_array* array); 144 : 145 : #endif 146 :