aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2020-01-15 11:45:20 +0100
committerFlorian Dold <florian.dold@gmail.com>2020-01-15 11:45:20 +0100
commit9f3f1753e8bd2b43a611e8f465dee2c770c998f5 (patch)
treedd0f4ebc44e5cf9a0f5c373be8752e86e944d103
parent55d610bb34afb2c2c8503a4949941855bbf7aeb9 (diff)
downloadgnunet-9f3f1753e8bd2b43a611e8f465dee2c770c998f5.tar.gz
gnunet-9f3f1753e8bd2b43a611e8f465dee2c770c998f5.zip
move buffer library from GNU Taler to GNUnet
-rw-r--r--src/include/Makefile.am4
-rw-r--r--src/include/gnunet_buffer_lib.h176
-rw-r--r--src/util/Makefile.am1
-rw-r--r--src/util/buffer.c226
4 files changed, 406 insertions, 1 deletions
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index c81f8e7d8..d79bc45b6 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -12,6 +12,7 @@ EXTRA_DIST = \
12if TALER_ONLY 12if TALER_ONLY
13gnunetinclude_HEADERS = \ 13gnunetinclude_HEADERS = \
14 platform.h gettext.h \ 14 platform.h gettext.h \
15 gnunet_buffer_lib.h \
15 gnunet_common.h \ 16 gnunet_common.h \
16 gnunet_container_lib.h \ 17 gnunet_container_lib.h \
17 gnunet_crypto_lib.h \ 18 gnunet_crypto_lib.h \
@@ -35,6 +36,7 @@ gnunetinclude_HEADERS = \
35 gnunet_block_lib.h \ 36 gnunet_block_lib.h \
36 gnunet_block_group_lib.h \ 37 gnunet_block_group_lib.h \
37 gnunet_block_plugin.h \ 38 gnunet_block_plugin.h \
39 gnunet_buffer_lib.h \
38 gnunet_client_lib.h \ 40 gnunet_client_lib.h \
39 gnunet_common.h \ 41 gnunet_common.h \
40 gnunet_constants.h \ 42 gnunet_constants.h \
@@ -101,7 +103,7 @@ gnunetinclude_HEADERS = \
101 gnunet_regex_service.h \ 103 gnunet_regex_service.h \
102 gnunet_rest_lib.h \ 104 gnunet_rest_lib.h \
103 gnunet_rest_plugin.h \ 105 gnunet_rest_plugin.h \
104 gnunet_rps_service.h \ 106 gnunet_rps_service.h \
105 gnunet_revocation_service.h \ 107 gnunet_revocation_service.h \
106 gnunet_scalarproduct_service.h \ 108 gnunet_scalarproduct_service.h \
107 gnunet_scheduler_lib.h \ 109 gnunet_scheduler_lib.h \
diff --git a/src/include/gnunet_buffer_lib.h b/src/include/gnunet_buffer_lib.h
new file mode 100644
index 000000000..c0ae06d77
--- /dev/null
+++ b/src/include/gnunet_buffer_lib.h
@@ -0,0 +1,176 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * Common buffer management functions.
23 *
24 * @author Florian Dold
25 */
26
27#ifndef GNUNET_BUFFER_LIB_H
28#define GNUNET_BUFFER_LIB_H
29
30/**
31 * Dynamically growing buffer. Can be used to construct
32 * strings and other objects with dynamic size.
33 *
34 * This structure should, in most cases, be stack-allocated and
35 * zero-initialized, like:
36 *
37 * struct GNUNET_Buffer my_buffer = { 0 };
38 */
39struct GNUNET_Buffer
40{
41 /**
42 * Capacity of the buffer.
43 */
44 size_t capacity;
45
46 /**
47 * Current write position.
48 */
49 size_t position;
50
51 /**
52 * Backing memory.
53 */
54 char *mem;
55
56 /**
57 * Log a warning if the buffer is grown over its initially allocated capacity.
58 */
59 int warn_grow;
60};
61
62
63/**
64 * Initialize a buffer with the given capacity.
65 *
66 * When a buffer is allocated with this function, a warning is logged
67 * when the buffer exceeds the initial capacity.
68 *
69 * @param buf the buffer to initialize
70 * @param capacity the capacity (in bytes) to allocate for @a buf
71 */
72void
73GNUNET_buffer_prealloc (struct GNUNET_Buffer *buf, size_t capacity);
74
75
76/**
77 * Make sure that at least @a n bytes remaining in the buffer.
78 *
79 * @param buf buffer to potentially grow
80 * @param n number of bytes that should be available to write
81 */
82void
83GNUNET_buffer_ensure_remaining (struct GNUNET_Buffer *buf, size_t n);
84
85
86/**
87 * Write bytes to the buffer.
88 *
89 * Grows the buffer if necessary.
90 *
91 * @param buf buffer to write to
92 * @param data data to read from
93 * @param len number of bytes to copy from @a data to @a buf
94 *
95 */
96void
97GNUNET_buffer_write (struct GNUNET_Buffer *buf, const char *data, size_t len);
98
99
100/**
101 * Write a 0-terminated string to a buffer, excluding the 0-terminator.
102 *
103 * Grows the buffer if necessary.
104 *
105 * @param buf the buffer to write to
106 * @param str the string to write to @a buf
107 */
108void
109GNUNET_buffer_write_str (struct GNUNET_Buffer *buf, const char *str);
110
111
112/**
113 * Write a path component to a buffer, ensuring that
114 * there is exactly one slash between the previous contents
115 * of the buffer and the new string.
116 *
117 * @param buf buffer to write to
118 * @param str string containing the new path component
119 */
120void
121GNUNET_buffer_write_path (struct GNUNET_Buffer *buf, const char *str);
122
123
124/**
125 * Write a 0-terminated formatted string to a buffer, excluding the
126 * 0-terminator.
127 *
128 * Grows the buffer if necessary.
129 *
130 * @param buf the buffer to write to
131 * @param fmt format string
132 * @param ... format arguments
133 */
134void
135GNUNET_buffer_write_fstr (struct GNUNET_Buffer *buf, const char *fmt, ...);
136
137
138/**
139 * Write a 0-terminated formatted string to a buffer, excluding the
140 * 0-terminator.
141 *
142 * Grows the buffer if necessary.
143 *
144 * @param buf the buffer to write to
145 * @param fmt format string
146 * @param args format argument list
147 */
148void
149GNUNET_buffer_write_vfstr (struct GNUNET_Buffer *buf, const char *fmt, va_list
150 args);
151
152
153/**
154 * Clear the buffer and return the string it contained.
155 * The caller is responsible to eventually #GNUNET_free
156 * the returned string.
157 *
158 * The returned string is always 0-terminated.
159 *
160 * @param buf the buffer to reap the string from
161 * @returns the buffer contained in the string
162 */
163char *
164GNUNET_buffer_reap_str (struct GNUNET_Buffer *buf);
165
166
167/**
168 * Free the backing memory of the given buffer.
169 * Does not free the memory of the buffer control structure,
170 * which is typically stack-allocated.
171 */
172void
173GNUNET_buffer_clear (struct GNUNET_Buffer *buf);
174
175
176#endif
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 387f22a9f..369fcc6c1 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -39,6 +39,7 @@ libgnunetutil_la_SOURCES = \
39 bandwidth.c \ 39 bandwidth.c \
40 $(BENCHMARK) \ 40 $(BENCHMARK) \
41 bio.c \ 41 bio.c \
42 buffer.c \
42 client.c \ 43 client.c \
43 common_allocation.c \ 44 common_allocation.c \
44 common_endian.c \ 45 common_endian.c \
diff --git a/src/util/buffer.c b/src/util/buffer.c
new file mode 100644
index 000000000..d89565d68
--- /dev/null
+++ b/src/util/buffer.c
@@ -0,0 +1,226 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2020 GNUnet e.V.
4
5 GNUnet is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 GNUnet; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file buffer.c
18 * @brief Common buffer management functions.
19 * @author Florian Dold
20 */
21#include "platform.h"
22#include "gnunet_util_lib.h"
23#include "gnunet_buffer_lib.h"
24
25/**
26 * Initialize a buffer with the given capacity.
27 *
28 * When a buffer is allocated with this function, a warning is logged
29 * when the buffer exceeds the initial capacity.
30 *
31 * @param buf the buffer to initialize
32 * @param capacity the capacity (in bytes) to allocate for @a buf
33 */
34void
35GNUNET_buffer_prealloc (struct GNUNET_Buffer *buf, size_t capacity)
36{
37 /* Buffer should be zero-initialized */
38 GNUNET_assert (0 == buf->mem);
39 GNUNET_assert (0 == buf->capacity);
40 GNUNET_assert (0 == buf->position);
41 buf->mem = GNUNET_malloc (capacity);
42 buf->capacity = capacity;
43 buf->warn_grow = GNUNET_YES;
44}
45
46
47/**
48 * Make sure that at least @a n bytes remaining in the buffer.
49 *
50 * @param buf buffer to potentially grow
51 * @param n number of bytes that should be available to write
52 */
53void
54GNUNET_buffer_ensure_remaining (struct GNUNET_Buffer *buf, size_t n)
55{
56 size_t new_capacity = buf->position + n;
57
58 if (new_capacity <= buf->capacity)
59 return;
60 /* warn if calculation of expected size was wrong */
61 GNUNET_break (GNUNET_YES != buf->warn_grow);
62 if (new_capacity < buf->capacity * 2)
63 new_capacity = buf->capacity * 2;
64 buf->capacity = new_capacity;
65 if (NULL != buf->mem)
66 buf->mem = GNUNET_realloc (buf->mem, new_capacity);
67 else
68 buf->mem = GNUNET_malloc (new_capacity);
69}
70
71
72/**
73 * Write bytes to the buffer.
74 *
75 * Grows the buffer if necessary.
76 *
77 * @param buf buffer to write to
78 * @param data data to read from
79 * @param len number of bytes to copy from @a data to @a buf
80 *
81 */
82void
83GNUNET_buffer_write (struct GNUNET_Buffer *buf, const char *data, size_t len)
84{
85 GNUNET_buffer_ensure_remaining (buf, len);
86 memcpy (buf->mem + buf->position, data, len);
87 buf->position += len;
88}
89
90
91/**
92 * Write a 0-terminated string to a buffer, excluding the 0-terminator.
93 *
94 * @param buf the buffer to write to
95 * @param str the string to write to @a buf
96 */
97void
98GNUNET_buffer_write_str (struct GNUNET_Buffer *buf, const char *str)
99{
100 size_t len = strlen (str);
101
102 GNUNET_buffer_write (buf, str, len);
103}
104
105
106/**
107 * Clear the buffer and return the string it contained.
108 * The caller is responsible to eventually #GNUNET_free
109 * the returned string.
110 *
111 * The returned string is always 0-terminated.
112 *
113 * @param buf the buffer to reap the string from
114 * @returns the buffer contained in the string
115 */
116char *
117GNUNET_buffer_reap_str (struct GNUNET_Buffer *buf)
118{
119 char *res;
120
121 /* ensure 0-termination */
122 if ( (0 == buf->position) || ('\0' != buf->mem[buf->position - 1]))
123 {
124 GNUNET_buffer_ensure_remaining (buf, 1);
125 buf->mem[buf->position++] = '\0';
126 }
127 res = buf->mem;
128 *buf = (struct GNUNET_Buffer) { 0 };
129 return res;
130}
131
132
133/**
134 * Free the backing memory of the given buffer.
135 * Does not free the memory of the buffer control structure,
136 * which is typically stack-allocated.
137 */
138void
139GNUNET_buffer_clear (struct GNUNET_Buffer *buf)
140{
141 GNUNET_free_non_null (buf->mem);
142 *buf = (struct GNUNET_Buffer) { 0 };
143}
144
145
146/**
147 * Write a path component to a buffer, ensuring that
148 * there is exactly one slash between the previous contents
149 * of the buffer and the new string.
150 *
151 * @param buf buffer to write to
152 * @param str string containing the new path component
153 */
154void
155GNUNET_buffer_write_path (struct GNUNET_Buffer *buf, const char *str)
156{
157 size_t len = strlen (str);
158
159 while ( (0 != len) && ('/' == str[0]) )
160 {
161 str++;
162 len--;
163 }
164 if ( (0 == buf->position) || ('/' != buf->mem[buf->position - 1]) )
165 {
166 GNUNET_buffer_ensure_remaining (buf, 1);
167 buf->mem[buf->position++] = '/';
168 }
169 GNUNET_buffer_write (buf, str, len);
170}
171
172
173/**
174 * Write a 0-terminated formatted string to a buffer, excluding the
175 * 0-terminator.
176 *
177 * Grows the buffer if necessary.
178 *
179 * @param buf the buffer to write to
180 * @param fmt format string
181 * @param ... format arguments
182 */
183void
184GNUNET_buffer_write_fstr (struct GNUNET_Buffer *buf, const char *fmt, ...)
185{
186 va_list args;
187
188 va_start (args, fmt);
189 GNUNET_buffer_write_vfstr (buf, fmt, args);
190 va_end (args);
191}
192
193
194/**
195 * Write a 0-terminated formatted string to a buffer, excluding the
196 * 0-terminator.
197 *
198 * Grows the buffer if necessary.
199 *
200 * @param buf the buffer to write to
201 * @param fmt format string
202 * @param args format argument list
203 */
204void
205GNUNET_buffer_write_vfstr (struct GNUNET_Buffer *buf,
206 const char *fmt,
207 va_list args)
208{
209 int res;
210 va_list args2;
211
212 va_copy (args2, args);
213 res = vsnprintf (NULL, 0, fmt, args2);
214 va_end (args2);
215
216 GNUNET_assert (res >= 0);
217 GNUNET_buffer_ensure_remaining (buf, res + 1);
218
219 va_copy (args2, args);
220 res = vsnprintf (buf->mem + buf->position, res + 1, fmt, args2);
221 va_end (args2);
222
223 GNUNET_assert (res >= 0);
224 buf->position += res;
225 GNUNET_assert (buf->position <= buf->capacity);
226}