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