Coverage Report

Created: 2025-07-01 07:09

/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
}