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