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