xref: /freebsd-src/contrib/libcbor/src/cbor/strings.c (revision abd872540f24cfc7dbd1ea29b6918c7082a22108)
110ff414cSEd Maste /*
210ff414cSEd Maste  * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
310ff414cSEd Maste  *
410ff414cSEd Maste  * libcbor is free software; you can redistribute it and/or modify
510ff414cSEd Maste  * it under the terms of the MIT license. See LICENSE for details.
610ff414cSEd Maste  */
710ff414cSEd Maste 
810ff414cSEd Maste #include "strings.h"
910ff414cSEd Maste #include <string.h>
1010ff414cSEd Maste #include "internal/memory_utils.h"
11*abd87254SEd Maste #include "internal/unicode.h"
1210ff414cSEd Maste 
cbor_new_definite_string(void)135d3e7166SEd Maste cbor_item_t *cbor_new_definite_string(void) {
145d3e7166SEd Maste   cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
1510ff414cSEd Maste   _CBOR_NOTNULL(item);
1610ff414cSEd Maste   *item = (cbor_item_t){
1710ff414cSEd Maste       .refcount = 1,
1810ff414cSEd Maste       .type = CBOR_TYPE_STRING,
1910ff414cSEd Maste       .metadata = {.string_metadata = {_CBOR_METADATA_DEFINITE, 0}}};
2010ff414cSEd Maste   return item;
2110ff414cSEd Maste }
2210ff414cSEd Maste 
cbor_new_indefinite_string(void)235d3e7166SEd Maste cbor_item_t *cbor_new_indefinite_string(void) {
245d3e7166SEd Maste   cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));
2510ff414cSEd Maste   _CBOR_NOTNULL(item);
2610ff414cSEd Maste   *item = (cbor_item_t){
2710ff414cSEd Maste       .refcount = 1,
2810ff414cSEd Maste       .type = CBOR_TYPE_STRING,
2910ff414cSEd Maste       .metadata = {.string_metadata = {.type = _CBOR_METADATA_INDEFINITE,
3010ff414cSEd Maste                                        .length = 0}},
315d3e7166SEd Maste       .data = _cbor_malloc(sizeof(struct cbor_indefinite_string_data))};
3210ff414cSEd Maste   _CBOR_DEPENDENT_NOTNULL(item, item->data);
3310ff414cSEd Maste   *((struct cbor_indefinite_string_data *)item->data) =
3410ff414cSEd Maste       (struct cbor_indefinite_string_data){
3510ff414cSEd Maste           .chunk_count = 0,
3610ff414cSEd Maste           .chunk_capacity = 0,
3710ff414cSEd Maste           .chunks = NULL,
3810ff414cSEd Maste       };
3910ff414cSEd Maste   return item;
4010ff414cSEd Maste }
4110ff414cSEd Maste 
cbor_build_string(const char * val)4210ff414cSEd Maste cbor_item_t *cbor_build_string(const char *val) {
4310ff414cSEd Maste   cbor_item_t *item = cbor_new_definite_string();
4410ff414cSEd Maste   _CBOR_NOTNULL(item);
4510ff414cSEd Maste   size_t len = strlen(val);
465d3e7166SEd Maste   unsigned char *handle = _cbor_malloc(len);
4710ff414cSEd Maste   _CBOR_DEPENDENT_NOTNULL(item, handle);
4810ff414cSEd Maste   memcpy(handle, val, len);
4910ff414cSEd Maste   cbor_string_set_handle(item, handle, len);
5010ff414cSEd Maste   return item;
5110ff414cSEd Maste }
5210ff414cSEd Maste 
cbor_build_stringn(const char * val,size_t length)5310ff414cSEd Maste cbor_item_t *cbor_build_stringn(const char *val, size_t length) {
5410ff414cSEd Maste   cbor_item_t *item = cbor_new_definite_string();
5510ff414cSEd Maste   _CBOR_NOTNULL(item);
565d3e7166SEd Maste   unsigned char *handle = _cbor_malloc(length);
5710ff414cSEd Maste   _CBOR_DEPENDENT_NOTNULL(item, handle);
5810ff414cSEd Maste   memcpy(handle, val, length);
5910ff414cSEd Maste   cbor_string_set_handle(item, handle, length);
6010ff414cSEd Maste   return item;
6110ff414cSEd Maste }
6210ff414cSEd Maste 
cbor_string_set_handle(cbor_item_t * item,cbor_mutable_data CBOR_RESTRICT_POINTER data,size_t length)6310ff414cSEd Maste void cbor_string_set_handle(cbor_item_t *item,
6410ff414cSEd Maste                             cbor_mutable_data CBOR_RESTRICT_POINTER data,
6510ff414cSEd Maste                             size_t length) {
665d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_string(item));
675d3e7166SEd Maste   CBOR_ASSERT(cbor_string_is_definite(item));
6810ff414cSEd Maste   item->data = data;
6910ff414cSEd Maste   item->metadata.string_metadata.length = length;
70*abd87254SEd Maste   struct _cbor_unicode_status unicode_status;
71*abd87254SEd Maste   size_t codepoint_count =
72*abd87254SEd Maste       _cbor_unicode_codepoint_count(data, length, &unicode_status);
73*abd87254SEd Maste   CBOR_ASSERT(codepoint_count <= length);
74*abd87254SEd Maste   if (unicode_status.status == _CBOR_UNICODE_OK) {
75*abd87254SEd Maste     item->metadata.string_metadata.codepoint_count = codepoint_count;
76*abd87254SEd Maste   } else {
77*abd87254SEd Maste     item->metadata.string_metadata.codepoint_count = 0;
78*abd87254SEd Maste   }
7910ff414cSEd Maste }
8010ff414cSEd Maste 
cbor_string_chunks_handle(const cbor_item_t * item)8110ff414cSEd Maste cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item) {
825d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_string(item));
835d3e7166SEd Maste   CBOR_ASSERT(cbor_string_is_indefinite(item));
8410ff414cSEd Maste   return ((struct cbor_indefinite_string_data *)item->data)->chunks;
8510ff414cSEd Maste }
8610ff414cSEd Maste 
cbor_string_chunk_count(const cbor_item_t * item)8710ff414cSEd Maste size_t cbor_string_chunk_count(const cbor_item_t *item) {
885d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_string(item));
895d3e7166SEd Maste   CBOR_ASSERT(cbor_string_is_indefinite(item));
9010ff414cSEd Maste   return ((struct cbor_indefinite_string_data *)item->data)->chunk_count;
9110ff414cSEd Maste }
9210ff414cSEd Maste 
cbor_string_add_chunk(cbor_item_t * item,cbor_item_t * chunk)9310ff414cSEd Maste bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk) {
945d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_string(item));
955d3e7166SEd Maste   CBOR_ASSERT(cbor_string_is_indefinite(item));
9610ff414cSEd Maste   struct cbor_indefinite_string_data *data =
9710ff414cSEd Maste       (struct cbor_indefinite_string_data *)item->data;
9810ff414cSEd Maste   if (data->chunk_count == data->chunk_capacity) {
9910ff414cSEd Maste     if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
10010ff414cSEd Maste       return false;
10110ff414cSEd Maste     }
10210ff414cSEd Maste 
10310ff414cSEd Maste     size_t new_chunk_capacity =
10410ff414cSEd Maste         data->chunk_capacity == 0 ? 1
10510ff414cSEd Maste                                   : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
10610ff414cSEd Maste     cbor_item_t **new_chunks_data = _cbor_realloc_multiple(
10710ff414cSEd Maste         data->chunks, sizeof(cbor_item_t *), new_chunk_capacity);
10810ff414cSEd Maste 
10910ff414cSEd Maste     if (new_chunks_data == NULL) {
11010ff414cSEd Maste       return false;
11110ff414cSEd Maste     }
11210ff414cSEd Maste 
11310ff414cSEd Maste     data->chunk_capacity = new_chunk_capacity;
11410ff414cSEd Maste     data->chunks = new_chunks_data;
11510ff414cSEd Maste   }
11610ff414cSEd Maste   data->chunks[data->chunk_count++] = cbor_incref(chunk);
11710ff414cSEd Maste   return true;
11810ff414cSEd Maste }
11910ff414cSEd Maste 
cbor_string_length(const cbor_item_t * item)12010ff414cSEd Maste size_t cbor_string_length(const cbor_item_t *item) {
1215d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_string(item));
12210ff414cSEd Maste   return item->metadata.string_metadata.length;
12310ff414cSEd Maste }
12410ff414cSEd Maste 
cbor_string_handle(const cbor_item_t * item)12510ff414cSEd Maste unsigned char *cbor_string_handle(const cbor_item_t *item) {
1265d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_string(item));
12710ff414cSEd Maste   return item->data;
12810ff414cSEd Maste }
12910ff414cSEd Maste 
cbor_string_codepoint_count(const cbor_item_t * item)13010ff414cSEd Maste size_t cbor_string_codepoint_count(const cbor_item_t *item) {
1315d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_string(item));
13210ff414cSEd Maste   return item->metadata.string_metadata.codepoint_count;
13310ff414cSEd Maste }
13410ff414cSEd Maste 
cbor_string_is_definite(const cbor_item_t * item)13510ff414cSEd Maste bool cbor_string_is_definite(const cbor_item_t *item) {
1365d3e7166SEd Maste   CBOR_ASSERT(cbor_isa_string(item));
13710ff414cSEd Maste   return item->metadata.string_metadata.type == _CBOR_METADATA_DEFINITE;
13810ff414cSEd Maste }
13910ff414cSEd Maste 
cbor_string_is_indefinite(const cbor_item_t * item)14010ff414cSEd Maste bool cbor_string_is_indefinite(const cbor_item_t *item) {
14110ff414cSEd Maste   return !cbor_string_is_definite(item);
14210ff414cSEd Maste }
143