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 /* do not exceed buffer size */ 201 if (count > size) 202 count = size; 203 for (i = 0; i < count; i++) 204 flatten(array->Elements[i], 205 (void *) ((char *) buffer + elem_size * i)); 206 } 207 208 return count; 209 } 210