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