aboutsummaryrefslogtreecommitdiff
path: root/src/cbor/bytestrings.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cbor/bytestrings.c')
-rw-r--r--src/cbor/bytestrings.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/cbor/bytestrings.c b/src/cbor/bytestrings.c
new file mode 100644
index 000000000000..75a737bd92ae
--- /dev/null
+++ b/src/cbor/bytestrings.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
+ *
+ * libcbor is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include "bytestrings.h"
+#include <string.h>
+#include "internal/memory_utils.h"
+
+size_t cbor_bytestring_length(const cbor_item_t *item) {
+ assert(cbor_isa_bytestring(item));
+ return item->metadata.bytestring_metadata.length;
+}
+
+unsigned char *cbor_bytestring_handle(const cbor_item_t *item) {
+ assert(cbor_isa_bytestring(item));
+ return item->data;
+}
+
+bool cbor_bytestring_is_definite(const cbor_item_t *item) {
+ assert(cbor_isa_bytestring(item));
+ return item->metadata.bytestring_metadata.type == _CBOR_METADATA_DEFINITE;
+}
+
+bool cbor_bytestring_is_indefinite(const cbor_item_t *item) {
+ return !cbor_bytestring_is_definite(item);
+}
+
+cbor_item_t *cbor_new_definite_bytestring() {
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ _CBOR_NOTNULL(item);
+ *item = (cbor_item_t){
+ .refcount = 1,
+ .type = CBOR_TYPE_BYTESTRING,
+ .metadata = {.bytestring_metadata = {_CBOR_METADATA_DEFINITE, 0}}};
+ return item;
+}
+
+cbor_item_t *cbor_new_indefinite_bytestring() {
+ cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
+ _CBOR_NOTNULL(item);
+ *item = (cbor_item_t){
+ .refcount = 1,
+ .type = CBOR_TYPE_BYTESTRING,
+ .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_INDEFINITE,
+ .length = 0}},
+ .data = _CBOR_MALLOC(sizeof(struct cbor_indefinite_string_data))};
+ _CBOR_DEPENDENT_NOTNULL(item, item->data);
+ *((struct cbor_indefinite_string_data *)item->data) =
+ (struct cbor_indefinite_string_data){
+ .chunk_count = 0,
+ .chunk_capacity = 0,
+ .chunks = NULL,
+ };
+ return item;
+}
+
+cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length) {
+ cbor_item_t *item = cbor_new_definite_bytestring();
+ _CBOR_NOTNULL(item);
+ void *content = _CBOR_MALLOC(length);
+ _CBOR_DEPENDENT_NOTNULL(item, content);
+ memcpy(content, handle, length);
+ cbor_bytestring_set_handle(item, content, length);
+ return item;
+}
+
+void cbor_bytestring_set_handle(cbor_item_t *item,
+ cbor_mutable_data CBOR_RESTRICT_POINTER data,
+ size_t length) {
+ assert(cbor_isa_bytestring(item));
+ assert(cbor_bytestring_is_definite(item));
+ item->data = data;
+ item->metadata.bytestring_metadata.length = length;
+}
+
+cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item) {
+ assert(cbor_isa_bytestring(item));
+ assert(cbor_bytestring_is_indefinite(item));
+ return ((struct cbor_indefinite_string_data *)item->data)->chunks;
+}
+
+size_t cbor_bytestring_chunk_count(const cbor_item_t *item) {
+ assert(cbor_isa_bytestring(item));
+ assert(cbor_bytestring_is_indefinite(item));
+ return ((struct cbor_indefinite_string_data *)item->data)->chunk_count;
+}
+
+bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk) {
+ assert(cbor_isa_bytestring(item));
+ assert(cbor_bytestring_is_indefinite(item));
+ struct cbor_indefinite_string_data *data =
+ (struct cbor_indefinite_string_data *)item->data;
+ if (data->chunk_count == data->chunk_capacity) {
+ // TODO: Add a test for this
+ if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) {
+ return false;
+ }
+
+ size_t new_chunk_capacity =
+ data->chunk_capacity == 0 ? 1
+ : CBOR_BUFFER_GROWTH * (data->chunk_capacity);
+
+ cbor_item_t **new_chunks_data = _cbor_realloc_multiple(
+ data->chunks, sizeof(cbor_item_t *), new_chunk_capacity);
+
+ if (new_chunks_data == NULL) {
+ return false;
+ }
+ data->chunk_capacity = new_chunk_capacity;
+ data->chunks = new_chunks_data;
+ }
+ data->chunks[data->chunk_count++] = cbor_incref(chunk);
+ return true;
+}