1 /* 2 * Copyright (c) 2014-2020 Pavel Kalvoda <me@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 "cbor/common.h" 9 #include "arrays.h" 10 #include "bytestrings.h" 11 #include "data.h" 12 #include "floats_ctrls.h" 13 #include "ints.h" 14 #include "maps.h" 15 #include "strings.h" 16 #include "tags.h" 17 18 #ifdef DEBUG 19 bool _cbor_enable_assert = true; 20 #endif 21 22 bool cbor_isa_uint(const cbor_item_t *item) { 23 return item->type == CBOR_TYPE_UINT; 24 } 25 26 bool cbor_isa_negint(const cbor_item_t *item) { 27 return item->type == CBOR_TYPE_NEGINT; 28 } 29 30 bool cbor_isa_bytestring(const cbor_item_t *item) { 31 return item->type == CBOR_TYPE_BYTESTRING; 32 } 33 34 bool cbor_isa_string(const cbor_item_t *item) { 35 return item->type == CBOR_TYPE_STRING; 36 } 37 38 bool cbor_isa_array(const cbor_item_t *item) { 39 return item->type == CBOR_TYPE_ARRAY; 40 } 41 42 bool cbor_isa_map(const cbor_item_t *item) { 43 return item->type == CBOR_TYPE_MAP; 44 } 45 46 bool cbor_isa_tag(const cbor_item_t *item) { 47 return item->type == CBOR_TYPE_TAG; 48 } 49 50 bool cbor_isa_float_ctrl(const cbor_item_t *item) { 51 return item->type == CBOR_TYPE_FLOAT_CTRL; 52 } 53 54 cbor_type cbor_typeof(const cbor_item_t *item) { return item->type; } 55 56 bool cbor_is_int(const cbor_item_t *item) { 57 return cbor_isa_uint(item) || cbor_isa_negint(item); 58 } 59 60 bool cbor_is_bool(const cbor_item_t *item) { 61 return cbor_isa_float_ctrl(item) && 62 (cbor_ctrl_value(item) == CBOR_CTRL_FALSE || 63 cbor_ctrl_value(item) == CBOR_CTRL_TRUE); 64 } 65 66 bool cbor_is_null(const cbor_item_t *item) { 67 return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_NULL; 68 } 69 70 bool cbor_is_undef(const cbor_item_t *item) { 71 return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_UNDEF; 72 } 73 74 bool cbor_is_float(const cbor_item_t *item) { 75 return cbor_isa_float_ctrl(item) && !cbor_float_ctrl_is_ctrl(item); 76 } 77 78 cbor_item_t *cbor_incref(cbor_item_t *item) { 79 item->refcount++; 80 return item; 81 } 82 83 void cbor_decref(cbor_item_t **item_ref) { 84 cbor_item_t *item = *item_ref; 85 CBOR_ASSERT(item->refcount > 0); 86 if (--item->refcount == 0) { 87 switch (item->type) { 88 case CBOR_TYPE_UINT: 89 /* Fallthrough */ 90 case CBOR_TYPE_NEGINT: 91 /* Combined allocation, freeing the item suffices */ 92 { break; } 93 case CBOR_TYPE_BYTESTRING: { 94 if (cbor_bytestring_is_definite(item)) { 95 _cbor_free(item->data); 96 } else { 97 /* We need to decref all chunks */ 98 cbor_item_t **handle = cbor_bytestring_chunks_handle(item); 99 for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) 100 cbor_decref(&handle[i]); 101 _cbor_free( 102 ((struct cbor_indefinite_string_data *)item->data)->chunks); 103 _cbor_free(item->data); 104 } 105 break; 106 } 107 case CBOR_TYPE_STRING: { 108 if (cbor_string_is_definite(item)) { 109 _cbor_free(item->data); 110 } else { 111 /* We need to decref all chunks */ 112 cbor_item_t **handle = cbor_string_chunks_handle(item); 113 for (size_t i = 0; i < cbor_string_chunk_count(item); i++) 114 cbor_decref(&handle[i]); 115 _cbor_free( 116 ((struct cbor_indefinite_string_data *)item->data)->chunks); 117 _cbor_free(item->data); 118 } 119 break; 120 } 121 case CBOR_TYPE_ARRAY: { 122 /* Get all items and decref them */ 123 cbor_item_t **handle = cbor_array_handle(item); 124 size_t size = cbor_array_size(item); 125 for (size_t i = 0; i < size; i++) 126 if (handle[i] != NULL) cbor_decref(&handle[i]); 127 _cbor_free(item->data); 128 break; 129 } 130 case CBOR_TYPE_MAP: { 131 struct cbor_pair *handle = cbor_map_handle(item); 132 for (size_t i = 0; i < item->metadata.map_metadata.end_ptr; 133 i++, handle++) { 134 cbor_decref(&handle->key); 135 if (handle->value != NULL) cbor_decref(&handle->value); 136 } 137 _cbor_free(item->data); 138 break; 139 } 140 case CBOR_TYPE_TAG: { 141 if (item->metadata.tag_metadata.tagged_item != NULL) 142 cbor_decref(&item->metadata.tag_metadata.tagged_item); 143 _cbor_free(item->data); 144 break; 145 } 146 case CBOR_TYPE_FLOAT_CTRL: { 147 /* Floats have combined allocation */ 148 break; 149 } 150 } 151 _cbor_free(item); 152 *item_ref = NULL; 153 } 154 } 155 156 void cbor_intermediate_decref(cbor_item_t *item) { cbor_decref(&item); } 157 158 size_t cbor_refcount(const cbor_item_t *item) { return item->refcount; } 159 160 cbor_item_t *cbor_move(cbor_item_t *item) { 161 item->refcount--; 162 return item; 163 } 164