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 #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 bool cbor_isa_uint(const cbor_item_t *item) {
     19   return item->type == CBOR_TYPE_UINT;
     20 }
     21 
     22 bool cbor_isa_negint(const cbor_item_t *item) {
     23   return item->type == CBOR_TYPE_NEGINT;
     24 }
     25 
     26 bool cbor_isa_bytestring(const cbor_item_t *item) {
     27   return item->type == CBOR_TYPE_BYTESTRING;
     28 }
     29 
     30 bool cbor_isa_string(const cbor_item_t *item) {
     31   return item->type == CBOR_TYPE_STRING;
     32 }
     33 
     34 bool cbor_isa_array(const cbor_item_t *item) {
     35   return item->type == CBOR_TYPE_ARRAY;
     36 }
     37 
     38 bool cbor_isa_map(const cbor_item_t *item) {
     39   return item->type == CBOR_TYPE_MAP;
     40 }
     41 
     42 bool cbor_isa_tag(const cbor_item_t *item) {
     43   return item->type == CBOR_TYPE_TAG;
     44 }
     45 
     46 bool cbor_isa_float_ctrl(const cbor_item_t *item) {
     47   return item->type == CBOR_TYPE_FLOAT_CTRL;
     48 }
     49 
     50 cbor_type cbor_typeof(const cbor_item_t *item) { return item->type; }
     51 
     52 bool cbor_is_int(const cbor_item_t *item) {
     53   return cbor_isa_uint(item) || cbor_isa_negint(item);
     54 }
     55 
     56 bool cbor_is_bool(const cbor_item_t *item) {
     57   return cbor_isa_float_ctrl(item) &&
     58          (cbor_ctrl_value(item) == CBOR_CTRL_FALSE ||
     59           cbor_ctrl_value(item) == CBOR_CTRL_TRUE);
     60 }
     61 
     62 bool cbor_is_null(const cbor_item_t *item) {
     63   return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_NULL;
     64 }
     65 
     66 bool cbor_is_undef(const cbor_item_t *item) {
     67   return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_UNDEF;
     68 }
     69 
     70 bool cbor_is_float(const cbor_item_t *item) {
     71   return cbor_isa_float_ctrl(item) && !cbor_float_ctrl_is_ctrl(item);
     72 }
     73 
     74 cbor_item_t *cbor_incref(cbor_item_t *item) {
     75   item->refcount++;
     76   return item;
     77 }
     78 
     79 void cbor_decref(cbor_item_t **item_ref) {
     80   cbor_item_t *item = *item_ref;
     81   assert(item->refcount > 0);
     82   if (--item->refcount == 0) {
     83     switch (item->type) {
     84       case CBOR_TYPE_UINT:
     85         /* Fallthrough */
     86       case CBOR_TYPE_NEGINT:
     87         /* Combined allocation, freeing the item suffices */
     88         { break; }
     89       case CBOR_TYPE_BYTESTRING: {
     90         if (cbor_bytestring_is_definite(item)) {
     91           _CBOR_FREE(item->data);
     92         } else {
     93           /* We need to decref all chunks */
     94           cbor_item_t **handle = cbor_bytestring_chunks_handle(item);
     95           for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
     96             cbor_decref(&handle[i]);
     97           _CBOR_FREE(
     98               ((struct cbor_indefinite_string_data *)item->data)->chunks);
     99           _CBOR_FREE(item->data);
    100         }
    101         break;
    102       }
    103       case CBOR_TYPE_STRING: {
    104         if (cbor_string_is_definite(item)) {
    105           _CBOR_FREE(item->data);
    106         } else {
    107           /* We need to decref all chunks */
    108           cbor_item_t **handle = cbor_string_chunks_handle(item);
    109           for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
    110             cbor_decref(&handle[i]);
    111           _CBOR_FREE(
    112               ((struct cbor_indefinite_string_data *)item->data)->chunks);
    113           _CBOR_FREE(item->data);
    114         }
    115         break;
    116       }
    117       case CBOR_TYPE_ARRAY: {
    118         /* Get all items and decref them */
    119         cbor_item_t **handle = cbor_array_handle(item);
    120         size_t size = cbor_array_size(item);
    121         for (size_t i = 0; i < size; i++)
    122           if (handle[i] != NULL) cbor_decref(&handle[i]);
    123         _CBOR_FREE(item->data);
    124         break;
    125       }
    126       case CBOR_TYPE_MAP: {
    127         struct cbor_pair *handle = cbor_map_handle(item);
    128         for (size_t i = 0; i < item->metadata.map_metadata.end_ptr;
    129              i++, handle++) {
    130           cbor_decref(&handle->key);
    131           if (handle->value != NULL) cbor_decref(&handle->value);
    132         }
    133         _CBOR_FREE(item->data);
    134         break;
    135       };
    136       case CBOR_TYPE_TAG: {
    137         if (item->metadata.tag_metadata.tagged_item != NULL)
    138           cbor_decref(&item->metadata.tag_metadata.tagged_item);
    139         _CBOR_FREE(item->data);
    140         break;
    141       }
    142       case CBOR_TYPE_FLOAT_CTRL: {
    143         /* Floats have combined allocation */
    144         break;
    145       }
    146     }
    147     _CBOR_FREE(item);
    148     // TODO
    149     *item_ref = NULL;
    150   }
    151 }
    152 
    153 void cbor_intermediate_decref(cbor_item_t *item) { cbor_decref(&item); }
    154 
    155 size_t cbor_refcount(const cbor_item_t *item) { return item->refcount; }
    156 
    157 cbor_item_t *cbor_move(cbor_item_t *item) {
    158   item->refcount--;
    159   return item;
    160 }
    161