jcs's openbsd hax
openbsd
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
17extern "C" {
18#endif
19
20typedef const unsigned char* cbor_data;
21typedef unsigned char* cbor_mutable_data;
22
23/** Specifies the Major type of ::cbor_item_t */
24typedef 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 */
44typedef 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 */
58typedef 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 */
66typedef 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 */
77typedef enum {
78 _CBOR_METADATA_DEFINITE,
79 _CBOR_METADATA_INDEFINITE
80} _cbor_dst_metadata;
81
82/** Semantic mapping for CTRL simple values */
83typedef 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 */
97struct _cbor_int_metadata {
98 cbor_int_width width;
99};
100
101/** Bytestrings specific metadata */
102struct _cbor_bytestring_metadata {
103 size_t length;
104 _cbor_dst_metadata type;
105};
106
107/** Strings specific metadata */
108struct _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 */
116struct _cbor_array_metadata {
117 size_t allocated;
118 size_t end_ptr;
119 _cbor_dst_metadata type;
120};
121
122/** Maps specific metadata */
123struct _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 */
135struct _cbor_tag_metadata {
136 struct cbor_item_t* tagged_item;
137 uint64_t value;
138};
139
140/** Floats specific metadata - includes CTRL values */
141struct _cbor_float_ctrl_metadata {
142 cbor_float_width width;
143 uint8_t ctrl;
144};
145
146/** Raw memory casts helper */
147union _cbor_float_helper {
148 float as_float;
149 uint32_t as_uint;
150};
151
152/** Raw memory casts helper */
153union _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 */
160union 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 */
171typedef 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 */
186struct 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 */
193struct 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 */
201struct cbor_pair {
202 cbor_item_t *key, *value;
203};
204
205/** High-level decoding result */
206struct 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 */
214enum 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 */
230struct 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