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_DATA_H 9 #define LIBCBOR_DATA_H 10 11 #include <stdbool.h> 12 #include <stddef.h> 13 #include <stdint.h> 14 #include <stdlib.h> 15 16 #ifdef __cplusplus 17 extern "C" { 18 #endif 19 20 typedef const unsigned char* cbor_data; 21 typedef unsigned char* cbor_mutable_data; 22 23 /** Specifies the Major type of ::cbor_item_t */ 24 typedef enum cbor_type { 25 CBOR_TYPE_UINT /** 0 - positive integers */ 26 , 27 CBOR_TYPE_NEGINT /** 1 - negative integers*/ 28 , 29 CBOR_TYPE_BYTESTRING /** 2 - byte strings */ 30 , 31 CBOR_TYPE_STRING /** 3 - strings */ 32 , 33 CBOR_TYPE_ARRAY /** 4 - arrays */ 34 , 35 CBOR_TYPE_MAP /** 5 - maps */ 36 , 37 CBOR_TYPE_TAG /** 6 - tags */ 38 , 39 CBOR_TYPE_FLOAT_CTRL /** 7 - decimals and special values (true, false, nil, 40 ...) */ 41 } cbor_type; 42 43 /** Possible decoding errors */ 44 typedef enum { 45 CBOR_ERR_NONE, 46 CBOR_ERR_NOTENOUGHDATA, 47 CBOR_ERR_NODATA, 48 // TODO: Should be "malformed" or at least "malformatted". Retained for 49 // backwards compatibility. 50 CBOR_ERR_MALFORMATED, 51 CBOR_ERR_MEMERROR /** Memory error - item allocation failed. Is it too big for 52 your allocator? */ 53 , 54 CBOR_ERR_SYNTAXERROR /** Stack parsing algorithm failed */ 55 } cbor_error_code; 56 57 /** Possible widths of #CBOR_TYPE_UINT items */ 58 typedef enum { 59 CBOR_INT_8, 60 CBOR_INT_16, 61 CBOR_INT_32, 62 CBOR_INT_64 63 } cbor_int_width; 64 65 /** Possible widths of #CBOR_TYPE_FLOAT_CTRL items */ 66 typedef enum { 67 CBOR_FLOAT_0 /** Internal use - ctrl and special values */ 68 , 69 CBOR_FLOAT_16 /** Half float */ 70 , 71 CBOR_FLOAT_32 /** Single float */ 72 , 73 CBOR_FLOAT_64 /** Double */ 74 } cbor_float_width; 75 76 /** Metadata for dynamically sized types */ 77 typedef enum { 78 _CBOR_METADATA_DEFINITE, 79 _CBOR_METADATA_INDEFINITE 80 } _cbor_dst_metadata; 81 82 /** Semantic mapping for CTRL simple values */ 83 typedef enum { 84 CBOR_CTRL_NONE = 0, 85 CBOR_CTRL_FALSE = 20, 86 CBOR_CTRL_TRUE = 21, 87 CBOR_CTRL_NULL = 22, 88 CBOR_CTRL_UNDEF = 23 89 } _cbor_ctrl; 90 91 // Metadata items use size_t (instead of uint64_t) because items in memory take 92 // up at least 1B per entry or string byte, so if size_t is narrower than 93 // uint64_t, we wouldn't be able to create them in the first place and can save 94 // some space. 95 96 /** Integers specific metadata */ 97 struct _cbor_int_metadata { 98 cbor_int_width width; 99 }; 100 101 /** Bytestrings specific metadata */ 102 struct _cbor_bytestring_metadata { 103 size_t length; 104 _cbor_dst_metadata type; 105 }; 106 107 /** Strings specific metadata */ 108 struct _cbor_string_metadata { 109 size_t length; 110 size_t codepoint_count; /* Sum of chunks' codepoint_counts for indefinite 111 strings */ 112 _cbor_dst_metadata type; 113 }; 114 115 /** Arrays specific metadata */ 116 struct _cbor_array_metadata { 117 size_t allocated; 118 size_t end_ptr; 119 _cbor_dst_metadata type; 120 }; 121 122 /** Maps specific metadata */ 123 struct _cbor_map_metadata { 124 size_t allocated; 125 size_t end_ptr; 126 _cbor_dst_metadata type; 127 }; 128 129 /** Arrays specific metadata 130 * 131 * The pointer is included - cbor_item_metadata is 132 * 2 * sizeof(size_t) + sizeof(_cbor_string_type_metadata), 133 * lets use the space 134 */ 135 struct _cbor_tag_metadata { 136 struct cbor_item_t* tagged_item; 137 uint64_t value; 138 }; 139 140 /** Floats specific metadata - includes CTRL values */ 141 struct _cbor_float_ctrl_metadata { 142 cbor_float_width width; 143 uint8_t ctrl; 144 }; 145 146 /** Raw memory casts helper */ 147 union _cbor_float_helper { 148 float as_float; 149 uint32_t as_uint; 150 }; 151 152 /** Raw memory casts helper */ 153 union _cbor_double_helper { 154 double as_double; 155 uint64_t as_uint; 156 }; 157 158 /** Union of metadata across all possible types - discriminated in #cbor_item_t 159 */ 160 union cbor_item_metadata { 161 struct _cbor_int_metadata int_metadata; 162 struct _cbor_bytestring_metadata bytestring_metadata; 163 struct _cbor_string_metadata string_metadata; 164 struct _cbor_array_metadata array_metadata; 165 struct _cbor_map_metadata map_metadata; 166 struct _cbor_tag_metadata tag_metadata; 167 struct _cbor_float_ctrl_metadata float_ctrl_metadata; 168 }; 169 170 /** The item handle */ 171 typedef struct cbor_item_t { 172 /** Discriminated by type */ 173 union cbor_item_metadata metadata; 174 /** Reference count - initialize to 0 */ 175 size_t refcount; 176 /** Major type discriminator */ 177 cbor_type type; 178 /** Raw data block - interpretation depends on metadata */ 179 unsigned char* data; 180 } cbor_item_t; 181 182 /** Defines cbor_item_t#data structure for indefinite strings and bytestrings 183 * 184 * Used to cast the raw representation for a sane manipulation 185 */ 186 struct cbor_indefinite_string_data { 187 size_t chunk_count; 188 size_t chunk_capacity; 189 cbor_item_t** chunks; 190 }; 191 192 /** High-level decoding error */ 193 struct cbor_error { 194 /** Approximate position */ 195 size_t position; 196 /** Description */ 197 cbor_error_code code; 198 }; 199 200 /** Simple pair of items for use in maps */ 201 struct cbor_pair { 202 cbor_item_t *key, *value; 203 }; 204 205 /** High-level decoding result */ 206 struct cbor_load_result { 207 /** Error indicator */ 208 struct cbor_error error; 209 /** Number of bytes read */ 210 size_t read; 211 }; 212 213 /** Streaming decoder result - status */ 214 enum cbor_decoder_status { 215 /** Decoding finished successfully (a callback has been invoked) 216 * 217 * Note that this does *not* mean that the buffer has been fully decoded; 218 * there may still be unread bytes for which no callback has been involved. 219 */ 220 CBOR_DECODER_FINISHED, 221 /** Not enough data to invoke a callback */ 222 // TODO: The name is inconsistent with CBOR_ERR_NOTENOUGHDATA. Retained for 223 // backwards compatibility. 224 CBOR_DECODER_NEDATA, 225 /** Bad data (reserved MTB, malformed value, etc.) */ 226 CBOR_DECODER_ERROR 227 }; 228 229 /** Streaming decoder result */ 230 struct cbor_decoder_result { 231 /** Input bytes read/consumed 232 * 233 * If this is less than the size of input buffer, the client will likely 234 * resume parsing starting at the next byte (e.g. `buffer + result.read`). 235 * 236 * Set to 0 if the #status is not #CBOR_DECODER_FINISHED. 237 */ 238 size_t read; 239 240 /** The decoding status */ 241 enum cbor_decoder_status status; 242 243 /** Number of bytes in the input buffer needed to resume parsing 244 * 245 * Set to 0 unless the result status is #CBOR_DECODER_NEDATA. If it is, then: 246 * - If at least one byte was passed, #required will be set to the minimum 247 * number of bytes needed to invoke a decoded callback on the current 248 * prefix. 249 * 250 * For example: Attempting to decode a 1B buffer containing `0x19` will 251 * set #required to 3 as `0x19` signals a 2B integer item, so we need at 252 * least 3B to continue (the `0x19` MTB byte and two bytes of data needed 253 * to invoke #cbor_callbacks.uint16). 254 * 255 * - If there was no data at all, #read will always be set to 1 256 */ 257 size_t required; 258 }; 259 260 #ifdef __cplusplus 261 } 262 #endif 263 264 #endif // LIBCBOR_DATA_H 265