/src/fluent-bit/lib/cfl/src/cfl_array.c
Line | Count | Source |
1 | | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* CFL |
4 | | * === |
5 | | * Copyright (C) 2022-2024 The CFL Authors |
6 | | * |
7 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
8 | | * you may not use this file except in compliance with the License. |
9 | | * You may obtain a copy of the License at |
10 | | * |
11 | | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | | * |
13 | | * Unless required by applicable law or agreed to in writing, software |
14 | | * distributed under the License is distributed on an "AS IS" BASIS, |
15 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | | * See the License for the specific language governing permissions and |
17 | | * limitations under the License. |
18 | | */ |
19 | | |
20 | | #include <cfl/cfl.h> |
21 | | #include <cfl/cfl_array.h> |
22 | | #include <cfl/cfl_variant.h> |
23 | | |
24 | | #include <stdint.h> |
25 | | |
26 | | #include <cfl/cfl_container.h> |
27 | | |
28 | | struct cfl_array *cfl_array_create(size_t slot_count) |
29 | 873k | { |
30 | 873k | struct cfl_array *array; |
31 | 873k | size_t alloc_count; |
32 | | |
33 | 873k | array = malloc(sizeof(struct cfl_array)); |
34 | 873k | if (array == NULL) { |
35 | 0 | cfl_errno(); |
36 | 0 | return NULL; |
37 | 0 | } |
38 | | |
39 | | /* by default arrays are not resizable */ |
40 | 873k | array->resizable = CFL_FALSE; |
41 | | |
42 | | /* allocate fixed number of entries */ |
43 | 873k | alloc_count = slot_count; |
44 | 873k | if (alloc_count == 0) { |
45 | 2.28k | alloc_count = 1; |
46 | 2.28k | } |
47 | 873k | if (alloc_count > SIZE_MAX / sizeof(void *)) { |
48 | 0 | free(array); |
49 | 0 | return NULL; |
50 | 0 | } |
51 | | |
52 | 873k | array->entries = calloc(alloc_count, sizeof(void *)); |
53 | 873k | if (array->entries == NULL) { |
54 | 0 | cfl_errno(); |
55 | 0 | free(array); |
56 | 0 | return NULL; |
57 | 0 | } |
58 | | |
59 | 873k | array->entry_count = 0; |
60 | 873k | array->slot_count = slot_count; |
61 | 873k | array->owner = NULL; |
62 | 873k | array->parent_array = NULL; |
63 | 873k | array->parent_kvlist = NULL; |
64 | | |
65 | 873k | return array; |
66 | 873k | } |
67 | | |
68 | | void cfl_array_destroy(struct cfl_array *array) |
69 | 873k | { |
70 | 873k | size_t index; |
71 | | |
72 | 873k | if (!array) { |
73 | 0 | return; |
74 | 0 | } |
75 | | |
76 | 873k | if (array->entries != NULL) { |
77 | 13.4M | for (index = 0 ; index < array->entry_count ; index++) { |
78 | 12.5M | if(array->entries[index] != NULL) { |
79 | 12.5M | cfl_variant_destroy(array->entries[index]); |
80 | 12.5M | } |
81 | 12.5M | } |
82 | | |
83 | 873k | free(array->entries); |
84 | 873k | } |
85 | 873k | free(array); |
86 | 873k | } |
87 | | |
88 | | int cfl_array_resizable(struct cfl_array *array, int v) |
89 | 28.4k | { |
90 | 28.4k | if (array == NULL) { |
91 | 0 | return -1; |
92 | 0 | } |
93 | | |
94 | 28.4k | if (v != CFL_TRUE && v != CFL_FALSE) { |
95 | 0 | return -1; |
96 | 0 | } |
97 | | |
98 | 28.4k | array->resizable = v; |
99 | 28.4k | return 0; |
100 | 28.4k | } |
101 | | |
102 | | int cfl_array_remove_by_index(struct cfl_array *array, |
103 | | size_t position) |
104 | 0 | { |
105 | 0 | if (array == NULL) { |
106 | 0 | return -1; |
107 | 0 | } |
108 | | |
109 | 0 | if (position >= array->entry_count) { |
110 | 0 | return -1; |
111 | 0 | } |
112 | | |
113 | 0 | cfl_variant_destroy(array->entries[position]); |
114 | |
|
115 | 0 | if (position != array->entry_count - 1) { |
116 | 0 | memmove(&array->entries[position], |
117 | 0 | &array->entries[position + 1], |
118 | 0 | sizeof(void *) * (array->entry_count - (position + 1))); |
119 | 0 | } |
120 | 0 | else { |
121 | 0 | array->entries[position] = NULL; |
122 | 0 | } |
123 | 0 | array->entry_count--; |
124 | |
|
125 | 0 | return 0; |
126 | 0 | } |
127 | | |
128 | | int cfl_array_remove_by_reference(struct cfl_array *array, |
129 | | struct cfl_variant *value) |
130 | 0 | { |
131 | 0 | size_t index; |
132 | |
|
133 | 0 | if (array == NULL || value == NULL) { |
134 | 0 | return -1; |
135 | 0 | } |
136 | | |
137 | 0 | for (index = 0 ; index < array->entry_count ; index++) { |
138 | 0 | if (array->entries[index] == value) { |
139 | 0 | return cfl_array_remove_by_index(array, index); |
140 | 0 | } |
141 | 0 | } |
142 | | |
143 | 0 | return 0; |
144 | 0 | } |
145 | | |
146 | | int cfl_array_append(struct cfl_array *array, |
147 | | struct cfl_variant *value) |
148 | 12.5M | { |
149 | 12.5M | void *tmp; |
150 | 12.5M | size_t new_slot_count; |
151 | 12.5M | size_t new_size; |
152 | 12.5M | size_t base_slot_count; |
153 | | |
154 | 12.5M | if (array == NULL || value == NULL) { |
155 | 0 | return -1; |
156 | 0 | } |
157 | | |
158 | 12.5M | if (array->entry_count >= array->slot_count) { |
159 | | /* |
160 | | * if there is no more space but the caller allowed to resize |
161 | | * the array, just double the size. Yeah, this is scary and should |
162 | | * be used only when the caller 'knows this is safe to do' because |
163 | | * it controls the input data. |
164 | | */ |
165 | 5.81k | if (array->resizable) { |
166 | 5.80k | base_slot_count = array->slot_count; |
167 | 5.80k | if (base_slot_count == 0) { |
168 | 0 | base_slot_count = 1; |
169 | 0 | } |
170 | | |
171 | | /* set new number of slots and total size */ |
172 | 5.80k | if (base_slot_count > SIZE_MAX / 2) { |
173 | 0 | return -1; |
174 | 0 | } |
175 | | |
176 | 5.80k | new_slot_count = (base_slot_count * 2); |
177 | 5.80k | if (new_slot_count > SIZE_MAX / sizeof(void *)) { |
178 | 0 | return -1; |
179 | 0 | } |
180 | | |
181 | 5.80k | new_size = (new_slot_count * sizeof(void *)); |
182 | | |
183 | 5.80k | tmp = realloc(array->entries, new_size); |
184 | 5.80k | if (!tmp) { |
185 | 0 | cfl_report_runtime_error(); |
186 | 0 | return -1; |
187 | 0 | } |
188 | 5.80k | array->slot_count = new_slot_count; |
189 | 5.80k | array->entries = tmp; |
190 | 5.80k | } |
191 | 10 | else { |
192 | 10 | return -1; |
193 | 10 | } |
194 | 5.81k | } |
195 | | |
196 | | /* this is just a double check to make sure the slot is really available */ |
197 | 12.5M | if (array->entry_count >= array->slot_count) { |
198 | 0 | return -1; |
199 | 0 | } |
200 | | |
201 | 12.5M | if (cfl_container_move_variant_to_array(array, value) != 0) { |
202 | 0 | return -1; |
203 | 0 | } |
204 | | |
205 | 12.5M | array->entries[array->entry_count++] = value; |
206 | 12.5M | return 0; |
207 | 12.5M | } |
208 | | |
209 | | int cfl_array_append_string(struct cfl_array *array, char *value) |
210 | 145k | { |
211 | 145k | struct cfl_variant *value_instance; |
212 | 145k | int result; |
213 | | |
214 | 145k | value_instance = cfl_variant_create_from_string(value); |
215 | | |
216 | 145k | if (value_instance == NULL) { |
217 | 0 | return -1; |
218 | 0 | } |
219 | | |
220 | 145k | result = cfl_array_append(array, value_instance); |
221 | 145k | if (result) { |
222 | 0 | cfl_variant_destroy(value_instance); |
223 | 0 | return -2; |
224 | 0 | } |
225 | | |
226 | 145k | return 0; |
227 | 145k | } |
228 | | |
229 | | int cfl_array_append_string_s(struct cfl_array *array, char *str, size_t str_len, int referenced) |
230 | 0 | { |
231 | 0 | struct cfl_variant *value_instance; |
232 | 0 | int result; |
233 | |
|
234 | 0 | value_instance = cfl_variant_create_from_string_s(str, str_len, referenced); |
235 | 0 | if (value_instance == NULL) { |
236 | 0 | return -1; |
237 | 0 | } |
238 | | |
239 | 0 | result = cfl_array_append(array, value_instance); |
240 | 0 | if (result) { |
241 | 0 | cfl_variant_destroy(value_instance); |
242 | 0 | return -2; |
243 | 0 | } |
244 | | |
245 | 0 | return 0; |
246 | 0 | } |
247 | | |
248 | | int cfl_array_append_bytes(struct cfl_array *array, |
249 | | char *value, |
250 | | size_t length, |
251 | | int referenced) |
252 | 217 | { |
253 | 217 | struct cfl_variant *value_instance; |
254 | 217 | int result; |
255 | | |
256 | 217 | value_instance = cfl_variant_create_from_bytes(value, length, referenced); |
257 | 217 | if (value_instance == NULL) { |
258 | 0 | return -1; |
259 | 0 | } |
260 | | |
261 | 217 | result = cfl_array_append(array, value_instance); |
262 | | |
263 | 217 | if (result) { |
264 | 0 | cfl_variant_destroy(value_instance); |
265 | |
|
266 | 0 | return -2; |
267 | 0 | } |
268 | | |
269 | 217 | return 0; |
270 | 217 | } |
271 | | |
272 | | int cfl_array_append_reference(struct cfl_array *array, void *value) |
273 | 0 | { |
274 | 0 | struct cfl_variant *value_instance; |
275 | 0 | int result; |
276 | |
|
277 | 0 | value_instance = cfl_variant_create_from_reference(value); |
278 | |
|
279 | 0 | if (value_instance == NULL) { |
280 | 0 | return -1; |
281 | 0 | } |
282 | | |
283 | 0 | result = cfl_array_append(array, value_instance); |
284 | |
|
285 | 0 | if (result) { |
286 | 0 | cfl_variant_destroy(value_instance); |
287 | |
|
288 | 0 | return -2; |
289 | 0 | } |
290 | | |
291 | 0 | return 0; |
292 | 0 | } |
293 | | |
294 | | int cfl_array_append_bool(struct cfl_array *array, int value) |
295 | 220 | { |
296 | 220 | struct cfl_variant *value_instance; |
297 | 220 | int result; |
298 | | |
299 | 220 | value_instance = cfl_variant_create_from_bool(value); |
300 | | |
301 | 220 | if (value_instance == NULL) { |
302 | 0 | return -1; |
303 | 0 | } |
304 | | |
305 | 220 | result = cfl_array_append(array, value_instance); |
306 | | |
307 | 220 | if (result) { |
308 | 0 | cfl_variant_destroy(value_instance); |
309 | |
|
310 | 0 | return -2; |
311 | 0 | } |
312 | | |
313 | 220 | return 0; |
314 | 220 | } |
315 | | |
316 | | int cfl_array_append_int64(struct cfl_array *array, int64_t value) |
317 | 663 | { |
318 | 663 | struct cfl_variant *value_instance; |
319 | 663 | int result; |
320 | | |
321 | 663 | value_instance = cfl_variant_create_from_int64(value); |
322 | | |
323 | 663 | if (value_instance == NULL) { |
324 | 0 | return -1; |
325 | 0 | } |
326 | | |
327 | 663 | result = cfl_array_append(array, value_instance); |
328 | | |
329 | 663 | if (result) { |
330 | 0 | cfl_variant_destroy(value_instance); |
331 | 0 | return -2; |
332 | 0 | } |
333 | | |
334 | 663 | return 0; |
335 | 663 | } |
336 | | |
337 | | int cfl_array_append_uint64(struct cfl_array *array, uint64_t value) |
338 | 0 | { |
339 | 0 | struct cfl_variant *value_instance; |
340 | 0 | int result; |
341 | |
|
342 | 0 | value_instance = cfl_variant_create_from_uint64(value); |
343 | |
|
344 | 0 | if (value_instance == NULL) { |
345 | 0 | return -1; |
346 | 0 | } |
347 | | |
348 | 0 | result = cfl_array_append(array, value_instance); |
349 | |
|
350 | 0 | if (result) { |
351 | 0 | cfl_variant_destroy(value_instance); |
352 | 0 | return -2; |
353 | 0 | } |
354 | | |
355 | 0 | return 0; |
356 | 0 | } |
357 | | |
358 | | |
359 | | int cfl_array_append_double(struct cfl_array *array, double value) |
360 | 0 | { |
361 | 0 | struct cfl_variant *value_instance; |
362 | 0 | int result; |
363 | |
|
364 | 0 | value_instance = cfl_variant_create_from_double(value); |
365 | |
|
366 | 0 | if (value_instance == NULL) { |
367 | 0 | return -1; |
368 | 0 | } |
369 | | |
370 | 0 | result = cfl_array_append(array, value_instance); |
371 | |
|
372 | 0 | if (result) { |
373 | 0 | cfl_variant_destroy(value_instance); |
374 | |
|
375 | 0 | return -2; |
376 | 0 | } |
377 | | |
378 | 0 | return 0; |
379 | 0 | } |
380 | | |
381 | | int cfl_array_append_null(struct cfl_array *array) |
382 | 0 | { |
383 | 0 | struct cfl_variant *value_instance; |
384 | 0 | int result; |
385 | |
|
386 | 0 | value_instance = cfl_variant_create_from_null(); |
387 | 0 | if (value_instance == NULL) { |
388 | 0 | return -1; |
389 | 0 | } |
390 | | |
391 | 0 | result = cfl_array_append(array, value_instance); |
392 | 0 | if (result) { |
393 | 0 | cfl_variant_destroy(value_instance); |
394 | 0 | return -2; |
395 | 0 | } |
396 | | |
397 | 0 | return 0; |
398 | 0 | } |
399 | | |
400 | | int cfl_array_append_array(struct cfl_array *array, struct cfl_array *value) |
401 | 78 | { |
402 | 78 | struct cfl_variant *value_instance; |
403 | 78 | int result; |
404 | | |
405 | 78 | if (array == NULL || value == NULL) { |
406 | 0 | return -1; |
407 | 0 | } |
408 | | |
409 | 78 | if (array == value) { |
410 | 0 | return -1; |
411 | 0 | } |
412 | | |
413 | 78 | value_instance = cfl_variant_create_from_array(value); |
414 | | |
415 | 78 | if (value_instance == NULL) { |
416 | 0 | return -1; |
417 | 0 | } |
418 | | |
419 | 78 | result = cfl_array_append(array, value_instance); |
420 | 78 | if (result) { |
421 | 0 | cfl_container_release_variant(value_instance); |
422 | 0 | value_instance->data.as_array = NULL; |
423 | 0 | cfl_variant_destroy(value_instance); |
424 | 0 | return -2; |
425 | 0 | } |
426 | | |
427 | 78 | return 0; |
428 | 78 | } |
429 | | |
430 | | |
431 | | int cfl_array_append_new_array(struct cfl_array *array, size_t size) |
432 | 0 | { |
433 | 0 | int result; |
434 | 0 | struct cfl_array *value; |
435 | |
|
436 | 0 | if (array == NULL) { |
437 | 0 | return -1; |
438 | 0 | } |
439 | | |
440 | 0 | value = cfl_array_create(size); |
441 | |
|
442 | 0 | if (value == NULL) { |
443 | 0 | return -1; |
444 | 0 | } |
445 | | |
446 | 0 | result = cfl_array_append_array(array, value); |
447 | 0 | if (result < 0) { |
448 | 0 | cfl_array_destroy(value); |
449 | 0 | } |
450 | |
|
451 | 0 | return result; |
452 | 0 | } |
453 | | |
454 | | int cfl_array_append_kvlist(struct cfl_array *array, struct cfl_kvlist *value) |
455 | 3.67k | { |
456 | 3.67k | struct cfl_variant *value_instance; |
457 | 3.67k | int result; |
458 | | |
459 | 3.67k | if (array == NULL || value == NULL) { |
460 | 0 | return -1; |
461 | 0 | } |
462 | | |
463 | 3.67k | value_instance = cfl_variant_create_from_kvlist(value); |
464 | 3.67k | if (value_instance == NULL) { |
465 | 0 | return -1; |
466 | 0 | } |
467 | 3.67k | result = cfl_array_append(array, value_instance); |
468 | | |
469 | 3.67k | if (result) { |
470 | 0 | cfl_container_release_variant(value_instance); |
471 | 0 | value_instance->data.as_kvlist = NULL; |
472 | 0 | cfl_variant_destroy(value_instance); |
473 | |
|
474 | 0 | return -2; |
475 | 0 | } |
476 | | |
477 | 3.67k | return 0; |
478 | 3.67k | } |
479 | | |
480 | | |
481 | | int cfl_array_print(FILE *fp, struct cfl_array *array) |
482 | 0 | { |
483 | 0 | size_t size; |
484 | 0 | size_t i; |
485 | 0 | int ret; |
486 | |
|
487 | 0 | if (fp == NULL || array == NULL) { |
488 | 0 | return -1; |
489 | 0 | } |
490 | | |
491 | 0 | size = array->entry_count; |
492 | 0 | if (size == 0) { |
493 | 0 | if (fputs("[]", fp) == EOF) { |
494 | 0 | return -1; |
495 | 0 | } |
496 | | |
497 | 0 | return 0; |
498 | 0 | } |
499 | | |
500 | 0 | if (fputc('[', fp) == EOF) { |
501 | 0 | return -1; |
502 | 0 | } |
503 | | |
504 | 0 | for (i=0; i<size-1; i++) { |
505 | 0 | ret = cfl_variant_print(fp, array->entries[i]); |
506 | 0 | if (ret < 0) { |
507 | 0 | return -1; |
508 | 0 | } |
509 | | |
510 | 0 | if (fputc(',', fp) == EOF) { |
511 | 0 | return -1; |
512 | 0 | } |
513 | 0 | } |
514 | | |
515 | 0 | ret = cfl_variant_print(fp, array->entries[size-1]); |
516 | 0 | if (ret < 0) { |
517 | 0 | return -1; |
518 | 0 | } |
519 | | |
520 | 0 | if (fputc(']', fp) == EOF) { |
521 | 0 | return -1; |
522 | 0 | } |
523 | | |
524 | 0 | return ret; |
525 | 0 | } |