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 "bytestrings.h" 9 #include <string.h> 10 #include "internal/memory_utils.h" 11 12 size_t cbor_bytestring_length(const cbor_item_t *item) { 13 CBOR_ASSERT(cbor_isa_bytestring(item)); 14 return item->metadata.bytestring_metadata.length; 15 } 16 17 unsigned char *cbor_bytestring_handle(const cbor_item_t *item) { 18 CBOR_ASSERT(cbor_isa_bytestring(item)); 19 return item->data; 20 } 21 22 bool cbor_bytestring_is_definite(const cbor_item_t *item) { 23 CBOR_ASSERT(cbor_isa_bytestring(item)); 24 return item->metadata.bytestring_metadata.type == _CBOR_METADATA_DEFINITE; 25 } 26 27 bool cbor_bytestring_is_indefinite(const cbor_item_t *item) { 28 return !cbor_bytestring_is_definite(item); 29 } 30 31 cbor_item_t *cbor_new_definite_bytestring(void) { 32 cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); 33 _CBOR_NOTNULL(item); 34 *item = (cbor_item_t){ 35 .refcount = 1, 36 .type = CBOR_TYPE_BYTESTRING, 37 .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_DEFINITE, 38 .length = 0}}}; 39 return item; 40 } 41 42 cbor_item_t *cbor_new_indefinite_bytestring(void) { 43 cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); 44 _CBOR_NOTNULL(item); 45 *item = (cbor_item_t){ 46 .refcount = 1, 47 .type = CBOR_TYPE_BYTESTRING, 48 .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_INDEFINITE, 49 .length = 0}}, 50 .data = _cbor_malloc(sizeof(struct cbor_indefinite_string_data))}; 51 _CBOR_DEPENDENT_NOTNULL(item, item->data); 52 *((struct cbor_indefinite_string_data *)item->data) = 53 (struct cbor_indefinite_string_data){ 54 .chunk_count = 0, 55 .chunk_capacity = 0, 56 .chunks = NULL, 57 }; 58 return item; 59 } 60 61 cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length) { 62 cbor_item_t *item = cbor_new_definite_bytestring(); 63 _CBOR_NOTNULL(item); 64 void *content = _cbor_malloc(length); 65 _CBOR_DEPENDENT_NOTNULL(item, content); 66 memcpy(content, handle, length); 67 cbor_bytestring_set_handle(item, content, length); 68 return item; 69 } 70 71 void cbor_bytestring_set_handle(cbor_item_t *item, 72 cbor_mutable_data CBOR_RESTRICT_POINTER data, 73 size_t length) { 74 CBOR_ASSERT(cbor_isa_bytestring(item)); 75 CBOR_ASSERT(cbor_bytestring_is_definite(item)); 76 item->data = data; 77 item->metadata.bytestring_metadata.length = length; 78 } 79 80 cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item) { 81 CBOR_ASSERT(cbor_isa_bytestring(item)); 82 CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); 83 return ((struct cbor_indefinite_string_data *)item->data)->chunks; 84 } 85 86 size_t cbor_bytestring_chunk_count(const cbor_item_t *item) { 87 CBOR_ASSERT(cbor_isa_bytestring(item)); 88 CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); 89 return ((struct cbor_indefinite_string_data *)item->data)->chunk_count; 90 } 91 92 bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk) { 93 CBOR_ASSERT(cbor_isa_bytestring(item)); 94 CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); 95 CBOR_ASSERT(cbor_isa_bytestring(chunk)); 96 CBOR_ASSERT(cbor_bytestring_is_definite(chunk)); 97 struct cbor_indefinite_string_data *data = 98 (struct cbor_indefinite_string_data *)item->data; 99 if (data->chunk_count == data->chunk_capacity) { 100 if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) { 101 return false; 102 } 103 104 size_t new_chunk_capacity = 105 data->chunk_capacity == 0 ? 1 106 : CBOR_BUFFER_GROWTH * (data->chunk_capacity); 107 108 cbor_item_t **new_chunks_data = _cbor_realloc_multiple( 109 data->chunks, sizeof(cbor_item_t *), new_chunk_capacity); 110 111 if (new_chunks_data == NULL) { 112 return false; 113 } 114 data->chunk_capacity = new_chunk_capacity; 115 data->chunks = new_chunks_data; 116 } 117 data->chunks[data->chunk_count++] = cbor_incref(chunk); 118 return true; 119 } 120