Parsing CBOR streams

Group of functions used to parse CBOR streams. More...

## Data Structures

struct | CborValue
| This type contains one value parsed from the CBOR stream. More...

## Functions

CborError | cbor_parser_init (const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it)
| Initializes the CBOR parser for parsing size bytes beginning at buffer.
CborError | cbor_value_validate_basic (const CborValue *it)
| Performs a basic validation of the CBOR stream pointed by it and returns the error it found.
CborError | cbor_value_advance_fixed (CborValue *it)
| Advances the CBOR value it by one fixed-size position.
CborError | cbor_value_advance (CborValue *it)
| Advances the CBOR value it by one element, skipping over containers.
CborError | cbor_value_skip_tag (CborValue *it)
| Advances the CBOR value it until it no longer points to a tag.
CborError | cbor_value_enter_container (const CborValue *it, CborValue *recursed)
| Creates a CborValue iterator pointing to the first element of the container represented by it and saves it in recursed.
CborError | cbor_value_leave_container (CborValue *it, const CborValue *recursed)
| Updates it to point to the next element after the container.
CborError | cbor_value_get_int64_checked (const CborValue *value, int64_t *result)
| Retrieves the CBOR integer value that value points to and stores it in result.
CborError | cbor_value_get_int_checked (const CborValue *value, int *result)
| Retrieves the CBOR integer value that value points to and stores it in result.
CborError | cbor_value_calculate_string_length (const CborValue *value, size_t *len)
| Calculates the length of the byte or text string that value points to and stores it in len.
CborError | cbor_value_text_string_equals (const CborValue *value, const char *string, bool *result)
| Compares the entry value with the string string and stores the result in result.
CborError | cbor_value_map_find_value (const CborValue *map, const char *string, CborValue *element)
| Attempts to find the value in map map that corresponds to the text string entry string.
CborError | cbor_value_validate (const CborValue *it, uint32_t flags)
| Performs a full validation, controlled by the flags options, of the CBOR stream pointed by it and returns the error it found.

## Detailed Description

Group of functions used to parse CBOR streams.

TinyCBOR provides functions for pull-based stream parsing of a CBOR-encoded payload. The main data type for the parsing is a CborValue, which behaves like an iterator and can be used to extract the encoded data. It is first initialized with a call to cbor_parser_init() and is usually used to extract exactly one item, most often an array or map.

Nested CborValue objects can be parsed using cbor_value_enter_container(). Each call to cbor_value_enter_container() must be matched by a call to cbor_value_leave_container(), with the exact same parameters.

The example below initializes a CborParser object, begins the parsing with a CborValue and decodes a single integer:

int extract_int(const uint8_t *buffer, size_t len)
{
CborParser parser;
CborValue value;
int result;
cbor_parser_init(buffer, len, 0, &parser, &value);
cbor_value_get_int(&value, &result);
return result;
}
cbor_parser_init
CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it)
Initializes the CBOR parser for parsing size bytes beginning at buffer.
Definition cborparser.c:346
CborValue
This type contains one value parsed from the CBOR stream.
Definition cbor.h:337

The code above does no error checking, which means it assumes the data comes from a source trusted to send one properly-encoded integer. The following example does the exact same operation, but includes error checking and returns 0 on parsing failure:

int extract_int(const uint8_t *buffer, size_t len)
{
CborParser parser;
CborValue value;
int result;
if (cbor_parser_init(buffer, len, 0, &parser, &value) != CborNoError)
return 0;
if (!cbor_value_is_integer(&value) ||
cbor_value_get_int(&value, &result) != CborNoError)
return 0;
return result;
}

Note, in the example above, that one can't distinguish a parsing failure from an encoded value of zero. Reporting a parsing error is left as an exercise to the reader.

The code above does not execute a range-check either: it is possible that the value decoded from the CBOR stream encodes a number larger than what can be represented in a variable of type ``{int}. If detecting that case is important, the code should call cbor_value_get_int_checked() instead.

### Memory and parsing constraints

TinyCBOR is designed to run with little memory and with minimal overhead. Except where otherwise noted, the parser functions always run on constant time (O(1)), do not recurse and never allocate memory (thus, stack usage is bounded and is O(1)).

### Error handling and preconditions

All functions operating on a CborValue return a CborError condition, with CborNoError standing for the normal situation in which no parsing error occurred. All functions may return parsing errors in case the stream cannot be decoded properly, be it due to corrupted data or due to reaching the end of the input buffer.

