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