Home | History | Annotate | Line # | Download | only in cbor
      1 /*
      2  * Copyright (c) 2014-2019 Pavel Kalvoda <me (at) 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   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   assert(cbor_isa_bytestring(item));
     19   return item->data;
     20 }
     21 
     22 bool cbor_bytestring_is_definite(const cbor_item_t *item) {
     23   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() {
     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 = {_CBOR_METADATA_DEFINITE, 0}}};
     38   return item;
     39 }
     40 
     41 cbor_item_t *cbor_new_indefinite_bytestring() {
     42   cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
     43   _CBOR_NOTNULL(item);
     44   *item = (cbor_item_t){
     45       .refcount = 1,
     46       .type = CBOR_TYPE_BYTESTRING,
     47       .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_INDEFINITE,
     48                                            .length = 0}},
     49       .data = _CBOR_MALLOC(sizeof(struct cbor_indefinite_string_data))};
     50   _CBOR_DEPENDENT_NOTNULL(item, item->data);
     51   *((struct cbor_indefinite_string_data *)item->data) =
     52       (struct cbor_indefinite_string_data){
     53           .chunk_count = 0,
     54           .chunk_capacity = 0,
     55           .chunks = NULL,
     56       };
     57   return item;
     58 }
     59 
     60 cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length) {
     61   cbor_item_t *item = cbor_new_definite_bytestring();
     62   _CBOR_NOTNULL(item);
     63   void *content = _CBOR_MALLOC(length);
     64   _CBOR_DEPENDENT_NOTNULL(item, content);
     65   memcpy(content, handle, length);
     66   cbor_bytestring_set_handle(item, content, length);
     67   return item;
     68 }
     69 
     70 void cbor_bytestring_set_handle(cbor_item_t *item,
     71                                 cbor_mutable_data CBOR_RESTRICT_POINTER data,
     72                                 size_t length) {
     73   assert(cbor_isa_bytestring(item));
     74   assert(cbor_bytestring_is_definite(item));
     75   item->data = data;
     76   item->metadata.bytestring_metadata.length = length;
     77 }
     78 
     79 cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item) {
     80   assert(cbor_isa_bytestring(item));
     81   assert(cbor_bytestring_is_indefinite(item));
     82   return ((struct cbor_indefinite_string_data *)item->data)->chunks;
     83 }
     84 
     85 size_t cbor_bytestring_chunk_count(const cbor_item_t *item) {
     86   assert(cbor_isa_bytestring(item));
     87   assert(cbor_bytestring_is_indefinite(item));
     88   return ((struct cbor_indefinite_string_data *)item->data)->chunk_count;
     89 }
     90 
     91 bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk) {
     92   assert(cbor_isa_bytestring(item));
     93   assert(cbor_bytestring_is_indefinite(item));
     94   struct cbor_indefinite_string_data *data =
     95       (struct cbor_indefinite_string_data *)item->data;
     96   if (data->chunk_count == data->chunk_capacity) {
     97     // TODO: Add a test for this
     98     if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
     99       return false;
    100     }
    101 
    102     size_t new_chunk_capacity =
    103         data->chunk_capacity == 0 ? 1
    104                                   : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
    105 
    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     data->chunk_capacity = new_chunk_capacity;
    113     data->chunks = new_chunks_data;
    114   }
    115   data->chunks[data->chunk_count++] = cbor_incref(chunk);
    116   return true;
    117 }
    118