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 "strings.h"
      9 #include <string.h>
     10 #include "internal/memory_utils.h"
     11 
     12 cbor_item_t *cbor_new_definite_string() {
     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() {
     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   assert(cbor_isa_string(item));
     66   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   assert(cbor_isa_string(item));
     73   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   assert(cbor_isa_string(item));
     79   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   assert(cbor_isa_string(item));
     85   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     // TODO: Add a test for this
     90     if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
     91       return false;
     92     }
     93 
     94     size_t new_chunk_capacity = data->chunk_capacity == 0
     95                                ? 1
     96                                : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
     97     cbor_item_t **new_chunks_data = _cbor_realloc_multiple(
     98         data->chunks, sizeof(cbor_item_t *), new_chunk_capacity);
     99 
    100     if (new_chunks_data == NULL) {
    101       return false;
    102     }
    103 
    104     data->chunk_capacity = new_chunk_capacity;
    105     data->chunks = new_chunks_data;
    106   }
    107   data->chunks[data->chunk_count++] = cbor_incref(chunk);
    108   return true;
    109 }
    110 
    111 size_t cbor_string_length(const cbor_item_t *item) {
    112   assert(cbor_isa_string(item));
    113   return item->metadata.string_metadata.length;
    114 }
    115 
    116 unsigned char *cbor_string_handle(const cbor_item_t *item) {
    117   assert(cbor_isa_string(item));
    118   return item->data;
    119 }
    120 
    121 size_t cbor_string_codepoint_count(const cbor_item_t *item) {
    122   assert(cbor_isa_string(item));
    123   return item->metadata.string_metadata.codepoint_count;
    124 }
    125 
    126 bool cbor_string_is_definite(const cbor_item_t *item) {
    127   assert(cbor_isa_string(item));
    128   return item->metadata.string_metadata.type == _CBOR_METADATA_DEFINITE;
    129 }
    130 
    131 bool cbor_string_is_indefinite(const cbor_item_t *item) {
    132   return !cbor_string_is_definite(item);
    133 }
    134