A basic CBOR library for C++.
  • C++ 99%
  • CMake 1%
Find a file
TennesseeTrash 5bab196f0c
All checks were successful
laminator
Typo and version bump
2026-07-08 08:38:14 +02:00
LibCBOR Typo and version bump 2026-07-08 08:38:14 +02:00
Tests Bughunting #2 2026-07-08 08:27:23 +02:00
.gitignore Basic project structure, basic encoder implementation 2025-09-14 13:58:26 +02:00
CMakeLists.txt Typo and version bump 2026-07-08 08:38:14 +02:00
LICENSE Add LICENSE and README.md with basic documentation 2026-06-14 13:59:35 +02:00
README.md Typo and version bump 2026-07-08 08:38:14 +02:00

LibCBOR

A basic two-way CBOR implementation for C++. Mostly compatible with RFC 8949, apart from float16_t.

Usage

The preferred way of using this library is pulling it in via CMake's FetchContent.

include(FetchContent)

FetchContent_Declare(
    libcbor
    GIT_REPOSITORY https://code.3011.io/TennesseeTrash/LibCBOR.git
    GIT_TAG        v0.2.6
)

FetchContent_MakeAvailable(
    libcbor
)

Afterwards, you can just link against the LibCBOR target, and include the library in your code.

target_link_libraries(${YOUR_PROJECT}
    PRIVATE # Or PUBLIC if you want to expose the functionality to downstream targets
    LibCBOR
)

If you'd rather not use CMake, the path is a bit more difficult, but it shouldn't be too problematic. The library is written such that you just need to add the TUs in the Source directory to your build, and add Include to your include paths. Note that this may change in the future.

Make sure to use a relatively recent toolchain, the library depends on some C++23 features. Clang 19 and GCC 14 are known to work.

Documentation

For encoding data to CBOR, include <CBOR/Encoder.hpp>, and prepare a buffer. Encoding is as simple as instantiating an instance of an Encoder on top of a fixed or dynamic buffer. Most standard containers should work out of the box, but for some less common types, please include <CBOR/EncoderHooks.hpp> (currently only std::tuple).

#include <CBOR/Encoder.hpp>

int main()
{
    std::array<std::uint8_t, 1024> buffer;

    CBOR::Encoder enc(buffer);

    enc.Encode("Hello!");
}

The encoder can be extended to consume custom types via ADL-provided EncodeHook functions.

#include <CBOR/Encoder.hpp>

struct Person
{
    std::string              Name;
    std::uint64_t            PhoneNumber;
    std::vector<std::string> Hobbies;
    double                   Height;
};

void EncodeHook(CBOR::Encoder &enc, const Person &person)
{
    enc.EncodeMap(
        "name",         person.Name,
        "phone_number", person.PhoneNumber,
        "hobbies",      person.Hobbies,
        "height",       person.Height
    );
}

Once the EncodeHook is provided, the type can be encoded identically to default supported types.

std::vector<std::uint8_t> buffer;
CBOR::Encoder enc(buffer);
Person john {
    .Name        = "John Doe",
    .PhoneNumber = 123'456'789,
    .Hobbies     = { "Fishing", "Skiing", "Diving", },
    .Height      = 1.91,
};
enc.Encode(john);

After Encode is called, the buffer is filled with the appropriate value. The encoder itself keeps minimal state, so it's possible to call Encode multiple times on the same buffer. Note, however, that this produces a CBOR Sequence instead of a single CBOR item.

Decoding is different from encoding by default. The decoder (implemented in <CBOR/Decoder.hpp>) uses custom decoding types to handle maps and arrays. This requires manually calling the decoder API in a pull-parser fashion to extract the data from the encoded CBOR buffer. This allows the library to stay allocation free, while handling all the possible CBOR types (including indefinite strings). However, for basic tasks this API is cumbersome, so the decoder also provides a unified Decode<T>() function, which behaves very similarly to its Encode counterpart. By default, Decode<T>() cannot handle standard containers. To enable their support, include <CBOR/DecoderHooks.hpp>. This header includes support for std::string, std::vector, std::tuple, std::map, and std::unordered_map. Support for custom types can be added via an ADL-provided DecodeHook, similar to its encoder variant. To make writing the decoder a bit more pleasant (including decoding maps with shuffled map items), the library provides a StructHelper.

#include <CBOR/Decoder.hpp>
#include <CBOR/DecoderHooks.hpp>
#include <CBOR/Utility.hpp>

void DecodeHook(CBOR::Decoder &dec, Person &person)
{
    constexpr CBOR::StructHelper helper {
        CBOR::StructMember { "name",         &Person::Name        },
        CBOR::StructMember { "phone_number", &Person::PhoneNumber },
        CBOR::StructMember { "hobbies",      &Person::Hobbies     },
        CBOR::StructMember { "height",       &Person::Height      },
    };
    helper.Decode(dec.AsItem(), person);
}

With this hook, the Person struct can now be decoded. Note that the decoded type must be default initializable. Similar to the encoder, the decoder can be used for CBOR Sequences by simply calling the Decode<T>() function multiple times.

std::array<std::uint8_t, 1024> buffer; // Assume we have filled this buffer with an encoded Person.
CBOR::Decoder dec(buffer);
auto person = dec.Decode<Person>();

The library supports some more niche functionality, such as nested CBOR encoding via CBOR::Binary, tagged items, and printing a formatted view of an encoded buffer via CBOR::Print. For examples of this, take a look at the tests.