13464ebd5Sriastradh/**************************************************************************
23464ebd5Sriastradh *
33464ebd5Sriastradh * Copyright 2010 LunarG, Inc.
43464ebd5Sriastradh * All Rights Reserved.
53464ebd5Sriastradh *
63464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a
73464ebd5Sriastradh * copy of this software and associated documentation files (the
83464ebd5Sriastradh * "Software"), to deal in the Software without restriction, including
93464ebd5Sriastradh * without limitation the rights to use, copy, modify, merge, publish,
103464ebd5Sriastradh * distribute, sub license, and/or sell copies of the Software, and to
113464ebd5Sriastradh * permit persons to whom the Software is furnished to do so, subject to
123464ebd5Sriastradh * the following conditions:
133464ebd5Sriastradh *
143464ebd5Sriastradh * The above copyright notice and this permission notice (including the
153464ebd5Sriastradh * next paragraph) shall be included in all copies or substantial portions
163464ebd5Sriastradh * of the Software.
173464ebd5Sriastradh *
183464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
193464ebd5Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
203464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
213464ebd5Sriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
223464ebd5Sriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
233464ebd5Sriastradh * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
243464ebd5Sriastradh * DEALINGS IN THE SOFTWARE.
253464ebd5Sriastradh *
263464ebd5Sriastradh **************************************************************************/
273464ebd5Sriastradh
283464ebd5Sriastradh
2901e04c3fSmrg#include <assert.h>
303464ebd5Sriastradh#include <stdlib.h>
313464ebd5Sriastradh#include <string.h>
323464ebd5Sriastradh
333464ebd5Sriastradh#include "egllog.h"
343464ebd5Sriastradh#include "eglarray.h"
353464ebd5Sriastradh
363464ebd5Sriastradh
373464ebd5Sriastradh/**
383464ebd5Sriastradh * Grow the size of the array.
393464ebd5Sriastradh */
403464ebd5Sriastradhstatic EGLBoolean
413464ebd5Sriastradh_eglGrowArray(_EGLArray *array)
423464ebd5Sriastradh{
433464ebd5Sriastradh   EGLint new_size;
443464ebd5Sriastradh   void **elems;
453464ebd5Sriastradh
463464ebd5Sriastradh   new_size = array->MaxSize;
473464ebd5Sriastradh   while (new_size <= array->Size)
483464ebd5Sriastradh      new_size *= 2;
493464ebd5Sriastradh
503464ebd5Sriastradh   elems = realloc(array->Elements, new_size * sizeof(array->Elements[0]));
513464ebd5Sriastradh   if (!elems) {
523464ebd5Sriastradh      _eglLog(_EGL_DEBUG, "failed to grow %s array to %d",
533464ebd5Sriastradh            array->Name, new_size);
543464ebd5Sriastradh      return EGL_FALSE;
553464ebd5Sriastradh   }
563464ebd5Sriastradh
573464ebd5Sriastradh   array->Elements = elems;
583464ebd5Sriastradh   array->MaxSize = new_size;
593464ebd5Sriastradh
603464ebd5Sriastradh   return EGL_TRUE;
613464ebd5Sriastradh}
623464ebd5Sriastradh
633464ebd5Sriastradh
643464ebd5Sriastradh/**
653464ebd5Sriastradh * Create an array.
663464ebd5Sriastradh */
673464ebd5Sriastradh_EGLArray *
683464ebd5Sriastradh_eglCreateArray(const char *name, EGLint init_size)
693464ebd5Sriastradh{
703464ebd5Sriastradh   _EGLArray *array;
713464ebd5Sriastradh
723464ebd5Sriastradh   array = calloc(1, sizeof(*array));
733464ebd5Sriastradh   if (array) {
743464ebd5Sriastradh      array->Name = name;
753464ebd5Sriastradh      array->MaxSize = (init_size > 0) ? init_size : 1;
763464ebd5Sriastradh      if (!_eglGrowArray(array)) {
773464ebd5Sriastradh         free(array);
783464ebd5Sriastradh         array = NULL;
793464ebd5Sriastradh      }
803464ebd5Sriastradh   }
813464ebd5Sriastradh
823464ebd5Sriastradh   return array;
833464ebd5Sriastradh}
843464ebd5Sriastradh
853464ebd5Sriastradh
863464ebd5Sriastradh/**
873464ebd5Sriastradh * Destroy an array, optionally free the data.
883464ebd5Sriastradh */
893464ebd5Sriastradhvoid
903464ebd5Sriastradh_eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
913464ebd5Sriastradh{
923464ebd5Sriastradh   if (free_cb) {
933464ebd5Sriastradh      EGLint i;
943464ebd5Sriastradh      for (i = 0; i < array->Size; i++)
953464ebd5Sriastradh         free_cb(array->Elements[i]);
963464ebd5Sriastradh   }
973464ebd5Sriastradh   free(array->Elements);
983464ebd5Sriastradh   free(array);
993464ebd5Sriastradh}
1003464ebd5Sriastradh
1013464ebd5Sriastradh
1023464ebd5Sriastradh/**
1033464ebd5Sriastradh * Append a element to an array.
1043464ebd5Sriastradh */
1053464ebd5Sriastradhvoid
1063464ebd5Sriastradh_eglAppendArray(_EGLArray *array, void *elem)
1073464ebd5Sriastradh{
1083464ebd5Sriastradh   if (array->Size >= array->MaxSize && !_eglGrowArray(array))
1093464ebd5Sriastradh      return;
1103464ebd5Sriastradh
1113464ebd5Sriastradh   array->Elements[array->Size++] = elem;
1123464ebd5Sriastradh}
1133464ebd5Sriastradh
1143464ebd5Sriastradh
1153464ebd5Sriastradh/**
1163464ebd5Sriastradh * Erase an element from an array.
1173464ebd5Sriastradh */
1183464ebd5Sriastradhvoid
1193464ebd5Sriastradh_eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *))
1203464ebd5Sriastradh{
1213464ebd5Sriastradh   if (free_cb)
1223464ebd5Sriastradh      free_cb(array->Elements[i]);
1233464ebd5Sriastradh   if (i < array->Size - 1) {
1243464ebd5Sriastradh      memmove(&array->Elements[i], &array->Elements[i + 1],
1253464ebd5Sriastradh            (array->Size - i - 1) * sizeof(array->Elements[0]));
1263464ebd5Sriastradh   }
1273464ebd5Sriastradh   array->Size--;
1283464ebd5Sriastradh}
1293464ebd5Sriastradh
1303464ebd5Sriastradh
1313464ebd5Sriastradh/**
1323464ebd5Sriastradh * Find in an array for the given element.
1333464ebd5Sriastradh */
1343464ebd5Sriastradhvoid *
1353464ebd5Sriastradh_eglFindArray(_EGLArray *array, void *elem)
1363464ebd5Sriastradh{
1373464ebd5Sriastradh   EGLint i;
1383464ebd5Sriastradh
1393464ebd5Sriastradh   if (!array)
1403464ebd5Sriastradh      return NULL;
1413464ebd5Sriastradh
1423464ebd5Sriastradh   for (i = 0; i < array->Size; i++)
1433464ebd5Sriastradh      if (array->Elements[i] == elem)
1443464ebd5Sriastradh         return elem;
1453464ebd5Sriastradh   return NULL;
1463464ebd5Sriastradh}
1473464ebd5Sriastradh
1483464ebd5Sriastradh
1493464ebd5Sriastradh/**
1503464ebd5Sriastradh * Filter an array and return the number of filtered elements.
1513464ebd5Sriastradh */
1523464ebd5SriastradhEGLint
1533464ebd5Sriastradh_eglFilterArray(_EGLArray *array, void **data, EGLint size,
1543464ebd5Sriastradh                _EGLArrayForEach filter, void *filter_data)
1553464ebd5Sriastradh{
1563464ebd5Sriastradh   EGLint count = 0, i;
1573464ebd5Sriastradh
1583464ebd5Sriastradh   if (!array)
1593464ebd5Sriastradh      return 0;
1603464ebd5Sriastradh
16101e04c3fSmrg   assert(filter);
16201e04c3fSmrg   for (i = 0; i < array->Size; i++) {
16301e04c3fSmrg      if (filter(array->Elements[i], filter_data)) {
16401e04c3fSmrg         if (data && count < size)
16501e04c3fSmrg            data[count] = array->Elements[i];
16601e04c3fSmrg         count++;
1673464ebd5Sriastradh      }
16801e04c3fSmrg      if (data && count >= size)
16901e04c3fSmrg         break;
1703464ebd5Sriastradh   }
1713464ebd5Sriastradh
1723464ebd5Sriastradh   return count;
1733464ebd5Sriastradh}
1743464ebd5Sriastradh
1753464ebd5Sriastradh
1763464ebd5Sriastradh/**
1773464ebd5Sriastradh * Flatten an array by converting array elements into another form and store
1783464ebd5Sriastradh * them in a buffer.
1793464ebd5Sriastradh */
1803464ebd5SriastradhEGLint
1813464ebd5Sriastradh_eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
1823464ebd5Sriastradh                 _EGLArrayForEach flatten)
1833464ebd5Sriastradh{
1843464ebd5Sriastradh   EGLint i, count;
1853464ebd5Sriastradh
1863464ebd5Sriastradh   if (!array)
1873464ebd5Sriastradh      return 0;
1883464ebd5Sriastradh
1893464ebd5Sriastradh   count = array->Size;
1903464ebd5Sriastradh   if (buffer) {
19101e04c3fSmrg      /* clamp size to 0 */
19201e04c3fSmrg      if (size < 0)
19301e04c3fSmrg         size = 0;
1943464ebd5Sriastradh      /* do not exceed buffer size */
1953464ebd5Sriastradh      if (count > size)
1963464ebd5Sriastradh         count = size;
1973464ebd5Sriastradh      for (i = 0; i < count; i++)
1983464ebd5Sriastradh         flatten(array->Elements[i],
1993464ebd5Sriastradh               (void *) ((char *) buffer + elem_size * i));
2003464ebd5Sriastradh   }
2013464ebd5Sriastradh
2023464ebd5Sriastradh   return count;
2033464ebd5Sriastradh}
204