Home | History | Annotate | Line # | Download | only in cbor
      1 /*
      2  * Copyright (c) 2014-2019 Pavel Kalvoda <me (at) 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