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(void) { 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(void) { 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 CBOR_ASSERT(cbor_isa_string(item)); 66 CBOR_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 CBOR_ASSERT(cbor_isa_string(item)); 73 CBOR_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 CBOR_ASSERT(cbor_isa_string(item)); 79 CBOR_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 CBOR_ASSERT(cbor_isa_string(item)); 85 CBOR_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 if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) { 90 return false; 91 } 92 93 size_t new_chunk_capacity = 94 data->chunk_capacity == 0 ? 1 95 : CBOR_BUFFER_GROWTH * (data->chunk_capacity); 96 cbor_item_t **new_chunks_data = _cbor_realloc_multiple( 97 data->chunks, sizeof(cbor_item_t *), new_chunk_capacity); 98 99 if (new_chunks_data == NULL) { 100 return false; 101 } 102 103 data->chunk_capacity = new_chunk_capacity; 104 data->chunks = new_chunks_data; 105 } 106 data->chunks[data->chunk_count++] = cbor_incref(chunk); 107 return true; 108 } 109 110 size_t cbor_string_length(const cbor_item_t *item) { 111 CBOR_ASSERT(cbor_isa_string(item)); 112 return item->metadata.string_metadata.length; 113 } 114 115 unsigned char *cbor_string_handle(const cbor_item_t *item) { 116 CBOR_ASSERT(cbor_isa_string(item)); 117 return item->data; 118 } 119 120 size_t cbor_string_codepoint_count(const cbor_item_t *item) { 121 CBOR_ASSERT(cbor_isa_string(item)); 122 return item->metadata.string_metadata.codepoint_count; 123 } 124 125 bool cbor_string_is_definite(const cbor_item_t *item) { 126 CBOR_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 return !cbor_string_is_definite(item); 132 } 133