Coverage Report

Created: 2025-07-11 06:31

/src/libcbor/src/cbor/strings.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 "strings.h"
9
#include <string.h>
10
#include "internal/memory_utils.h"
11
#include "internal/unicode.h"
12
13
323k
cbor_item_t *cbor_new_definite_string(void) {
14
323k
  cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
15
323k
  _CBOR_NOTNULL(item);
16
323k
  *item = (cbor_item_t){
17
323k
      .refcount = 1,
18
323k
      .type = CBOR_TYPE_STRING,
19
323k
      .metadata = {.string_metadata = {_CBOR_METADATA_DEFINITE, 0}}};
20
323k
  return item;
21
323k
}
22
23
2.84k
cbor_item_t *cbor_new_indefinite_string(void) {
24
2.84k
  cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
25
2.84k
  _CBOR_NOTNULL(item);
26
2.84k
  *item = (cbor_item_t){
27
2.84k
      .refcount = 1,
28
2.84k
      .type = CBOR_TYPE_STRING,
29
2.84k
      .metadata = {.string_metadata = {.type = _CBOR_METADATA_INDEFINITE,
30
2.84k
                                       .length = 0}},
31
2.84k
      .data = _cbor_malloc(sizeof(struct cbor_indefinite_string_data))};
32
2.84k
  _CBOR_DEPENDENT_NOTNULL(item, item->data);
33
2.84k
  *((struct cbor_indefinite_string_data *)item->data) =
34
2.84k
      (struct cbor_indefinite_string_data){
35
2.84k
          .chunk_count = 0,
36
2.84k
          .chunk_capacity = 0,
37
2.84k
          .chunks = NULL,
38
2.84k
      };
39
2.84k
  return item;
40
2.84k
}
41
42
53.6k
cbor_item_t *cbor_build_string(const char *val) {
43
53.6k
  cbor_item_t *item = cbor_new_definite_string();
44
53.6k
  _CBOR_NOTNULL(item);
45
53.6k
  size_t len = strlen(val);
46
53.6k
  unsigned char *handle = _cbor_malloc(len);
47
53.6k
  _CBOR_DEPENDENT_NOTNULL(item, handle);
48
53.6k
  memcpy(handle, val, len);
49
53.6k
  cbor_string_set_handle(item, handle, len);
50
53.6k
  return item;
51
53.6k
}
52
53
0
cbor_item_t *cbor_build_stringn(const char *val, size_t length) {
54
0
  cbor_item_t *item = cbor_new_definite_string();
55
0
  _CBOR_NOTNULL(item);
56
0
  unsigned char *handle = _cbor_malloc(length);
57
0
  _CBOR_DEPENDENT_NOTNULL(item, handle);
58
0
  memcpy(handle, val, length);
59
0
  cbor_string_set_handle(item, handle, length);
60
0
  return item;
61
0
}
62
63
void cbor_string_set_handle(cbor_item_t *item,
64
                            cbor_mutable_data CBOR_RESTRICT_POINTER data,
65
323k
                            size_t length) {
66
323k
  CBOR_ASSERT(cbor_isa_string(item));
67
323k
  CBOR_ASSERT(cbor_string_is_definite(item));
68
323k
  item->data = data;
69
323k
  item->metadata.string_metadata.length = length;
70
323k
  struct _cbor_unicode_status unicode_status;
71
323k
  size_t codepoint_count =
72
323k
      _cbor_unicode_codepoint_count(data, length, &unicode_status);
73
323k
  CBOR_ASSERT(codepoint_count <= length);
74
323k
  if (unicode_status.status == _CBOR_UNICODE_OK) {
75
303k
    item->metadata.string_metadata.codepoint_count = codepoint_count;
76
303k
  } else {
77
20.1k
    item->metadata.string_metadata.codepoint_count = 0;
78
20.1k
  }
79
323k
}
80
81
2.84k
cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item) {
82
2.84k
  CBOR_ASSERT(cbor_isa_string(item));
83
2.84k
  CBOR_ASSERT(cbor_string_is_indefinite(item));
84
2.84k
  return ((struct cbor_indefinite_string_data *)item->data)->chunks;
85
2.84k
}
86
87
39.3k
size_t cbor_string_chunk_count(const cbor_item_t *item) {
88
39.3k
  CBOR_ASSERT(cbor_isa_string(item));
89
39.3k
  CBOR_ASSERT(cbor_string_is_indefinite(item));
90
39.3k
  return ((struct cbor_indefinite_string_data *)item->data)->chunk_count;
91
39.3k
}
92
93
36.5k
bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk) {
94
36.5k
  CBOR_ASSERT(cbor_isa_string(item));
95
36.5k
  CBOR_ASSERT(cbor_string_is_indefinite(item));
96
36.5k
  struct cbor_indefinite_string_data *data =
97
36.5k
      (struct cbor_indefinite_string_data *)item->data;
98
36.5k
  if (data->chunk_count == data->chunk_capacity) {
99
890
    if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
100
0
      return false;
101
0
    }
102
103
890
    size_t new_chunk_capacity =
104
890
        data->chunk_capacity == 0 ? 1
105
890
                                  : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
106
890
    cbor_item_t **new_chunks_data = _cbor_realloc_multiple(
107
890
        data->chunks, sizeof(cbor_item_t *), new_chunk_capacity);
108
109
890
    if (new_chunks_data == NULL) {
110
1
      return false;
111
1
    }
112
113
889
    data->chunk_capacity = new_chunk_capacity;
114
889
    data->chunks = new_chunks_data;
115
889
  }
116
36.5k
  data->chunks[data->chunk_count++] = cbor_incref(chunk);
117
36.5k
  return true;
118
36.5k
}
119
120
230k
size_t cbor_string_length(const cbor_item_t *item) {
121
230k
  CBOR_ASSERT(cbor_isa_string(item));
122
230k
  return item->metadata.string_metadata.length;
123
230k
}
124
125
110k
unsigned char *cbor_string_handle(const cbor_item_t *item) {
126
110k
  CBOR_ASSERT(cbor_isa_string(item));
127
110k
  return item->data;
128
110k
}
129
130
0
size_t cbor_string_codepoint_count(const cbor_item_t *item) {
131
0
  CBOR_ASSERT(cbor_isa_string(item));
132
0
  return item->metadata.string_metadata.codepoint_count;
133
0
}
134
135
470k
bool cbor_string_is_definite(const cbor_item_t *item) {
136
470k
  CBOR_ASSERT(cbor_isa_string(item));
137
470k
  return item->metadata.string_metadata.type == _CBOR_METADATA_DEFINITE;
138
470k
}
139
140
36.7k
bool cbor_string_is_indefinite(const cbor_item_t *item) {
141
36.7k
  return !cbor_string_is_definite(item);
142
36.7k
}