Coverage Report

Created: 2025-08-26 06:55

/src/libcbor/src/cbor/maps.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 "maps.h"
9
#include "internal/memory_utils.h"
10
11
8.44M
size_t cbor_map_size(const cbor_item_t *item) {
12
8.44M
  CBOR_ASSERT(cbor_isa_map(item));
13
8.44M
  return item->metadata.map_metadata.end_ptr;
14
8.44M
}
15
16
0
size_t cbor_map_allocated(const cbor_item_t *item) {
17
0
  CBOR_ASSERT(cbor_isa_map(item));
18
0
  return item->metadata.map_metadata.allocated;
19
0
}
20
21
5.87M
cbor_item_t *cbor_new_definite_map(size_t size) {
22
5.87M
  cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
23
5.87M
  _CBOR_NOTNULL(item);
24
25
5.87M
  *item = (cbor_item_t){
26
5.87M
      .refcount = 1,
27
5.87M
      .type = CBOR_TYPE_MAP,
28
5.87M
      .metadata = {.map_metadata = {.allocated = size,
29
5.87M
                                    .type = _CBOR_METADATA_DEFINITE,
30
5.87M
                                    .end_ptr = 0}},
31
5.87M
      .data = _cbor_alloc_multiple(sizeof(struct cbor_pair), size)};
32
5.87M
  _CBOR_DEPENDENT_NOTNULL(item, item->data);
33
34
5.87M
  return item;
35
5.87M
}
36
37
1.27M
cbor_item_t *cbor_new_indefinite_map(void) {
38
1.27M
  cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
39
1.27M
  _CBOR_NOTNULL(item);
40
41
1.27M
  *item = (cbor_item_t){
42
1.27M
      .refcount = 1,
43
1.27M
      .type = CBOR_TYPE_MAP,
44
1.27M
      .metadata = {.map_metadata = {.allocated = 0,
45
1.27M
                                    .type = _CBOR_METADATA_INDEFINITE,
46
1.27M
                                    .end_ptr = 0}},
47
1.27M
      .data = NULL};
48
49
1.27M
  return item;
50
1.27M
}
51
52
2.56M
bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key) {
53
2.56M
  CBOR_ASSERT(cbor_isa_map(item));
54
2.56M
  struct _cbor_map_metadata *metadata =
55
2.56M
      (struct _cbor_map_metadata *)&item->metadata;
56
2.56M
  if (cbor_map_is_definite(item)) {
57
420k
    struct cbor_pair *data = cbor_map_handle(item);
58
420k
    if (metadata->end_ptr >= metadata->allocated) {
59
      /* Don't realloc definite preallocated map */
60
0
      return false;
61
0
    }
62
63
420k
    data[metadata->end_ptr].key = key;
64
420k
    data[metadata->end_ptr++].value = NULL;
65
2.14M
  } else {
66
2.14M
    if (metadata->end_ptr >= metadata->allocated) {
67
      /* Exponential realloc */
68
      // Check for overflows first
69
1.31M
      if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) {
70
0
        return false;
71
0
      }
72
73
1.31M
      size_t new_allocation = metadata->allocated == 0
74
1.31M
                                  ? 1
75
1.31M
                                  : CBOR_BUFFER_GROWTH * metadata->allocated;
76
77
1.31M
      unsigned char *new_data = _cbor_realloc_multiple(
78
1.31M
          item->data, sizeof(struct cbor_pair), new_allocation);
79
80
1.31M
      if (new_data == NULL) {
81
2
        return false;
82
2
      }
83
84
1.31M
      item->data = new_data;
85
1.31M
      metadata->allocated = new_allocation;
86
1.31M
    }
87
2.14M
    struct cbor_pair *data = cbor_map_handle(item);
88
2.14M
    data[metadata->end_ptr].key = key;
89
2.14M
    data[metadata->end_ptr++].value = NULL;
90
2.14M
  }
91
2.56M
  cbor_incref(key);
92
2.56M
  return true;
93
2.56M
}
94
95
2.56M
bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value) {
96
2.56M
  CBOR_ASSERT(cbor_isa_map(item));
97
2.56M
  cbor_incref(value);
98
2.56M
  cbor_map_handle(item)[
99
      /* Move one back since we are assuming _add_key (which increased the ptr)
100
       * was the previous operation on this object */
101
2.56M
      item->metadata.map_metadata.end_ptr - 1]
102
2.56M
      .value = value;
103
2.56M
  return true;
104
2.56M
}
105
106
// TODO: Add a more convenient API like add(item, key, val)
107
1.29M
bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair) {
108
1.29M
  CBOR_ASSERT(cbor_isa_map(item));
109
1.29M
  if (!_cbor_map_add_key(item, pair.key)) return false;
110
1.29M
  return _cbor_map_add_value(item, pair.value);
111
1.29M
}
112
113
8.29M
bool cbor_map_is_definite(const cbor_item_t *item) {
114
8.29M
  CBOR_ASSERT(cbor_isa_map(item));
115
8.29M
  return item->metadata.map_metadata.type == _CBOR_METADATA_DEFINITE;
116
8.29M
}
117
118
23.8k
bool cbor_map_is_indefinite(const cbor_item_t *item) {
119
23.8k
  return !cbor_map_is_definite(item);
120
23.8k
}
121
122
19.3M
struct cbor_pair *cbor_map_handle(const cbor_item_t *item) {
123
19.3M
  CBOR_ASSERT(cbor_isa_map(item));
124
19.3M
  return (struct cbor_pair *)item->data;
125
19.3M
}