xref: /freebsd/contrib/libcbor/src/cbor/common.c (revision b5b9517bfe394e55088f5a05882eabae7e9b7b29)
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)22 cbor_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)28 bool 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)32 bool 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)36 bool 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)40 bool 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)44 bool 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)48 bool 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)52 bool 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)56 bool 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)60 bool 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)64 bool 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)70 bool 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)75 bool 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)80 bool 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)84 cbor_item_t* cbor_incref(cbor_item_t* item) {
85   item->refcount++;
86   return item;
87 }
88 
cbor_decref(cbor_item_t ** item_ref)89 void 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)160 void cbor_intermediate_decref(cbor_item_t* item) { cbor_decref(&item); }
161 
cbor_refcount(const cbor_item_t * item)162 size_t cbor_refcount(const cbor_item_t* item) { return item->refcount; }
163 
cbor_move(cbor_item_t * item)164 cbor_item_t* cbor_move(cbor_item_t* item) {
165   item->refcount--;
166   return item;
167 }
168