Line data Source code
1 : /* 2 : * Copyright (c) 2013, 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 blocks of fixed 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 block, without reallocating 34 : * the already used memory, and thus **not increasing** the heap fragmentation, 35 : * and **minimizing** the space occupation. 36 : * This also implies that the address of the stored elements never change. 37 : * 38 : * Allocated blocks are always of the same fixed size of 4 Ki pointers. 39 : */ 40 : 41 : #ifndef __TOMMYARRAYBLK_H 42 : #define __TOMMYARRAYBLK_H 43 : 44 : #include "tommytypes.h" 45 : #include "tommyarray.h" 46 : 47 : #include <assert.h> /* for assert */ 48 : 49 : /******************************************************************************/ 50 : /* array */ 51 : 52 : /** 53 : * Elements for each block. 54 : */ 55 : #define TOMMY_ARRAYBLK_SIZE (4 * 1024) 56 : 57 : /** 58 : * Array container type. 59 : * \note Don't use internal fields directly, but access the container only using functions. 60 : */ 61 : typedef struct tommy_arrayblk_struct { 62 : tommy_array block; /**< Array of blocks. */ 63 : tommy_size_t count; /**< Number of initialized elements in the array. */ 64 : } tommy_arrayblk; 65 : 66 : /** 67 : * Initializes the array. 68 : */ 69 : TOMMY_API void tommy_arrayblk_init(tommy_arrayblk* array); 70 : 71 : /** 72 : * Deinitializes the array. 73 : */ 74 : TOMMY_API void tommy_arrayblk_done(tommy_arrayblk* array); 75 : 76 : /** 77 : * Grows the size up to the specified value. 78 : * All the new elements in the array are initialized with the 0 value. 79 : */ 80 : TOMMY_API void tommy_arrayblk_grow(tommy_arrayblk* array, tommy_size_t size); 81 : 82 : /** 83 : * Gets a reference of the element at the specified position. 84 : * You must be sure that space for this position is already 85 : * allocated calling tommy_arrayblk_grow(). 86 : */ 87 150000000 : tommy_inline void** tommy_arrayblk_ref(tommy_arrayblk* array, tommy_size_t pos) 88 : { 89 : void** ptr; 90 : 91 150000000 : assert(pos < array->count); 92 : 93 150000000 : ptr = tommy_cast(void**, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLK_SIZE)); 94 : 95 150000000 : return &ptr[pos % TOMMY_ARRAYBLK_SIZE]; 96 : } 97 : 98 : /** 99 : * Sets the element at the specified position. 100 : * You must be sure that space for this position is already 101 : * allocated calling tommy_arrayblk_grow(). 102 : */ 103 50000000 : tommy_inline void tommy_arrayblk_set(tommy_arrayblk* array, tommy_size_t pos, void* element) 104 : { 105 50000000 : *tommy_arrayblk_ref(array, pos) = element; 106 50000000 : } 107 : 108 : /** 109 : * Gets the element at the specified position. 110 : * You must be sure that space for this position is already 111 : * allocated calling tommy_arrayblk_grow(). 112 : */ 113 100000000 : tommy_inline void* tommy_arrayblk_get(tommy_arrayblk* array, tommy_size_t pos) 114 : { 115 100000000 : return *tommy_arrayblk_ref(array, pos); 116 : } 117 : 118 : /** 119 : * Grows and inserts a new element at the end of the array. 120 : */ 121 : tommy_inline void tommy_arrayblk_insert(tommy_arrayblk* array, void* element) 122 : { 123 : tommy_size_t pos = array->count; 124 : 125 : tommy_arrayblk_grow(array, pos + 1); 126 : 127 : tommy_arrayblk_set(array, pos, element); 128 : } 129 : 130 : /** 131 : * Gets the initialized size of the array. 132 : */ 133 : tommy_inline tommy_size_t tommy_arrayblk_size(tommy_arrayblk* array) 134 : { 135 : return array->count; 136 : } 137 : 138 : /** 139 : * Gets the size of allocated memory. 140 : */ 141 : TOMMY_API tommy_size_t tommy_arrayblk_memory_usage(tommy_arrayblk* array); 142 : 143 : #endif