libcbor  0.5.0
libcbor is a C library for parsing and generating CBOR, the general-purpose schema-less binary data format.
maps.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2017 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 
11 size_t cbor_map_size(const cbor_item_t *item)
12 {
13  assert(cbor_isa_map(item));
14  return item->metadata.map_metadata.end_ptr;
15 }
16 
17 size_t cbor_map_allocated(const cbor_item_t *item)
18 {
19  assert(cbor_isa_map(item));
20  return item->metadata.map_metadata.allocated;
21 }
22 
24 {
25  cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
26  if (item == NULL) {
27  return NULL;
28  }
29  *item = (cbor_item_t) {
30  .refcount = 1,
31  .type = CBOR_TYPE_MAP,
32  .metadata = {.map_metadata = {
33  .allocated = size,
35  .end_ptr = 0
36  }},
37  .data = _cbor_alloc_multiple(sizeof(struct cbor_pair), size)
38  };
39  if (item->data == NULL) {
40  _CBOR_FREE(item);
41  return NULL;
42  }
43  return item;
44 }
45 
47 {
48  cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
49  if (item == NULL)
50  return NULL;
51  *item = (cbor_item_t) {
52  .refcount = 1,
53  .type = CBOR_TYPE_MAP,
54  .metadata = {.map_metadata = {
55  .allocated = 0,
57  .end_ptr = 0
58  }},
59  .data = NULL
60  };
61 
62  return item;
63 }
64 
65 
67 {
68  assert(cbor_isa_map(item));
69  struct _cbor_map_metadata *metadata = (struct _cbor_map_metadata *) &item->metadata;
70  if (cbor_map_is_definite(item)) {
71  struct cbor_pair *data = cbor_map_handle(item);
72  if (metadata->end_ptr >= metadata->allocated) {
73  /* Don't realloc definite preallocated map */
74  return false;
75  }
76 
77  data[metadata->end_ptr].key = key;
78  data[metadata->end_ptr++].value = NULL;
79  } else {
80  if (metadata->end_ptr >= metadata->allocated) {
81  /* Exponential realloc */
82  // Check for overflows first
83  if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) {
84  return false;
85  }
86 
87  size_t new_allocation = metadata->allocated == 0 ? 1 : CBOR_BUFFER_GROWTH * metadata->allocated;
88 
89  unsigned char * new_data = _cbor_realloc_multiple(item->data, sizeof(struct cbor_pair), new_allocation);
90 
91  if (new_data == NULL) {
92  return false;
93  }
94 
95  item->data = new_data;
96  metadata->allocated = new_allocation;
97  }
98  struct cbor_pair *data = cbor_map_handle(item);
99  data[metadata->end_ptr].key = key;
100  data[metadata->end_ptr++].value = NULL;
101  }
102  cbor_incref(key);
103  return true;
104 }
105 
107 {
108  assert(cbor_isa_map(item));
109  cbor_incref(value);
110  cbor_map_handle(item)[
111  /* Move one back since we are assuming _add_key (which increased the ptr)
112  * was the previous operation on this object */
113  item->metadata.map_metadata.end_ptr - 1
114  ].value = value;
115  return true;
116 }
117 
118 bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair)
119 {
120  assert(cbor_isa_map(item));
121  if (!_cbor_map_add_key(item, pair.key))
122  return false;
123  return _cbor_map_add_value(item, pair.value);
124 }
125 
127 {
128  assert(cbor_isa_map(item));
130 }
131 
133 {
134  return !cbor_map_is_definite(item);
135 }
136 
138 {
139  assert(cbor_isa_map(item));
140  return (struct cbor_pair *) item->data;
141 }
struct cbor_item_t cbor_item_t
The item handle.
size_t cbor_map_allocated(const cbor_item_t *item)
Get the size of the allocated storage.
Definition: maps.c:17
union cbor_item_metadata metadata
Discriminated by type.
Definition: data.h:151
struct _cbor_map_metadata map_metadata
Definition: data.h:143
void * _cbor_realloc_multiple(void *pointer, size_t item_size, size_t item_count)
Overflow-proof contiguous array reallocation.
Definition: memory_utils.c:39
cbor_item_t * value
Definition: data.h:180
size_t cbor_map_size(const cbor_item_t *item)
Get the number of pairs.
Definition: maps.c:11
cbor_item_t * key
Definition: data.h:180
bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key)
Add a key to the map.
Definition: maps.c:66
void * _cbor_alloc_multiple(size_t item_size, size_t item_count)
Overflow-proof contiguous array allocation.
Definition: memory_utils.c:30
size_t end_ptr
Definition: data.h:104
#define _CBOR_FREE
Definition: common.h:86
#define _CBOR_MALLOC
Definition: common.h:84
bool cbor_map_is_indefinite(const cbor_item_t *item)
Is this map indefinite?
Definition: maps.c:132
Simple pair of items for use in maps.
Definition: data.h:179
size_t refcount
Reference count - initialize to 0.
Definition: data.h:153
Maps specific metadata.
Definition: data.h:102
cbor_item_t * cbor_incref(cbor_item_t *item)
Increases the reference count by one.
Definition: common.c:93
_cbor_dst_metadata type
Definition: data.h:105
bool cbor_isa_map(const cbor_item_t *item)
Does the item have the appropriate major type?
Definition: common.c:43
bool cbor_map_is_definite(const cbor_item_t *item)
Is this map definite?
Definition: maps.c:126
bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value)
Add a value to the map.
Definition: maps.c:106
unsigned char * data
Raw data block - interpretation depends on metadata.
Definition: data.h:157
size_t allocated
Definition: data.h:103
cbor_item_t * cbor_new_indefinite_map()
Create a new indefinite map.
Definition: maps.c:46
bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair)
Add a pair to the map.
Definition: maps.c:118
bool _cbor_safe_to_multiply(size_t a, size_t b)
Can a and b be multiplied without overflowing size_t?
Definition: memory_utils.c:25
The item handle.
Definition: data.h:149
struct cbor_pair * cbor_map_handle(const cbor_item_t *item)
Get the pairs storage.
Definition: maps.c:137
cbor_item_t * cbor_new_definite_map(size_t size)
Create a new definite map.
Definition: maps.c:23
5 - maps
Definition: data.h:30