Error conditions must not be ignored. All decoder functions have undefined behavior if called after an error has been reported, and may crash.

Some functions are also documented to have preconditions, like cbor_value_get_int() requiring that the input be an integral value. Violation of preconditions also results in undefined behavior and the program may crash.

## Function Documentation

## cbor_parser_init()

CborError cbor_parser_init | ( | const uint8_t * | buffer,
|  | size_t | size,
|  | uint32_t | flags,
|  | CborParser * | parser,
|  | CborValue * | it
| ) |  |

Initializes the CBOR parser for parsing size bytes beginning at buffer.

Parsing will use flags set in flags. The iterator to the first element is returned in it.

The parser structure needs to remain valid throughout the decoding process. It is not thread-safe to share one CborParser among multiple threads iterating at the same time, but the object can be copied so multiple threads can iterate.

## cbor_value_advance()

CborError cbor_value_advance | ( | CborValue * | it | ) |

Advances the CBOR value it by one element, skipping over containers.

Unlike cbor_value_advance_fixed(), this function can be called on a CBOR value of any type. However, if the type is a container (map or array) or a string with a chunked payload, this function will not run in constant time and will recurse into itself (it will run on O(n) time for the number of elements or chunks and will use O(n) memory for the number of nested containers).

The number of recursions can be limited at compile time to avoid stack exhaustion in constrained systems.

See also
  cbor_value_at_end(), cbor_value_advance_fixed(), cbor_value_enter_container(), cbor_value_leave_container()

Referenced by cbor_value_map_find_value(), and cbor_value_validate_basic().

## cbor_value_advance_fixed()

CborError cbor_value_advance_fixed | ( | CborValue * | it | ) |

Advances the CBOR value it by one fixed-size position.

Fixed-size types are: integers, tags, simple types (including boolean, null and undefined values) and floating point types.

If the type is not of fixed size, this function has undefined behavior. Code must be sure that the current type is one of the fixed-size types before calling this function. This function is provided because it can guarantee that it runs in constant time (O(1)).

If the caller is not able to determine whether the type is fixed or not, code can use the cbor_value_advance() function instead.

See also
  cbor_value_at_end(), cbor_value_advance(), cbor_value_enter_container(), cbor_value_leave_container()

Referenced by cbor_value_skip_tag().

## cbor_value_calculate_string_length()

CborError cbor_value_calculate_string_length | ( | const CborValue * | value,
|  | size_t * | len
| ) |  |

Calculates the length of the byte or text string that value points to and stores it in len.

If the iterator value does not point to a text string or a byte string, the behaviour is undefined, so checking with cbor_value_get_type, with cbor_value_is_text_string or cbor_value_is_byte_string is recommended.

This function is different from cbor_value_get_string_length() in that it calculates the length even for strings sent in chunks. For that reason, this function may not run in constant time (it will run in O(n) time on the number of chunks). It does use constant memory (O(1)).

Note
  On 32-bit platforms, this function will return error condition of CborErrorDataTooLarge if the stream indicates a length that is too big to fit in 32-bit.

See also
  cbor_value_get_string_length(), cbor_value_copy_text_string(), cbor_value_copy_byte_string(), cbor_value_is_length_known()

## cbor_value_enter_container()

CborError cbor_value_enter_container | ( | const CborValue * | it,
|  | CborValue * | recursed
| ) |  |

Creates a CborValue iterator pointing to the first element of the container represented by it and saves it in recursed.

The it container object needs to be kept and passed again to cbor_value_leave_container() in order to continue iterating past this container.

The it CborValue iterator must point to a container.

See also
  cbor_value_is_container(), cbor_value_leave_container(), cbor_value_advance()

Referenced by cbor_value_map_find_value().

## cbor_value_get_int64_checked()

CborError cbor_value_get_int64_checked | ( | const CborValue * | value,
|  | int64_t * | result
| ) |  |

Retrieves the CBOR integer value that value points to and stores it in result.

If the iterator value does not point to an integer value, the behavior is undefined, so checking with cbor_value_get_type or with cbor_value_is_integer is recommended.

Unlike cbor_value_get_int64(), this function performs a check to see if the stored integer fits in result without data loss. If the number is outside the valid range for the data type, this function returns the recoverable error CborErrorDataTooLarge. In that case, use either cbor_value_get_uint64() (if the number is positive) or cbor_value_get_raw_integer().

See also
  cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64()

## cbor_value_get_int_checked()

CborError cbor_value_get_int_checked | ( | const CborValue * | value,
|  | int * | result
| ) |  |

