xref: /openbsd-src/lib/libcbor/src/cbor/bytestrings.c (revision 4dcc46c4d04180142eda526ce521dfb137776d05)
1da0d961cSdjm /*
2d3425be1Sdjm  * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
3da0d961cSdjm  *
4da0d961cSdjm  * libcbor is free software; you can redistribute it and/or modify
5da0d961cSdjm  * it under the terms of the MIT license. See LICENSE for details.
6da0d961cSdjm  */
7da0d961cSdjm 
8da0d961cSdjm #include "bytestrings.h"
99e5c2ddcSdjm #include <string.h>
10da0d961cSdjm #include "internal/memory_utils.h"
11da0d961cSdjm 
cbor_bytestring_length(const cbor_item_t * item)129e5c2ddcSdjm size_t cbor_bytestring_length(const cbor_item_t *item) {
13*4dcc46c4Sdjm   CBOR_ASSERT(cbor_isa_bytestring(item));
14da0d961cSdjm   return item->metadata.bytestring_metadata.length;
15da0d961cSdjm }
16da0d961cSdjm 
cbor_bytestring_handle(const cbor_item_t * item)179e5c2ddcSdjm unsigned char *cbor_bytestring_handle(const cbor_item_t *item) {
18*4dcc46c4Sdjm   CBOR_ASSERT(cbor_isa_bytestring(item));
19da0d961cSdjm   return item->data;
20da0d961cSdjm }
21da0d961cSdjm 
cbor_bytestring_is_definite(const cbor_item_t * item)229e5c2ddcSdjm bool cbor_bytestring_is_definite(const cbor_item_t *item) {
23*4dcc46c4Sdjm   CBOR_ASSERT(cbor_isa_bytestring(item));
24da0d961cSdjm   return item->metadata.bytestring_metadata.type == _CBOR_METADATA_DEFINITE;
25da0d961cSdjm }
26da0d961cSdjm 
cbor_bytestring_is_indefinite(const cbor_item_t * item)279e5c2ddcSdjm bool cbor_bytestring_is_indefinite(const cbor_item_t *item) {
28da0d961cSdjm   return !cbor_bytestring_is_definite(item);
29da0d961cSdjm }
30da0d961cSdjm 
cbor_new_definite_bytestring(void)31*4dcc46c4Sdjm cbor_item_t *cbor_new_definite_bytestring(void) {
32*4dcc46c4Sdjm   cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
339e5c2ddcSdjm   _CBOR_NOTNULL(item);
34da0d961cSdjm   *item = (cbor_item_t){
35da0d961cSdjm       .refcount = 1,
36da0d961cSdjm       .type = CBOR_TYPE_BYTESTRING,
37*4dcc46c4Sdjm       .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_DEFINITE,
38*4dcc46c4Sdjm                                            .length = 0}}};
39da0d961cSdjm   return item;
40da0d961cSdjm }
41da0d961cSdjm 
cbor_new_indefinite_bytestring(void)42*4dcc46c4Sdjm cbor_item_t *cbor_new_indefinite_bytestring(void) {
43*4dcc46c4Sdjm   cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
449e5c2ddcSdjm   _CBOR_NOTNULL(item);
45da0d961cSdjm   *item = (cbor_item_t){
46da0d961cSdjm       .refcount = 1,
47da0d961cSdjm       .type = CBOR_TYPE_BYTESTRING,
489e5c2ddcSdjm       .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_INDEFINITE,
499e5c2ddcSdjm                                            .length = 0}},
50*4dcc46c4Sdjm       .data = _cbor_malloc(sizeof(struct cbor_indefinite_string_data))};
519e5c2ddcSdjm   _CBOR_DEPENDENT_NOTNULL(item, item->data);
529e5c2ddcSdjm   *((struct cbor_indefinite_string_data *)item->data) =
539e5c2ddcSdjm       (struct cbor_indefinite_string_data){
54da0d961cSdjm           .chunk_count = 0,
55da0d961cSdjm           .chunk_capacity = 0,
56da0d961cSdjm           .chunks = NULL,
57da0d961cSdjm       };
58da0d961cSdjm   return item;
59da0d961cSdjm }
60da0d961cSdjm 
cbor_build_bytestring(cbor_data handle,size_t length)619e5c2ddcSdjm cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length) {
629e5c2ddcSdjm   cbor_item_t *item = cbor_new_definite_bytestring();
639e5c2ddcSdjm   _CBOR_NOTNULL(item);
64*4dcc46c4Sdjm   void *content = _cbor_malloc(length);
659e5c2ddcSdjm   _CBOR_DEPENDENT_NOTNULL(item, content);
66da0d961cSdjm   memcpy(content, handle, length);
679e5c2ddcSdjm   cbor_bytestring_set_handle(item, content, length);
689e5c2ddcSdjm   return item;
69da0d961cSdjm }
70da0d961cSdjm 
cbor_bytestring_set_handle(cbor_item_t * item,cbor_mutable_data CBOR_RESTRICT_POINTER data,size_t length)719e5c2ddcSdjm void cbor_bytestring_set_handle(cbor_item_t *item,
729e5c2ddcSdjm                                 cbor_mutable_data CBOR_RESTRICT_POINTER data,
739e5c2ddcSdjm                                 size_t length) {
74*4dcc46c4Sdjm   CBOR_ASSERT(cbor_isa_bytestring(item));
75*4dcc46c4Sdjm   CBOR_ASSERT(cbor_bytestring_is_definite(item));
76da0d961cSdjm   item->data = data;
77da0d961cSdjm   item->metadata.bytestring_metadata.length = length;
78da0d961cSdjm }
79da0d961cSdjm 
cbor_bytestring_chunks_handle(const cbor_item_t * item)809e5c2ddcSdjm cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item) {
81*4dcc46c4Sdjm   CBOR_ASSERT(cbor_isa_bytestring(item));
82*4dcc46c4Sdjm   CBOR_ASSERT(cbor_bytestring_is_indefinite(item));
83da0d961cSdjm   return ((struct cbor_indefinite_string_data *)item->data)->chunks;
84da0d961cSdjm }
85da0d961cSdjm 
cbor_bytestring_chunk_count(const cbor_item_t * item)869e5c2ddcSdjm size_t cbor_bytestring_chunk_count(const cbor_item_t *item) {
87*4dcc46c4Sdjm   CBOR_ASSERT(cbor_isa_bytestring(item));
88*4dcc46c4Sdjm   CBOR_ASSERT(cbor_bytestring_is_indefinite(item));
89da0d961cSdjm   return ((struct cbor_indefinite_string_data *)item->data)->chunk_count;
90da0d961cSdjm }
91da0d961cSdjm 
cbor_bytestring_add_chunk(cbor_item_t * item,cbor_item_t * chunk)929e5c2ddcSdjm bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk) {
93*4dcc46c4Sdjm   CBOR_ASSERT(cbor_isa_bytestring(item));
94*4dcc46c4Sdjm   CBOR_ASSERT(cbor_bytestring_is_indefinite(item));
95*4dcc46c4Sdjm   CBOR_ASSERT(cbor_isa_bytestring(chunk));
96*4dcc46c4Sdjm   CBOR_ASSERT(cbor_bytestring_is_definite(chunk));
979e5c2ddcSdjm   struct cbor_indefinite_string_data *data =
989e5c2ddcSdjm       (struct cbor_indefinite_string_data *)item->data;
99da0d961cSdjm   if (data->chunk_count == data->chunk_capacity) {
100da0d961cSdjm     if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
101da0d961cSdjm       return false;
102da0d961cSdjm     }
103da0d961cSdjm 
1049e5c2ddcSdjm     size_t new_chunk_capacity =
1059e5c2ddcSdjm         data->chunk_capacity == 0 ? 1
1069e5c2ddcSdjm                                   : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
107da0d961cSdjm 
1089e5c2ddcSdjm     cbor_item_t **new_chunks_data = _cbor_realloc_multiple(
1099e5c2ddcSdjm         data->chunks, sizeof(cbor_item_t *), new_chunk_capacity);
110da0d961cSdjm 
111da0d961cSdjm     if (new_chunks_data == NULL) {
112da0d961cSdjm       return false;
113da0d961cSdjm     }
1149e5c2ddcSdjm     data->chunk_capacity = new_chunk_capacity;
115da0d961cSdjm     data->chunks = new_chunks_data;
116da0d961cSdjm   }
117da0d961cSdjm   data->chunks[data->chunk_count++] = cbor_incref(chunk);
118da0d961cSdjm   return true;
119da0d961cSdjm }
120