libcbor 0.12.0
libcbor is a C library for parsing and generating CBOR, the general-purpose schema-less binary data format.
Loading...
Searching...
No Matches
maps.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
3 *
4 * libcbor is free software; you can redistribute it and/or modify
5 * it under the terms of the MIT license. See LICENSE for details.
6 */
7
8#include "maps.h"
10
11size_t cbor_map_size(const cbor_item_t* item) {
13 return item->metadata.map_metadata.end_ptr;
14}
15
16size_t cbor_map_allocated(const cbor_item_t* item) {
18 return item->metadata.map_metadata.allocated;
19}
20
22 cbor_item_t* item = _cbor_malloc(sizeof(cbor_item_t));
23 _CBOR_NOTNULL(item);
24
25 *item = (cbor_item_t){
26 .refcount = 1,
27 .type = CBOR_TYPE_MAP,
28 .metadata = {.map_metadata = {.allocated = size,
30 .end_ptr = 0}},
31 .data = _cbor_alloc_multiple(sizeof(struct cbor_pair), size)};
32 _CBOR_DEPENDENT_NOTNULL(item, item->data);
33
34 return item;
35}
36
38 cbor_item_t* item = _cbor_malloc(sizeof(cbor_item_t));
39 _CBOR_NOTNULL(item);
40
41 *item = (cbor_item_t){
42 .refcount = 1,
43 .type = CBOR_TYPE_MAP,
44 .metadata = {.map_metadata = {.allocated = 0,
46 .end_ptr = 0}},
47 .data = NULL};
48
49 return item;
50}
51
54 struct _cbor_map_metadata* metadata =
55 (struct _cbor_map_metadata*)&item->metadata;
56 if (cbor_map_is_definite(item)) {
57 struct cbor_pair* data = cbor_map_handle(item);
58 if (metadata->end_ptr >= metadata->allocated) {
59 /* Don't realloc definite preallocated map */
60 return false;
61 }
62
63 data[metadata->end_ptr].key = key;
64 data[metadata->end_ptr++].value = NULL;
65 } else {
66 if (metadata->end_ptr >= metadata->allocated) {
67 /* Exponential realloc */
68 // Check for overflows first
69 if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) {
70 return false;
71 }
72
73 size_t new_allocation = metadata->allocated == 0
74 ? 1
75 : CBOR_BUFFER_GROWTH * metadata->allocated;
76
77 unsigned char* new_data = _cbor_realloc_multiple(
78 item->data, sizeof(struct cbor_pair), new_allocation);
79
80 if (new_data == NULL) {
81 return false;
82 }
83
84 item->data = new_data;
85 metadata->allocated = new_allocation;
86 }
87 struct cbor_pair* data = cbor_map_handle(item);
88 data[metadata->end_ptr].key = key;
89 data[metadata->end_ptr++].value = NULL;
90 }
92 return true;
93}
94
98 cbor_map_handle(item)[
99 /* Move one back since we are assuming _add_key (which increased the ptr)
100 * was the previous operation on this object */
101 item->metadata.map_metadata.end_ptr - 1]
102 .value = value;
103 return true;
104}
105
106// TODO: Add a more convenient API like add(item, key, val)
107bool cbor_map_add(cbor_item_t* item, struct cbor_pair pair) {
109 if (!_cbor_map_add_key(item, pair.key)) return false;
110 return _cbor_map_add_value(item, pair.value);
111}
112
117
119 return !cbor_map_is_definite(item);
120}
121
124 return (struct cbor_pair*)item->data;
125}
_cbor_malloc_t _cbor_malloc
Definition allocators.c:10
cbor_item_t * cbor_incref(cbor_item_t *item)
Increases the item's reference count by one.
Definition common.c:78
bool cbor_isa_map(const cbor_item_t *item)
Does the item have the appropriate major type?
Definition common.c:42
#define _CBOR_DEPENDENT_NOTNULL(cbor_item, pointer)
Definition common.h:119
#define _CBOR_NOTNULL(cbor_item)
Definition common.h:111
#define CBOR_ASSERT(e)
Definition common.h:73
@ CBOR_TYPE_MAP
5 - maps
Definition data.h:35
@ _CBOR_METADATA_DEFINITE
Definition data.h:78
@ _CBOR_METADATA_INDEFINITE
Definition data.h:79
bool cbor_map_is_definite(const cbor_item_t *item)
Is this map definite?
Definition maps.c:113
struct cbor_pair * cbor_map_handle(const cbor_item_t *item)
Get the pairs storage.
Definition maps.c:122
size_t cbor_map_size(const cbor_item_t *item)
Get the number of pairs.
Definition maps.c:11
size_t cbor_map_allocated(const cbor_item_t *item)
Get the size of the allocated storage.
Definition maps.c:16
bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key)
Add a key to the map.
Definition maps.c:52
cbor_item_t * cbor_new_indefinite_map(void)
Create a new indefinite map.
Definition maps.c:37
bool cbor_map_is_indefinite(const cbor_item_t *item)
Is this map indefinite?
Definition maps.c:118
bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value)
Add a value to the map.
Definition maps.c:95
cbor_item_t * cbor_new_definite_map(size_t size)
Create a new definite map.
Definition maps.c:21
bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair)
Add a pair to the map.
Definition maps.c:107
void * _cbor_realloc_multiple(void *pointer, size_t item_size, size_t item_count)
Overflow-proof contiguous array reallocation.
void * _cbor_alloc_multiple(size_t item_size, size_t item_count)
Overflow-proof contiguous array allocation.
bool _cbor_safe_to_multiply(size_t a, size_t b)
Can a and b be multiplied without overflowing size_t?
Maps specific metadata.
Definition data.h:123
size_t end_ptr
Definition data.h:125
size_t allocated
Definition data.h:124
_cbor_dst_metadata type
Definition data.h:126
The item handle.
Definition data.h:171
unsigned char * data
Raw data block - interpretation depends on metadata.
Definition data.h:179
union cbor_item_metadata metadata
Discriminated by type.
Definition data.h:173
Simple pair of items for use in maps.
Definition data.h:201
cbor_item_t * value
Definition data.h:202
cbor_item_t * key
Definition data.h:202
struct _cbor_map_metadata map_metadata
Definition data.h:165