/src/libcbor/src/cbor/arrays.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com> |
3 | | * |
4 | | * libcbor is free software; you can redistribute it and/or modify |
5 | | * it under the terms of the MIT license. See LICENSE for details. |
6 | | */ |
7 | | |
8 | | #include "arrays.h" |
9 | | #include <string.h> |
10 | | #include "internal/memory_utils.h" |
11 | | |
12 | 0 | size_t cbor_array_size(const cbor_item_t *item) { |
13 | 0 | CBOR_ASSERT(cbor_isa_array(item)); |
14 | 0 | return item->metadata.array_metadata.end_ptr; |
15 | 0 | } |
16 | | |
17 | 0 | size_t cbor_array_allocated(const cbor_item_t *item) { |
18 | 0 | CBOR_ASSERT(cbor_isa_array(item)); |
19 | 0 | return item->metadata.array_metadata.allocated; |
20 | 0 | } |
21 | | |
22 | 0 | cbor_item_t *cbor_array_get(const cbor_item_t *item, size_t index) { |
23 | 0 | return cbor_incref(((cbor_item_t **)item->data)[index]); |
24 | 0 | } |
25 | | |
26 | 0 | bool cbor_array_set(cbor_item_t *item, size_t index, cbor_item_t *value) { |
27 | 0 | if (index == item->metadata.array_metadata.end_ptr) { |
28 | 0 | return cbor_array_push(item, value); |
29 | 0 | } else if (index < item->metadata.array_metadata.end_ptr) { |
30 | 0 | return cbor_array_replace(item, index, value); |
31 | 0 | } else { |
32 | 0 | return false; |
33 | 0 | } |
34 | 0 | } |
35 | | |
36 | 0 | bool cbor_array_replace(cbor_item_t *item, size_t index, cbor_item_t *value) { |
37 | 0 | if (index >= item->metadata.array_metadata.end_ptr) return false; |
38 | | /* We cannot use cbor_array_get as that would increase the refcount */ |
39 | 0 | cbor_intermediate_decref(((cbor_item_t **)item->data)[index]); |
40 | 0 | ((cbor_item_t **)item->data)[index] = cbor_incref(value); |
41 | 0 | return true; |
42 | 0 | } |
43 | | |
44 | 0 | bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee) { |
45 | 0 | CBOR_ASSERT(cbor_isa_array(array)); |
46 | 0 | struct _cbor_array_metadata *metadata = |
47 | 0 | (struct _cbor_array_metadata *)&array->metadata; |
48 | 0 | cbor_item_t **data = (cbor_item_t **)array->data; |
49 | 0 | if (cbor_array_is_definite(array)) { |
50 | | /* Do not reallocate definite arrays */ |
51 | 0 | if (metadata->end_ptr >= metadata->allocated) { |
52 | 0 | return false; |
53 | 0 | } |
54 | 0 | data[metadata->end_ptr++] = pushee; |
55 | 0 | } else { |
56 | | /* Exponential realloc */ |
57 | 0 | if (metadata->end_ptr >= metadata->allocated) { |
58 | | // Check for overflows first |
59 | 0 | if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) { |
60 | 0 | return false; |
61 | 0 | } |
62 | | |
63 | 0 | size_t new_allocation = metadata->allocated == 0 |
64 | 0 | ? 1 |
65 | 0 | : CBOR_BUFFER_GROWTH * metadata->allocated; |
66 | |
|
67 | 0 | unsigned char *new_data = _cbor_realloc_multiple( |
68 | 0 | array->data, sizeof(cbor_item_t *), new_allocation); |
69 | 0 | if (new_data == NULL) { |
70 | 0 | return false; |
71 | 0 | } |
72 | | |
73 | 0 | array->data = new_data; |
74 | 0 | metadata->allocated = new_allocation; |
75 | 0 | } |
76 | 0 | ((cbor_item_t **)array->data)[metadata->end_ptr++] = pushee; |
77 | 0 | } |
78 | 0 | cbor_incref(pushee); |
79 | 0 | return true; |
80 | 0 | } |
81 | | |
82 | 0 | bool cbor_array_is_definite(const cbor_item_t *item) { |
83 | 0 | CBOR_ASSERT(cbor_isa_array(item)); |
84 | 0 | return item->metadata.array_metadata.type == _CBOR_METADATA_DEFINITE; |
85 | 0 | } |
86 | | |
87 | 0 | bool cbor_array_is_indefinite(const cbor_item_t *item) { |
88 | 0 | CBOR_ASSERT(cbor_isa_array(item)); |
89 | 0 | return item->metadata.array_metadata.type == _CBOR_METADATA_INDEFINITE; |
90 | 0 | } |
91 | | |
92 | 0 | cbor_item_t **cbor_array_handle(const cbor_item_t *item) { |
93 | 0 | CBOR_ASSERT(cbor_isa_array(item)); |
94 | 0 | return (cbor_item_t **)item->data; |
95 | 0 | } |
96 | | |
97 | 0 | cbor_item_t *cbor_new_definite_array(size_t size) { |
98 | 0 | cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); |
99 | 0 | _CBOR_NOTNULL(item); |
100 | 0 | cbor_item_t **data = _cbor_alloc_multiple(sizeof(cbor_item_t *), size); |
101 | 0 | _CBOR_DEPENDENT_NOTNULL(item, data); |
102 | | |
103 | 0 | for (size_t i = 0; i < size; i++) { |
104 | 0 | data[i] = NULL; |
105 | 0 | } |
106 | |
|
107 | 0 | *item = (cbor_item_t){ |
108 | 0 | .refcount = 1, |
109 | 0 | .type = CBOR_TYPE_ARRAY, |
110 | 0 | .metadata = {.array_metadata = {.type = _CBOR_METADATA_DEFINITE, |
111 | 0 | .allocated = size, |
112 | 0 | .end_ptr = 0}}, |
113 | 0 | .data = (unsigned char *)data}; |
114 | |
|
115 | 0 | return item; |
116 | 0 | } |
117 | | |
118 | 0 | cbor_item_t *cbor_new_indefinite_array(void) { |
119 | 0 | cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); |
120 | 0 | _CBOR_NOTNULL(item); |
121 | | |
122 | 0 | *item = (cbor_item_t){ |
123 | 0 | .refcount = 1, |
124 | 0 | .type = CBOR_TYPE_ARRAY, |
125 | 0 | .metadata = {.array_metadata = {.type = _CBOR_METADATA_INDEFINITE, |
126 | 0 | .allocated = 0, |
127 | 0 | .end_ptr = 0}}, |
128 | | .data = NULL /* Can be safely realloc-ed */ |
129 | 0 | }; |
130 | 0 | return item; |
131 | 0 | } |