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
_eglGrowArray(_EGLArray * array)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 *
_eglCreateArray(const char * name,EGLint init_size)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
_eglDestroyArray(_EGLArray * array,void (* free_cb)(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
_eglAppendArray(_EGLArray * array,void * elem)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
_eglEraseArray(_EGLArray * array,EGLint i,void (* free_cb)(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 *
_eglFindArray(_EGLArray * array,void * elem)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
_eglFilterArray(_EGLArray * array,void ** data,EGLint size,_EGLArrayForEach filter,void * filter_data)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
_eglFlattenArray(_EGLArray * array,void * buffer,EGLint elem_size,EGLint size,_EGLArrayForEach flatten)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