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