xref: /freebsd/contrib/libcbor/src/cbor/common.h (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
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 #ifndef LIBCBOR_COMMON_H
9 #define LIBCBOR_COMMON_H
10 
11 #include <assert.h>
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include "cbor/cbor_export.h"
17 #include "cbor/configuration.h"
18 #include "data.h"
19 
20 #ifdef __cplusplus
21 extern "C" {
22 
23 /**
24  * C++ is not a subset of C99 -- 'restrict' qualifier is not a part of the
25  * language. This is a workaround to keep it in C headers -- compilers allow
26  * linking non-restrict signatures with restrict implementations.
27  *
28  * If you know a nicer way, please do let me know.
29  */
30 #define CBOR_RESTRICT_POINTER
31 
32 #else
33 
34 // MSVC + C++ workaround
35 #define CBOR_RESTRICT_POINTER CBOR_RESTRICT_SPECIFIER
36 
37 #endif
38 
39 static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION;
40 static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION;
41 static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION;
42 
43 #define CBOR_VERSION         \
44   TO_STR(CBOR_MAJOR_VERSION) \
45   "." TO_STR(CBOR_MINOR_VERSION) "." TO_STR(CBOR_PATCH_VERSION)
46 #define CBOR_HEX_VERSION \
47   ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION)
48 
49 /* http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing
50  */
51 #ifdef DEBUG
52 #include <stdio.h>
53 #define debug_print(fmt, ...)                                           \
54   do {                                                                  \
55     if (DEBUG)                                                          \
56       fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, \
57               __VA_ARGS__);                                             \
58   } while (0)
59 #else
60 #define debug_print(fmt, ...) \
61   do {                        \
62   } while (0)
63 #endif
64 
65 #define TO_STR_(x) #x
66 #define TO_STR(x) TO_STR_(x) /* enables proper double expansion */
67 
68 // Macro to short-circuit builder functions when memory allocation fails
69 #define _CBOR_NOTNULL(cbor_item) \
70   do {                           \
71     if (cbor_item == NULL) {     \
72       return NULL;               \
73     }                            \
74   } while (0)
75 
76 // Macro to short-circuit builders when memory allocation of nested data fails
77 #define _CBOR_DEPENDENT_NOTNULL(cbor_item, pointer) \
78   do {                                              \
79     if (pointer == NULL) {                          \
80       _CBOR_FREE(cbor_item);                        \
81       return NULL;                                  \
82     }                                               \
83   } while (0)
84 
85 #if CBOR_CUSTOM_ALLOC
86 
87 typedef void *(*_cbor_malloc_t)(size_t);
88 typedef void *(*_cbor_realloc_t)(void *, size_t);
89 typedef void (*_cbor_free_t)(void *);
90 
91 CBOR_EXPORT extern _cbor_malloc_t _cbor_malloc;
92 CBOR_EXPORT extern _cbor_realloc_t _cbor_realloc;
93 CBOR_EXPORT extern _cbor_free_t _cbor_free;
94 
95 /** Sets the memory management routines to use.
96  *
97  * Only available when `CBOR_CUSTOM_ALLOC` is truthy
98  *
99  * \rst
100  * .. warning:: This function modifies the global state and should therefore be
101  *  used accordingly. Changing the memory handlers while allocated items exist
102  *  will result in a ``free``/``malloc`` mismatch. This function is not thread
103  *  safe with respect to both itself and all the other *libcbor* functions that
104  *  work with the heap.
105  *
106  * .. note:: `realloc` implementation must correctly support `NULL` reallocation
107  *  (see e.g. http://en.cppreference.com/w/c/memory/realloc)
108  * \endrst
109  *
110  * @param custom_malloc malloc implementation
111  * @param custom_realloc realloc implementation
112  * @param custom_free free implementation
113  */
114 CBOR_EXPORT void cbor_set_allocs(_cbor_malloc_t custom_malloc,
115                                  _cbor_realloc_t custom_realloc,
116                                  _cbor_free_t custom_free);
117 
118 #define _CBOR_MALLOC _cbor_malloc
119 #define _CBOR_REALLOC _cbor_realloc
120 #define _CBOR_FREE _cbor_free
121 
122 #else
123 
124 #define _CBOR_MALLOC malloc
125 #define _CBOR_REALLOC realloc
126 #define _CBOR_FREE free
127 
128 #endif
129 
130 /*
131  * ============================================================================
132  * Type manipulation
133  * ============================================================================
134  */
135 
136 /** Get the type of the item
137  *
138  * @param item[borrow]
139  * @return The type
140  */
141 CBOR_EXPORT cbor_type cbor_typeof(
142     const cbor_item_t *item); /* Will be inlined iff link-time opt is enabled */
143 
144 /* Standard item types as described by the RFC */
145 
146 /** Does the item have the appropriate major type?
147  * @param item[borrow] the item
148  * @return Is the item an #CBOR_TYPE_UINT?
149  */
150 CBOR_EXPORT bool cbor_isa_uint(const cbor_item_t *item);
151 
152 /** Does the item have the appropriate major type?
153  * @param item[borrow] the item
154  * @return Is the item a #CBOR_TYPE_NEGINT?
155  */
156 CBOR_EXPORT bool cbor_isa_negint(const cbor_item_t *item);
157 
158 /** Does the item have the appropriate major type?
159  * @param item[borrow] the item
160  * @return Is the item a #CBOR_TYPE_BYTESTRING?
161  */
162 CBOR_EXPORT bool cbor_isa_bytestring(const cbor_item_t *item);
163 
164 /** Does the item have the appropriate major type?
165  * @param item[borrow] the item
166  * @return Is the item a #CBOR_TYPE_STRING?
167  */
168 CBOR_EXPORT bool cbor_isa_string(const cbor_item_t *item);
169 
170 /** Does the item have the appropriate major type?
171  * @param item[borrow] the item
172  * @return Is the item an #CBOR_TYPE_ARRAY?
173  */
174 CBOR_EXPORT bool cbor_isa_array(const cbor_item_t *item);
175 
176 /** Does the item have the appropriate major type?
177  * @param item[borrow] the item
178  * @return Is the item a #CBOR_TYPE_MAP?
179  */
180 CBOR_EXPORT bool cbor_isa_map(const cbor_item_t *item);
181 
182 /** Does the item have the appropriate major type?
183  * @param item[borrow] the item
184  * @return Is the item a #CBOR_TYPE_TAG?
185  */
186 CBOR_EXPORT bool cbor_isa_tag(const cbor_item_t *item);
187 
188 /** Does the item have the appropriate major type?
189  * @param item[borrow] the item
190  * @return Is the item a #CBOR_TYPE_FLOAT_CTRL?
191  */
192 CBOR_EXPORT bool cbor_isa_float_ctrl(const cbor_item_t *item);
193 
194 /* Practical types with respect to their semantics (but not tag values) */
195 
196 /** Is the item an integer, either positive or negative?
197  * @param item[borrow] the item
198  * @return  Is the item an integer, either positive or negative?
199  */
200 CBOR_EXPORT bool cbor_is_int(const cbor_item_t *item);
201 
202 /** Is the item an a floating point number?
203  * @param item[borrow] the item
204  * @return  Is the item a floating point number?
205  */
206 CBOR_EXPORT bool cbor_is_float(const cbor_item_t *item);
207 
208 /** Is the item an a boolean?
209  * @param item[borrow] the item
210  * @return  Is the item a boolean?
211  */
212 CBOR_EXPORT bool cbor_is_bool(const cbor_item_t *item);
213 
214 /** Does this item represent `null`
215  *
216  * \rst
217  * .. warning:: This is in no way related to the value of the pointer. Passing a
218  *  null pointer will most likely result in a crash.
219  * \endrst
220  *
221  * @param item[borrow] the item
222  * @return  Is the item (CBOR logical) null?
223  */
224 CBOR_EXPORT bool cbor_is_null(const cbor_item_t *item);
225 
226 /** Does this item represent `undefined`
227  *
228  * \rst
229  * .. warning:: Care must be taken to distinguish nulls and undefined values in
230  *  C.
231  * \endrst
232  *
233  * @param item[borrow] the item
234  * @return Is the item (CBOR logical) undefined?
235  */
236 CBOR_EXPORT bool cbor_is_undef(const cbor_item_t *item);
237 
238 /*
239  * ============================================================================
240  * Memory management
241  * ============================================================================
242  */
243 
244 /** Increases the reference count by one
245  *
246  * No dependent items are affected.
247  *
248  * @param item[incref] item the item
249  * @return the input reference
250  */
251 CBOR_EXPORT cbor_item_t *cbor_incref(cbor_item_t *item);
252 
253 /** Decreases the reference count by one, deallocating the item if needed
254  *
255  * In case the item is deallocated, the reference count of any dependent items
256  * is adjusted accordingly in a recursive manner.
257  *
258  * @param item[take] the item. Set to `NULL` if deallocated
259  */
260 CBOR_EXPORT void cbor_decref(cbor_item_t **item);
261 
262 /** Decreases the reference count by one, deallocating the item if needed
263  *
264  * Convenience wrapper for #cbor_decref when its set-to-null behavior is not
265  * needed
266  *
267  * @param item[take] the item
268  */
269 CBOR_EXPORT void cbor_intermediate_decref(cbor_item_t *item);
270 
271 /** Get the reference count
272  *
273  * \rst
274  * .. warning:: This does *not* account for transitive references.
275  * \endrst
276  *
277  * @param item[borrow] the item
278  * @return the reference count
279  */
280 CBOR_EXPORT size_t cbor_refcount(const cbor_item_t *item);
281 
282 /** Provides CPP-like move construct
283  *
284  * Decreases the reference count by one, but does not deallocate the item even
285  * if its refcount reaches zero. This is useful for passing intermediate values
286  * to functions that increase reference count. Should only be used with
287  * functions that `incref` their arguments.
288  *
289  * \rst
290  * .. warning:: If the item is moved without correctly increasing the reference
291  *  count afterwards, the memory will be leaked.
292  * \endrst
293  *
294  * @param item[take] the item
295  * @return the item with reference count decreased by one
296  */
297 CBOR_EXPORT cbor_item_t *cbor_move(cbor_item_t *item);
298 
299 #ifdef __cplusplus
300 }
301 #endif
302 
303 #endif  // LIBCBOR_COMMON_H
304