Retrieves the CBOR integer value that value points to and stores it in result.

If the iterator value does not point to an integer value, the behavior is undefined, so checking with cbor_value_get_type or with cbor_value_is_integer is recommended.

Unlike cbor_value_get_int(), this function performs a check to see if the stored integer fits in result without data loss. If the number is outside the valid range for the data type, this function returns the recoverable error CborErrorDataTooLarge. In that case, use one of the other integer functions to obtain the value.

See also
  cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64(), cbor_value_get_uint64(), cbor_value_get_int64_checked(), cbor_value_get_raw_integer()

## cbor_value_leave_container()

CborError cbor_value_leave_container | ( | CborValue * | it,
|  | const CborValue * | recursed
| ) |  |

Updates it to point to the next element after the container.

The recursed object needs to point to the element obtained either by advancing the last element of the container (via cbor_value_advance(), cbor_value_advance_fixed(), a nested cbor_value_leave_container(), or the `next` pointer from cbor_value_copy_string() or cbor_value_dup_string()).

The it and recursed parameters must be the exact same as passed to cbor_value_enter_container().

See also
  cbor_value_enter_container(), cbor_value_at_end()

## cbor_value_map_find_value()

CborError cbor_value_map_find_value | ( | const CborValue * | map,
|  | const char * | string,
|  | CborValue * | element
| ) |  |

Attempts to find the value in map map that corresponds to the text string entry string.

If the iterator value does not point to a CBOR map, the behaviour is undefined, so checking with cbor_value_get_type or cbor_value_is_map is recommended.

If the item is found, it is stored in result. If no item is found matching the key, then result will contain an element of type CborInvalidType. Matching is performed using cbor_value_text_string_equals(), so tagged strings will also match.

This function has a time complexity of O(n) where n is the number of elements in the map to be searched. In addition, this function is has O(n) memory requirement based on the number of nested containers (maps or arrays) found as elements of this map.

See also
  cbor_value_is_valid(), cbor_value_text_string_equals(), cbor_value_advance()

## cbor_value_skip_tag()

CborError cbor_value_skip_tag | ( | CborValue * | it | ) |

Advances the CBOR value it until it no longer points to a tag.

If it is already not pointing to a tag, then this function returns it unchanged.

This function does not run in constant time: it will run on O(n) for n being the number of tags. It does use constant memory (O(1) memory requirements).

See also
  cbor_value_advance_fixed(), cbor_value_advance()

Referenced by cbor_value_map_find_value(), and cbor_value_text_string_equals().

## cbor_value_text_string_equals()

CborError cbor_value_text_string_equals | ( | const CborValue * | value,
|  | const char * | string,
|  | bool * | result
| ) |  |

Compares the entry value with the string string and stores the result in result.

If the value is different from string result will contain `false`.

The entry at value may be a tagged string. If value is not a string or a tagged string, the comparison result will be false.

CBOR requires text strings to be encoded in UTF-8, but this function does not validate either the strings in the stream or the string string to be matched. Moreover, comparison is done on strict codepoint comparison, without any Unicode normalization.

This function may not run in constant time (it will run in O(n) time on the number of chunks). It requires constant memory (O(1)).

See also
  cbor_value_skip_tag(), cbor_value_copy_text_string()

## cbor_value_validate()

CborError cbor_value_validate | ( | const CborValue * | it,
|  | uint32_t | flags
| ) |  |

Performs a full validation, controlled by the flags options, of the CBOR stream pointed by it and returns the error it found.

If no error was found, it returns CborNoError and the application can iterate over the items with certainty that no errors will appear during parsing.

If flags is CborValidateBasic, the result should be the same as cbor_value_validate_basic().

This function has the same timing and memory requirements as cbor_value_advance() and cbor_value_validate_basic().

See also
  CborValidationFlags, cbor_value_validate_basic(), cbor_value_advance()

## cbor_value_validate_basic()

CborError cbor_value_validate_basic | ( | const CborValue * | it | ) |

Performs a basic validation of the CBOR stream pointed by it and returns the error it found.

If no error was found, it returns CborNoError and the application can iterate over the items with certainty that no other errors will appear during parsing.

A basic validation checks for: \list

- absence of undefined additional information bytes;
- well-formedness of all numbers, lengths, and simple values;
- string contents match reported sizes;
- arrays and maps contain the number of elements they are reported to have; \endlist

For further checks, see cbor_value_validate().

This function has the same timing and memory requirements as cbor_value_advance().

See also
  cbor_value_validate(), cbor_value_advance()