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