Merge remote branch 'origin/master' into glsl2
[mesa.git] / src / egl / main / eglarray.c
1 #include <stdlib.h>
2 #include <string.h>
3
4 #include "egllog.h"
5 #include "eglarray.h"
6
7
8 /**
9 * Grow the size of the array.
10 */
11 static EGLBoolean
12 _eglGrowArray(_EGLArray *array)
13 {
14 EGLint new_size;
15 void **elems;
16
17 new_size = array->MaxSize;
18 while (new_size <= array->Size)
19 new_size *= 2;
20
21 elems = realloc(array->Elements, new_size * sizeof(array->Elements[0]));
22 if (!elems) {
23 _eglLog(_EGL_DEBUG, "failed to grow %s array to %d",
24 array->Name, new_size);
25 return EGL_FALSE;
26 }
27
28 array->Elements = elems;
29 array->MaxSize = new_size;
30
31 return EGL_TRUE;
32 }
33
34
35 /**
36 * Create an array.
37 */
38 _EGLArray *
39 _eglCreateArray(const char *name, EGLint init_size)
40 {
41 _EGLArray *array;
42
43 array = calloc(1, sizeof(*array));
44 if (array) {
45 array->Name = name;
46 array->MaxSize = (init_size > 0) ? init_size : 1;
47 if (!_eglGrowArray(array)) {
48 free(array);
49 array = NULL;
50 }
51 }
52
53 return array;
54 }
55
56
57 /**
58 * Destroy an array, optionally free the data.
59 */
60 void
61 _eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
62 {
63 if (free_cb) {
64 EGLint i;
65 for (i = 0; i < array->Size; i++)
66 free_cb(array->Elements[i]);
67 }
68 free(array->Elements);
69 free(array);
70 }
71
72
73 /**
74 * Append a element to an array.
75 */
76 void
77 _eglAppendArray(_EGLArray *array, void *elem)
78 {
79 if (array->Size >= array->MaxSize && !_eglGrowArray(array))
80 return;
81
82 array->Elements[array->Size++] = elem;
83 }
84
85
86 /**
87 * Erase an element from an array.
88 */
89 void
90 _eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *))
91 {
92 if (free_cb)
93 free_cb(array->Elements[i]);
94 if (i < array->Size - 1) {
95 memmove(&array->Elements[i], &array->Elements[i + 1],
96 (array->Size - i - 1) * sizeof(array->Elements[0]));
97 }
98 array->Size--;
99 }
100
101
102 /**
103 * Find in an array for the given element.
104 */
105 void *
106 _eglFindArray(_EGLArray *array, void *elem)
107 {
108 EGLint i;
109
110 if (!array)
111 return NULL;
112
113 for (i = 0; i < array->Size; i++)
114 if (array->Elements[i] == elem)
115 return elem;
116 return NULL;
117 }
118
119
120 /**
121 * Filter an array and return the filtered data. The returned data pointer
122 * should be freed.
123 */
124 void **
125 _eglFilterArray(_EGLArray *array, EGLint *size,
126 _EGLArrayForEach filter, void *filter_data)
127 {
128 void **data;
129 EGLint count = 0, i;
130
131 if (!array) {
132 *size = 0;
133 return malloc(0);
134 }
135
136 data = malloc(array->Size * sizeof(array->Elements[0]));
137 if (!data)
138 return NULL;
139
140 if (filter) {
141 for (i = 0; i < array->Size; i++) {
142 if (filter(array->Elements[i], filter_data))
143 data[count++] = array->Elements[i];
144 }
145 }
146 else {
147 memcpy(data, array->Elements, array->Size * sizeof(array->Elements[0]));
148 }
149
150 *size = count;
151
152 return data;
153 }
154
155
156 /**
157 * Flatten an array by converting array elements into another form and store
158 * them in a buffer.
159 */
160 EGLint
161 _eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
162 _EGLArrayForEach flatten)
163 {
164 EGLint i, count;
165
166 if (!array)
167 return 0;
168
169 count = array->Size;
170 if (buffer) {
171 /* do not exceed buffer size */
172 if (count > size)
173 count = size;
174 for (i = 0; i < count; i++)
175 flatten(array->Elements[i],
176 (void *) ((char *) buffer + elem_size * i));
177 }
178
179 return count;
180 }