egl: Update MaxSize when a dynamic array is grown.
[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 * Find in an array for the given element.
88 */
89 void *
90 _eglFindArray(_EGLArray *array, void *elem)
91 {
92 EGLint i;
93
94 if (!array)
95 return NULL;
96
97 for (i = 0; i < array->Size; i++)
98 if (array->Elements[i] == elem)
99 return elem;
100 return NULL;
101 }
102
103
104 /**
105 * Filter an array and return the filtered data. The returned data pointer
106 * should be freed.
107 */
108 void **
109 _eglFilterArray(_EGLArray *array, EGLint *size,
110 _EGLArrayForEach filter, void *filter_data)
111 {
112 void **data;
113 EGLint count = 0, i;
114
115 if (!array) {
116 *size = 0;
117 return malloc(0);
118 }
119
120 data = malloc(array->Size * sizeof(array->Elements[0]));
121 if (!data)
122 return NULL;
123
124 if (filter) {
125 for (i = 0; i < array->Size; i++) {
126 if (filter(array->Elements[i], filter_data))
127 data[count++] = array->Elements[i];
128 }
129 }
130 else {
131 memcpy(data, array->Elements, array->Size * sizeof(array->Elements[0]));
132 }
133
134 *size = count;
135
136 return data;
137 }
138
139
140 /**
141 * Flatten an array by converting array elements into another form and store
142 * them in a buffer.
143 */
144 EGLint
145 _eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
146 _EGLArrayForEach flatten)
147 {
148 EGLint i, count;
149
150 if (!array)
151 return 0;
152
153 count = (size < array->Size) ? size : array->Size;
154 if (buffer) {
155 for (i = 0; i < count; i++)
156 flatten(array->Elements[i],
157 (void *) ((char *) buffer + elem_size * i));
158 }
159
160 return count;
161 }