Force usage of assert() condition when NDEBUG is defined
[lttng-tools.git] / src / common / dynamic-buffer.c
1 /*
2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/dynamic-buffer.h>
9 #include <common/buffer-view.h>
10 #include <common/utils.h>
11
12 /*
13 * Round to (upper) power of two, val is returned if it already is a power of
14 * two.
15 */
16 static
17 size_t round_to_power_of_2(size_t val)
18 {
19 size_t rounded;
20 const int order = utils_get_count_order_u64(val);
21
22 LTTNG_ASSERT(order >= 0);
23 rounded = (1ULL << order);
24 LTTNG_ASSERT(rounded >= val);
25
26 return rounded;
27 }
28
29 LTTNG_HIDDEN
30 void lttng_dynamic_buffer_init(struct lttng_dynamic_buffer *buffer)
31 {
32 LTTNG_ASSERT(buffer);
33 memset(buffer, 0, sizeof(*buffer));
34 }
35
36 LTTNG_HIDDEN
37 int lttng_dynamic_buffer_append(struct lttng_dynamic_buffer *buffer,
38 const void *buf, size_t len)
39 {
40 int ret = 0;
41
42 if (!buffer || (!buf && len)) {
43 ret = -1;
44 goto end;
45 }
46
47 if (len == 0) {
48 /* Not an error, no-op. */
49 goto end;
50 }
51
52 LTTNG_ASSERT(buffer->_capacity >= buffer->size);
53 if (buffer->_capacity < (len + buffer->size)) {
54 ret = lttng_dynamic_buffer_set_capacity(buffer,
55 buffer->_capacity +
56 (len - (buffer->_capacity - buffer->size)));
57 if (ret) {
58 goto end;
59 }
60 }
61
62 memcpy(buffer->data + buffer->size, buf, len);
63 buffer->size += len;
64 end:
65 return ret;
66 }
67
68 LTTNG_HIDDEN
69 int lttng_dynamic_buffer_append_buffer(struct lttng_dynamic_buffer *dst_buffer,
70 const struct lttng_dynamic_buffer *src_buffer)
71 {
72 int ret;
73
74 if (!dst_buffer || !src_buffer) {
75 ret = -1;
76 goto end;
77 }
78
79 ret = lttng_dynamic_buffer_append(dst_buffer, src_buffer->data,
80 src_buffer->size);
81 end:
82 return ret;
83 }
84
85 LTTNG_HIDDEN
86 int lttng_dynamic_buffer_append_view(struct lttng_dynamic_buffer *buffer,
87 const struct lttng_buffer_view *src)
88 {
89 int ret;
90
91 if (!buffer || !src) {
92 ret = -1;
93 goto end;
94 }
95
96 ret = lttng_dynamic_buffer_append(buffer, src->data,
97 src->size);
98 end:
99 return ret;
100 }
101
102 LTTNG_HIDDEN
103 int lttng_dynamic_buffer_set_size(struct lttng_dynamic_buffer *buffer,
104 size_t new_size)
105 {
106 int ret = 0;
107
108 if (!buffer) {
109 goto end;
110 }
111
112 if (new_size == buffer->size) {
113 goto end;
114 }
115
116 if (new_size > buffer->_capacity) {
117 ret = lttng_dynamic_buffer_set_capacity(buffer, new_size);
118 if (ret) {
119 goto end;
120 }
121
122 memset(buffer->data + buffer->size, 0, new_size - buffer->size);
123 } else if (new_size > buffer->size) {
124 memset(buffer->data + buffer->size, 0, new_size - buffer->size);
125 } else {
126 /*
127 * Shrinking size. There is no need to zero-out the newly
128 * released memory as it will either be:
129 * - overwritten by lttng_dynamic_buffer_append,
130 * - expanded later, which will zero-out the memory
131 *
132 * Users of external APIs are encouraged to set the buffer's
133 * size _before_ making such calls.
134 */
135 }
136
137 buffer->size = new_size;
138 end:
139 return ret;
140 }
141
142 LTTNG_HIDDEN
143 int lttng_dynamic_buffer_set_capacity(struct lttng_dynamic_buffer *buffer,
144 size_t demanded_capacity)
145 {
146 int ret = 0;
147 void *new_buf;
148 size_t new_capacity = demanded_capacity ?
149 round_to_power_of_2(demanded_capacity) : 0;
150
151 if (!buffer || demanded_capacity < buffer->size) {
152 /*
153 * Shrinking a buffer's size by changing its capacity is
154 * unsupported.
155 */
156 ret = -1;
157 goto end;
158 }
159
160 if (new_capacity == buffer->_capacity) {
161 goto end;
162 }
163
164 /* Memory is initialized by the size increases. */
165 new_buf = realloc(buffer->data, new_capacity);
166 if (!new_buf) {
167 ret = -1;
168 goto end;
169 }
170
171 buffer->data = new_buf;
172 buffer->_capacity = new_capacity;
173 end:
174 return ret;
175 }
176
177 /* Release any memory used by the dynamic buffer. */
178 LTTNG_HIDDEN
179 void lttng_dynamic_buffer_reset(struct lttng_dynamic_buffer *buffer)
180 {
181 if (!buffer) {
182 return;
183 }
184
185 buffer->size = 0;
186 buffer->_capacity = 0;
187 free(buffer->data);
188 buffer->data = NULL;
189 }
190
191 LTTNG_HIDDEN
192 size_t lttng_dynamic_buffer_get_capacity_left(
193 struct lttng_dynamic_buffer *buffer)
194 {
195 if (!buffer) {
196 return 0;
197 }
198
199 return buffer->_capacity - buffer->size;
200 }
This page took 0.032245 seconds and 4 git commands to generate.