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).

enum cbor_float_width

Possible widths of CBOR_TYPE_FLOAT_CTRL items.

Values:

CBOR_FLOAT_0

Internal use - ctrl and special values.

CBOR_FLOAT_16

Half float.

CBOR_FLOAT_32

Single float.

CBOR_FLOAT_64

Double.

Corresponding cbor_type

CBOR_TYPE_FLOAT_CTRL

Number of allocations

One per lifetime

Storage requirements

sizeof(cbor_item_t) + 1/4/8

Getting metadata

bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item)

Is this a ctrl value?

Return

Is this a ctrl value?

Parameters
  • item[borrow]: A float or ctrl item

cbor_float_width cbor_float_get_width(const cbor_item_t *item)

Get the float width.

Return

The width.

Parameters
  • item[borrow]: A float or ctrl item

bool cbor_ctrl_is_bool(const cbor_item_t *item)

Is this ctrl item a boolean?

Return

Is this ctrl item a boolean?

Parameters
  • item[borrow]: A ctrl item

Reading data

float cbor_float_get_float2(const cbor_item_t *item)

Get a half precision float.

The item must have the corresponding width

Parameters

float cbor_float_get_float4(const cbor_item_t *item)

Get a single precision float.

The item must have the corresponding width

Parameters

double cbor_float_get_float8(const cbor_item_t *item)

Get a double precision float.

The item must have the corresponding width

Parameters

double cbor_float_get_float(const cbor_item_t *item)

Get the float value represented as double.

Can be used regardless of the width.

Parameters

uint8_t cbor_ctrl_value(const cbor_item_t *item)

Reads the control value.

Return

the simple value

Parameters
  • item[borrow]: A ctrl item

Creating new items

cbor_item_t *cbor_new_ctrl()

Constructs a new ctrl item.

The width cannot be changed once the item is created

Return

new 1B ctrl or NULL upon memory allocation failure

cbor_item_t *cbor_new_float2()

Constructs a new float item.

The width cannot be changed once the item is created

Return

new 2B float or NULL upon memory allocation failure

cbor_item_t *cbor_new_float4()

Constructs a new float item.

The width cannot be changed once the item is created

Return

new 4B float or NULL upon memory allocation failure

cbor_item_t *cbor_new_float8()

Constructs a new float item.

The width cannot be changed once the item is created

Return

new 8B float or NULL upon memory allocation failure

cbor_item_t *cbor_new_null()

Constructs new null ctrl item.

Return

new null ctrl item or NULL upon memory allocation failure

cbor_item_t *cbor_new_undef()

Constructs new undef ctrl item.

Return

new undef ctrl item or NULL upon memory allocation failure

Building items

cbor_item_t *cbor_build_bool(bool value)

Constructs new boolean ctrl item.

Return

new boolen ctrl item or NULL upon memory allocation failure

Parameters
  • value: The value to use

cbor_item_t *cbor_build_ctrl(uint8_t value)

Constructs a ctrl item.

Return

new ctrl item or NULL upon memory allocation failure

Parameters
  • value: the value to use

cbor_item_t *cbor_build_float2(float value)

Constructs a new float.

Return

new float

Parameters
  • value: the value to use

cbor_item_t *cbor_build_float4(float value)

Constructs a new float.

Return

new float or NULL upon memory allocation failure

Parameters
  • value: the value to use

cbor_item_t *cbor_build_float8(double value)

Constructs a new float.

Return

new float or NULL upon memory allocation failure

Parameters
  • value: the value to use

Manipulating existing items

void cbor_set_ctrl(cbor_item_t *item, uint8_t value)

Assign a control value.

Warning

It is possible to produce an invalid CBOR value by assigning a

invalid value using this mechanism. Please consult the standard before use.

Parameters
  • item[borrow]: A ctrl item

  • value: The simple value to assign. Please consult the standard for allowed values

void cbor_set_float2(cbor_item_t *item, float value)

Assigns a float value.

Parameters
  • item[borrow]: A half precision float

  • value: The value to assign

void cbor_set_float4(cbor_item_t *item, float value)

Assigns a float value.

Parameters
  • item[borrow]: A single precision float

  • value: The value to assign

void cbor_set_float8(cbor_item_t *item, double value)

Assigns a float value.

Parameters
  • item[borrow]: A double precision float

  • value: The value to assign

Half floats

CBOR supports two bytes wide (“half-precision”) floats which are not supported by the C language. libcbor represents them using float <https://en.cppreference.com/w/c/language/type> 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:

size_t cbor_encode_half(float, unsigned char *, size_t)

Encodes a half-precision float.

Since there is no native representation or semantics for half floats in the language, we use single-precision floats, as every value that can be expressed as a half-float can also be expressed as a float.

This however means that not all floats passed to this function can be unambiguously encoded. The behavior is as follows:

  • Infinity, NaN are preserved

  • Zero is preserved

  • Denormalized numbers keep their sign bit and 10 most significant bit of the significand

  • All other numbers

    • If the logical value of the exponent is < -24, the output is zero

    • If the logical value of the exponent is between -23 and -14, the output is cut off to represent the ‘magnitude’ of the input, by which we mean (-1)^{signbit} x 1.0e{exponent}. The value in the significand is lost.

    • In all other cases, the sign bit, the exponent, and 10 most significant bits of the significand are kept

Return

number of bytes written

Parameters
  • value:

  • buffer: Target buffer

  • buffer_size: Available space in the buffer