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