xref: /aosp_15_r20/external/mesa3d/src/egl/main/eglarray.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 #include <assert.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "eglarray.h"
33 #include "egllog.h"
34 
35 /**
36  * Grow the size of the array.
37  */
38 static EGLBoolean
_eglGrowArray(_EGLArray * array)39 _eglGrowArray(_EGLArray *array)
40 {
41    EGLint new_size;
42    void **elems;
43 
44    new_size = array->MaxSize;
45    while (new_size <= array->Size)
46       new_size *= 2;
47 
48    elems = realloc(array->Elements, new_size * sizeof(array->Elements[0]));
49    if (!elems) {
50       _eglLog(_EGL_DEBUG, "failed to grow %s array to %d", array->Name,
51               new_size);
52       return EGL_FALSE;
53    }
54 
55    array->Elements = elems;
56    array->MaxSize = new_size;
57 
58    return EGL_TRUE;
59 }
60 
61 /**
62  * Create an array.
63  */
64 _EGLArray *
_eglCreateArray(const char * name,EGLint init_size)65 _eglCreateArray(const char *name, EGLint init_size)
66 {
67    _EGLArray *array;
68 
69    array = calloc(1, sizeof(*array));
70    if (array) {
71       array->Name = name;
72       array->MaxSize = (init_size > 0) ? init_size : 1;
73       if (!_eglGrowArray(array)) {
74          free(array);
75          array = NULL;
76       }
77    }
78 
79    return array;
80 }
81 
82 /**
83  * Destroy an array, optionally free the data.
84  */
85 void
_eglDestroyArray(_EGLArray * array,void (* free_cb)(void *))86 _eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
87 {
88    if (free_cb) {
89       EGLint i;
90       for (i = 0; i < array->Size; i++)
91          free_cb(array->Elements[i]);
92    }
93    free(array->Elements);
94    free(array);
95 }
96 
97 /**
98  * Append a element to an array.
99  */
100 void
_eglAppendArray(_EGLArray * array,void * elem)101 _eglAppendArray(_EGLArray *array, void *elem)
102 {
103    if (array->Size >= array->MaxSize && !_eglGrowArray(array))
104       return;
105 
106    array->Elements[array->Size++] = elem;
107 }
108 
109 /**
110  * Erase an element from an array.
111  */
112 void
_eglEraseArray(_EGLArray * array,EGLint i,void (* free_cb)(void *))113 _eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *))
114 {
115    if (free_cb)
116       free_cb(array->Elements[i]);
117    if (i < array->Size - 1) {
118       memmove(&array->Elements[i], &array->Elements[i + 1],
119               (array->Size - i - 1) * sizeof(array->Elements[0]));
120    }
121    array->Size--;
122 }
123 
124 /**
125  * Find in an array for the given element.
126  */
127 void *
_eglFindArray(_EGLArray * array,void * elem)128 _eglFindArray(_EGLArray *array, void *elem)
129 {
130    EGLint i;
131 
132    if (!array)
133       return NULL;
134 
135    for (i = 0; i < array->Size; i++)
136       if (array->Elements[i] == elem)
137          return elem;
138    return NULL;
139 }
140 
141 /**
142  * Filter an array and return the number of filtered elements.
143  */
144 EGLint
_eglFilterArray(_EGLArray * array,void ** data,EGLint size,_EGLArrayForEach filter,void * filter_data)145 _eglFilterArray(_EGLArray *array, void **data, EGLint size,
146                 _EGLArrayForEach filter, void *filter_data)
147 {
148    EGLint count = 0, i;
149 
150    if (!array)
151       return 0;
152 
153    assert(filter);
154    for (i = 0; i < array->Size; i++) {
155       if (filter(array->Elements[i], filter_data)) {
156          if (data && count < size)
157             data[count] = array->Elements[i];
158          count++;
159       }
160       if (data && count >= size)
161          break;
162    }
163 
164    return count;
165 }
166 
167 /**
168  * Flatten an array by converting array elements into another form and store
169  * them in a buffer.
170  */
171 EGLint
_eglFlattenArray(_EGLArray * array,void * buffer,EGLint elem_size,EGLint size,_EGLArrayForEach flatten)172 _eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
173                  _EGLArrayForEach flatten)
174 {
175    EGLint i, count;
176 
177    if (!array)
178       return 0;
179 
180    count = array->Size;
181    if (buffer) {
182       /* clamp size to 0 */
183       if (size < 0)
184          size = 0;
185       /* do not exceed buffer size */
186       if (count > size)
187          count = size;
188       for (i = 0; i < count; i++)
189          flatten(array->Elements[i], (void *)((char *)buffer + elem_size * i));
190    }
191 
192    return count;
193 }
194