Update contrib.
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
14 * Description: Dynamic pointer array implementation
22 * \brief Dynamic pointer array implementation
26 #ifndef M3G_CORE_INCLUDE
27 # error included by m3g_core.c; do not compile separately.
30 #include "m3g_array.h"
33 /* Define a minimum (default) capacity and a maximum amount of growth
34 * for the array, to try and keep memory usage reasonable */
36 #define MIN_CAPACITY 8 /* 32 bytes */
37 #define MAX_GROWTH 1024 /* 4 KB */
39 M3G_CT_ASSERT(MIN_CAPACITY < MAX_GROWTH);
41 /*----------------------------------------------------------------------
43 *--------------------------------------------------------------------*/
47 * \brief Resizes an array to the given size
49 static M3Gbool m3gReallocateArray(PointerArray *array,
54 M3G_VALIDATE_INTERFACE(m3g);
56 /* Allocate the new data block */
58 newItems = m3gAlloc(m3g, (M3Gsize) newCapacity * sizeof(void*));
59 if (newItems == NULL) {
60 return M3G_FALSE; /* automatic out of memory raised by m3gAlloc */
63 /* Copy array contents */
65 if (array->items != NULL) {
67 M3G_ASSERT(array->size <= newCapacity);
69 for (i = 0; i < array->size; ++i) {
70 newItems[i] = array->items[i];
72 m3gFree(m3g, array->items);
75 array->capacity = newCapacity;
76 array->items = newItems;
82 * \brief Increases the capacity of the array
84 * Array growth is limited by the \c MAX_GROWTH constant, to avoid
85 * blowing memory management for very large arrays. Small arrays are
86 * always grown to the next power of two, to allow for easier
87 * recycling of memory blocks.
89 static M3Gbool m3gGrowArray(PointerArray *array, Interface *m3g)
91 M3Gsizei capacity = array->capacity;
94 /* Calculate the new capacity for the array */
96 if (capacity >= MIN_CAPACITY) {
97 if (capacity < MAX_GROWTH) {
98 newCapacity = MIN_CAPACITY << 1;
99 while (newCapacity <= capacity) {
104 newCapacity = capacity + MAX_GROWTH;
108 newCapacity = MIN_CAPACITY;
111 /* Reallocate the array to the new capacity */
113 return m3gReallocateArray(array, newCapacity, m3g);
116 /*----------------------------------------------------------------------
117 * M3G internal functions
118 *--------------------------------------------------------------------*/
122 * \brief Appends a new item to the end of the array
124 * Grows the array if necessary, by allocating new data from the
127 static M3Gint m3gArrayAppend(PointerArray *array, void *item, Interface *m3g)
129 M3G_VALIDATE_PTR(array);
130 M3G_ASSERT(array->size <= array->capacity);
131 if (array->size == array->capacity) {
132 if (!m3gGrowArray(array, m3g)) {
136 array->items[array->size] = item;
137 return (array->size++);
142 * \brief Deletes an element in the array
144 * All subsequent elements will move back to fill the gap, and the
145 * size of the array decremented by one.
147 static void m3gArrayDelete(PointerArray *array, M3Gint idx)
150 M3G_VALIDATE_PTR(array);
151 M3G_ASSERT(idx >= 0 && idx < array->size);
154 for (i = idx; i < n; ++i) {
155 array->items[i] = array->items[i+1];
158 M3G_ASSERT(array->size >= 0);
163 * \brief Finds the first occurrence of an item in the array
165 * \return index of \c item, or -1 if not found
167 static M3Gint m3gArrayFind(const PointerArray *array, void *item)
170 M3G_VALIDATE_PTR(array);
172 for (i = 0; i < array->size; ++i) {
173 if (array->items[i] == item) {
182 * \brief Inserts an element into the array
184 * All subsequent elements move forward by one index.
186 static M3Gint m3gArrayInsert(PointerArray *array,
192 M3G_VALIDATE_PTR(array);
193 M3G_ASSERT(idx >= 0 && idx <= array->size);
195 if (array->size == array->capacity) {
196 if (!m3gGrowArray(array, m3g)) {
201 for (i = array->size++; i > idx; --i) {
202 array->items[i] = array->items[i-1];
204 array->items[idx] = item;
208 #if 0 /* currently unused, but available here */
211 * \brief Removes the first instance of an item from the array
213 * \return true if \c item found, false otherwise
215 static M3Gbool m3gArrayRemove(PointerArray *array, void *item)
217 M3Gint idx = m3gArrayFind(array, item);
219 m3gArrayDelete(array, idx);
228 * \brief Clears all array elements
230 * Does not affect the capacity of the array
232 static void m3gClearArray(PointerArray *array)
234 M3G_VALIDATE_PTR(array);
240 * \brief Destroys the array, freeing any resources allocated
242 static void m3gDestroyArray(PointerArray *array, Interface *m3g)
244 M3G_VALIDATE_PTR(array);
245 m3gFree(m3g, array->items);
251 * \brief Initializes an array prior to its first use
253 * \note This is also accomplished by clearing the array structure to
256 static void m3gInitArray(PointerArray *array)
258 M3G_VALIDATE_PTR(array);
259 m3gZero(array, sizeof(PointerArray));
264 * \brief Ensures that the array has a specified capacity
266 static M3Gbool m3gEnsureArrayCapacity(PointerArray *array,
270 M3G_VALIDATE_PTR(array);
271 if (array->capacity < capacity) {
272 return m3gReallocateArray(array, capacity, m3g);
277 #if 0 /* currently unused, but available here */
280 * \brief Minimizes the memory usage of the array
282 static M3Gbool m3gTrimArray(PointerArray *array, Interface *m3g)
284 M3G_VALIDATE_PTR(array);
285 M3G_ASSERT(array->size <= array->capacity);
286 return m3gReallocateArray(array, array->size, m3g);