xref: /freebsd/contrib/libcbor/src/cbor/strings.c (revision d5b0e70f7e04d971691517ce1304d86a1e367e2e)
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 
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 
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 
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 
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 
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 
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 
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 
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 =
95         data->chunk_capacity == 0 ? 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 
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 
116 unsigned char *cbor_string_handle(const cbor_item_t *item) {
117   assert(cbor_isa_string(item));
118   return item->data;
119 }
120 
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 
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 
131 bool cbor_string_is_indefinite(const cbor_item_t *item) {
132   return !cbor_string_is_definite(item);
133 }
134