libcbor man page

libcbor — libcbor Documentation

Documentation for version 0.5.0, updated on Feb 01, 2019.

Overview

libcbor is a C library for parsing and generating CBOR, the general-purpose schema-less binary data format.

Main features
  • Complete RFC conformance [1]
  • Robust C99 implementation
  • Layered architecture offers both control and convenience
  • Flexible memory management
  • No shared global state - threading friendly [2]
  • Proper handling of UTF-8
  • Full support for streams & incremental processing
  • Extensive documentation and test suite
  • No runtime dependencies, small footprint
[1]

See rfc_conformance

[2]

With the exception of custom memory allocators (see api/item_reference_counting)

Contents

Getting started

Pre-built Linux packages are distributed from the libcbor website.

OS X users can use Homebrew:

brew tap pjk/libcbor
brew install libcbor

For other platforms, you will need to compile it from source.

Building & installing libcbor

Prerequisites:
  • C99 compiler
  • CMake 2.8 or newer (might also be called cmakesetup, cmake-gui or ccmake depending on the installed version and system)
  • C build system CMake can target (make, Apple Xcode, MinGW, ...)
NOTE:

As of May 2015, not even the 2015 release candidate of Visual Studio supports C99. While CMake will be happy to generate a VS solution that you can play with, libcbor currently cannot be compiled using the MSVC toolchain. ICC, GCC under Cygwin, and MinGW's GCC will all work. The MinGW build process is described below.

Configuration options

A handful of configuration flags can be passed to cmake. The following table lists libcbor compile-time directives and several important generic flags.

OptionMeaningDefaultPossible values
CMAKE_C_COMPILERC compiler to useccgcc, clang, clang-3.5, ...
CMAKE_INSTALL_PREFIXInstallation prefixSystem-dependent/usr/local/lib, ...
HUGE_FUZZFuzz test with 8GB of dataOFFON, OFF
SANE_MALLOCAssume malloc will refuse unreasonable allocationsOFFON, OFF
COVERAGEGenerate test coverage instrumentationOFFON, OFF
WITH_TESTSBuild unit tests (see development)OFFON, OFF

