1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2010 LunarG, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include <assert.h>
30bf215546Sopenharmony_ci#include <stdlib.h>
31bf215546Sopenharmony_ci#include <string.h>
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "egllog.h"
34bf215546Sopenharmony_ci#include "eglarray.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci/**
38bf215546Sopenharmony_ci * Grow the size of the array.
39bf215546Sopenharmony_ci */
40bf215546Sopenharmony_cistatic EGLBoolean
41bf215546Sopenharmony_ci_eglGrowArray(_EGLArray *array)
42bf215546Sopenharmony_ci{
43bf215546Sopenharmony_ci   EGLint new_size;
44bf215546Sopenharmony_ci   void **elems;
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci   new_size = array->MaxSize;
47bf215546Sopenharmony_ci   while (new_size <= array->Size)
48bf215546Sopenharmony_ci      new_size *= 2;
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci   elems = realloc(array->Elements, new_size * sizeof(array->Elements[0]));
51bf215546Sopenharmony_ci   if (!elems) {
52bf215546Sopenharmony_ci      _eglLog(_EGL_DEBUG, "failed to grow %s array to %d",
53bf215546Sopenharmony_ci            array->Name, new_size);
54bf215546Sopenharmony_ci      return EGL_FALSE;
55bf215546Sopenharmony_ci   }
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci   array->Elements = elems;
58bf215546Sopenharmony_ci   array->MaxSize = new_size;
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci   return EGL_TRUE;
61bf215546Sopenharmony_ci}
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci/**
65bf215546Sopenharmony_ci * Create an array.
66bf215546Sopenharmony_ci */
67bf215546Sopenharmony_ci_EGLArray *
68bf215546Sopenharmony_ci_eglCreateArray(const char *name, EGLint init_size)
69bf215546Sopenharmony_ci{
70bf215546Sopenharmony_ci   _EGLArray *array;
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci   array = calloc(1, sizeof(*array));
73bf215546Sopenharmony_ci   if (array) {
74bf215546Sopenharmony_ci      array->Name = name;
75bf215546Sopenharmony_ci      array->MaxSize = (init_size > 0) ? init_size : 1;
76bf215546Sopenharmony_ci      if (!_eglGrowArray(array)) {
77bf215546Sopenharmony_ci         free(array);
78bf215546Sopenharmony_ci         array = NULL;
79bf215546Sopenharmony_ci      }
80bf215546Sopenharmony_ci   }
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   return array;
83bf215546Sopenharmony_ci}
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci/**
87bf215546Sopenharmony_ci * Destroy an array, optionally free the data.
88bf215546Sopenharmony_ci */
89bf215546Sopenharmony_civoid
90bf215546Sopenharmony_ci_eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
91bf215546Sopenharmony_ci{
92bf215546Sopenharmony_ci   if (free_cb) {
93bf215546Sopenharmony_ci      EGLint i;
94bf215546Sopenharmony_ci      for (i = 0; i < array->Size; i++)
95bf215546Sopenharmony_ci         free_cb(array->Elements[i]);
96bf215546Sopenharmony_ci   }
97bf215546Sopenharmony_ci   free(array->Elements);
98bf215546Sopenharmony_ci   free(array);
99bf215546Sopenharmony_ci}
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci/**
103bf215546Sopenharmony_ci * Append a element to an array.
104bf215546Sopenharmony_ci */
105bf215546Sopenharmony_civoid
106bf215546Sopenharmony_ci_eglAppendArray(_EGLArray *array, void *elem)
107bf215546Sopenharmony_ci{
108bf215546Sopenharmony_ci   if (array->Size >= array->MaxSize && !_eglGrowArray(array))
109bf215546Sopenharmony_ci      return;
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci   array->Elements[array->Size++] = elem;
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci/**
116bf215546Sopenharmony_ci * Erase an element from an array.
117bf215546Sopenharmony_ci */
118bf215546Sopenharmony_civoid
119bf215546Sopenharmony_ci_eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *))
120bf215546Sopenharmony_ci{
121bf215546Sopenharmony_ci   if (free_cb)
122bf215546Sopenharmony_ci      free_cb(array->Elements[i]);
123bf215546Sopenharmony_ci   if (i < array->Size - 1) {
124bf215546Sopenharmony_ci      memmove(&array->Elements[i], &array->Elements[i + 1],
125bf215546Sopenharmony_ci            (array->Size - i - 1) * sizeof(array->Elements[0]));
126bf215546Sopenharmony_ci   }
127bf215546Sopenharmony_ci   array->Size--;
128bf215546Sopenharmony_ci}
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci/**
132bf215546Sopenharmony_ci * Find in an array for the given element.
133bf215546Sopenharmony_ci */
134bf215546Sopenharmony_civoid *
135bf215546Sopenharmony_ci_eglFindArray(_EGLArray *array, void *elem)
136bf215546Sopenharmony_ci{
137bf215546Sopenharmony_ci   EGLint i;
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci   if (!array)
140bf215546Sopenharmony_ci      return NULL;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   for (i = 0; i < array->Size; i++)
143bf215546Sopenharmony_ci      if (array->Elements[i] == elem)
144bf215546Sopenharmony_ci         return elem;
145bf215546Sopenharmony_ci   return NULL;
146bf215546Sopenharmony_ci}
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci/**
150bf215546Sopenharmony_ci * Filter an array and return the number of filtered elements.
151bf215546Sopenharmony_ci */
152bf215546Sopenharmony_ciEGLint
153bf215546Sopenharmony_ci_eglFilterArray(_EGLArray *array, void **data, EGLint size,
154bf215546Sopenharmony_ci                _EGLArrayForEach filter, void *filter_data)
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci   EGLint count = 0, i;
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci   if (!array)
159bf215546Sopenharmony_ci      return 0;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   assert(filter);
162bf215546Sopenharmony_ci   for (i = 0; i < array->Size; i++) {
163bf215546Sopenharmony_ci      if (filter(array->Elements[i], filter_data)) {
164bf215546Sopenharmony_ci         if (data && count < size)
165bf215546Sopenharmony_ci            data[count] = array->Elements[i];
166bf215546Sopenharmony_ci         count++;
167bf215546Sopenharmony_ci      }
168bf215546Sopenharmony_ci      if (data && count >= size)
169bf215546Sopenharmony_ci         break;
170bf215546Sopenharmony_ci   }
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci   return count;
173bf215546Sopenharmony_ci}
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci/**
177bf215546Sopenharmony_ci * Flatten an array by converting array elements into another form and store
178bf215546Sopenharmony_ci * them in a buffer.
179bf215546Sopenharmony_ci */
180bf215546Sopenharmony_ciEGLint
181bf215546Sopenharmony_ci_eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
182bf215546Sopenharmony_ci                 _EGLArrayForEach flatten)
183bf215546Sopenharmony_ci{
184bf215546Sopenharmony_ci   EGLint i, count;
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   if (!array)
187bf215546Sopenharmony_ci      return 0;
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   count = array->Size;
190bf215546Sopenharmony_ci   if (buffer) {
191bf215546Sopenharmony_ci      /* clamp size to 0 */
192bf215546Sopenharmony_ci      if (size < 0)
193bf215546Sopenharmony_ci         size = 0;
194bf215546Sopenharmony_ci      /* do not exceed buffer size */
195bf215546Sopenharmony_ci      if (count > size)
196bf215546Sopenharmony_ci         count = size;
197bf215546Sopenharmony_ci      for (i = 0; i < count; i++)
198bf215546Sopenharmony_ci         flatten(array->Elements[i],
199bf215546Sopenharmony_ci               (void *) ((char *) buffer + elem_size * i));
200bf215546Sopenharmony_ci   }
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   return count;
203bf215546Sopenharmony_ci}
204