egl: Add dynamic array.
[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
30 return EGL_TRUE;
31 }
32
33
34 /**
35 * Create an array.
36 */
37 _EGLArray *
38 _eglCreateArray(const char *name, EGLint init_size)
39 {
40 _EGLArray *array;
41
42 array = calloc(1, sizeof(*array));
43 if (array) {
44 array->Name = name;
45 array->MaxSize = (init_size > 0) ? init_size : 1;
46 if (!_eglGrowArray(array)) {
47 free(array);
48 array = NULL;
49 }
50 }
51
52 return array;
53 }
54
55
56 /**
57 * Destroy an array, optionally free the data.
58 */
59 void
60 _eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
61 {
62 if (free_cb) {
63 EGLint i;
64 for (i = 0; i < array->Size; i++)
65 free_cb(array->Elements[i]);
66 }
67 free(array->Elements);
68 free(array);
69 }
70
71
72 /**
73 * Append a element to an array.
74 */
75 void
76 _eglAppendArray(_EGLArray *array, void *elem)
77 {
78 if (array->Size >= array->MaxSize && !_eglGrowArray(array))
79 return;
80
81 array->Elements[array->Size++] = elem;
82 }
83
84
85 /**
86 * Find in an array for the given element.
87 */
88 void *
89 _eglFindArray(_EGLArray *array, void *elem)
90 {
91 EGLint i;
92
93 if (!array)
94 return NULL;
95
96 for (i = 0; i < array->Size; i++)
97 if (array->Elements[i] == elem)
98 return elem;
99 return NULL;
100 }
101
102
103 /**
104 * Filter an array and return the filtered data. The returned data pointer
105 * should be freed.
106 */
107 void **
108 _eglFilterArray(_EGLArray *array, EGLint *size,
109 _EGLArrayForEach filter, void *filter_data)
110 {
111 void **data;
112 EGLint count = 0, i;
113
114 if (!array) {
115 *size = 0;
116 return malloc(0);
117 }
118
119 data = malloc(array->Size * sizeof(array->Elements[0]));
120 if (!data)
121 return NULL;
122
123 if (filter) {
124 for (i = 0; i < array->Size; i++) {
125 if (filter(array->Elements[i], filter_data))
126 data[count++] = array->Elements[i];
127 }
128 }
129 else {
130 memcpy(data, array->Elements, array->Size * sizeof(array->Elements[0]));
131 }
132
133 *size = count;
134
135 return data;
136 }
137
138
139 /**
140 * Flatten an array by converting array elements into another form and store
141 * them in a buffer.
142 */
143 EGLint
144 _eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
145 _EGLArrayForEach flatten)
146 {
147 EGLint i, count;
148
149 if (!array)
150 return 0;
151
152 count = (size < array->Size) ? size : array->Size;
153 if (buffer) {
154 for (i = 0; i < count; i++)
155 flatten(array->Elements[i],
156 (void *) ((char *) buffer + elem_size * i));
157 }
158
159 return count;
160 }