Type 5 – Maps
CBOR maps are the plain old associative maps similar JSON objects or Python dictionaries.
Definite maps have a fixed size which is stored in the header, whereas indefinite maps do not and are terminated by a special “break” byte instead.
Maps are explicitly created or decoded as definite or indefinite and will be encoded using the corresponding wire representation, regardless of whether the actual size is known at the time of encoding.
Note
Indefinite maps can be conveniently used with streaming decoding and encoding. Keys and values can simply be output one by one, alternating keys and values.
Warning
Any CBOR data item is a legal map key (not just strings).
Corresponding |
|
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) |
|
Storage requirements (indefinite) |
|
Examples
0xbf Start indefinite map (represents {1: 2})
0x01 Unsigned integer 1 (key)
0x02 Unsigned integer 2 (value)
0xff "Break" control token
0xa0 Map of size 0
Getting metadata
-
size_t cbor_map_size(const cbor_item_t *item)
Get the number of pairs.
- param item:
A map
- return:
The number of pairs
-
size_t cbor_map_allocated(const cbor_item_t *item)
Get the size of the allocated storage.
- param item:
A map
- return:
Allocated storage size (as the number of cbor_pair items)
-
bool cbor_map_is_definite(const cbor_item_t *item)
Is this map definite?
- param item:
A map
- return:
Is this map definite?
-
bool cbor_map_is_indefinite(const cbor_item_t *item)
Is this map indefinite?
- param item:
A map
- return:
Is this map indefinite?
Reading data
-
struct cbor_pair *cbor_map_handle(const cbor_item_t *item)
Get the pairs storage.
- param item:
A map
- return:
Array of cbor_map_size pairs. Manipulation is possible as long as references remain valid.
-
cbor_item_t *cbor_map_get(const cbor_item_t *map, const cbor_item_t *key, bool (*eq)(const cbor_item_t*, const cbor_item_t*))
Look up a value in a map by key using a caller-supplied equality function.
Scans the map linearly and returns the first value whose key compares equal to
keyundereq. Makes at most n calls toeq, where n is the number of entries (fewer if a match is found early).The equality function is intentionally parameterized. Most applications constrain their map keys to a single type (e.g., text strings or small integers), which lets them implement a cheaper, type-specific comparator instead of a fully generic one. The parameter also allows callers to plug in any desired semantics — structural equality via cbor_structurally_equal, a data-model comparator that ignores encoding width, a case-insensitive string comparator, etc. — without the library having to anticipate every use case.
// Look up a text-string key using structural equality cbor_item_t *key = cbor_build_string("alg"); cbor_item_t *value = cbor_map_get(map, key, cbor_structurally_equal); if (value != NULL) { // use value ... cbor_decref(&value); } cbor_decref(&key);
- param map:
A map item; must not be
NULL- param key:
The key to search for; must not be
NULL- param eq:
Equality predicate, called as
eq(candidate_key, key); must not beNULL- return:
The first matching value with its reference count incremented by one, or
NULLif no key matched. The caller is responsible for releasing the returned item with cbor_decref.
Note
The equality function passed to cbor_map_get() is intentionally
parameterized. Most applications constrain their map keys to a single
type (e.g., always text strings, or always small integers), so a
type-specific comparator can be both simpler and faster than a fully
generic one. The parameter also lets callers choose between structural
equality (cbor_structurally_equal()) and any data-model or
application-level semantics they need — the library does not need to
anticipate every use case.
Examples of equality functions that can be passed:
cbor_structurally_equal()— encoding-level identity; encoding width, definite/indefinite, and map entry order all count.A custom integer comparator that ignores encoding width, so that
uint8(1)anduint64(1)are treated as the same key.A text-string comparator that skips the type check, useful when the protocol guarantees that all keys are text strings.
Creating new items
-
cbor_item_t *cbor_new_definite_map(size_t size)
Create a new definite map.
- param size:
The number of slots to preallocate
- return:
Reference to the new map item. The item’s reference count is initialized to one.
- return:
NULLif memory allocation fails
-
cbor_item_t *cbor_new_indefinite_map(void)
Create a new indefinite map.
- return:
Reference to the new map item. The item’s reference count is initialized to one.
- return:
NULLif memory allocation fails
Modifying items
-
bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair)
Add a pair to the map.
For definite maps, items can only be added to the preallocated space. For indefinite maps, the storage will be expanded as needed
- param item:
A map
- param pair:
The key-value pair to add. Reference count of the cbor_pair.key and cbor_pair.value will be increased by one.
- return:
trueon success,falseif memory allocation failed (indefinite maps) or the preallocated storage is full (definite maps)