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