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