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 <stdlib.h>
     30 #include <string.h>
     31 
     32 #include "egllog.h"
     33 #include "eglarray.h"
     34 
     35 
     36 /**
     37  * Grow the size of the array.
     38  */
     39 static EGLBoolean
     40 _eglGrowArray(_EGLArray *array)
     41 {
     42    EGLint new_size;
     43    void **elems;
     44 
     45    new_size = array->MaxSize;
     46    while (new_size <= array->Size)
     47       new_size *= 2;
     48 
     49    elems = realloc(array->Elements, new_size * sizeof(array->Elements[0]));
     50    if (!elems) {
     51       _eglLog(_EGL_DEBUG, "failed to grow %s array to %d",
     52             array->Name, new_size);
     53       return EGL_FALSE;
     54    }
     55 
     56    array->Elements = elems;
     57    array->MaxSize = new_size;
     58 
     59    return EGL_TRUE;
     60 }
     61 
     62 
     63 /**
     64  * Create an array.
     65  */
     66 _EGLArray *
     67 _eglCreateArray(const char *name, EGLint init_size)
     68 {
     69    _EGLArray *array;
     70 
     71    array = calloc(1, sizeof(*array));
     72    if (array) {
     73       array->Name = name;
     74       array->MaxSize = (init_size > 0) ? init_size : 1;
     75       if (!_eglGrowArray(array)) {
     76          free(array);
     77          array = NULL;
     78       }
     79    }
     80 
     81    return array;
     82 }
     83 
     84 
     85 /**
     86  * Destroy an array, optionally free the data.
     87  */
     88 void
     89 _eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
     90 {
     91    if (free_cb) {
     92       EGLint i;
     93       for (i = 0; i < array->Size; i++)
     94          free_cb(array->Elements[i]);
     95    }
     96    free(array->Elements);
     97    free(array);
     98 }
     99 
    100 
    101 /**
    102  * Append a element to an array.
    103  */
    104 void
    105 _eglAppendArray(_EGLArray *array, void *elem)
    106 {
    107    if (array->Size >= array->MaxSize && !_eglGrowArray(array))
    108       return;
    109 
    110    array->Elements[array->Size++] = elem;
    111 }
    112 
    113 
    114 /**
    115  * Erase an element from an array.
    116  */
    117 void
    118 _eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *))
    119 {
    120    if (free_cb)
    121       free_cb(array->Elements[i]);
    122    if (i < array->Size - 1) {
    123       memmove(&array->Elements[i], &array->Elements[i + 1],
    124             (array->Size - i - 1) * sizeof(array->Elements[0]));
    125    }
    126    array->Size--;
    127 }
    128 
    129 
    130 /**
    131  * Find in an array for the given element.
    132  */
    133 void *
    134 _eglFindArray(_EGLArray *array, void *elem)
    135 {
    136    EGLint i;
    137 
    138    if (!array)
    139       return NULL;
    140 
    141    for (i = 0; i < array->Size; i++)
    142       if (array->Elements[i] == elem)
    143          return elem;
    144    return NULL;
    145 }
    146 
    147 
    148 /**
    149  * Filter an array and return the number of filtered elements.
    150  */
    151 EGLint
    152 _eglFilterArray(_EGLArray *array, void **data, EGLint size,
    153                 _EGLArrayForEach filter, void *filter_data)
    154 {
    155    EGLint count = 0, i;
    156 
    157    if (!array)
    158       return 0;
    159 
    160    if (filter) {
    161       for (i = 0; i < array->Size; i++) {
    162          if (filter(array->Elements[i], filter_data)) {
    163             if (data && count < size)
    164                data[count] = array->Elements[i];
    165             count++;
    166          }
    167          if (data && count >= size)
    168             break;
    169       }
    170    }
    171    else {
    172       if (data) {
    173          count = (size < array->Size) ? size : array->Size;
    174          memcpy(data, array->Elements, count * sizeof(array->Elements[0]));
    175       }
    176       else {
    177          count = array->Size;
    178       }
    179    }
    180 
    181    return count;
    182 }
    183 
    184 
    185 /**
    186  * Flatten an array by converting array elements into another form and store
    187  * them in a buffer.
    188  */
    189 EGLint
    190 _eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
    191                  _EGLArrayForEach flatten)
    192 {
    193    EGLint i, count;
    194 
    195    if (!array)
    196       return 0;
    197 
    198    count = array->Size;
    199    if (buffer) {
    200       /* clamp size to 0 */
    201       if (size < 0)
    202          size = 0;
    203       /* do not exceed buffer size */
    204       if (count > size)
    205          count = size;
    206       for (i = 0; i < count; i++)
    207          flatten(array->Elements[i],
    208                (void *) ((char *) buffer + elem_size * i));
    209    }
    210 
    211    return count;
    212 }
    213