{"id":42050760,"url":"https://github.com/rimio/libecbor","last_synced_at":"2026-01-26T06:35:45.656Z","repository":{"id":29779701,"uuid":"122758585","full_name":"rimio/libecbor","owner":"rimio","description":"CBOR library with no dependencies, small memory footprint and code size, developed for both desktop and embedded applications.","archived":false,"fork":false,"pushed_at":"2025-05-21T18:52:35.000Z","size":98,"stargazers_count":9,"open_issues_count":10,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-21T19:51:30.108Z","etag":null,"topics":["cbor","cbor-library","embedded"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rimio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-02-24T16:39:29.000Z","updated_at":"2025-05-21T18:52:41.000Z","dependencies_parsed_at":"2025-05-21T19:41:29.541Z","dependency_job_id":"de4ce842-1f4b-4834-a877-3998d5a49f7c","html_url":"https://github.com/rimio/libecbor","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/rimio/libecbor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimio%2Flibecbor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimio%2Flibecbor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimio%2Flibecbor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimio%2Flibecbor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rimio","download_url":"https://codeload.github.com/rimio/libecbor/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rimio%2Flibecbor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28768466,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T03:54:34.369Z","status":"ssl_error","status_checked_at":"2026-01-26T03:54:33.031Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cbor","cbor-library","embedded"],"created_at":"2026-01-26T06:35:45.107Z","updated_at":"2026-01-26T06:35:45.649Z","avatar_url":"https://github.com/rimio.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# libecbor\n\nCBOR library with no dependencies, small memory footprint and code size, developed for both desktop and embedded applications.\n\n## Compiling\n\nCompiling the library:\n\n```\ncmake .\nmake\n```\n\nThis will generate the following files:\n* `lib/libecbor.so` - dynamic linking version\n* `lib/libecbor.a` - static linking version\n* `include/ecbor.h` - header file for library\n* `ecbor-describe` - describe tool, loads CBOR contents from file and displays them\n\n## Testing\n\nFunctional tests can be run with:\n\n```\ncd test/\n./runtests.sh\n```\n\nUnit tests depend on `gtest` and must be explicitly built:\n\n```\ncmake . -DTESTING=ON\n```\n\nThey can be run either via CMake:\n\n```\nctest\n```\n\nor by directly running the unit tests executable, which provides more verbose output:\n\n```\n./bin/unittest\n```\n\n## Installation\n\nInstalling can be performed with:\n\n```\ncmake . -DCMAKE_INSTALL_PREFIX=\u003cinstall_prefix\u003e\nmake\nmake install\n```\n\nIf `\u003cinstall_prefix\u003e` is omitted, then the default install path is used (usually `/usr/local`).\n\n## Guide\n\n### Memory usage\n\n`libecbor` guarantees that no memory other than the buffers provided by the caller is used; it has no dependency on any memory manager or standard library, other than the standard type definitions. While this can be sometimes cumbersome, it is a desired trait for memory-constrained devices.\n\nMoreover, both encoding and decoding have an *absolute upper bound* on stack usage, regardless of the depth or size of the CBOR object. Actual numbers depend on the compiler and flags.\n\n### Error handling\n\nMost `libecbor` API calls return an error code. It is a good practice to check it consistently, especially when building for embedded targets where debugging may be more difficult.\n\nUsually you would look for a return code of `ECBOR_OK`. The full error list can be found in the header file `include/ecbor.h` under the `ecbor_error_t` enum.\n\n### Encoder\n\nEach encoding operation must use an encode context (`ecbor_encode_context_t`), usually defined on the stack:\n\n```c\necbor_encode_context_t context;\n```\n\nThe encoder must be initialized either in *normal* encoding mode\n\n```c\nuint8_t buffer[BUFFER_SIZE];\necbor_error_t rc = ecbor_initialize_encode(\u0026context, buffer, BUFFER_SIZE);\n```\n\nor in *streamed* mode\n\n```c\nuint8_t buffer[BUFFER_SIZE];\necbor_error_t rc = ecbor_initialize_encode_streamed(\u0026context, buffer, BUFFER_SIZE);\n```\n\nWhile in *normal* mode the user can encode a whole item tree at once (including children), it lacks support for encoding indefinite strings, maps and arrays, since it is assumed the item is pre-built and the size is already known.\n\nIf support for indefinite items is mandatory then the *streamed* mode can be used, but the user must encode the children manually. Please be attentive that the desired CBOR structure is followed in this case.\n\n`buffer` is simply an output buffer of size `BUFFER_SIZE` where the encoder will place the resulting CBOR object.\n\nOnce the context has been initialized, items can be encoded with\n\n```c\necbor_error_t rc = ecbor_encode (\u0026context, \u0026item);\n```\n\nwhere `item` is of type `ecbor_item_t`. If the item is too large for the context output buffer, then `ECBOR_ERR_INVALID_END_OF_BUFFER` will be returned.\n\nSimple items can be built by using one of the following APIs:\n\n```c\necbor_item_t item = ecbor_int (uint_value);\necbor_item_t item = ecbor_uint (int_value);\n\necbor_item_t item = ecbor_fp32 (float_value);\necbor_item_t item = ecbor_fp64 (double_value);\n\necbor_item_t item = ecbor_bool (bool_or_int_value);\n\necbor_item_t item = ecbor_bstr (bin_buffer_ptr, BIN_BUFFER_SIZE);\necbor_item_t item = ecbor_str (c_str_ptr, strlen(c_str_ptr));\necbor_item_t item = ecbor_tag (\u0026child_item, tag_int_value);\n\necbor_item_t item = ecbor_null ();\necbor_item_t item = ecbor_undefined ();\n```\n\nArrays can be created with\n\n```c\necbor_error_t rc = ecbor_array (\u0026arr, array_items, item_count);\n```\n\nwhere `arr` is the output `ecbor_item_t`, `array_items` is a `ecbor_item_t*` pointing to the children and `item_count` is the size of `array_items`.\n\nMaps can be created with\n\n```c\necbor_error_t rc = ecbor_map (\u0026map, keys, values, keyval_count);\n```\n\nwhere `map` is the output `ecbor_item_t`, `keys` and `values` are `ecbor_item_t*`, and `keyval_count` is the size of `keys` and `values`. Note that the *i*-th key-value pair is composed of `keys[i]` and `values[i]`.\n\nIf using *streamed* encoding mode, then only the placeholder (token) items must be built:\n\n```c\necbor_item_t item = ecbor_array_token (item_count);\necbor_item_t item = ecbor_indefinite_array_token ();\n\necbor_item_t item = ecbor_map_token (keyval_count);\necbor_item_t item = ecbor_indefinite_map_token ();\n\necbor_item_t item = ecbor_stop_code ();\n```\n\nbut the user must subsequently encode the correct amount of child items (for definite-size arrays and maps) or the stop code (for indefinite arrays and maps).\n\nOnce all the items have been encoded, the length of the output buffer can be obtained either by calling \n```c\nsize_t sz;\necbor_error_t rc = ecbor_get_encoded_buffer_size(\u0026context, \u0026sz);\n```\n\nor by using the `ECBOR_GET_ENCODED_BUFFER_SIZE` macro.\n\n### Decoder\n\nJust like encoding, the decoding operation must use a decode context (`ecbor_decode_context_t`), usually defined on the stack:\n\n```c\necbor_decode_context_t context;\n```\n\nThe decoder must be initialized either in *normal* decoding mode\n\n```c\necbor_error_t rc = ecbor_initialize_decode (\u0026context, buffer, buffer_size);\n```\n\nin *streamed* mode\n\n```c\necbor_error_t rc = ecbor_initialize_decode_streamed (\u0026context, buffer, buffer_size);\n```\n\nor in *tree* mode\n\n```c\necbor_item_t item_buffer[MAX_ITEMS];\necbor_error_t rc = ecbor_initialize_decode_streamed (\u0026context, buffer, buffer_size, item_buffer, MAX_ITEMS);\n```\n\nwhere `buffer` is the input `uint8_t*` buffer of size `buffer_size`, and `item_buffer` is an output item buffer.\n\nIn *streamed* mode, any decoding API call will parse and retrieve *one* item from the buffer, without children, in the order specified in the buffer. This is a *dumb* but fast mode where absolutely no semantic checking is performed. Linking parents to children is left to the user, hence this mode is recommended only for very simple scenarios.\n\nIn *normal* mode, any decoding API call will parse one *whole* item, including it's children, but will *not* store the parsed children. Children can later be retrieved with special API calls, but each of them will trigger a re-parsing of part of the subtree. This mode only uses one instance of *ecbor_item_t*, and has no limit on the size of the parsed CBOR, but may be heavy on CPU usage since no parsing results are cached.\n\nIn *tree* mode, any decoding API call will parse one *whole* item, including its children, and all parsing results are cached in `item_buffer`. User must make sure this buffer is sufficiently large to store all items. Subsequent API calls to retrieve children will simply explore the parsed tree.\n\n**IMPORTANT:** String items will *not* copy the payload from the original CBOR buffer. Moreover, in *normal* mode children are being re-parsed from the CBOR buffer as well. Do *not* destroy this buffer until *all* manipulation on the CBOR items has been finished.\n\nIn *normal* and *streamed* mode, one item can be decoded with\n\n```c\necbor_item_t item;\necbor_error_t rc = ecbor_decode (\u0026context, \u0026item);\n```\n\nwhile in *tree* mode, the root item can be decoded with\n\n```c\necbor_item_t *root = NULL;\necbor_error_t rc = ecbor_decode_tree (\u0026context, \u0026root);\n```\n\nAfter the call, `root` will point to the root item from the `item_buffer`.\n\nFor item manipulation there are two alternative APIs that can be used.\n\n### Decoder - strict API\n\nTo retrieve the type of an item:\n\n```c\necbor_type_t type = ecbor_get_type (\u0026item);\n```\n\nTo retrieve the values of numerics and booleans:\n\n```c\nuint8_t val;\necbor_error_t rc = ecbor_get_uint8 (item, \u0026val);\n\nuint16_t val;\necbor_error_t rc = ecbor_get_uint16 (item, \u0026val);\n\nuint32_t val;\necbor_error_t rc = ecbor_get_uint32 (item, \u0026val);\n\nuint64_t val;\necbor_error_t rc = ecbor_get_uint64 (item, \u0026val);\n\n\nint8_t val;\necbor_error_t rc = ecbor_get_int8 (item, \u0026val);\n\nint16_t val;\necbor_error_t rc = ecbor_get_int16 (item, \u0026val);\n\nint32_t val;\necbor_error_t rc = ecbor_get_int32 (item, \u0026val);\n\nint64_t val;\necbor_error_t rc = ecbor_get_int64 (item, \u0026val);\n\n\nfloat val;\necbor_error_t rc = ecbor_get_fp32 (item, \u0026val);\n\ndouble val;\necbor_error_t rc = ecbor_get_fp64 (item, \u0026val);\n\n\nuint8_t val;\necbor_error_t rc = ecbor_get_bool (item, \u0026val);\n```\n\nTo retrieve the *tag value* of a tag item:\n\n```c\nuint64_t tag_val;\necbor_error_t rc = ecbor_get_tag_value (\u0026tag_item, \u0026tag_val);\n```\n\nTo retrieve the length of a binary string, string, array or map:\n\n```c\nsize_t length = 0;\necbor_error_t rc = ecbor_get_length (\u0026item, \u0026length);\n```\n\nTo retrieve a child of a tag, array or map:\n\n```c\necbor_item_t arr_item;\necbor_error_t rc = ecbor_get_array_item (\u0026array, index, \u0026arr_item);\n\necbor_item_t *arr_item_ptr = NULL;\necbor_error_t rc = ecbor_get_array_item_ptr (\u0026array, index, \u0026arr_item_ptr);\n\n\necbor_item_t key, val;\necbor_error_t rc = ecbor_get_map_item (\u0026map, index, \u0026key, \u0026val);\n\necbor_item_t *key_ptr = NULL, *val_ptr = NULL;\necbor_error_t rc = ecbor_get_map_item_ptr (\u0026map, index, \u0026key_ptr, \u0026val_ptr);\n\n\necbor_item_t item;\necbor_error_t rc = ecbor_get_tag_item (\u0026tag, \u0026item);\n\necbor_item_t *item_ptr = NULL;\necbor_error_t rc = ecbor_get_tag_item_ptr (\u0026tag, \u0026item_ptr);\n```\n\n**IMPORTANT:** Note that the `*_ptr` versions of the APIs work only in *tree* mode.\n\nTo retrieve the payload of definite strings and binary strings:\n\n```c\nconst char *c_str = NULL;\necbor_error_t rc = ecbor_get_str (\u0026str_item, \u0026c_str);\n\nconst uint8_t *buffer = NULL;\necbor_error_t rc = ecbor_get_bstr (\u0026bstr_item, \u0026buffer);\n```\n\nFor *indefinite* strings and binary strings, each chunk must be parsed individually (a chunk is a child item of the same type, but with *definite* length):\n\n```c\nsize_t chunk_count;\necbor_error_t rc = ecbor_get_str_chunk_count (\u0026str_item, \u0026chunk_count);\n\necbor_item_t chunk;\necbor_error_t rc = ecbor_get_str_chunk (\u0026str_item, index, \u0026chunk);\n\n\nsize_t chunk_count;\necbor_error_t rc = ecbor_get_bstr_chunk_count (\u0026bstr_item, \u0026chunk_count);\n\necbor_item_t chunk;\necbor_error_t rc = ecbor_get_bstr_chunk (\u0026bstr_item, index, \u0026chunk);\n```\n\n### Decoder - fast API\n\nThe following macros help to identify the type of the item:\n\n```c\necbor_item_t item;\n\necbor_type_t type = ECBOR_GET_TYPE(\u0026item)\n\nECBOR_IS_INDEFINITE(\u0026item)\nECBOR_IS_DEFINITE(\u0026item)\n\nECBOR_IS_NINT(\u0026item)\nECBOR_IS_UINT(\u0026item)\nECBOR_IS_INTEGER(\u0026item)\nECBOR_IS_BSTR(\u0026item)\nECBOR_IS_STR(\u0026item)\nECBOR_IS_ARRAY(\u0026item)\nECBOR_IS_MAP(\u0026item)\nECBOR_IS_TAG(\u0026item)\nECBOR_IS_FP32(\u0026item)\nECBOR_IS_FLOAT(\u0026item)\nECBOR_IS_FP64(\u0026item)\nECBOR_IS_DOUBLE(\u0026item)\nECBOR_IS_BOOL(\u0026item)\nECBOR_IS_NULL(\u0026item)\nECBOR_IS_UNDEFINED(\u0026item)\n```\n\nIn order to retrieve the value:\n\n```c\necbor_item_t item;\n\nint64_t val = ECBOR_GET_INT(\u0026item)\nuint64_t val = ECBOR_GET_UINT(\u0026item)\n\nconst char *c_str = ECBOR_GET_STRING(\u0026item)\n\nfloat val = ECBOR_GET_FP32(\u0026item)\ndoube val = ECBOR_GET_FP64(\u0026item)\n\nuint8_t bool_value = ECBOR_GET_BOOL(\u0026item)\n\nuint64_t tag_value = ECBOR_GET_TAG_VALUE(\u0026item)\necbor_item_t tag_item = ECBOR_GET_TAG_ITEM(\u0026item)\n```\n\nAnd finally, in order to retrieve the length of arrays, maps, strings:\n\n```c\necbor_item_t item;\nsize_t len = ECBOR_GET_LENGTH(\u0026item)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frimio%2Flibecbor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frimio%2Flibecbor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frimio%2Flibecbor/lists"}