xref: /freebsd/contrib/libcbor/src/cbor/common.h (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 #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 
17 #include "cbor/cbor_export.h"
18 #include "cbor/configuration.h"
19 #include "data.h"
20 
21 #ifdef __cplusplus
22 extern "C" {
23 
24 /**
25  * C99 is not a subset of C++ -- 'restrict' qualifier is not a part of the
26  * language. This is a workaround to keep it in C headers -- compilers allow
27  * linking non-restrict signatures with restrict implementations.
28  *
29  * If you know a nicer way, please do let me know.
30  */
31 #define CBOR_RESTRICT_POINTER
32 
33 #else
34 
35 // MSVC + C++ workaround
36 #define CBOR_RESTRICT_POINTER CBOR_RESTRICT_SPECIFIER
37 
38 #endif
39 
40 static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION;
41 static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION;
42 static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION;
43 
44 #define CBOR_VERSION               \
45   _CBOR_TO_STR(CBOR_MAJOR_VERSION) \
46   "." _CBOR_TO_STR(CBOR_MINOR_VERSION) "." _CBOR_TO_STR(CBOR_PATCH_VERSION)
47 #define CBOR_HEX_VERSION \
48   ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION)
49 
50 /* http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing
51  */
52 #ifdef DEBUG
53 #include <stdio.h>
54 #define _cbor_debug_print(fmt, ...)                                     \
55   do {                                                                  \
56     if (DEBUG)                                                          \
57       fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, \
58               __VA_ARGS__);                                             \
59   } while (0)
60 extern bool _cbor_enable_assert;
61 // Like `assert`, but can be dynamically disabled in tests to allow testing
62 // invalid behaviors.
63 #define CBOR_ASSERT(e) assert(!_cbor_enable_assert || (e))
64 #define _CBOR_TEST_DISABLE_ASSERT(block) \
65   do {                                   \
66     _cbor_enable_assert = false;         \
67     block _cbor_enable_assert = true;    \
68   } while (0)
69 #else
70 #define debug_print(fmt, ...) \
71   do {                        \
72   } while (0)
73 #define CBOR_ASSERT(e)
74 #define _CBOR_TEST_DISABLE_ASSERT(block) \
75   do {                                   \
76     block                                \
77   } while (0)
78 #endif
79 
80 #define CBOR_ASSERT_VALID_TYPE(item_type) \
81   CBOR_ASSERT(item_type >= CBOR_TYPE_UINT && item_type <= CBOR_TYPE_FLOAT_CTRL);
82 
83 #define _CBOR_TO_STR_(x) #x
84 #define _CBOR_TO_STR(x) _CBOR_TO_STR_(x) /* enables proper double expansion */
85 
86 #ifdef CBOR_HAS_NODISCARD_ATTRIBUTE
87 #define CBOR_NODISCARD [[nodiscard]]
88 #else
89 #define CBOR_NODISCARD
90 #endif
91 
92 #ifdef __GNUC__
93 #define _CBOR_UNUSED __attribute__((__unused__))
94 // Fall back to __attribute__((warn_unused_result)) if we don't have
95 // [[nodiscard]]
96 #ifndef CBOR_HAS_NODISCARD_ATTRIBUTE
97 #define _CBOR_NODISCARD __attribute__((warn_unused_result))
98 #endif
99 #elif defined(_MSC_VER)
100 #define _CBOR_UNUSED __pragma(warning(suppress : 4100 4101))
101 #define _CBOR_NODISCARD
102 #else
103 #define _CBOR_UNUSED
104 #define _CBOR_NODISCARD
105 #endif
106 
107 #ifdef CBOR_HAS_BUILTIN_UNREACHABLE
108 #define _CBOR_UNREACHABLE __builtin_unreachable()
109 #else
110 #define _CBOR_UNREACHABLE
111 #endif
112 
113 typedef void* (*_cbor_malloc_t)(size_t);
114 typedef void* (*_cbor_realloc_t)(void*, size_t);
115 typedef void (*_cbor_free_t)(void*);
116 
117 CBOR_EXPORT extern _cbor_malloc_t _cbor_malloc;
118 CBOR_EXPORT extern _cbor_realloc_t _cbor_realloc;
119 CBOR_EXPORT extern _cbor_free_t _cbor_free;
120 
121 // Macro to short-circuit builder functions when memory allocation fails
122 #define _CBOR_NOTNULL(cbor_item) \
123   do {                           \
124     if (cbor_item == NULL) {     \
125       return NULL;               \
126     }                            \
127   } while (0)
128 
129 // Macro to short-circuit builders when memory allocation of nested data
130 // fails
131 #define _CBOR_DEPENDENT_NOTNULL(cbor_item, pointer) \
132   do {                                              \
133     if (pointer == NULL) {                          \
134       _cbor_free(cbor_item);                        \
135       return NULL;                                  \
136     }                                               \
137   } while (0)
138 
139 /** Sets the memory management routines to use.
140  *
141  * By default, libcbor will use the standard library `malloc`, `realloc`,
142  * and `free`.
143  *
144  * \rst
145  * .. warning::
146  *   This function modifies the global state and should
147  *   therefore be used accordingly. Changing the memory handlers while
148  *   allocated items exist will result in a ``free``/``malloc`` mismatch.
149  *   This function is not thread safe with respect to both itself and all
150  *   the other *libcbor* functions that work with the heap.
151  *
152  * .. note::
153  *   `realloc` implementation must correctly support `NULL`
154  *   reallocation (see e.g. http://en.cppreference.com/w/c/memory/realloc)
155  *
156  * \endrst
157  *
158  * @param custom_malloc malloc implementation
159  * @param custom_realloc realloc implementation
160  * @param custom_free free implementation
161  */
162 CBOR_EXPORT void cbor_set_allocs(_cbor_malloc_t custom_malloc,
163                                  _cbor_realloc_t custom_realloc,
164                                  _cbor_free_t custom_free);
165 
166 /*
167  * ============================================================================
168  * Type manipulation
169  * ============================================================================
170  */
171 
172 /** Get the type of the item
173  *
174  * @param item
175  * @return The type
176  */
177 _CBOR_NODISCARD
178 CBOR_EXPORT cbor_type cbor_typeof(
179     const cbor_item_t* item); /* Will be inlined iff link-time opt is enabled */
180 
181 /* Standard CBOR Major item types */
182 
183 /** Does the item have the appropriate major type?
184  * @param item the item
185  * @return Is the item an #CBOR_TYPE_UINT?
186  */
187 _CBOR_NODISCARD
188 CBOR_EXPORT bool cbor_isa_uint(const cbor_item_t* item);
189 
190 /** Does the item have the appropriate major type?
191  * @param item the item
192  * @return Is the item a #CBOR_TYPE_NEGINT?
193  */
194 _CBOR_NODISCARD
195 CBOR_EXPORT bool cbor_isa_negint(const cbor_item_t* item);
196 
197 /** Does the item have the appropriate major type?
198  * @param item the item
199  * @return Is the item a #CBOR_TYPE_BYTESTRING?
200  */
201 _CBOR_NODISCARD
202 CBOR_EXPORT bool cbor_isa_bytestring(const cbor_item_t* item);
203 
204 /** Does the item have the appropriate major type?
205  * @param item the item
206  * @return Is the item a #CBOR_TYPE_STRING?
207  */
208 _CBOR_NODISCARD
209 CBOR_EXPORT bool cbor_isa_string(const cbor_item_t* item);
210 
211 /** Does the item have the appropriate major type?
212  * @param item the item
213  * @return Is the item an #CBOR_TYPE_ARRAY?
214  */
215 _CBOR_NODISCARD
216 CBOR_EXPORT bool cbor_isa_array(const cbor_item_t* item);
217 
218 /** Does the item have the appropriate major type?
219  * @param item the item
220  * @return Is the item a #CBOR_TYPE_MAP?
221  */
222 _CBOR_NODISCARD
223 CBOR_EXPORT bool cbor_isa_map(const cbor_item_t* item);
224 
225 /** Does the item have the appropriate major type?
226  * @param item the item
227  * @return Is the item a #CBOR_TYPE_TAG?
228  */
229 _CBOR_NODISCARD
230 CBOR_EXPORT bool cbor_isa_tag(const cbor_item_t* item);
231 
232 /** Does the item have the appropriate major type?
233  * @param item the item
234  * @return Is the item a #CBOR_TYPE_FLOAT_CTRL?
235  */
236 _CBOR_NODISCARD
237 CBOR_EXPORT bool cbor_isa_float_ctrl(const cbor_item_t* item);
238 
239 /* Practical types with respect to their semantics (but not tag values) */
240 
241 /** Is the item an integer, either positive or negative?
242  * @param item the item
243  * @return  Is the item an integer, either positive or negative?
244  */
245 _CBOR_NODISCARD
246 CBOR_EXPORT bool cbor_is_int(const cbor_item_t* item);
247 
248 /** Is the item an a floating point number?
249  * @param item the item
250  * @return  Is the item a floating point number?
251  */
252 _CBOR_NODISCARD
253 CBOR_EXPORT bool cbor_is_float(const cbor_item_t* item);
254 
255 /** Is the item an a boolean?
256  * @param item the item
257  * @return  Is the item a boolean?
258  */
259 _CBOR_NODISCARD
260 CBOR_EXPORT bool cbor_is_bool(const cbor_item_t* item);
261 
262 /** Does this item represent `null`
263  *
264  * \rst
265  * .. warning::
266  *   This is in no way related to the value of the pointer.
267  *   Passing a null pointer will most likely result in a crash.
268  * \endrst
269  *
270  * @param item the item
271  * @return  Is the item (CBOR logical) null?
272  */
273 _CBOR_NODISCARD
274 CBOR_EXPORT bool cbor_is_null(const cbor_item_t* item);
275 
276 /** Does this item represent `undefined`
277  *
278  * \rst
279  * .. warning::
280  *   Care must be taken to distinguish nulls and undefined values in C.
281  * \endrst
282  *
283  * @param item the item
284  * @return Is the item (CBOR logical) undefined?
285  */
286 _CBOR_NODISCARD
287 CBOR_EXPORT bool cbor_is_undef(const cbor_item_t* item);
288 
289 /*
290  * ============================================================================
291  * Memory management
292  * ============================================================================
293  */
294 
295 /** Increases the item's reference count by one
296  *
297  * Constant complexity; items referring to this one or items being
298  * referred to are not updated.
299  *
300  * This function can be used to extend reference counting to client code.
301  *
302  * @param item Reference to an item
303  * @return The input \p item
304  */
305 CBOR_EXPORT cbor_item_t* cbor_incref(cbor_item_t* item);
306 
307 /** Decreases the item's reference count by one, deallocating the item if
308  * needed
309  *
310  * In case the item is deallocated, the reference count of all items this
311  * item references will also be #cbor_decref 'ed recursively.
312  *
313  * @param item Reference to an item. Will be set to `NULL` if deallocated
314  */
315 CBOR_EXPORT void cbor_decref(cbor_item_t** item);
316 
317 /** Decreases the item's reference count by one, deallocating the item if
318  * needed
319  *
320  * Convenience wrapper for #cbor_decref when its set-to-null behavior is
321  * not needed
322  *
323  * @param item Reference to an item
324  */
325 CBOR_EXPORT void cbor_intermediate_decref(cbor_item_t* item);
326 
327 /** Get the item's reference count
328  *
329  * \rst
330  * .. warning::
331  *   This does *not* account for transitive references.
332  * \endrst
333  *
334  * @todo Add some inline examples for reference counting
335  *
336  * @param item the item
337  * @return the reference count
338  */
339 _CBOR_NODISCARD
340 CBOR_EXPORT size_t cbor_refcount(const cbor_item_t* item);
341 
342 /** Provides CPP-like move construct
343  *
344  * Decreases the reference count by one, but does not deallocate the item
345  * even if its refcount reaches zero. This is useful for passing
346  * intermediate values to functions that increase reference count. Should
347  * only be used with functions that `incref` their arguments.
348  *
349  * \rst
350  * .. warning::
351  *   If the item is moved without correctly increasing the
352  *   reference count afterwards, the memory will be leaked.
353  * \endrst
354  *
355  * @param item Reference to an item
356  * @return the item with reference count decreased by one
357  */
358 _CBOR_NODISCARD
359 CBOR_EXPORT cbor_item_t* cbor_move(cbor_item_t* item);
360 
361 #ifdef __cplusplus
362 }
363 #endif
364 
365 #endif  // LIBCBOR_COMMON_H
366