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