/src/S2OPC/src/Common/helpers/sopc_array.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Licensed to Systerel under one or more contributor license |
3 | | * agreements. See the NOTICE file distributed with this work |
4 | | * for additional information regarding copyright ownership. |
5 | | * Systerel licenses this file to you under the Apache |
6 | | * License, Version 2.0 (the "License"); you may not use this |
7 | | * file except in compliance with the License. You may obtain |
8 | | * a copy of the License at |
9 | | * |
10 | | * http://www.apache.org/licenses/LICENSE-2.0 |
11 | | * |
12 | | * Unless required by applicable law or agreed to in writing, |
13 | | * software distributed under the License is distributed on an |
14 | | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
15 | | * KIND, either express or implied. See the License for the |
16 | | * specific language governing permissions and limitations |
17 | | * under the License. |
18 | | */ |
19 | | |
20 | | #include "sopc_array.h" |
21 | | |
22 | | #include <stdint.h> |
23 | | #include <stdlib.h> /* qsort */ |
24 | | #include <string.h> |
25 | | |
26 | | #include "sopc_assert.h" |
27 | | #include "sopc_mem_alloc.h" |
28 | | |
29 | 0 | #define ARRAY_ELT(a, idx) ((void*) (a->data + idx * a->element_size)) |
30 | | |
31 | | struct _SOPC_Array |
32 | | { |
33 | | uint8_t* data; |
34 | | size_t element_size; |
35 | | size_t sz; |
36 | | size_t cap; |
37 | | SOPC_Array_Free_Func* free_func; |
38 | | }; |
39 | | |
40 | | static bool array_grow(SOPC_Array* a, size_t min_size) |
41 | 0 | { |
42 | 0 | SOPC_ASSERT(a != NULL); |
43 | | |
44 | 0 | if (a->cap >= min_size) |
45 | 0 | { |
46 | 0 | return true; |
47 | 0 | } |
48 | | |
49 | 0 | size_t cap = (a->cap != 0 ? a->cap : 1); |
50 | |
|
51 | 0 | while (cap < min_size) |
52 | 0 | { |
53 | 0 | cap *= 2; |
54 | 0 | } |
55 | |
|
56 | 0 | void* data = SOPC_Realloc(a->data, a->cap * a->element_size, cap * a->element_size); |
57 | |
|
58 | 0 | if (data == NULL) |
59 | 0 | { |
60 | 0 | return false; |
61 | 0 | } |
62 | | |
63 | 0 | a->data = data; |
64 | 0 | a->cap = cap; |
65 | |
|
66 | 0 | return true; |
67 | 0 | } |
68 | | |
69 | | SOPC_Array* SOPC_Array_Create(size_t element_size, size_t initial_capacity, SOPC_Array_Free_Func* free_func) |
70 | 0 | { |
71 | 0 | SOPC_Array* a = SOPC_Calloc(1, sizeof(SOPC_Array)); |
72 | |
|
73 | 0 | if (a == NULL) |
74 | 0 | { |
75 | 0 | return NULL; |
76 | 0 | } |
77 | | |
78 | 0 | a->element_size = element_size; |
79 | 0 | a->free_func = free_func; |
80 | |
|
81 | 0 | if (!array_grow(a, initial_capacity)) |
82 | 0 | { |
83 | 0 | SOPC_Free(a); |
84 | 0 | return NULL; |
85 | 0 | } |
86 | | |
87 | 0 | return a; |
88 | 0 | } |
89 | | |
90 | | SOPC_Array* SOPC_Array_Copy(const SOPC_Array* array) |
91 | 0 | { |
92 | 0 | if (NULL == array) |
93 | 0 | { |
94 | 0 | return NULL; |
95 | 0 | } |
96 | | |
97 | 0 | SOPC_Array* copy = SOPC_Array_Create(array->element_size, array->sz, array->free_func); |
98 | |
|
99 | 0 | if (copy == NULL) |
100 | 0 | { |
101 | 0 | return NULL; |
102 | 0 | } |
103 | | |
104 | 0 | if (copy->data != NULL) |
105 | 0 | { |
106 | 0 | memcpy(copy->data, array->data, array->element_size * array->sz); |
107 | 0 | } |
108 | |
|
109 | 0 | copy->sz = array->sz; |
110 | |
|
111 | 0 | return copy; |
112 | 0 | } |
113 | | |
114 | | void SOPC_Array_Delete(SOPC_Array* array) |
115 | 0 | { |
116 | 0 | if (array == NULL) |
117 | 0 | { |
118 | 0 | return; |
119 | 0 | } |
120 | | |
121 | 0 | if (array->free_func != NULL) |
122 | 0 | { |
123 | 0 | for (size_t i = 0; i < array->sz; ++i) |
124 | 0 | { |
125 | 0 | array->free_func(ARRAY_ELT(array, i)); |
126 | 0 | } |
127 | 0 | } |
128 | |
|
129 | 0 | SOPC_Free(array->data); |
130 | 0 | SOPC_Free(array); |
131 | 0 | } |
132 | | |
133 | | bool SOPC_Array_Append_Values(SOPC_Array* array, const void* data, size_t n_elements) |
134 | 0 | { |
135 | 0 | if (NULL == array) |
136 | 0 | { |
137 | 0 | return false; |
138 | 0 | } |
139 | | |
140 | 0 | if (n_elements == 0) |
141 | 0 | { |
142 | 0 | return true; |
143 | 0 | } |
144 | | |
145 | 0 | if (!array_grow(array, array->sz + n_elements)) |
146 | 0 | { |
147 | 0 | return false; |
148 | 0 | } |
149 | | |
150 | 0 | if (data != NULL) |
151 | 0 | { |
152 | 0 | memcpy(ARRAY_ELT(array, array->sz), data, n_elements * array->element_size); |
153 | 0 | } |
154 | 0 | else |
155 | 0 | { |
156 | 0 | memset(ARRAY_ELT(array, array->sz), 0, n_elements * array->element_size); |
157 | 0 | } |
158 | |
|
159 | 0 | array->sz += n_elements; |
160 | |
|
161 | 0 | return true; |
162 | 0 | } |
163 | | |
164 | | void* SOPC_Array_Get_Ptr(const SOPC_Array* array, size_t index) |
165 | 0 | { |
166 | 0 | if (NULL == array) |
167 | 0 | { |
168 | 0 | return NULL; |
169 | 0 | } |
170 | 0 | SOPC_ASSERT(index < array->sz); |
171 | | |
172 | 0 | return ARRAY_ELT(array, index); |
173 | 0 | } |
174 | | |
175 | | size_t SOPC_Array_Size(const SOPC_Array* array) |
176 | 0 | { |
177 | 0 | if (array != NULL) |
178 | 0 | { |
179 | 0 | return array->sz; |
180 | 0 | } |
181 | 0 | return 0; |
182 | 0 | } |
183 | | |
184 | | void SOPC_Array_Sort(SOPC_Array* array, SOPC_Array_Compare_Func* compare_func) |
185 | 0 | { |
186 | 0 | SOPC_ASSERT(array != NULL); |
187 | 0 | qsort(array->data, array->sz, array->element_size, compare_func); |
188 | 0 | } |
189 | | |
190 | | void* SOPC_Array_Into_Raw(SOPC_Array* array) |
191 | 0 | { |
192 | 0 | if (NULL == array) |
193 | 0 | { |
194 | 0 | return NULL; |
195 | 0 | } |
196 | | |
197 | 0 | void* data = array->data; |
198 | |
|
199 | 0 | if (array->sz < array->cap) |
200 | 0 | { |
201 | 0 | data = SOPC_Realloc(data, array->cap * array->element_size, array->sz * array->element_size); |
202 | 0 | } |
203 | |
|
204 | 0 | SOPC_Free(array); |
205 | |
|
206 | 0 | return data; |
207 | 0 | } |
208 | | |
209 | | SOPC_Array_Free_Func* SOPC_Array_Get_Free_Func(SOPC_Array* array) |
210 | 0 | { |
211 | 0 | if (NULL == array) |
212 | 0 | { |
213 | 0 | return NULL; |
214 | 0 | } |
215 | 0 | return array->free_func; |
216 | 0 | } |
217 | | |
218 | | void SOPC_Array_Set_Free_Func(SOPC_Array* array, SOPC_Array_Free_Func* func) |
219 | 0 | { |
220 | 0 | SOPC_ASSERT(array != NULL); |
221 | 0 | array->free_func = func; |
222 | 0 | } |