Add lttng_dynamic_buffer_append_view util
[lttng-tools.git] / src / common / dynamic-buffer.c
CommitLineData
5966417e
JG
1/*
2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18#include <common/dynamic-buffer.h>
3f4ef714 19#include <common/buffer-view.h>
5966417e
JG
20#include <common/utils.h>
21#include <assert.h>
22
df94ef0f
JG
23/*
24 * Round to (upper) power of two, val is returned if it already is a power of
25 * two.
26 */
5966417e
JG
27static
28size_t round_to_power_of_2(size_t val)
29{
30 int order;
31 size_t rounded;
32
33 order = utils_get_count_order_u64(val);
34 assert(order >= 0);
35 rounded = (1ULL << order);
36 assert(rounded >= val);
37
38 return rounded;
39}
40
c90647fe 41LTTNG_HIDDEN
5966417e
JG
42void lttng_dynamic_buffer_init(struct lttng_dynamic_buffer *buffer)
43{
44 assert(buffer);
45 memset(buffer, 0, sizeof(*buffer));
46}
47
c90647fe 48LTTNG_HIDDEN
5966417e
JG
49int lttng_dynamic_buffer_append(struct lttng_dynamic_buffer *buffer,
50 const void *buf, size_t len)
51{
52 int ret = 0;
53
54 if (!buffer || (!buf && len)) {
55 ret = -1;
56 goto end;
57 }
58
59 if (len == 0) {
60 /* Not an error, no-op. */
61 goto end;
62 }
63
63557623
JG
64 assert(buffer->_capacity >= buffer->size);
65 if (buffer->_capacity < (len + buffer->size)) {
5966417e 66 ret = lttng_dynamic_buffer_set_capacity(buffer,
63557623
JG
67 buffer->_capacity +
68 (len - (buffer->_capacity - buffer->size)));
5966417e
JG
69 if (ret) {
70 goto end;
71 }
72 }
73
74 memcpy(buffer->data + buffer->size, buf, len);
75 buffer->size += len;
76end:
77 return ret;
78}
79
c90647fe 80LTTNG_HIDDEN
5966417e
JG
81int lttng_dynamic_buffer_append_buffer(struct lttng_dynamic_buffer *dst_buffer,
82 struct lttng_dynamic_buffer *src_buffer)
83{
84 int ret;
85
86 if (!dst_buffer || !src_buffer) {
87 ret = -1;
88 goto end;
89 }
90
91 ret = lttng_dynamic_buffer_append(dst_buffer, src_buffer->data,
92 src_buffer->size);
93end:
94 return ret;
95}
96
3f4ef714
JG
97LTTNG_HIDDEN
98int lttng_dynamic_buffer_append_view(struct lttng_dynamic_buffer *buffer,
99 const struct lttng_buffer_view *src)
100{
101 int ret;
102
103 if (!buffer || !src) {
104 ret = -1;
105 goto end;
106 }
107
108 ret = lttng_dynamic_buffer_append(buffer, src->data,
109 src->size);
110end:
111 return ret;
112}
113
c90647fe 114LTTNG_HIDDEN
5966417e
JG
115int lttng_dynamic_buffer_set_size(struct lttng_dynamic_buffer *buffer,
116 size_t new_size)
117{
118 int ret = 0;
119
120 if (!buffer) {
121 goto end;
122 }
123
124 if (new_size == buffer->size) {
125 goto end;
126 }
127
63557623 128 if (new_size > buffer->_capacity) {
5966417e
JG
129 ret = lttng_dynamic_buffer_set_capacity(buffer, new_size);
130 if (ret) {
131 goto end;
132 }
1c6def05 133
6ee96b4d 134 memset(buffer->data + buffer->size, 0, new_size - buffer->size);
5966417e
JG
135 } else if (new_size > buffer->size) {
136 memset(buffer->data + buffer->size, 0, new_size - buffer->size);
137 } else {
138 /*
139 * Shrinking size. There is no need to zero-out the newly
140 * released memory as it will either be:
141 * - overwritten by lttng_dynamic_buffer_append,
142 * - expanded later, which will zero-out the memory
143 *
144 * Users of external APIs are encouraged to set the buffer's
145 * size _before_ making such calls.
146 */
147 }
148 buffer->size = new_size;
149end:
150 return ret;
151}
152
c90647fe 153LTTNG_HIDDEN
5966417e 154int lttng_dynamic_buffer_set_capacity(struct lttng_dynamic_buffer *buffer,
fc804d0f 155 size_t demanded_capacity)
5966417e
JG
156{
157 int ret = 0;
fc804d0f 158 void *new_buf;
e9347dad
JG
159 size_t new_capacity = demanded_capacity ?
160 round_to_power_of_2(demanded_capacity) : 0;
5966417e 161
fc804d0f
JG
162 if (!buffer || demanded_capacity < buffer->size) {
163 /*
164 * Shrinking a buffer's size by changing its capacity is
165 * unsupported.
166 */
5966417e
JG
167 ret = -1;
168 goto end;
169 }
170
63557623 171 if (new_capacity == buffer->_capacity) {
5966417e
JG
172 goto end;
173 }
174
fc804d0f
JG
175 /* Memory is initialized by the size increases. */
176 new_buf = realloc(buffer->data, new_capacity);
177 if (!new_buf) {
178 ret = -1;
179 goto end;
5966417e 180 }
fc804d0f 181 buffer->data = new_buf;
63557623 182 buffer->_capacity = new_capacity;
5966417e
JG
183end:
184 return ret;
185}
186
187/* Release any memory used by the dynamic buffer. */
c90647fe 188LTTNG_HIDDEN
5966417e
JG
189void lttng_dynamic_buffer_reset(struct lttng_dynamic_buffer *buffer)
190{
191 if (!buffer) {
192 return;
193 }
194 buffer->size = 0;
63557623 195 buffer->_capacity = 0;
5966417e
JG
196 free(buffer->data);
197}
201bd415
JG
198
199LTTNG_HIDDEN
200size_t lttng_dynamic_buffer_get_capacity_left(
201 struct lttng_dynamic_buffer *buffer)
202{
203 if (!buffer) {
204 return 0;
205 }
206 return buffer->_capacity - buffer->size;
207}
This page took 0.057854 seconds and 4 git commands to generate.