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