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