Home | History | Annotate | Download | only in main
      1 /**************************************************************************
      2  *
      3  * Copyright 2010 LunarG, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     24  * DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 
     29 #include <assert.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 
     33 #include "egllog.h"
     34 #include "eglarray.h"
     35 
     36 
     37 /**
     38  * Grow the size of the array.
     39  */
     40 static EGLBoolean
     41 _eglGrowArray(_EGLArray *array)
     42 {
     43    EGLint new_size;
     44    void **elems;
     45 
     46    new_size = array->MaxSize;
     47    while (new_size <= array->Size)
     48       new_size *= 2;
     49 
     50    elems = realloc(array->Elements, new_size * sizeof(array->Elements[0]));
     51    if (!elems) {
     52       _eglLog(_EGL_DEBUG, "failed to grow %s array to %d",
     53             array->Name, new_size);
     54       return EGL_FALSE;
     55    }
     56 
     57    array->Elements = elems;
     58    array->MaxSize = new_size;
     59 
     60    return EGL_TRUE;
     61 }
     62 
     63 
     64 /**
     65  * Create an array.
     66  */
     67 _EGLArray *
     68 _eglCreateArray(const char *name, EGLint init_size)
     69 {
     70    _EGLArray *array;
     71 
     72    array = calloc(1, sizeof(*array));
     73    if (array) {
     74       array->Name = name;
     75       array->MaxSize = (init_size > 0) ? init_size : 1;
     76       if (!_eglGrowArray(array)) {
     77          free(array);
     78          array = NULL;
     79       }
     80    }
     81 
     82    return array;
     83 }
     84 
     85 
     86 /**
     87  * Destroy an array, optionally free the data.
     88  */
     89 void
     90 _eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
     91 {
     92    if (free_cb) {
     93       EGLint i;
     94       for (i = 0; i < array->Size; i++)
     95          free_cb(array->Elements[i]);
     96    }
     97    free(array->Elements);
     98    free(array);
     99 }
    100 
    101 
    102 /**
    103  * Append a element to an array.
    104  */
    105 void
    106 _eglAppendArray(_EGLArray *array, void *elem)
    107 {
    108    if (array->Size >= array->MaxSize && !_eglGrowArray(array))
    109       return;
    110 
    111    array->Elements[array->Size++] = elem;
    112 }
    113 
    114 
    115 /**
    116  * Erase an element from an array.
    117  */
    118 void
    119 _eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *))
    120 {
    121    if (free_cb)
    122       free_cb(array->Elements[i]);
    123    if (i < array->Size - 1) {
    124       memmove(&array->Elements[i], &array->Elements[i + 1],
    125             (array->Size - i - 1) * sizeof(array->Elements[0]));
    126    }
    127    array->Size--;
    128 }
    129 
    130 
    131 /**
    132  * Find in an array for the given element.
    133  */
    134 void *
    135 _eglFindArray(_EGLArray *array, void *elem)
    136 {
    137    EGLint i;
    138 
    139    if (!array)
    140       return NULL;
    141 
    142    for (i = 0; i < array->Size; i++)
    143       if (array->Elements[i] == elem)
    144          return elem;
    145    return NULL;
    146 }
    147 
    148 
    149 /**
    150  * Filter an array and return the number of filtered elements.
    151  */
    152 EGLint
    153 _eglFilterArray(_EGLArray *array, void **data, EGLint size,
    154                 _EGLArrayForEach filter, void *filter_data)
    155 {
    156    EGLint count = 0, i;
    157 
    158    if (!array)
    159       return 0;
    160 
    161    assert(filter);
    162    for (i = 0; i < array->Size; i++) {
    163       if (filter(array->Elements[i], filter_data)) {
    164          if (data && count < size)
    165             data[count] = array->Elements[i];
    166          count++;
    167       }
    168       if (data && count >= size)
    169          break;
    170    }
    171 
    172    return count;
    173 }
    174 
    175 
    176 /**
    177  * Flatten an array by converting array elements into another form and store
    178  * them in a buffer.
    179  */
    180 EGLint
    181 _eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
    182                  _EGLArrayForEach flatten)
    183 {
    184    EGLint i, count;
    185 
    186    if (!array)
    187       return 0;
    188 
    189    count = array->Size;
    190    if (buffer) {
    191       /* clamp size to 0 */
    192       if (size < 0)
    193          size = 0;
    194       /* do not exceed buffer size */
    195       if (count > size)
    196          count = size;
    197       for (i = 0; i < count; i++)
    198          flatten(array->Elements[i],
    199                (void *) ((char *) buffer + elem_size * i));
    200    }
    201 
    202    return count;
    203 }
    204