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