shl: array: add shl_array_zresize()
[platform/upstream/kmscon.git] / src / shl_array.h
1 /*
2  * shl - Dynamic Array
3  *
4  * Copyright (c) 2011-2012 David Herrmann <dh.herrmann@googlemail.com>
5  * Copyright (c) 2011 University of Tuebingen
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files
9  * (the "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26
27 /*
28  * A dynamic array implementation
29  */
30
31 #ifndef SHL_ARRAY_H
32 #define SHL_ARRAY_H
33
34 #include <stdbool.h>
35 #include <stddef.h>
36 #include <stdint.h>
37 #include <stdlib.h>
38 #include "shl_misc.h"
39
40 struct shl_array {
41         size_t element_size;
42         size_t length;
43         size_t size;
44         void *data;
45 };
46
47 #define SHL_ARRAY_AT(_arr, _type, _pos) \
48         (&((_type*)shl_array_get_array(_arr))[(_pos)])
49
50 static inline int shl_array_new(struct shl_array **out, size_t element_size,
51                                 size_t initial_size)
52 {
53         struct shl_array *arr;
54
55         if (!out || !element_size)
56                 return -EINVAL;
57
58         if (!initial_size)
59                 initial_size = 4;
60
61         arr = malloc(sizeof(*arr));
62         if (!arr)
63                 return -ENOMEM;
64         memset(arr, 0, sizeof(*arr));
65         arr->element_size = element_size;
66         arr->length = 0;
67         arr->size = initial_size;
68
69         arr->data = malloc(arr->element_size * arr->size);
70         if (!arr->data) {
71                 free(arr);
72                 return -ENOMEM;
73         }
74
75         *out = arr;
76         return 0;
77 }
78
79 static inline void shl_array_free(struct shl_array *arr)
80 {
81         if (!arr)
82                 return;
83
84         free(arr->data);
85         free(arr);
86 }
87
88 /* resize to length=size and zero out new array entries */
89 static inline int shl_array_zresize(struct shl_array *arr, size_t size)
90 {
91         void *tmp;
92         size_t newsize;
93
94         if (!arr)
95                 return -EINVAL;
96
97         if (size > arr->size) {
98                 newsize = shl_next_pow2(size);
99                 tmp = realloc(arr->data, arr->element_size * newsize);
100                 if (!tmp)
101                         return -ENOMEM;
102
103                 arr->data = tmp;
104                 arr->size = newsize;
105
106                 memset(((uint8_t*)arr->data) + arr->element_size * arr->length,
107                        0, arr->element_size * (size - arr->length));
108         }
109
110         arr->length = size;
111         return 0;
112 }
113
114 static inline int shl_array_push(struct shl_array *arr, const void *data)
115 {
116         void *tmp;
117         size_t newsize;
118
119         if (!arr || !data)
120                 return -EINVAL;
121
122         if (arr->length >= arr->size) {
123                 newsize = arr->size * 2;
124                 tmp = realloc(arr->data, arr->element_size * newsize);
125                 if (!tmp)
126                         return -ENOMEM;
127
128                 arr->data = tmp;
129                 arr->size = newsize;
130         }
131
132         memcpy(((uint8_t*)arr->data) + arr->element_size * arr->length,
133                data, arr->element_size);
134         ++arr->length;
135
136         return 0;
137 }
138
139 static inline void shl_array_pop(struct shl_array *arr)
140 {
141         if (!arr || !arr->length)
142                 return;
143
144         --arr->length;
145 }
146
147 static inline void *shl_array_get_array(struct shl_array *arr)
148 {
149         if (!arr)
150                 return NULL;
151
152         return arr->data;
153 }
154
155 static inline size_t shl_array_get_length(struct shl_array *arr)
156 {
157         if (!arr)
158                 return 0;
159
160         return arr->length;
161 }
162
163 static inline size_t shl_array_get_bsize(struct shl_array *arr)
164 {
165         if (!arr)
166                 return 0;
167
168         return arr->length * arr->element_size;
169 }
170
171 static inline size_t shl_array_get_element_size(struct shl_array *arr)
172 {
173         if (!arr)
174                 return 0;
175
176         return arr->element_size;
177 }
178
179 #endif /* SHL_ARRAY_H */