CBOR
This is a minimalistic implementation for CBOR, the Concise Binary Object Representation. CBOR is defined by IETF RFC 8949, and Wikipedia has a good description.
Features
C99
No dynamic memory allocation
Small code footprint
Build
Make
CBOR_ROOT ?= <THIRD_PARTY_DIR>/cbor
include $(CBOR_ROOT)/cbor.mk
CMake
include(FetchContent)
FetchContent_Declare(cbor
GIT_REPOSITORY https://github.com/libmcu/cbor.git
GIT_TAG main
)
FetchContent_MakeAvailable(cbor)
or
set(CBOR_ROOT <THIRD_PARTY_DIR>/cbor)
include(${CBOR_ROOT}/cbor.cmake)
Usage
static void parse_cert(const cbor_reader_t *reader,
const struct cbor_parser *parser,
const cbor_item_t *item, void *arg) {
struct your_data_type *out = arg;
cbor_decode(reader, item, out->cert, sizeof(out->cert));
}
static void parse_key(const cbor_reader_t *reader,
const struct cbor_parser *parser,
const cbor_item_t *item, void *arg) {
struct your_data_type *out = arg;
cbor_decode(reader, item, out->key, sizeof(out->key));
}
static const struct cbor_parser parsers[] = {
{ .key = "certificate", .run = parse_cert },
{ .key = "privateKey", .run = parse_key },
};
cbor_reader_t reader;
cbor_item_t items[MAX_ITEMS];
cbor_reader_init(&reader, items, sizeof(items) / sizeof(*items));
cbor_unmarshal(&reader, parsers, sizeof(parsers) / sizeof(*parsers),
msg, msglen, &your_data_type);
...
Please refer to examples.
Option
CBOR_BIG_ENDIAN
Define the macro for big endian machine. The default is little endian.
CBOR_RECURSION_MAX_LEVEL
This is set to avoid stack overflow from recursion. The default maximum depth is 8.
Parser
The parser takes 626 bytes on ARM Cortex-M0 optimizing for code size -Os
.
arm-none-eabi-gcc
10-2020-q4-major
was used for the check.
Stack usage per the major type functions:
Major type |
Bytes |
---|---|
0: unsigned integer |
12 |
1: negative integer |
12 |
2: byte string |
32 |
3: text string |
32 |
4: array |
32 |
5: map |
32 |
6: tag(not implemented yet) |
0 |
7: floating-point numbers, simple values and break |
32 |
And the call stack for each recursion is 24 bytes.
cbor_reader_t reader;
cbor_item_t items[MAX_ITEMS];
size_t n;
cbor_reader_init(&reader, items, sizeof(items) / sizeof(*items));
cbor_parse(&reader, cbor_message, cbor_message_len, &n);
for (i = 0; i < n; i++) {
printf("item: %s, size: %zu\n",
cbor_stringify_item(&items[i]),
cbor_get_item_size(&items[i]);
}
Decoder
union {
int8_t i8;
int16_t i16;
int32_t i32;
int64_t i64;
float f32;
double f64;
uint8_t s[MTU];
} val;
cbor_decode(&reader, &items[i], &val, sizeof(val));
Encoder
cbor_writer_t writer;
cbor_writer_init(&reader, buf, sizeof(buf));
cbor_encode_map(&writer, 2);
/* 1st */
cbor_encode_text_string(&writer, "key");
cbor_encode_text_string(&writer, "value");
/* 2nd */
cbor_encode_text_string(&writer, "age");
cbor_encode_negative_integer(&writer, -1);
Limitation
The maximum item length is
size_t
because the interface return type issize_t
. The argument’s value in the specification can go up touint64_t
thoughA negative integer ranges down to -2^63-1 other than -2^64 in the specification
Sorting of encoded map keys is not supported
Tag item is not implemented yet
cbor_unmarshal()
only works on the major type 5: map with string key
API
Base
Functions
-
void cbor_reader_init(cbor_reader_t *reader, cbor_item_t *items, size_t maxitems)
Initialize the reader for CBOR encoded messages.
- Parameters:
reader – [inout] reader context for the actual encoded message
items – [out] a pointer to item buffers
maxitems – [in] the maximum number of items to be stored in
items
-
void cbor_writer_init(cbor_writer_t *writer, void *buf, size_t bufsize)
-
size_t cbor_writer_len(cbor_writer_t const *writer)
-
uint8_t const *cbor_writer_get_encoded(cbor_writer_t const *writer)
-
cbor_item_data_t cbor_get_item_type(cbor_item_t const *item)
-
size_t cbor_get_item_size(cbor_item_t const *item)
-
uint8_t cbor_get_following_bytes(uint8_t additional_info)
-
size_t cbor_copy(uint8_t *dst, uint8_t const *src, size_t len)
-
size_t cbor_copy_be(uint8_t *dst, uint8_t const *src, size_t len)
-
struct cbor_item_t
- #include <base.h>
Public Members
-
cbor_item_data_t type
-
size_t offset
-
size_t size
either of the length of value in bytes or the number of items in case of container type
-
cbor_item_data_t type
-
struct cbor_reader_t
- #include <base.h>
-
struct cbor_writer_t
- #include <base.h>
Enums
-
enum cbor_error_t
Values:
-
enumerator CBOR_SUCCESS
well-formed
-
enumerator CBOR_ILLEGAL
not well-formed
-
enumerator CBOR_INVALID
well-formed but invalid
-
enumerator CBOR_OVERRUN
more items than given buffer space
-
enumerator CBOR_BREAK
-
enumerator CBOR_EXCESSIVE
recursion more than CBOR_RECURSION_MAX_LEVEL
-
enumerator CBOR_SUCCESS
-
enum cbor_item_data_t
Values:
-
enumerator CBOR_ITEM_UNKNOWN
-
enumerator CBOR_ITEM_INTEGER
unsigned integer and negative integer
-
enumerator CBOR_ITEM_STRING
byte string and text string
-
enumerator CBOR_ITEM_ARRAY
-
enumerator CBOR_ITEM_MAP
-
enumerator CBOR_ITEM_FLOAT
-
enumerator CBOR_ITEM_SIMPLE_VALUE
-
enumerator CBOR_ITEM_UNKNOWN
Parser
Functions
-
cbor_error_t cbor_parse(cbor_reader_t *reader, void const *msg, size_t msgsize, size_t *nitems_parsed)
Parse the encoded CBOR messages into items.
- Parameters:
reader – [inout] reader context for the actual encoded message
msg – [in] CBOR encoded message
msgsize – [in] the
msg
size in bytesnitems_parsed – [out] the number of items parsed gets stored if not null
- Returns:
a code of cbor_error_t
Encoder
Functions
-
cbor_error_t cbor_encode_unsigned_integer(cbor_writer_t *writer, uint64_t value)
-
cbor_error_t cbor_encode_negative_integer(cbor_writer_t *writer, int64_t value)
-
cbor_error_t cbor_encode_byte_string(cbor_writer_t *writer, uint8_t const *data, size_t datasize)
-
cbor_error_t cbor_encode_byte_string_indefinite(cbor_writer_t *writer)
-
cbor_error_t cbor_encode_text_string(cbor_writer_t *writer, char const *text, size_t textsize)
-
cbor_error_t cbor_encode_null_terminated_text_string(cbor_writer_t *writer, char const *text)
-
cbor_error_t cbor_encode_text_string_indefinite(cbor_writer_t *writer)
-
cbor_error_t cbor_encode_array(cbor_writer_t *writer, size_t length)
-
cbor_error_t cbor_encode_array_indefinite(cbor_writer_t *writer)
-
cbor_error_t cbor_encode_map(cbor_writer_t *writer, size_t length)
-
cbor_error_t cbor_encode_map_indefinite(cbor_writer_t *writer)
-
cbor_error_t cbor_encode_break(cbor_writer_t *writer)
-
cbor_error_t cbor_encode_simple(cbor_writer_t *writer, uint8_t value)
-
cbor_error_t cbor_encode_bool(cbor_writer_t *writer, bool value)
-
cbor_error_t cbor_encode_null(cbor_writer_t *writer)
-
cbor_error_t cbor_encode_undefined(cbor_writer_t *writer)
-
cbor_error_t cbor_encode_float(cbor_writer_t *writer, float value)
-
cbor_error_t cbor_encode_double(cbor_writer_t *writer, double value)
Decoder
Functions
-
cbor_error_t cbor_decode(cbor_reader_t const *reader, cbor_item_t const *item, void *buf, size_t bufsize)
Decode a CBOR data item
- Parameters:
reader – [in] reader context for the actual encoded message
item – [in] meta data about the item to be decoded
buf – [out] the buffer where decoded value to be written in
bufsize – [in] the buffer size
- Returns:
a code of cbor_error_t
-
void const *cbor_decode_pointer(cbor_reader_t const *reader, cbor_item_t const *item)
Get the pointer to an item value
- Parameters:
reader – [in] reader context for the actual encoded message
item – [in] meta data about the item to be decoded
- Returns:
the pointer to the item value
IEEE754
Functions
-
uint16_t ieee754_convert_single_to_half(float value)
-
double ieee754_convert_half_to_double(uint16_t value)
-
bool ieee754_is_shrinkable_to_half(float value)
-
bool ieee754_is_shrinkable_to_single(double value)
-
union ieee754_half_t
- #include <ieee754.h>
-
union ieee754_single_t
- #include <ieee754.h>
-
union ieee754_double_t
- #include <ieee754.h>
Helper
Functions
-
bool cbor_unmarshal(cbor_reader_t *reader, const struct cbor_parser *parsers, size_t nr_parsers, const void *msg, size_t msglen, void *arg)
-
size_t cbor_iterate(const cbor_reader_t *reader, const cbor_item_t *parent, void (*callback_each)(const cbor_reader_t *reader, const cbor_item_t *item, const cbor_item_t *parent, void *arg), void *arg)
-
const char *cbor_stringify_error(cbor_error_t err)
-
const char *cbor_stringify_item(cbor_item_t *item)
-
struct cbor_parser
- #include <helper.h>
Public Members
-
const void *key
-
size_t keylen
-
void (*run)(const cbor_reader_t *reader, const struct cbor_parser *parser, const cbor_item_t *item, void *arg)
-
const void *key