os/graphics/m3g/m3gcore11/src/m3g_array.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     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".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: Dynamic pointer array implementation
    15 *
    16 */
    17 
    18 
    19 /*!
    20  * \internal
    21  * \file
    22  * \brief Dynamic pointer array implementation
    23  *
    24  */
    25 
    26 #ifndef M3G_CORE_INCLUDE
    27 #   error included by m3g_core.c; do not compile separately.
    28 #endif
    29 
    30 #include "m3g_array.h"
    31 
    32 
    33 /* Define a minimum (default) capacity and a maximum amount of growth
    34  * for the array, to try and keep memory usage reasonable */
    35 
    36 #define MIN_CAPACITY 8  /* 32 bytes */
    37 #define MAX_GROWTH 1024 /* 4 KB */
    38 
    39 M3G_CT_ASSERT(MIN_CAPACITY < MAX_GROWTH);
    40 
    41 /*----------------------------------------------------------------------
    42  * Private functions
    43  *--------------------------------------------------------------------*/
    44 
    45 /*!
    46  * \internal
    47  * \brief Resizes an array to the given size
    48  */
    49 static M3Gbool m3gReallocateArray(PointerArray *array,
    50                                   M3Gsizei newCapacity,
    51                                   Interface *m3g)
    52 {
    53     void **newItems;
    54     M3G_VALIDATE_INTERFACE(m3g);
    55     
    56     /* Allocate the new data block */
    57     
    58     newItems = m3gAlloc(m3g, (M3Gsize) newCapacity * sizeof(void*));
    59     if (newItems == NULL) {
    60         return M3G_FALSE; /* automatic out of memory raised by m3gAlloc */
    61     }
    62 
    63     /* Copy array contents */
    64     
    65     if (array->items != NULL) {
    66         int i;
    67         M3G_ASSERT(array->size <= newCapacity);
    68         
    69         for (i = 0; i < array->size; ++i) {
    70             newItems[i] = array->items[i];
    71         }
    72         m3gFree(m3g, array->items);
    73     }
    74 
    75     array->capacity = newCapacity;
    76     array->items = newItems;
    77     return M3G_TRUE;
    78 }
    79 
    80 /*!
    81  * \internal
    82  * \brief Increases the capacity of the array
    83  *
    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.
    88  */
    89 static M3Gbool m3gGrowArray(PointerArray *array, Interface *m3g)
    90 {
    91     M3Gsizei capacity = array->capacity;
    92     M3Gsizei newCapacity;
    93 
    94     /* Calculate the new capacity for the array */
    95 
    96     if (capacity >= MIN_CAPACITY) {
    97         if (capacity < MAX_GROWTH) {
    98             newCapacity = MIN_CAPACITY << 1;
    99             while (newCapacity <= capacity) {
   100                 newCapacity <<= 1;
   101             }
   102         }
   103         else {
   104             newCapacity = capacity + MAX_GROWTH;
   105         }
   106     }
   107     else {
   108         newCapacity = MIN_CAPACITY;
   109     }
   110 
   111     /* Reallocate the array to the new capacity */
   112 
   113     return m3gReallocateArray(array, newCapacity, m3g);
   114 }
   115 
   116 /*----------------------------------------------------------------------
   117  * M3G internal functions
   118  *--------------------------------------------------------------------*/
   119 
   120 /*!
   121  * \internal
   122  * \brief Appends a new item to the end of the array
   123  *
   124  * Grows the array if necessary, by allocating new data from the
   125  * interface \c m3g.
   126  */
   127 static M3Gint m3gArrayAppend(PointerArray *array, void *item, Interface *m3g)
   128 {
   129     M3G_VALIDATE_PTR(array);
   130     M3G_ASSERT(array->size <= array->capacity);
   131     if (array->size == array->capacity) {
   132         if (!m3gGrowArray(array, m3g)) {
   133             return -1;
   134         }
   135     }
   136     array->items[array->size] = item;
   137     return (array->size++);
   138 }
   139 
   140 /*!
   141  * \internal
   142  * \brief Deletes an element in the array
   143  *
   144  * All subsequent elements will move back to fill the gap, and the
   145  * size of the array decremented by one.
   146  */
   147 static void m3gArrayDelete(PointerArray *array, M3Gint idx)
   148 {
   149     int i, n;
   150     M3G_VALIDATE_PTR(array);
   151     M3G_ASSERT(idx >= 0 && idx < array->size);
   152 
   153     n = --array->size;
   154     for (i = idx; i < n; ++i) {
   155         array->items[i] = array->items[i+1];
   156     }
   157 
   158     M3G_ASSERT(array->size >= 0);
   159 }
   160 
   161 /*!
   162  * \internal
   163  * \brief Finds the first occurrence of an item in the array
   164  *
   165  * \return index of \c item, or -1 if not found
   166  */
   167 static M3Gint m3gArrayFind(const PointerArray *array, void *item)
   168 {
   169     int i;
   170     M3G_VALIDATE_PTR(array);
   171 
   172     for (i = 0; i < array->size; ++i) {
   173         if (array->items[i] == item) {
   174             return i;
   175         }
   176     }
   177     return -1;
   178 }
   179 
   180 /*!
   181  * \internal
   182  * \brief Inserts an element into the array
   183  *
   184  * All subsequent elements move forward by one index.
   185  */
   186 static M3Gint m3gArrayInsert(PointerArray *array,
   187                              M3Gint idx,
   188                              void *item,
   189                              Interface *m3g)
   190 {
   191     int i;
   192     M3G_VALIDATE_PTR(array);
   193     M3G_ASSERT(idx >= 0 && idx <= array->size);
   194     
   195     if (array->size == array->capacity) {
   196         if (!m3gGrowArray(array, m3g)) {
   197             return -1;
   198         }
   199     }
   200 
   201     for (i = array->size++; i > idx; --i) {
   202         array->items[i] = array->items[i-1];
   203     }
   204     array->items[idx] = item;
   205     return idx;
   206 }
   207 
   208 #if 0 /* currently unused, but available here */
   209 /*!
   210  * \internal
   211  * \brief Removes the first instance of an item from the array
   212  *
   213  * \return true if \c item found, false otherwise
   214  */
   215 static M3Gbool m3gArrayRemove(PointerArray *array, void *item)
   216 {
   217     M3Gint idx = m3gArrayFind(array, item);
   218     if (idx >= 0) {
   219         m3gArrayDelete(array, idx);
   220         return M3G_TRUE;
   221     }
   222     return M3G_FALSE;
   223 }
   224 #endif
   225 
   226 /*!
   227  * \internal
   228  * \brief Clears all array elements
   229  *
   230  * Does not affect the capacity of the array
   231  */
   232 static void m3gClearArray(PointerArray *array)
   233 {
   234     M3G_VALIDATE_PTR(array);
   235     array->size = 0;
   236 }
   237 
   238 /*!
   239  * \internal
   240  * \brief Destroys the array, freeing any resources allocated
   241  */
   242 static void m3gDestroyArray(PointerArray *array, Interface *m3g)
   243 {
   244     M3G_VALIDATE_PTR(array);
   245     m3gFree(m3g, array->items);
   246     array->items = NULL;
   247 }
   248 
   249 /*!
   250  * \internal
   251  * \brief Initializes an array prior to its first use
   252  *
   253  * \note This is also accomplished by clearing the array structure to
   254  * zero
   255  */
   256 static void m3gInitArray(PointerArray *array)
   257 {
   258     M3G_VALIDATE_PTR(array);
   259     m3gZero(array, sizeof(PointerArray));
   260 }
   261 
   262 /*!
   263  * \internal
   264  * \brief Ensures that the array has a specified capacity
   265  */
   266 static M3Gbool m3gEnsureArrayCapacity(PointerArray *array,
   267                                       M3Gsizei capacity,
   268                                       Interface *m3g)
   269 {
   270     M3G_VALIDATE_PTR(array);    
   271     if (array->capacity < capacity) {
   272         return m3gReallocateArray(array, capacity, m3g);
   273     }
   274     return M3G_TRUE;
   275 }
   276 
   277 #if 0 /* currently unused, but available here */
   278 /*!
   279  * \internal
   280  * \brief Minimizes the memory usage of the array
   281  */
   282 static M3Gbool m3gTrimArray(PointerArray *array, Interface *m3g)
   283 {
   284     M3G_VALIDATE_PTR(array);
   285     M3G_ASSERT(array->size <= array->capacity);
   286     return m3gReallocateArray(array, array->size, m3g);
   287 }
   288 #endif
   289 
   290 
   291 #undef MIN_CAPACITY
   292 #undef MAX_GROWTH
   293