1 /*
2 * Copyright (c) 2014-2019 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
cbor_new_definite_string()12 cbor_item_t *cbor_new_definite_string() {
13 cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
14 _CBOR_NOTNULL(item);
15 *item = (cbor_item_t){
16 .refcount = 1,
17 .type = CBOR_TYPE_STRING,
18 .metadata = {.string_metadata = {_CBOR_METADATA_DEFINITE, 0}}};
19 return item;
20 }
21
cbor_new_indefinite_string()22 cbor_item_t *cbor_new_indefinite_string() {
23 cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
24 _CBOR_NOTNULL(item);
25 *item = (cbor_item_t){
26 .refcount = 1,
27 .type = CBOR_TYPE_STRING,
28 .metadata = {.string_metadata = {.type = _CBOR_METADATA_INDEFINITE,
29 .length = 0}},
30 .data = _CBOR_MALLOC(sizeof(struct cbor_indefinite_string_data))};
31 _CBOR_DEPENDENT_NOTNULL(item, item->data);
32 *((struct cbor_indefinite_string_data *)item->data) =
33 (struct cbor_indefinite_string_data){
34 .chunk_count = 0,
35 .chunk_capacity = 0,
36 .chunks = NULL,
37 };
38 return item;
39 }
40
cbor_build_string(const char * val)41 cbor_item_t *cbor_build_string(const char *val) {
42 cbor_item_t *item = cbor_new_definite_string();
43 _CBOR_NOTNULL(item);
44 size_t len = strlen(val);
45 unsigned char *handle = _CBOR_MALLOC(len);
46 _CBOR_DEPENDENT_NOTNULL(item, handle);
47 memcpy(handle, val, len);
48 cbor_string_set_handle(item, handle, len);
49 return item;
50 }
51
cbor_build_stringn(const char * val,size_t length)52 cbor_item_t *cbor_build_stringn(const char *val, size_t length) {
53 cbor_item_t *item = cbor_new_definite_string();
54 _CBOR_NOTNULL(item);
55 unsigned char *handle = _CBOR_MALLOC(length);
56 _CBOR_DEPENDENT_NOTNULL(item, handle);
57 memcpy(handle, val, length);
58 cbor_string_set_handle(item, handle, length);
59 return item;
60 }
61
cbor_string_set_handle(cbor_item_t * item,cbor_mutable_data CBOR_RESTRICT_POINTER data,size_t length)62 void cbor_string_set_handle(cbor_item_t *item,
63 cbor_mutable_data CBOR_RESTRICT_POINTER data,
64 size_t length) {
65 assert(cbor_isa_string(item));
66 assert(cbor_string_is_definite(item));
67 item->data = data;
68 item->metadata.string_metadata.length = length;
69 }
70
cbor_string_chunks_handle(const cbor_item_t * item)71 cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item) {
72 assert(cbor_isa_string(item));
73 assert(cbor_string_is_indefinite(item));
74 return ((struct cbor_indefinite_string_data *)item->data)->chunks;
75 }
76
cbor_string_chunk_count(const cbor_item_t * item)77 size_t cbor_string_chunk_count(const cbor_item_t *item) {
78 assert(cbor_isa_string(item));
79 assert(cbor_string_is_indefinite(item));
80 return ((struct cbor_indefinite_string_data *)item->data)->chunk_count;
81 }
82
cbor_string_add_chunk(cbor_item_t * item,cbor_item_t * chunk)83 bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk) {
84 assert(cbor_isa_string(item));
85 assert(cbor_string_is_indefinite(item));
86 struct cbor_indefinite_string_data *data =
87 (struct cbor_indefinite_string_data *)item->data;
88 if (data->chunk_count == data->chunk_capacity) {
89 // TODO: Add a test for this
90 if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
91 return false;
92 }
93
94 size_t new_chunk_capacity = data->chunk_capacity == 0
95 ? 1
96 : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
97 cbor_item_t **new_chunks_data = _cbor_realloc_multiple(
98 data->chunks, sizeof(cbor_item_t *), new_chunk_capacity);
99
100 if (new_chunks_data == NULL) {
101 return false;
102 }
103
104 data->chunk_capacity = new_chunk_capacity;
105 data->chunks = new_chunks_data;
106 }
107 data->chunks[data->chunk_count++] = cbor_incref(chunk);
108 return true;
109 }
110
cbor_string_length(const cbor_item_t * item)111 size_t cbor_string_length(const cbor_item_t *item) {
112 assert(cbor_isa_string(item));
113 return item->metadata.string_metadata.length;
114 }
115
cbor_string_handle(const cbor_item_t * item)116 unsigned char *cbor_string_handle(const cbor_item_t *item) {
117 assert(cbor_isa_string(item));
118 return item->data;
119 }
120
cbor_string_codepoint_count(const cbor_item_t * item)121 size_t cbor_string_codepoint_count(const cbor_item_t *item) {
122 assert(cbor_isa_string(item));
123 return item->metadata.string_metadata.codepoint_count;
124 }
125
cbor_string_is_definite(const cbor_item_t * item)126 bool cbor_string_is_definite(const cbor_item_t *item) {
127 assert(cbor_isa_string(item));
128 return item->metadata.string_metadata.type == _CBOR_METADATA_DEFINITE;
129 }
130
cbor_string_is_indefinite(const cbor_item_t * item)131 bool cbor_string_is_indefinite(const cbor_item_t *item) {
132 return !cbor_string_is_definite(item);
133 }
134