chiark / gitweb /
struct/buf.c: Add functions for serializing and deserializing `kludge64'.
[mLib] / struct / dstr.h
... / ...
CommitLineData
1/* -*-c-*-
2 *
3 * Handle dynamically growing strings
4 *
5 * (c) 1998 Straylight/Edgeware
6 */
7
8/*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of the mLib utilities library.
11 *
12 * mLib is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * mLib is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with mLib; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
28#ifndef MLIB_DSTR_H
29#define MLIB_DSTR_H
30
31#ifdef __cplusplus
32 extern "C" {
33#endif
34
35/*----- Rationale ---------------------------------------------------------*
36 *
37 * This file declares what is hopefully a fairly useful collection of
38 * primitive string handling functions. The idea is that the strings
39 * allocate memory for themselves as required. The @dstr@ routines don't
40 * assume any sort of terminator character, so arbitrary binary data can
41 * be stored in a dynamic string. With luck, this should put a stop to
42 * any buffer overflow problems.
43 */
44
45/*----- Header files ------------------------------------------------------*/
46
47#include <stdarg.h>
48#include <stdio.h>
49#include <stdlib.h>
50
51#ifndef MLIB_ALLOC_H
52# include "alloc.h"
53#endif
54
55#ifndef MLIB_ARENA_H
56# include "arena.h"
57#endif
58
59#ifndef MLIB_MACROS_H
60# include "macros.h"
61#endif
62
63/*----- Data structures ---------------------------------------------------*/
64
65typedef struct dstr {
66 char *buf; /* Pointer to string buffer */
67 size_t sz; /* Size of the buffer */
68 size_t len; /* Length of the string */
69 arena *a; /* Pointer to arena */
70} dstr;
71
72#define DSTR_INIT { 0, 0, 0, &arena_stdlib } /* How to initialize one */
73
74/*----- Functions provided ------------------------------------------------*/
75
76/* --- @dstr_create@ --- *
77 *
78 * Arguments: @dstr *d@ = pointer to a dynamic string block
79 *
80 * Returns: ---
81 *
82 * Use: Initializes a dynamic string.
83 */
84
85extern void dstr_create(dstr */*d*/);
86
87#define DCREATE(d) do { \
88 dstr *_dd = (d); \
89 _dd->buf = 0; \
90 _dd->sz = 0; \
91 _dd->len = 0; \
92 _dd->a = &arena_stdlib; \
93} while (0)
94
95/* --- @dstr_destroy@ --- *
96 *
97 * Arguments: @dstr *d@ = pointer to a dynamic string block
98 *
99 * Returns: ---
100 *
101 * Use: Reclaims the space used by a dynamic string.
102 */
103
104extern void dstr_destroy(dstr */*d*/);
105
106#define DDESTROY(d) do { \
107 dstr *_d = (d); \
108 if (_d->buf) \
109 x_free(_d->a, _d->buf); \
110 DCREATE(_d); \
111} while (0)
112
113/* --- @dstr_reset@ --- *
114 *
115 * Arguments: @dstr *d@ = pointer to a dynamic string block
116 *
117 * Returns: ---
118 *
119 * Use: Resets a string so that new data gets put at the beginning.
120 */
121
122extern void dstr_reset(dstr */*d*/);
123
124#define DRESET(d) ((d)->len = 0)
125
126/* --- @dstr_ensure@ --- *
127 *
128 * Arguments: @dstr *d@ = pointer to a dynamic string block
129 * @size_t sz@ = amount of free space to ensure
130 *
131 * Returns: ---
132 *
133 * Use: Ensures that at least @sz@ bytes are available in the
134 * given string.
135 */
136
137extern void dstr_ensure(dstr */*d*/, size_t /*sz*/);
138
139#define DENSURE(d, rq) do { \
140 dstr *_dd = (d); \
141 size_t _rq = (rq); \
142 if (_dd->len + _rq > _dd->sz) dstr_ensure(_dd, _rq); \
143} while (0)
144
145/* --- @dstr_putc@ --- *
146 *
147 * Arguments: @dstr *d@ = pointer to a dynamic string block
148 * @int ch@ = character to append
149 *
150 * Returns: ---
151 *
152 * Use: Appends a character to a string.
153 */
154
155extern void dstr_putc(dstr */*d*/, int /*ch*/);
156
157#define DPUTC(d, ch) do { \
158 dstr *_d = (d); \
159 DENSURE(_d, 1); \
160 *((unsigned char *)_d->buf + _d->len++) = (ch); \
161} while (0)
162
163/* --- @dstr_putz@ --- *
164 *
165 * Arguments: @dstr *d@ = pointer to a dynamic string block
166 *
167 * Returns: ---
168 *
169 * Use: Appends a null byte to a string. The null byte does not
170 * contribute to the string's length, and will be overwritten
171 * by subsequent `put' operations.
172 */
173
174extern void dstr_putz(dstr */*d*/);
175
176#define DPUTZ(d) do { \
177 dstr *_d = (d); \
178 DENSURE(_d, 1); \
179 _d->buf[_d->len] = 0; \
180} while (0)
181
182/* --- @dstr_puts@ --- *
183 *
184 * Arguments: @dstr *d@ = pointer to a dynamic string block
185 * @const char *s@ = pointer to string to append
186 *
187 * Returns: ---
188 *
189 * Use: Appends a character string to a string. A trailing null
190 * byte is added, as for @dstr_putz@.
191 */
192
193extern void dstr_puts(dstr */*d*/, const char */*s*/);
194
195#define DPUTS(d, s) do { \
196 dstr *_d = (d); \
197 const char *_s = (s); \
198 size_t _sz = strlen(_s); \
199 DENSURE(_d, _sz + 1); \
200 memcpy(_d->buf + _d->len, _s, _sz + 1); \
201 _d->len += _sz; \
202} while (0)
203
204/* --- @dstr_vputf@ --- *
205 *
206 * Arguments: @dstr *d@ = pointer to a dynamic string block
207 * @const char *p@ = pointer to @printf@-style format string
208 * @va_list *ap@ = argument handle
209 *
210 * Returns: The number of characters written to the string.
211 *
212 * Use: As for @dstr_putf@, but may be used as a back-end to user-
213 * supplied functions with @printf@-style interfaces.
214 */
215
216extern int dstr_vputf(dstr */*d*/, const char */*p*/, va_list */*ap*/);
217
218/* --- @dstr_putf@ --- *
219 *
220 * Arguments: @dstr *d@ = pointer to a dynamic string block
221 * @const char *p@ = pointer to @printf@-style format string
222 * @...@ = argument handle
223 *
224 * Returns: The number of characters written to the string.
225 *
226 * Use: Writes a piece of text to a dynamic string, doing @printf@-
227 * style substitutions as it goes. Intended to be robust if
228 * faced with malicious arguments, but not if the format string
229 * itself is malicious.
230 */
231
232extern int PRINTF_LIKE(2, 3)
233 dstr_putf(dstr */*d*/, const char */*p*/, ...);
234
235/* --- @dstr_putd@ --- *
236 *
237 * Arguments: @dstr *d@ = pointer to a dynamic string block
238 * @const dstr *s@ = pointer to a dynamic string to append
239 *
240 * Returns: ---
241 *
242 * Use: Appends a dynamic string to a string. A trailing null
243 * byte is added, as for @dstr_putz@.
244 */
245
246extern void dstr_putd(dstr */*d*/, const dstr */*s*/);
247
248#define DPUTD(d, s) do { \
249 dstr *_d = (d); \
250 const dstr *_s = (s); \
251 DENSURE(_d, _s->len + 1); \
252 memcpy(_d->buf + _d->len, _s->buf, _s->len); \
253 _d->len += _s->len; \
254 _d->buf[_d->len] = 0; \
255} while (0)
256
257/* --- @dstr_putm@ --- *
258 *
259 * Arguments: @dstr *d@ = pointer to a dynamic string block
260 * @const void *p@ = pointer to a block to append
261 * @size_t sz@ = size of the block
262 *
263 * Returns: Appends an arbitrary data block to a string. No trailing
264 * null is appended.
265 */
266
267extern void dstr_putm(dstr */*d*/, const void */*p*/, size_t /*sz*/);
268
269#define DPUTM(d, p, sz) do { \
270 dstr *_d = (d); \
271 size_t _sz = (sz); \
272 DENSURE(_d, _sz); \
273 memcpy(_d->buf + _d->len, (p), _sz); \
274 _d->len += _sz; \
275} while (0)
276
277/* --- @dstr_tidy@ --- *
278 *
279 * Arguments: @dstr *d@ = pointer to a dynamic string block
280 *
281 * Returns: ---
282 *
283 * Use: Reduces the amount of memory used by a string. A trailing
284 * null byte is added, as for @dstr_putz@.
285 */
286
287extern void dstr_tidy(dstr */*d*/);
288
289/* --- @dstr_putline@ --- *
290 *
291 * Arguments: @dstr *d@ = pointer to a dynamic string block
292 * @FILE *fp@ = a stream to read from
293 *
294 * Returns: The number of characters read into the buffer, or @EOF@ if
295 * end-of-file was reached before any characters were read.
296 *
297 * Use: Appends the next line from the given input stream to the
298 * string. A trailing newline is not added; a trailing null
299 * byte is appended, as for @dstr_putz@.
300 */
301
302extern int dstr_putline(dstr */*d*/, FILE */*fp*/);
303
304/* --- @dstr_write@ --- *
305 *
306 * Arguments: @dstr *d@ = pointer to a dynamic string block
307 * @FILE *fp@ = a stream to write on
308 *
309 * Returns: The number of bytes written (as for @fwrite@).
310 *
311 * Use: Writes a dynamic string to a file.
312 */
313
314extern size_t dstr_write(const dstr */*d*/, FILE */*fp*/);
315
316#define DWRITE(d, fp) fwrite((d)->buf, 1, (d)->len, (fp))
317
318/*----- That's all, folks -------------------------------------------------*/
319
320#ifdef __cplusplus
321 }
322#endif
323
324#endif