libcbor  0.5.0
libcbor is a C library for parsing and generating CBOR, the general-purpose schema-less binary data format.
cbor.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2017 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 #include "cbor.h"
10 #include "cbor/internal/loaders.h"
11 
13  size_t source_size,
14  struct cbor_load_result *result)
15 {
16  /* Context stack */
17  static struct cbor_callbacks callbacks = {
22 
24  .negint16 = &cbor_builder_negint16_callback,
25  .negint32 = &cbor_builder_negint32_callback,
26  .negint64 = &cbor_builder_negint64_callback,
27 
28  .byte_string = &cbor_builder_byte_string_callback,
29  .byte_string_start = &cbor_builder_byte_string_start_callback,
30 
32  .string_start = &cbor_builder_string_start_callback,
33 
34  .array_start = &cbor_builder_array_start_callback,
35  .indef_array_start = &cbor_builder_indef_array_start_callback,
36 
37  .map_start = &cbor_builder_map_start_callback,
38  .indef_map_start = &cbor_builder_indef_map_start_callback,
39 
41 
43  .undefined = &cbor_builder_undefined_callback,
48  .indef_break = &cbor_builder_indef_break_callback
49  };
50 
51  if (source_size == 0) {
52  result->error.code = CBOR_ERR_NODATA;
53  return NULL;
54  }
55  struct _cbor_stack stack = _cbor_stack_init();
56 
57  /* Target for callbacks */
58  struct _cbor_decoder_context context = (struct _cbor_decoder_context) {
59  .stack = &stack,
60  .creation_failed = false,
61  .syntax_error = false
62  };
63  struct cbor_decoder_result decode_result;
64  *result = (struct cbor_load_result) {.read = 0, .error = {.code = CBOR_ERR_NONE}};
65 
66  do {
67  if (source_size > result->read) { /* Check for overflows */
68  decode_result = cbor_stream_decode(
69  source + result->read,
70  source_size - result->read,
71  &callbacks,
72  &context);
73  } else {
74  result->error = (struct cbor_error) {
75  .code = CBOR_ERR_NOTENOUGHDATA,
76  .position = result->read
77  };
78  goto error;
79  }
80 
81  switch (decode_result.status) {
83  /* Everything OK */
84  {
85  result->read += decode_result.read;
86  break;
87  }
89  /* Data length doesn't match MTB expectation */
90  {
91  result->error.code = CBOR_ERR_NOTENOUGHDATA;
92  goto error;
93  }
95  /* Fallthrough */
96  case CBOR_DECODER_ERROR:
97  /* Reserved/malformated item */
98  {
99  result->error.code = CBOR_ERR_MALFORMATED;
100  goto error;
101  }
102  }
103 
104  if (context.creation_failed) {
105  /* Most likely unsuccessful allocation - our callback has failed */
106  result->error.code = CBOR_ERR_MEMERROR;
107  goto error;
108  } else if (context.syntax_error) {
109  result->error.code = CBOR_ERR_SYNTAXERROR;
110  goto error;
111  }
112  } while (stack.size > 0);
113 
114  /* Move the result before free */
115  cbor_item_t *result_item = context.root;
116  return result_item;
117 
118  error:
119  result->error.position = result->read;
120  //debug_print("Failed with decoder error %d at %d\n", result->error.code, result->error.position);
121  //cbor_describe(stack.top->item, stdout);
122  /* Free the stack */
123  while (stack.size > 0) {
124  cbor_decref(&stack.top->item);
125  _cbor_stack_pop(&stack);
126  }
127  return NULL;
128 }
129 
130 
131 static cbor_item_t * _cbor_copy_int(cbor_item_t * item, bool negative)
132 {
133  cbor_item_t * res;
134  switch (cbor_int_get_width(item)) {
135  case CBOR_INT_8: res = cbor_build_uint8(cbor_get_uint8(item)); break;
136  case CBOR_INT_16: res = cbor_build_uint16(cbor_get_uint16(item)); break;
137  case CBOR_INT_32: res = cbor_build_uint32(cbor_get_uint32(item)); break;
138  case CBOR_INT_64: res = cbor_build_uint64(cbor_get_uint64(item)); break;
139  default: return NULL;
140  }
141 
142  if (negative)
143  cbor_mark_negint(res);
144 
145  return res;
146 }
147 
148 static cbor_item_t * _cbor_copy_float_ctrl(cbor_item_t * item)
149 {
150  switch (cbor_float_get_width(item)) {
151  case CBOR_FLOAT_0:
152  return cbor_build_ctrl(cbor_ctrl_value(item));
153  case CBOR_FLOAT_16:
155  case CBOR_FLOAT_32:
157  case CBOR_FLOAT_64:
159  }
160 
161  return NULL;
162 }
163 
165 {
166  switch (cbor_typeof(item)) {
167  case CBOR_TYPE_UINT:
168  return _cbor_copy_int(item, false);
169  case CBOR_TYPE_NEGINT:
170  return _cbor_copy_int(item, true);
172  if (cbor_bytestring_is_definite(item)) {
174  } else {
176  for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
178  res,
179  cbor_move(
181  )
182  );
183  return res;
184  }
185  case CBOR_TYPE_STRING:
186  if (cbor_string_is_definite(item)) {
187  return cbor_build_stringn((const char *) cbor_string_handle(item), cbor_string_length(item));
188  } else {
190  for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
192  res,
193  cbor_move(
195  )
196  );
197  return res;
198  }
199  case CBOR_TYPE_ARRAY: {
200  cbor_item_t * res;
201  if (cbor_array_is_definite(item))
203  else
205 
206  for (size_t i = 0; i < cbor_array_size(item); i++)
208  res,
210  );
211  return res;
212  }
213  case CBOR_TYPE_MAP: {
214  cbor_item_t * res;
215  if (cbor_map_is_definite(item))
217  else
218  res = cbor_new_indefinite_map();
219 
220  struct cbor_pair * it = cbor_map_handle(item);
221  for (size_t i = 0; i < cbor_map_size(item); i++)
222  cbor_map_add(res, (struct cbor_pair) {
223  .key = cbor_move(cbor_copy(it[i].key)),
224  .value = cbor_move(cbor_copy(it[i].value))
225  });
226  return res;
227  }
228  case CBOR_TYPE_TAG:
229  return cbor_build_tag(
230  cbor_tag_value(item),
232  );
234  return _cbor_copy_float_ctrl(item);
235  }
236 
237  return NULL;
238 }
239 
240 #if CBOR_PRETTY_PRINTER
241 
242 #include <inttypes.h>
243 #include <wchar.h>
244 #include <locale.h>
245 #include <stdlib.h>
246 
247 #define __STDC_FORMAT_MACROS
248 
249 static int _pow(int b, int ex)
250 {
251  if (ex == 0) return 1;
252  int res = b;
253  while (--ex > 0) res *= b;
254  return res;
255 }
256 
257 static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent)
258 {
259  setlocale(LC_ALL, "");
260  switch (cbor_typeof(item)) {
261  case CBOR_TYPE_UINT: {
262  fprintf(out, "%*s[CBOR_TYPE_UINT] ", indent, " ");
263  fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
264  fprintf(out, "Value: %"PRIu64"\n", cbor_get_int(item));
265  break;
266  };
267  case CBOR_TYPE_NEGINT: {
268  fprintf(out, "%*s[CBOR_TYPE_NEGINT] ", indent, " ");
269  fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item)));
270  fprintf(out, "Value: -%"PRIu64" -1\n", cbor_get_int(item));
271  break;
272  };
273  case CBOR_TYPE_BYTESTRING: {
274  fprintf(out, "%*s[CBOR_TYPE_BYTESTRING] ", indent, " ");
275  if (cbor_bytestring_is_indefinite(item)) {
276  fprintf(out,
277  "Indefinite, with %zu chunks:\n",
279  for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++)
280  _cbor_nested_describe(
282  out,
283  indent + 4);
284  } else {
285  fprintf(out,
286  "Definite, length %zuB\n",
287  cbor_bytestring_length(item));
288  }
289  break;
290  };
291  case CBOR_TYPE_STRING: {
292  fprintf(out, "%*s[CBOR_TYPE_STRING] ", indent, " ");
293  if (cbor_string_is_indefinite(item)) {
294  fprintf(out,
295  "Indefinite, with %zu chunks:\n",
297  for (size_t i = 0; i < cbor_string_chunk_count(item); i++)
298  _cbor_nested_describe(
299  cbor_string_chunks_handle(item)[i],
300  out,
301  indent + 4);
302  } else {
303  fprintf(out,
304  "Definite, length %zuB, %zu codepoints\n",
305  cbor_string_length(item),
307  /* Careful - this doesn't support multibyte characters! */
308  /* Printing those is out of the scope of this demo :) */
309  /* libICU is your friend */
310  fprintf(out, "%*s", indent + 4, " ");
311  /* XXX: no null at the end -> confused vprintf */
312  fwrite(cbor_string_handle(item), (int) cbor_string_length(item), 1, out);
313  fprintf(out, "\n");
314  }
315  break;
316  };
317  case CBOR_TYPE_ARRAY: {
318  fprintf(out, "%*s[CBOR_TYPE_ARRAY] ", indent, " ");
319  if (cbor_array_is_definite(item)) {
320  fprintf(out,
321  "Definite, size: %zu\n",
322  cbor_array_size(item));
323  } else {
324  fprintf(out,
325  "Indefinite, size: %zu\n",
326  cbor_array_size(item));
327  }
328 
329  for (size_t i = 0; i < cbor_array_size(item); i++)
330  _cbor_nested_describe(
331  cbor_array_handle(item)[i],
332  out,
333  indent + 4);
334  break;
335  };
336  case CBOR_TYPE_MAP: {
337  fprintf(out, "%*s[CBOR_TYPE_MAP] ", indent, " ");
338  if (cbor_map_is_definite(item)) {
339  fprintf(out,
340  "Definite, size: %zu\n",
341  cbor_map_size(item));
342  } else {
343  fprintf(out,
344  "Indefinite, size: %zu\n",
345  cbor_map_size(item));
346  }
347 
348  for (size_t i = 0; i < cbor_map_size(item); i++) {
349  _cbor_nested_describe(
350  cbor_map_handle(item)[i].key,
351  out,
352  indent + 4);
353  _cbor_nested_describe(
354  cbor_map_handle(item)[i].value,
355  out,
356  indent + 4);
357  }
358  break;
359  };
360  case CBOR_TYPE_TAG: {
361  fprintf(out, "%*s[CBOR_TYPE_TAG] ", indent, " ");
362  fprintf(out, "Value: %"PRIu64"\n", cbor_tag_value(item));
363  _cbor_nested_describe(cbor_tag_item(item), out, indent + 4);
364  break;
365  };
366  case CBOR_TYPE_FLOAT_CTRL: {
367  fprintf(out, "%*s[CBOR_TYPE_FLOAT_CTRL] ", indent, " ");
368  if (cbor_float_ctrl_is_ctrl(item)) {
369  if (cbor_is_bool(item))
370  fprintf(out, "Bool: %s\n", cbor_ctrl_is_bool(item) ? "true" : "false");
371  else if (cbor_is_undef(item))
372  fprintf(out, "Undefined\n");
373  else if (cbor_is_null(item))
374  fprintf(out, "Null\n");
375  else
376  fprintf(out, "Simple value %d\n", cbor_ctrl_value(item));
377  } else {
378  fprintf(out, "Width: %dB, ", _pow(2, cbor_float_get_width(item)));
379  fprintf(out, "value: %lf\n", cbor_float_get_float(item));
380  }
381  break;
382  };
383  }
384 }
385 
386 void cbor_describe(cbor_item_t *item, FILE *out)
387 {
388  _cbor_nested_describe(item, out, 0);
389 }
390 
391 #endif
Malformed or reserved MTB/value.
Definition: data.h:197
cbor_item_t * cbor_build_uint8(uint8_t value)
Constructs a new positive integer.
Definition: ints.c:145
void cbor_builder_float4_callback(void *context, float value)
High-level decoding result.
Definition: data.h:184
size_t size
Definition: stack.h:27
bool cbor_bytestring_is_definite(const cbor_item_t *item)
Is the byte string definite?
Definition: bytestrings.c:24
bool syntax_error
Stack expectation mismatch.
6 - tags
Definition: data.h:31
uint64_t cbor_get_int(const cbor_item_t *item)
Extracts the integer value.
Definition: ints.c:44
Stack handle - contents and size.
Definition: stack.h:25
double cbor_float_get_float(const cbor_item_t *item)
Get the float value represented as double.
Definition: floats_ctrls.c:52
cbor_item_t * cbor_build_stringn(const char *val, size_t length)
Creates a new string and initializes it.
Definition: strings.c:50
3 - strings
Definition: data.h:28
void cbor_builder_byte_string_callback(void *context, cbor_data data, size_t length)
OK, finished.
Definition: data.h:194
void cbor_builder_uint32_callback(void *context, uint32_t value)
size_t read
Bytes read.
Definition: data.h:203
cbor_int_width cbor_int_get_width(const cbor_item_t *item)
Queries the integer width.
Definition: ints.c:10
2 - byte strings
Definition: data.h:27
Internal use - ctrl and special values.
Definition: data.h:55
unsigned char * cbor_string_handle(const cbor_item_t *item)
Get the handle to the underlying string.
Definition: strings.c:112
cbor_item_t * cbor_new_indefinite_bytestring()
Creates a new indefinite byte string.
Definition: bytestrings.c:46
cbor_item_t * cbor_new_indefinite_string()
Creates a new indefinite string.
Definition: strings.c:23
cbor_item_t * value
Definition: data.h:180
cbor_item_t * cbor_build_float2(float value)
Constructs a new float.
Definition: floats_ctrls.c:165
void cbor_builder_uint8_callback(void *context, uint8_t value)
void cbor_decref(cbor_item_t **item_ref)
Decreases the reference count by one, deallocating the item if needed.
Definition: common.c:99
cbor_int8_callback uint8
Unsigned int.
Definition: callbacks.h:50
size_t cbor_bytestring_chunk_count(const cbor_item_t *item)
Get the number of chunks this string consist of.
Definition: bytestrings.c:87
cbor_item_t ** cbor_string_chunks_handle(const cbor_item_t *item)
Get the handle to the array of chunks.
Definition: strings.c:67
void cbor_builder_uint64_callback(void *context, uint64_t value)
void cbor_builder_tag_callback(void *context, uint64_t value)
void cbor_builder_float2_callback(void *context, float value)
void cbor_builder_indef_break_callback(void *context)
void cbor_builder_negint8_callback(void *context, uint8_t value)
struct _cbor_stack _cbor_stack_init()
Definition: stack.c:10
size_t cbor_map_size(const cbor_item_t *item)
Get the number of pairs.
Definition: maps.c:11
cbor_item_t * cbor_build_ctrl(uint8_t value)
Constructs a ctrl item.
Definition: floats_ctrls.c:186
cbor_item_t ** cbor_bytestring_chunks_handle(const cbor_item_t *item)
Get the handle to the array of chunks.
Definition: bytestrings.c:80
bool cbor_bytestring_is_indefinite(const cbor_item_t *item)
Is the byte string indefinite?
Definition: bytestrings.c:30
4 - arrays
Definition: data.h:29
cbor_item_t * cbor_tag_item(const cbor_item_t *item)
Get the tagged item.
Definition: tags.c:22
cbor_item_t * key
Definition: data.h:180
cbor_item_t * cbor_new_indefinite_array()
Create new indefinite array.
Definition: arrays.c:138
cbor_item_t * cbor_build_tag(uint64_t value, cbor_item_t *item)
Build a new tag.
Definition: tags.c:41
void cbor_builder_negint16_callback(void *context, uint16_t value)
7 - decimals and special values (true, false, nil, ...)
Definition: data.h:32
uint32_t cbor_get_uint32(const cbor_item_t *item)
Extracts the integer value.
Definition: ints.c:30
void cbor_mark_negint(cbor_item_t *item)
Marks the integer item as a negative integer.
Definition: ints.c:91
High-level decoding context.
Simple pair of items for use in maps.
Definition: data.h:179
void cbor_builder_undefined_callback(void *context)
cbor_error_code code
Description.
Definition: data.h:175
cbor_item_t * cbor_build_uint32(uint32_t value)
Constructs a new positive integer.
Definition: ints.c:161
void _cbor_stack_pop(struct _cbor_stack *stack)
Definition: stack.c:15
bool cbor_array_is_definite(const cbor_item_t *item)
Is the array definite?
Definition: arrays.c:88
cbor_item_t * cbor_build_float4(float value)
Constructs a new float.
Definition: floats_ctrls.c:172
void cbor_builder_null_callback(void *context)
Double.
Definition: data.h:58
High-level decoding error.
Definition: data.h:171
uint16_t cbor_get_uint16(const cbor_item_t *item)
Extracts the integer value.
Definition: ints.c:23
Half float.
Definition: data.h:56
struct cbor_error error
Error indicator.
Definition: data.h:186
bool cbor_is_null(const cbor_item_t *item)
Does this item represent null
Definition: common.c:77
bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee)
Append to the end.
Definition: arrays.c:52
cbor_item_t * cbor_copy(cbor_item_t *item)
Deep copy of an item.
Definition: cbor.c:164
void cbor_builder_string_start_callback(void *context)
void cbor_builder_array_start_callback(void *context, size_t size)
size_t cbor_string_chunk_count(const cbor_item_t *item)
Get the number of chunks this string consist of.
Definition: strings.c:74
void cbor_builder_string_callback(void *context, cbor_data data, size_t length)
size_t cbor_array_size(const cbor_item_t *item)
Get the number of members.
Definition: arrays.c:12
0 - positive integers
Definition: data.h:25
bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk)
Appends a chunk to the bytestring.
Definition: bytestrings.c:95
cbor_item_t * cbor_build_uint16(uint16_t value)
Constructs a new positive integer.
Definition: ints.c:153
uint8_t cbor_get_uint8(const cbor_item_t *item)
Extracts the integer value.
Definition: ints.c:16
float cbor_float_get_float4(const cbor_item_t *item)
Get a single precision float.
Definition: floats_ctrls.c:38
uint64_t cbor_get_uint64(const cbor_item_t *item)
Extracts the integer value.
Definition: ints.c:37
uint8_t cbor_ctrl_value(const cbor_item_t *item)
Reads the control value.
Definition: floats_ctrls.c:18
void cbor_builder_indef_array_start_callback(void *context)
Streaming decoder result.
Definition: data.h:201
uint64_t cbor_tag_value(const cbor_item_t *item)
Get tag value.
Definition: tags.c:28
cbor_float_width cbor_float_get_width(const cbor_item_t *item)
Get the float width.
Definition: floats_ctrls.c:12
const unsigned char * cbor_data
Definition: data.h:20
cbor_item_t * cbor_load(cbor_data source, size_t source_size, struct cbor_load_result *result)
Loads data item from a buffer.
Definition: cbor.c:12
struct _cbor_stack * stack
cbor_item_t * cbor_build_uint64(uint64_t value)
Constructs a new positive integer.
Definition: ints.c:169
bool cbor_map_is_definite(const cbor_item_t *item)
Is this map definite?
Definition: maps.c:126
float cbor_float_get_float2(const cbor_item_t *item)
Get a half precision float.
Definition: floats_ctrls.c:31
cbor_item_t * cbor_build_float8(double value)
Constructs a new float.
Definition: floats_ctrls.c:179
cbor_item_t * cbor_move(cbor_item_t *item)
Provides CPP-like move construct.
Definition: common.c:184
void cbor_builder_negint32_callback(void *context, uint32_t value)
double cbor_float_get_float8(const cbor_item_t *item)
Get a double precision float.
Definition: floats_ctrls.c:45
bool cbor_is_bool(const cbor_item_t *item)
Is the item an a boolean?
Definition: common.c:71
enum cbor_decoder_status status
The result.
Definition: data.h:205
void cbor_builder_negint64_callback(void *context, uint64_t value)
Callback bundle – passed to the decoder.
Definition: callbacks.h:48
bool cbor_is_undef(const cbor_item_t *item)
Does this item represent undefined
Definition: common.c:82
void cbor_builder_float8_callback(void *context, double value)
cbor_type cbor_typeof(const cbor_item_t *item)
Get the type of the item.
Definition: common.c:59
Stack parsing algorithm failed.
Definition: data.h:42
Not enough data - mismatch with MTB.
Definition: data.h:195
size_t cbor_string_codepoint_count(const cbor_item_t *item)
The number of codepoints in this string.
Definition: strings.c:118
bool cbor_ctrl_is_bool(const cbor_item_t *item)
Is this ctrl item a boolean?
Definition: floats_ctrls.c:92
bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk)
Appends a chunk to the string.
Definition: strings.c:82
bool cbor_string_is_definite(const cbor_item_t *item)
Is the string definite?
Definition: strings.c:124
unsigned char * cbor_bytestring_handle(const cbor_item_t *item)
Get the handle to the binary data.
Definition: bytestrings.c:18
cbor_item_t * cbor_new_definite_array(size_t size)
Create new definite array.
Definition: arrays.c:106
void cbor_builder_map_start_callback(void *context, size_t size)
void cbor_builder_boolean_callback(void *context, bool value)
cbor_item_t * item
Definition: stack.h:20
bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item)
Is this a ctrl value?
Definition: floats_ctrls.c:25
size_t cbor_string_length(const cbor_item_t *item)
Returns the length of the underlying string.
Definition: strings.c:106
cbor_item_t * cbor_new_indefinite_map()
Create a new indefinite map.
Definition: maps.c:46
void cbor_builder_uint16_callback(void *context, uint16_t value)
bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair)
Add a pair to the map.
Definition: maps.c:118
The item handle.
Definition: data.h:149
cbor_item_t * cbor_build_bytestring(cbor_data handle, size_t length)
Creates a new byte string and initializes it.
Definition: bytestrings.c:63
void cbor_builder_byte_string_start_callback(void *context)
1 - negative integers
Definition: data.h:26
struct cbor_pair * cbor_map_handle(const cbor_item_t *item)
Get the pairs storage.
Definition: maps.c:137
cbor_item_t * cbor_new_definite_map(size_t size)
Create a new definite map.
Definition: maps.c:23
cbor_item_t * cbor_array_get(const cbor_item_t *item, size_t index)
Get item by index.
Definition: arrays.c:25
void cbor_builder_indef_map_start_callback(void *context)
size_t cbor_bytestring_length(const cbor_item_t *item)
Returns the length of the binary data.
Definition: bytestrings.c:12
Memory error - item allocation failed.
Definition: data.h:41
size_t read
Number of bytes read.
Definition: data.h:188
Buffer manipulation problem.
Definition: data.h:196
struct _cbor_stack_record * top
Definition: stack.h:26
struct cbor_decoder_result cbor_stream_decode(cbor_data source, size_t source_size, const struct cbor_callbacks *callbacks, void *context)
Stateless decoder.
Definition: streaming.c:26
cbor_item_t ** cbor_array_handle(const cbor_item_t *item)
Get the array contents.
Definition: arrays.c:100
5 - maps
Definition: data.h:30
Single float.
Definition: data.h:57
bool cbor_string_is_indefinite(const cbor_item_t *item)
Is the string indefinite?
Definition: strings.c:130
bool creation_failed
Callback creating the last item has failed.