libcbor  0.5.0
libcbor is a C library for parsing and generating CBOR, the general-purpose schema-less binary data format.
arrays.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 <string.h>
9 #include "arrays.h"
10 #include "internal/memory_utils.h"
11 
12 size_t cbor_array_size(const cbor_item_t *item)
13 {
14  assert(cbor_isa_array(item));
15  return item->metadata.array_metadata.end_ptr;
16 }
17 
18 size_t cbor_array_allocated(const cbor_item_t * item)
19 {
20  assert(cbor_isa_array(item));
21  return item->metadata.array_metadata.allocated;
22 }
23 
24 
25 cbor_item_t * cbor_array_get(const cbor_item_t * item, size_t index)
26 {
27  return cbor_incref(((cbor_item_t **) item->data)[index]);
28 }
29 
30 bool cbor_array_set(cbor_item_t * item, size_t index, cbor_item_t * value)
31 {
32  if (index == item->metadata.array_metadata.end_ptr) {
33  return cbor_array_push(item, value);
34  } else if (index < item->metadata.array_metadata.end_ptr) {
35  return cbor_array_replace(item, index, value);
36  } else {
37  return false;
38  }
39  return true;
40 }
41 
42 bool cbor_array_replace(cbor_item_t * item, size_t index, cbor_item_t * value)
43 {
44  if (index >= item->metadata.array_metadata.end_ptr)
45  return false;
46  /* We cannot use cbor_array_get as that would increase the refcount */
47  cbor_intermediate_decref(((cbor_item_t **) item->data)[index]);
48  ((cbor_item_t **) item->data)[index] = cbor_incref(value);
49  return true;
50 }
51 
53 {
54  assert(cbor_isa_array(array));
55  struct _cbor_array_metadata *metadata = (struct _cbor_array_metadata *) &array->metadata;
56  cbor_item_t **data = (cbor_item_t **) array->data;
57  if (cbor_array_is_definite(array)) {
58  /* Do not reallocate definite arrays */
59  if (metadata->end_ptr >= metadata->allocated) {
60  return false;
61  }
62  data[metadata->end_ptr++] = pushee;
63  } else {
64  /* Exponential realloc */
65  if (metadata->end_ptr >= metadata->allocated) {
66  // Check for overflows first
67  if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) {
68  return false;
69  }
70 
71  size_t new_allocation = metadata->allocated == 0 ? 1 : CBOR_BUFFER_GROWTH * metadata->allocated;
72 
73  unsigned char * new_data = _cbor_realloc_multiple(array->data, sizeof(cbor_item_t *), new_allocation);
74  if (new_data == NULL) {
75  return false;
76  }
77 
78  array->data = new_data;
79  metadata->allocated = new_allocation;
80  }
81  ((cbor_item_t **)array->data)[metadata->end_ptr++] = pushee;
82  }
83  cbor_incref(pushee);
84  return true;
85 }
86 
87 
89 {
90  assert(cbor_isa_array(item));
92 }
93 
95 {
96  assert(cbor_isa_array(item));
98 }
99 
101 {
102  assert(cbor_isa_array(item));
103  return (cbor_item_t **) item->data;
104 }
105 
107 {
108  cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
109  if (item == NULL) {
110  return NULL;
111  }
112 
113  cbor_item_t ** data = _cbor_alloc_multiple(sizeof(cbor_item_t *), size);
114  if (data == NULL) {
115  _CBOR_FREE(item);
116  return NULL;
117  }
118 
119  for (size_t i = 0; i < size; i++)
120  data[i] = NULL;
121 
122  *item = (cbor_item_t) {
123  .refcount = 1,
124  .type = CBOR_TYPE_ARRAY,
125  .metadata = {
126  .array_metadata = {
127  .type = _CBOR_METADATA_DEFINITE,
128  .allocated = size,
129  .end_ptr = 0
130  }
131  },
132  .data = (unsigned char *)data
133  };
134 
135  return item;
136 }
137 
139 {
140  cbor_item_t *item = _CBOR_MALLOC(sizeof(cbor_item_t));
141  if (item == NULL)
142  return NULL;
143 
144  *item = (cbor_item_t) {
145  .refcount = 1,
146  .type = CBOR_TYPE_ARRAY,
147  .metadata = {
148  .array_metadata = {
150  .allocated = 0,
151  .end_ptr = 0
152  }
153  },
154  .data = NULL /* Can be safely realloc-ed */
155  };
156  return item;
157 }
struct cbor_item_t cbor_item_t
The item handle.
size_t end_ptr
Definition: data.h:97
union cbor_item_metadata metadata
Discriminated by type.
Definition: data.h:151
void cbor_intermediate_decref(cbor_item_t *item)
Decreases the reference count by one, deallocating the item if needed.
Definition: common.c:174
bool cbor_array_replace(cbor_item_t *item, size_t index, cbor_item_t *value)
Replace item at an index.
Definition: arrays.c:42
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 allocated
Definition: data.h:96
struct _cbor_array_metadata array_metadata
Definition: data.h:142
_cbor_dst_metadata type
Definition: data.h:98
4 - arrays
Definition: data.h:29
void * _cbor_alloc_multiple(size_t item_size, size_t item_count)
Overflow-proof contiguous array allocation.
Definition: memory_utils.c:30
cbor_item_t * cbor_new_indefinite_array()
Create new indefinite array.
Definition: arrays.c:138
#define _CBOR_FREE
Definition: common.h:86
#define _CBOR_MALLOC
Definition: common.h:84
bool cbor_array_set(cbor_item_t *item, size_t index, cbor_item_t *value)
Set item by index.
Definition: arrays.c:30
size_t refcount
Reference count - initialize to 0.
Definition: data.h:153
bool cbor_array_is_definite(const cbor_item_t *item)
Is the array definite?
Definition: arrays.c:88
bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee)
Append to the end.
Definition: arrays.c:52
size_t cbor_array_size(const cbor_item_t *item)
Get the number of members.
Definition: arrays.c:12
cbor_item_t * cbor_incref(cbor_item_t *item)
Increases the reference count by one.
Definition: common.c:93
Arrays specific metadata.
Definition: data.h:95
bool cbor_isa_array(const cbor_item_t *item)
Does the item have the appropriate major type?
Definition: common.c:38
cbor_item_t * cbor_new_definite_array(size_t size)
Create new definite array.
Definition: arrays.c:106
unsigned char * data
Raw data block - interpretation depends on metadata.
Definition: data.h:157
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
size_t cbor_array_allocated(const cbor_item_t *item)
Get the size of the allocated storage.
Definition: arrays.c:18
cbor_item_t * cbor_array_get(const cbor_item_t *item, size_t index)
Get item by index.
Definition: arrays.c:25
bool cbor_array_is_indefinite(const cbor_item_t *item)
Is the array indefinite?
Definition: arrays.c:94
cbor_item_t ** cbor_array_handle(const cbor_item_t *item)
Get the array contents.
Definition: arrays.c:100