xref: /freebsd/contrib/libcbor/src/cbor/common.c (revision a03411e84728e9b267056fd31c7d1d9d1dc1b01e)
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