The following configuration options will also be defined as macros[#]_ in <cbor/common.h> and can therefore be used in client code:

OptionMeaningDefaultPossible values
CBOR_CUSTOM_ALLOCEnable custom allocator supportOFFON, OFF
CBOR_PRETTY_PRINTERInclude a pretty-printing routineONON, OFF
CBOR_BUFFER_GROWTHFactor for buffer growth & shrinking2Decimals > 1
[1]

ON & OFF will be translated to 1 and 0 using cmakedefine.

If you want to pass other custom configuration options, please refer to http://www.cmake.org/Wiki/CMake_Useful_Variables.

Building using make

CMake will generate a Makefile and other configuration files for the build. As a rule of thumb, you should configure the build outside of the source tree in order to keep different configurations isolated. If you are unsure where to execute the build, just use a temporary directory:

cd $(mktemp -d /tmp/cbor_build.XXXX)

Now, assuming you are in the directory where you want to build, execute the following to configure the build and run make

cmake -DCMAKE_BUILD_TYPE=Release path_to_libcbor_dir
make cbor cbor_shared

Both the shared (libcbor.so) and the static (libcbor.a) libraries should now be in the src subdirectory.

In order to install the libcbor headers and libraries, the usual

make install

is what your're looking for. Root permissions are required on most systems when using the default installation prefix.

Portability

libcbor is highly portable and works on both little- and big-endian systems regardless of the operating system. After building on an exotic platform, you might wish to verify the result by running the test suite. If you encounter any problems, please report them to the issue tracker.

libcbor is known to successfully work on ARM Android devices. Cross-compilation is possible with arm-linux-gnueabi-gcc.

Linking with libcbor

If you include and linker paths include the directories to which libcbor has been installed, compiling programs that uses libcbor requires no extra considerations.

You can verify that everything has been set up properly by creating a file with the following contents

#include <cbor.h>
#include <stdio.h>

int main(int argc, char * argv[])
{
    printf("Hello from libcbor %s\n", CBOR_VERSION);
}

and compiling it

cc hello_cbor.c -lcbor -o hello_cbor

libcbor also comes with pkg-config support. If you install libcbor with a custom prefix, you can use pkg-config to resolve the headers and objects:

cc $(pkg-config --cflags libcbor) hello_cbor.c $(pkg-config --libs libcbor) -o hello_cbor

MinGW build instructions

Prerequisites:
  • MinGW
  • CMake GUI

First of all, create a folder that will be used for the output. For this demonstration, we will use cbor_out. Start CMake and select the source path and the destination folder. [image]

Then hit the 'Configure' button. You will be prompted to select the build system: [image]

Choose MinGW and confirm.

NOTE:

If you select Visual Studio at this point, a MSVC project will be generated for you. This is useful if you just want to browse through the source code.

You can then adjust the build options. The defaults will work just fine. Hit 'Generate' when you are done. [image]

You can then adjust the build options. The defaults will work just fine. Hit 'Generate' when you are done.

Open the shell, navigate to the output directory, and run mingw32-make cbor cbor_shared. [image]

libcbor will be built and your .dll should be ready at this point [image]

Feel free to also try building and running some of the examples, e.g. mingw32-make sort [image]

Troubleshooting

cbor.h not found: The headers directory is probably not in your include path. First, verify the installation location by checking the installation log. If you used make, it will look something like

...
-- Installing: /usr/local/include/cbor
-- Installing: /usr/local/include/cbor/callbacks.h
-- Installing: /usr/local/include/cbor/encoding.h
...

Make sure that CMAKE_INSTALL_PREFIX (if you provided it) was correct. Including the path path during compilation should suffice, e.g.:

cc -I/usr/local/include hello_cbor.c -lcbor -o hello_cbor

cannot find -lcbor during linking: Most likely the same problem as before. Include the installation directory in the linker shared path using -R, e.g.:

cc -Wl,-rpath,/usr/local/lib -lcbor -o hello_cbor

shared library missing during execution: Verify the linkage using ldd, otool, or similar and adjust the compilation directives accordingly:

⇒  ldd hello_cbor
    linux-vdso.so.1 =>  (0x00007ffe85585000)
    libcbor.so => /usr/local/lib/libcbor.so (0x00007f9af69da000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9af65eb000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f9af6be9000)

compilation failed: If your compiler supports C99 yet the compilation has failed, please report the issue to the issue tracker.

Usage & preliminaries

Version information

libcbor exports its version using three self-explanatory macros:

  • CBOR_MAJOR_VERSION
  • CBOR_MINOR_VERSION
  • CBOR_PATCH_VERSION

The CBOR_VERSION is a string concatenating these three identifiers into one (e.g. 0.2.0).

In order to simplify version comparisons, the version is also exported as

#define CBOR_HEX_VERSION ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION)

Since macros are difficult to work with through FFIs, the same information is also available through three uint8_t constants, namely

  • cbor_major_version
  • cbor_minor_version
  • cbor_patch_version

Headers to include

The cbor.h header includes all the symbols. If, for any reason, you don't want to include all the exported symbols, feel free to use just some of the cbor/*.h headers:

  • cbor/arrays.h - api/type_4
  • cbor/bytestrings.h - api/type_2
  • cbor/callbacks.h - Callbacks used for streaming/decoding
  • cbor/common.h - Common utilities - always transitively included
  • cbor/data.h - Data types definitions - always transitively included
  • cbor/encoding.h - Streaming encoders for streaming/encoding
  • cbor/floats_ctrls.h - api/type_7
  • cbor/ints.h - api/type_0_1
  • cbor/maps.h - api/type_5
  • cbor/serialization.h - High level serialization such as cbor_serialize()
  • cbor/streaming.h - Home of cbor_stream_decode()
  • cbor/strings.h - api/type_3
  • cbor/tags.h - api/type_6

Using libcbor

If you want to get more familiar with CBOR, we recommend the cbor.io website. Once you get the grasp of what is it CBOR does, the examples (located in the examples directory) should give you a good feel of the API. The API documentation should then provide with all the information you may need.

Creating and serializing items

#include "cbor.h"
#include <stdio.h>

int main(int argc, char * argv[])
{
    /* Preallocate the map structure */
    cbor_item_t * root = cbor_new_definite_map(2);
    /* Add the content */
    cbor_map_add(root, (struct cbor_pair) {
        .key = cbor_move(cbor_build_string("Is CBOR awesome?")),
        .value = cbor_move(cbor_build_bool(true))
    });
    cbor_map_add(root, (struct cbor_pair) {
        .key = cbor_move(cbor_build_uint8(42)),
        .value = cbor_move(cbor_build_string("Is the answer"))
    });
    /* Output: `length` bytes of data in the `buffer` */
    unsigned char * buffer;
    size_t buffer_size, length = cbor_serialize_alloc(root, &buffer, &buffer_size);

    fwrite(buffer, 1, length, stdout);
    free(buffer);

    fflush(stdout);
    cbor_decref(&root);
}

Reading serialized data

#include "cbor.h"
#include <stdio.h>

/*
 * Reads data from a file. Example usage:
 * $ ./examples/readfile examples/data/nested_array.cbor
 */

int main(int argc, char * argv[])
{
    FILE * f = fopen(argv[1], "rb");
    fseek(f, 0, SEEK_END);
    size_t length = (size_t)ftell(f);
    fseek(f, 0, SEEK_SET);
    unsigned char * buffer = malloc(length);
    fread(buffer, length, 1, f);

    /* Assuming `buffer` contains `info.st_size` bytes of input data */
    struct cbor_load_result result;
    cbor_item_t * item = cbor_load(buffer, length, &result);
    /* Pretty-print the result */
    cbor_describe(item, stdout);
    fflush(stdout);
    /* Deallocate the result */
    cbor_decref(&item);

    fclose(f);
}

Using the streaming parser

#include "cbor.h"
#include <stdio.h>
#include <string.h>

/*
 * Illustrates how one might skim through a map (which is assumed to have
 * string keys and values only), looking for the value of a specific key
 *
 * Use the examples/data/map.cbor input to test this.
 */

const char * key = "a secret key";
bool key_found = false;

void find_string(void * _ctx, cbor_data buffer, size_t len)
{
    if (key_found) {
        printf("Found the value: %*s\n", (int) len, buffer);
        key_found = false;
    } else if (len == strlen(key)) {
        key_found = (memcmp(key, buffer, len) == 0);
    }
}

int main(int argc, char * argv[])
{
    FILE * f = fopen(argv[1], "rb");
    fseek(f, 0, SEEK_END);
    size_t length = (size_t)ftell(f);
    fseek(f, 0, SEEK_SET);
    unsigned char * buffer = malloc(length);
    fread(buffer, length, 1, f);

    struct cbor_callbacks callbacks = cbor_empty_callbacks;
    struct cbor_decoder_result decode_result;
    size_t bytes_read = 0;
    callbacks.string = find_string;
    while (bytes_read < length) {
        decode_result = cbor_stream_decode(buffer + bytes_read,
                                           length - bytes_read,
                                           &callbacks, NULL);
        bytes_read += decode_result.read;
    }

    fclose(f);
}

API

The data API is centered around cbor_item_t, a generic handle for any CBOR item. There are functions to

  • create items,
  • set items' data,
  • parse serialized data into items,
  • manage, move, and links item together.

The single most important thing to keep in mind is: cbor_item_t is an opaque type and should only be manipulated using the appropriate functions! Think of it as an object.

The libcbor API closely follows the semantics outlined by CBOR standard. This part of the documentation provides a short overview of the CBOR constructs, as well as a general introduction to the libcbor API. Remaining reference can be found in the following files structured by data types.

The API is designed to allow both very tight control & flexibility and general convenience with sane defaults. [1] For example, client with very specific requirements (constrained environment, custom application protocol built on top of CBOR, etc.) may choose to take full control (and responsibility) of memory and data structures management by interacting directly with the decoder. Other clients might want to take control of specific aspects (streamed collections, hash maps storage), but leave other responsibilities to libcbor. More general clients might prefer to be abstracted away from all aforementioned details and only be presented complete data structures.

libcbor provides
  • stateless encoders and decoders
  • encoding and decoding drivers, routines that coordinate encoding and decoding of complex structures
  • data structures to represent and transform CBOR structures
  • routines for building and manipulating these structures
  • utilities for inspection and debugging

Types of items

Every cbor_item_t has a cbor_type associated with it - these constants correspond to the types specified by the CBOR standard:

WARNING:

doxygenenum: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

To find out the type of an item, one can use

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Please note the distinction between functions like cbor_isa_uint() and cbor_is_int(). The following functions work solely with the major type value.

Binary queries

Alternatively, there are functions to query each particular type.

WARNING:

Passing an invalid cbor_item_t reference to any of these functions results in undefined behavior.

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Logical queries

These functions provide information about the item type from a more high-level perspective

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Memory management and reference counting

Due to the nature of its domain libcbor will need to work with heap memory. The stateless decoder and encoder don't allocate any memory.

If you have specific requirements, you should consider rolling your own driver for the stateless API.

Using custom allocator

libcbor gives you with the ability to provide your own implementations of malloc, realloc, and free. This can be useful if you are using a custom allocator throughout your application, or if you want to implement custom policies (e.g. tighter restrictions on the amount of allocated memory).

In order to use this feature, libcbor has to be compiled with the appropriate flags. You can verify the configuration using the CBOR_CUSTOM_ALLOC macro. A simple usage might be as follows:

#if CBOR_CUSTOM_ALLOC
    cbor_set_allocs(malloc, realloc, free);
#else
   #error "libcbor built with support for custom allocation is required"
#endif
WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Reference counting

As CBOR items may require complex cleanups at the end of their lifetime, there is a reference counting mechanism in place. This also enables very simple GC when integrating libcbor into managed environment. Every item starts its life (by either explicit creation, or as a result of parsing) with reference count set to 1. When the refcount reaches zero, it will be destroyed.

Items containing nested items will be destroyed recursively - refcount of every nested item will be decreased by one.

The destruction is synchronous and renders any pointers to items with refcount zero invalid immediately after calling the cbor_decref().

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Decoding

The following diagram illustrates the relationship among different parts of libcbor from the decoding standpoint.

┌──────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                              │
│                                      Client application                                      │
│                                                                                              │
│                                                 ┌────────────────────────────────────────────┘
│                                                 │                     ↕
│                                                 │ ┌──────────────────────────────────────────┐
│                                                 │ │                                          │
│                                                 │ │          Manipulation routines           │
│                                                 │ │                                          │
│           ┌─────────────────────────────────────┘ └──────────────────────────────────────────┘
│           │     ↑    ↑                  ↑                              ↑
│           │     │    │    ┌─────────────╫──────────┬───────────────────┴─┐
│           │     │   CDS   │             ║          │                     │
│           │     │    │   PDS            ║         PDS                   PDS
│           │     ↓    ↓    ↓             ↓          ↓                     ↓
│           │ ┌─────────────────┐   ┌────────────────────┐   ┌────────────────────────────┐
│           │ │                 │   │                    │   │                            │
│           │ │  Custom driver  │ ↔ │  Streaming driver  │ ↔ │       Default driver       │ ↔ CD
│           │ │                 │   │                    │   │                            │
└───────────┘ └─────────────────┘   └────────────────────┘   └────────────────────────────┘
      ↕                ↕                        ↕                           ↕
┌──────────────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                              │
│                            Stateless event─driven decoder                                    │
│                                                                                              │
└──────────────────────────────────────────────────────────────────────────────────────────────┘

              (PSD = Provided Data Structures, CDS = Custom Data Structures)

This section will deal with the API that is labeled as the "Default driver" in the diagram. That is, routines that decode complete libcbor data items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Associated data structures

WARNING:

doxygenenum: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenstruct: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenstruct: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Encoding

The easiest way to encode data items is using the cbor_serialize() or cbor_serialize_alloc() functions:

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Type-specific serializers

In case you know the type of the item you want to serialize beforehand, you can use one of the type-specific serializers.

NOTE:

Unless compiled in debug mode, these do not verify the type. Passing an incorrect item will result in an undefined behavior.

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Types 0 & 1 – Positive and negative integers

CBOR has two types of integers – positive (which may be effectively regarded as unsigned), and negative. There are four possible widths for an integer – 1, 2, 4, or 8 bytes. These are represented by

WARNING:

doxygenenum: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Type 0 - positive integers

Corresponding cbor_typeCBOR_TYPE_UINT
Number of allocationsOne per lifetime
Storage requirementssizeof(cbor_item_t) + sizeof(uint*_t)

Note: once a positive integer has been created, its width cannot be changed.

Type 1 - negative integers

Corresponding cbor_typeCBOR_TYPE_NEGINT
Number of allocationsOne per lifetime
Storage requirementssizeof(cbor_item_t) + sizeof(uint*_t)

Note: once a positive integer has been created, its width cannot be changed.

Type 0 & 1

Due to their largely similar semantics, the following functions can be used for both Type 0 and Type 1 items. One can convert between them freely using the conversion functions.

Actual Type of the integer can be checked using item types API.

An integer item is created with one of the four widths. Because integers' storage is bundled together with the handle, the width cannot be changed over its lifetime.

WARNING:

Due to the fact that CBOR negative integers represent integers in the range [-1, -2^N], cbor_set_uint API is somewhat counter-intuitive as the resulting logical value is 1 less. This behavior is necessary in order to permit uniform manipulation with the full range of permitted values. For example, the following snippet

cbor_item_t * item = cbor_new_int8();
cbor_mark_negint(item);
cbor_set_uint8(0);

will produce an item with the logical value of -1. There is, however, an upside to this as well: There is only one representation of zero.

Building new items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Retrieving values

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Setting values

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Dealing with width

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Dealing with signedness

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Creating new items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Type 2 – Byte strings

CBOR byte strings are just (ordered) series of bytes without further interpretation (unless there is a tag). Byte string's length may or may not be known during encoding. These two kinds of byte strings can be distinguished using cbor_bytestring_is_definite() and cbor_bytestring_is_indefinite() respectively.

In case a byte string is indefinite, it is encoded as a series of definite byte strings. These are called "chunks". For example, the encoded item

0xf5            Start indefinite byte string
    0x41        Byte string (1B long)
        0x00
    0x41        Byte string (1B long)
        0xff
    0xff        "Break" control token

represents two bytes, 0x00 and 0xff. This on one hand enables streaming messages even before they are fully generated, but on the other hand it adds more complexity to the client code.

Corresponding cbor_typeCBOR_TYPE_BYTESTRING
Number of allocations (definite)One plus any manipulations with the data
Number of allocations (indefinite)One plus logarithmically many reallocations relative  to chunk count
Storage requirements (definite)sizeof(cbor_item_t) + length(handle)
Storage requirements (indefinite)sizeof(cbor_item_t) * (1 + chunk_count) + chunks

Streaming indefinite byte strings

Please refer to /streaming.

Getting metadata

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Reading data

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Creating new items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Building items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Manipulating existing items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Type 3 – UTF-8 strings

CBOR strings work in much the same ways as type_2.

Corresponding cbor_typeCBOR_TYPE_STRING
Number of allocations (definite)One plus any manipulations with the data
Number of allocations (indefinite)One plus logarithmically many reallocations relative  to chunk count
Storage requirements (definite)sizeof(cbor_item_t) + length(handle)
Storage requirements (indefinite)sizeof(cbor_item_t) * (1 + chunk_count) + chunks

Streaming indefinite strings

Please refer to /streaming.

UTF-8 encoding validation

libcbor considers UTF-8 encoding validity to be a part of the well-formedness notion of CBOR and therefore invalid UTF-8 strings will be rejected by the parser. Strings created by the user are not checked.

Getting metadata

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Reading data

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Creating new items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Building items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Manipulating existing items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Type 4 – Arrays

CBOR arrays, just like byte strings and strings, can be encoded either as definite, or as indefinite.

Corresponding cbor_typeCBOR_TYPE_ARRAY
Number of allocations (definite)Two plus any manipulations with the data
Number of allocations (indefinite)Two plus logarithmically many reallocations relative to additions
Storage requirements (definite)(sizeof(cbor_item_t) + 1) * size
Storage requirements (indefinite)<= sizeof(cbor_item_t) + sizeof(cbor_item_t) * size * BUFFER_GROWTH

Examples

0x9f        Start indefinite array
    0x01        Unsigned integer 1
    0xff        "Break" control token
0x9f        Start array, 1B length follows
0x20        Unsigned integer 32
    ...        32 items follow

Streaming indefinite arrays

Please refer to /streaming.

Getting metadata

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Reading data

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Creating new items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Modifying items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Type 5 – Maps

CBOR maps are the plain old associate hash maps known from JSON and many other formats and languages, with one exception: any CBOR data item can be a key, not just strings. This is somewhat unusual and you, as an application developer, should keep that in mind.

Maps can be either definite or indefinite, in much the same way as type_4.

Corresponding cbor_typeCBOR_TYPE_MAP
Number of allocations (definite)Two plus any manipulations with the data
Number of allocations (indefinite)Two plus logarithmically many reallocations relative to additions
Storage requirements (definite)sizeof(cbor_pair) * size + sizeof(cbor_item_t)
Storage requirements (indefinite)<= sizeof(cbor_item_t) + sizeof(cbor_pair) * size * BUFFER_GROWTH

Streaming maps

Please refer to /streaming.

Getting metadata

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Reading data

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Creating new items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Modifying items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Type 6 – Semantic tags

Tag are additional metadata that can be used to extend or specialize the meaning or interpretation of the other data items.

For example, one might tag an array of numbers to communicate that it should be interpreted as a vector.

Please consult the official IANA repository of CBOR tags before inventing new ones.

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Type 7 – Floats & control tokens

This type combines two completely unrelated types of items -- floating point numbers and special values such as true, false, null, etc. We refer to these special values as 'control values' or 'ctrls' for short throughout the code.

Just like integers, they have different possible width (resulting in different value ranges and precisions).

WARNING:

doxygenenum: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Corresponding cbor_typeCBOR_TYPE_FLOAT_CTRL
Number of allocationsOne per lifetime
Storage requirementssizeof(cbor_item_t) + 1/4/8

Getting metadata

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Reading data

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Creating new items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Building items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Manipulating existing items

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Half floats

CBOR supports two bytes wide ("half-precision") floats which are not supported by the C language. libcbor represents them using float values throughout the API, which has important implications when manipulating these values.

In particular, if a user uses some of the manipulation APIs (e.g. cbor_set_float2(), cbor_new_float2()) to introduce a value that doesn't have an exect half-float representation, the encoding semantics are given by cbor_encode_half() as follows:

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

[1]

http://softwareengineering.vazexqi.com/files/pattern.html

Streaming & indefinite items

CBOR strings, byte strings, arrays, and maps can be encoded as indefinite, meaning their length or size is not specified. Instead, they are divided into chunks (strings, byte strings), or explicitly terminated (arrays, maps).

This is one of the most important (and due to poor implementations, underutilized) features of CBOR. It enables low-overhead streaming just about anywhere without dealing with channels or pub/sub mechanism. It is, however, important to recognize that CBOR streaming is not a substitute for  Websockets [1] and similar technologies.

[1]

RFC 6455

Decoding

Another way to decode data using libcbor is to specify a callbacks that will be invoked when upon finding certain items in the input. This service is provided by

WARNING:

doxygenfunction: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

To get started, you might want to have a look at the simple streaming example:

#include "cbor.h"
#include <stdio.h>
#include <string.h>

/*
 * Illustrates how one might skim through a map (which is assumed to have
 * string keys and values only), looking for the value of a specific key
 *
 * Use the examples/data/map.cbor input to test this.
 */

const char * key = "a secret key";
bool key_found = false;

void find_string(void * _ctx, cbor_data buffer, size_t len)
{
    if (key_found) {
        printf("Found the value: %*s\n", (int) len, buffer);
        key_found = false;
    } else if (len == strlen(key)) {
        key_found = (memcmp(key, buffer, len) == 0);
    }
}

int main(int argc, char * argv[])
{
    FILE * f = fopen(argv[1], "rb");
    fseek(f, 0, SEEK_END);
    size_t length = (size_t)ftell(f);
    fseek(f, 0, SEEK_SET);
    unsigned char * buffer = malloc(length);
    fread(buffer, length, 1, f);

    struct cbor_callbacks callbacks = cbor_empty_callbacks;
    struct cbor_decoder_result decode_result;
    size_t bytes_read = 0;
    callbacks.string = find_string;
    while (bytes_read < length) {
        decode_result = cbor_stream_decode(buffer + bytes_read,
                                           length - bytes_read,
                                           &callbacks, NULL);
        bytes_read += decode_result.read;
    }

    free(buffer);
    fclose(f);
}

The callbacks are defined by

WARNING:

doxygenstruct: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

When building custom sets of callbacks, feel free to start from

WARNING:

doxygenvariable: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Callback types definition

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

WARNING:

doxygentypedef: Cannot find file: /builddir/build/BUILD/libcbor-0.5.0/doc/build/doxygen/xml/index.xml

Encoding

TODO

Tests

Unit tests

There is a comprehensive test suite employing CMocka. You can run all of them using ctest in the build directory. Individual tests are themselves runnable. Please refer to CTest documentation for detailed information on how to specify particular subset of tests.

Testing for memory leaks

Every release is tested for memory correctness. You can run these tests by passing the -T memcheck flag to ctest. [1]

[1]

Project should be configured with -DCMAKE_BUILD_TYPE=Debug to obtain meaningful description of location of the leak. You might also need --dsymutil=yes on OS X.

Code coverage

Every release is inspected using GCOV/LCOV. Platform-independent code should be fully covered by the test suite. Simply run

make coverage

or alternatively run lcov by hand using

lcov --capture --directory . --output-file coverage.info
genhtml coverage.info --output-directory out

Fuzz testing

Every release is tested using a fuzz test. In this test, a huge buffer filled with random data is passed to the decoder. We require that it either succeeds or fail with a sensible error, without leaking any memory. This is intended to simulate real-world situations where data received from the network are CBOR-decoded before any further processing.

RFC conformance

libcbor is, generally speaking, very faithful implementation of RFC 7049. There are, however, some limitations imposed by technical constraints.

Bytestring length

There is no explicit limitation of indefinite length byte strings. [1] libcbor will not handle byte strings with more chunks than the maximum value of size_t. On any sane platform, such string would not fit in the memory anyway. It is, however, possible to process arbitrarily long strings and byte strings using the streaming decoder.

[1]

http://tools.ietf.org/html/rfc7049#section-2.2.2

Half-precision IEEE 754 floats

As of C99 and even C11, there is no standard implementation for 2 bytes floats. libcbor packs them as a float. When encoding, libcbor selects the appropriate wire representation based on metadata and the actual value. This applies both to canonical and normal mode.

For more information on half-float serialization, please refer to the section on api_type_7_hard_floats.

Internal mechanics

Internal workings of libcbor are mostly derived from the specification. The purpose of this document is to describe technical choices made during design & implementation and to explicate the reasoning behind those choices.

Terminology

MTBMajor Type Bytehttp://tools.ietf.org/html/rfc7049#section-2.1
DSTDynamically Sized TypeType whose storage requirements cannot be determined

during compilation (originated in the Rust community)

Conventions

API symbols start with cbor_ or CBOR_ prefix, internal symbols have _cbor_ or _CBOR_ prefix.

General notes on the API design

The API design has two main driving priciples:

  1. Let the client manage the memory as much as possible
  2. Behave exactly as specified by the standard

Combining these two principles in practice turns out to be quite difficult. Indefinite-length strings, arrays, and maps require client to handle every fixed-size chunk explicitly in order to

  • ensure the client never runs out of memory due to libcbor
  • use realloc() sparsely and predictably [1]

    • provide strong guarantees about its usage (to prevent latency spikes)
    • provide APIs to avoid realloc() altogether
  • allow proper handling of (streamed) data bigger than available memory
[1]

Reasonable handling of DSTs requires reallocation if the API is to remain sane.

Coding style

This code loosely follows the Linux kernel coding style. Tabs are tabs, and they are 4 characters wide.

Memory layout

CBOR is very dynamic in the sense that it contains many data elements of variable length, sometimes even indefinite length. This section describes internal representation of all CBOR data types.

Generally speaking, data items consist of three parts:

  • a generic handle,
  • the associated metadata,
  • and the actual data
type cbor_item_t

Represents the item. Used as an opaque type

cbor_type type

Type discriminator

size_t refcount

Reference counter. Used by cbor_decref(), cbor_incref()

union cbor_item_metadata metadata

Union discriminated by cbor_item_t.type. Contains type-specific metadata

unsigned char *data

Contains pointer to the actual data. Small, fixed size items (api/type_0_1, api/type_6, api/type_7) are allocated as a single memory block.

Consider the following snippet

cbor_item_t * item = cbor_new_int8();

then the memory is laid out as follows

+-----------+---------------+---------------+-----------------------------------++-----------+
|           |               |               |                                   ||           |
|   type    |   refcount    |   metadata    |              data                 ||  uint8_t  |
|           |               |               |   (= item + sizeof(cbor_item_t))  ||           |
+-----------+---------------+---------------+-----------------------------------++-----------+
^                                                                                ^
|                                                                                |
+--- item                                                                        +--- item->data

Dynamically sized types (api/type_2, api/type_3, api/type_4, api/type_5) may store handle and data in separate locations. This enables creating large items (e.g byte strings) without realloc() or copying large blocks of memory. One simply attaches the correct pointer to the handle.

union cbor_item_metadata
struct _cbor_int_metadata int_metadata;

Used both by both api/type_0_1

struct _cbor_bytestring_metadata bytestring_metadata;

struct _cbor_string_metadata string_metadata;

struct _cbor_array_metadata array_metadata;

struct _cbor_map_metadata map_metadata;

struct _cbor_tag_metadata tag_metadata;

struct _cbor_float_ctrl_metadata float_ctrl_metadata;

Decoding

As outlined in api, there decoding is based on the streaming decoder Essentially, the decoder is a custom set of callbacks for the streaming decoder.

Changelog

Next

0.5.0 (2017-02-06)

  • Remove cmocka from the subtree (always rely on system or user-provided version)
  • Windows CI
  • Only build tests if explicitly enabled (-DWITH_TESTS=ON)
  • Fixed static header declarations (by cedric-d)
  • Improved documentation (by Michael Richardson)
  • Improved examples/readfile.c
  • Reworked (re)allocation to handle huge inputs and overflows in size_t [#16]
  • Improvements to C++ linkage (corrected cbor_empty_callbacks, fixed restrict pointers) (by Dennis Bijwaard)
  • Fixed Linux installation directory depending on architecture [#34] (by jvymazal)
  • Improved 32-bit support [#35]
  • Fixed MSVC compatibility [#31]
  • Fixed and improved half-float encoding [#5] [#11]

0.4.0 (2015-12-25)

Breaks build & header compatibility due to:

  • Improved build configuration and feature check macros
  • Endianess configuration fixes (by Erwin Kroon and David Grigsby)
  • pkg-config compatibility (by Vincent Bernat)
  • enable use of versioned SONAME (by Vincent Bernat)
  • better fuzzer (wasn't random until now, ooops)

0.3.1 (2015-05-21)

  • documentation and comments improvements, mostly for the API reference

0.3.0 (2015-05-21)

  • Fixes, polishing, niceties across the code base
  • Updated examples
  • cbor_copy
  • cbor_build_negint8, 16, 32, 64, matching asserts
  • cbor_build_stringn
  • cbor_build_tag
  • cbor_build_float2, ...

0.2.1 (2015-05-17)

  • C99 support

0.2.0 (2015-05-17)

  • cbor_ctrl_bool -> cbor_ctrl_is_bool
  • Added cbor_array_allocated & map equivalent
  • Overhauled endianess conversion - ARM now works as expected
  • 'sort.c' example added
  • Significantly improved and doxyfied documentation

0.1.0 (2015-05-06)

The initial release, yay!

Development

Development dependencies

  • CMocka (testing)
  • Python and pip (Sphinx platform)
  • Doxygen
  • Sphinx (documentation)
  • There are some Ruby scripts in misc
  • Valgrind (memory correctness & profiling)
  • GCOV/LCOV (test coverage)

Installing sphinx

pip install sphinx
pip install sphinx_rtd_theme
pip install breathe
pip install https://github.com/lepture/python-livereload/archive/master.zip
pip install sphinx-autobuild

Further instructions on configuring advanced features can be found at http://read-the-docs.readthedocs.org/en/latest/install.html.

Live preview of docs

cd doc
make livehtml

Set up git hooks

A git hook that automatically refereshes the GH pages contents located in docs can be symlinked:

ln -s misc/hooks/pre-commit .git/hooks

Testing and code coverage

Please refer to tests

Author

Pavel Kalvoda

Info

Feb 01, 2019 0.5