Path: blob/main/contrib/libcbor/src/cbor/arrays.c
105579 views
/*1* Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]>2*3* libcbor is free software; you can redistribute it and/or modify4* it under the terms of the MIT license. See LICENSE for details.5*/67#include "arrays.h"8#include <string.h>9#include "internal/memory_utils.h"1011size_t cbor_array_size(const cbor_item_t *item) {12CBOR_ASSERT(cbor_isa_array(item));13return item->metadata.array_metadata.end_ptr;14}1516size_t cbor_array_allocated(const cbor_item_t *item) {17CBOR_ASSERT(cbor_isa_array(item));18return item->metadata.array_metadata.allocated;19}2021cbor_item_t *cbor_array_get(const cbor_item_t *item, size_t index) {22return cbor_incref(((cbor_item_t **)item->data)[index]);23}2425bool cbor_array_set(cbor_item_t *item, size_t index, cbor_item_t *value) {26if (index == item->metadata.array_metadata.end_ptr) {27return cbor_array_push(item, value);28} else if (index < item->metadata.array_metadata.end_ptr) {29return cbor_array_replace(item, index, value);30} else {31return false;32}33}3435bool cbor_array_replace(cbor_item_t *item, size_t index, cbor_item_t *value) {36if (index >= item->metadata.array_metadata.end_ptr) return false;37/* We cannot use cbor_array_get as that would increase the refcount */38cbor_intermediate_decref(((cbor_item_t **)item->data)[index]);39((cbor_item_t **)item->data)[index] = cbor_incref(value);40return true;41}4243bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee) {44CBOR_ASSERT(cbor_isa_array(array));45struct _cbor_array_metadata *metadata =46(struct _cbor_array_metadata *)&array->metadata;47cbor_item_t **data = (cbor_item_t **)array->data;48if (cbor_array_is_definite(array)) {49/* Do not reallocate definite arrays */50if (metadata->end_ptr >= metadata->allocated) {51return false;52}53data[metadata->end_ptr++] = pushee;54} else {55/* Exponential realloc */56if (metadata->end_ptr >= metadata->allocated) {57// Check for overflows first58if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) {59return false;60}6162size_t new_allocation = metadata->allocated == 063? 164: CBOR_BUFFER_GROWTH * metadata->allocated;6566unsigned char *new_data = _cbor_realloc_multiple(67array->data, sizeof(cbor_item_t *), new_allocation);68if (new_data == NULL) {69return false;70}7172array->data = new_data;73metadata->allocated = new_allocation;74}75((cbor_item_t **)array->data)[metadata->end_ptr++] = pushee;76}77cbor_incref(pushee);78return true;79}8081bool cbor_array_is_definite(const cbor_item_t *item) {82CBOR_ASSERT(cbor_isa_array(item));83return item->metadata.array_metadata.type == _CBOR_METADATA_DEFINITE;84}8586bool cbor_array_is_indefinite(const cbor_item_t *item) {87CBOR_ASSERT(cbor_isa_array(item));88return item->metadata.array_metadata.type == _CBOR_METADATA_INDEFINITE;89}9091cbor_item_t **cbor_array_handle(const cbor_item_t *item) {92CBOR_ASSERT(cbor_isa_array(item));93return (cbor_item_t **)item->data;94}9596cbor_item_t *cbor_new_definite_array(size_t size) {97cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));98_CBOR_NOTNULL(item);99cbor_item_t **data = _cbor_alloc_multiple(sizeof(cbor_item_t *), size);100_CBOR_DEPENDENT_NOTNULL(item, data);101102for (size_t i = 0; i < size; i++) {103data[i] = NULL;104}105106*item = (cbor_item_t){107.refcount = 1,108.type = CBOR_TYPE_ARRAY,109.metadata = {.array_metadata = {.type = _CBOR_METADATA_DEFINITE,110.allocated = size,111.end_ptr = 0}},112.data = (unsigned char *)data};113114return item;115}116117cbor_item_t *cbor_new_indefinite_array(void) {118cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t));119_CBOR_NOTNULL(item);120121*item = (cbor_item_t){122.refcount = 1,123.type = CBOR_TYPE_ARRAY,124.metadata = {.array_metadata = {.type = _CBOR_METADATA_INDEFINITE,125.allocated = 0,126.end_ptr = 0}},127.data = NULL /* Can be safely realloc-ed */128};129return item;130}131132133