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       /* 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