chiark / gitweb /
New functions `dstr_putf' and `dstr_vputf' which do `printf'-style
[mLib] / dstr.h
1 /* -*-c-*-
2  *
3  * $Id: dstr.h,v 1.2 1998/12/15 23:53:23 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 General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (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 General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with mLib; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Revision history --------------------------------------------------*
30  *
31  * $Log: dstr.h,v $
32  * Revision 1.2  1998/12/15 23:53:23  mdw
33  * New functions `dstr_putf' and `dstr_vputf' which do `printf'-style
34  * formatting in a safe way.
35  *
36  * Revision 1.1.1.1  1998/06/17 23:44:42  mdw
37  * Initial version of mLib
38  *
39  */
40
41 #ifndef DSTR_H
42 #define DSTR_H
43
44 #ifdef __cplusplus
45   extern "C" {
46 #endif
47
48 /*----- Rationale ---------------------------------------------------------*
49  *
50  * This file declares what is hopefully a fairly useful collection of
51  * primitive string handling functions.  The idea is that the strings
52  * allocate memory for themselves as required.  The @dstr@ routines don't
53  * assume any sort of terminator character, so arbitrary binary data can
54  * be stored in a dynamic string.  With luck, this should put a stop to
55  * any buffer overflow problems.
56  */
57
58 /*----- Header files ------------------------------------------------------*/
59
60 #include <stdarg.h>
61 #include <stdio.h>
62
63 /*----- Data structures ---------------------------------------------------*/
64
65 typedef 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 } dstr;
70
71 /*----- Functions provided ------------------------------------------------*/
72
73 /* --- @dstr_create@ --- *
74  *
75  * Arguments:   @dstr *d@ = pointer to a dynamic string block
76  *
77  * Returns:     ---
78  *
79  * Use:         Initialises a dynamic string.
80  */
81
82 extern void dstr_create(dstr */*d*/);
83
84 /* --- @dstr_destroy@ --- *
85  *
86  * Arguments:   @dstr *d@ = pointer to a dynamic string block
87  *
88  * Returns:     ---
89  *
90  * Use:         Reclaims the space used by a dynamic string.
91  */
92
93 extern void dstr_destroy(dstr */*d*/);
94
95 /* --- @dstr_reset@ --- *
96  *
97  * Arguments:   @dstr *d@ = pointer to a dynaimc string block
98  *
99  * Returns:     ---
100  *
101  * Use:         Resets a string so that new data gets put at the beginning.
102  */
103
104 extern void dstr_reset(dstr */*d*/);
105
106 /* --- @dstr_ensure@ --- *
107  *
108  * Arguments:   @dstr *d@ = pointer to a dynamic string block
109  *              @size_t sz@ = amount of free space to ensure
110  *
111  * Returns:     ---
112  *
113  * Use:         Ensures that at least @sz@ bytes are available in the
114  *              given string.
115  */
116
117 extern void dstr_ensure(dstr */*d*/, size_t /*sz*/);
118
119 #define DENSURE(d, rq) do {                                             \
120   if ((d)->len + (rq) > (d)->sz) dstr_ensure((d), (rq));                \
121 } while (0)
122
123 /* --- @dstr_putc@ --- *
124  *
125  * Arguments:   @dstr *d@ = pointer to a dynamic string block
126  *              @char ch@ = character to append
127  *
128  * Returns:     ---
129  *
130  * Use:         Appends a character to a string.
131  */
132
133 extern void dstr_putc(dstr */*d*/, char /*ch*/);
134
135 #define DPUTC(d, ch) do {                                               \
136   DENSURE((d), 1);                                                      \
137   (d)->buf[(d)->len++] = (ch);                                          \
138 } while (0)
139
140 /* --- @dstr_putz@ --- *
141  *
142  * Arguments:   @dstr *d@ = pointer to a dynamic string block
143  *
144  * Returns:     ---
145  *
146  * Use:         Appends a null byte to a string.  The null byte does not
147  *              contribute to the string's length, and will be overwritten
148  *              by subsequent `put' operations.
149  */
150
151 extern void dstr_putz(dstr */*d*/);
152
153 #define DPUTZ(d) do {                                                   \
154   DENSURE((d), 1);                                                      \
155   (d)->buf[(d)->len] = 0;                                               \
156 } while (0)
157
158 /* --- @dstr_puts@ --- *
159  *
160  * Arguments:   @dstr *d@ = pointer to a dynamic string block
161  *              @const char *s@ = pointer to string to append
162  *
163  * Returns:     ---
164  *
165  * Use:         Appends a character string to a string.  A trailing null
166  *              byte is added, as for @dstr_putz@.
167  */
168
169 extern void dstr_puts(dstr */*d*/, const char */*s*/);
170
171 #define DPUTS(d, s) do {                                                \
172   size_t sz = strlen(s);                                                \
173   DENSURE((d), sz + 1);                                                 \
174   memcpy((d)->buf + (d)->len, (s), sz + 1);                             \
175   (d)->len += sz;                                                       \
176 } while (0)
177
178 /* --- @dstr_vputf@ --- *
179  *
180  * Arguments:   @dstr *d@ = pointer to a dynamic string block
181  *              @const char *p@ = pointer to @printf@-style format string
182  *              @va_list ap@ = argument handle
183  *
184  * Returns:     ---
185  *
186  * Use:         As for @dstr_putf@, but may be used as a back-end to user-
187  *              supplied functions with @printf@-style interfaces.
188  */
189
190 extern int dstr_vputf(dstr */*d*/, const char */*p*/, va_list /*ap*/);
191
192 /* --- @dstr_putf@ --- *
193  *
194  * Arguments:   @dstr *d@ = pointer to a dynamic string block
195  *              @const char *p@ = pointer to @printf@-style format string
196  *              @...@ = argument handle
197  *
198  * Returns:     ---
199  *
200  * Use:         Writes a piece of text to a dynamic string, doing @printf@-
201  *              style substitutions as it goes.  Intended to be robust if
202  *              faced with malicious arguments, but not if the format string
203  *              itself is malicious.
204  */
205
206 extern int dstr_putf(dstr */*d*/, const char */*p*/, ...);
207
208 /* --- @dstr_putd@ --- *
209  *
210  * Arguments:   @dstr *d@ = pointer to a dynamic string block
211  *              @const dstr *s@ = pointer to a dynamic string to append
212  *
213  * Returns:     ---
214  *
215  * Use:         Appends a dynamic string to a string.  A trailing null
216  *              byte is added, as for @dstr_putz@.
217  */
218
219 extern void dstr_putd(dstr */*d*/, const dstr */*s*/);
220
221 #define DPUTD(d, s) do {                                                \
222   DENSURE((d), (s)->len + 1);                                           \
223   memcpy((d)->buf + (d)->len, (s)->buf, (s)->len);                      \
224   (d)->len += (s)->len;                                                 \
225   (d)->buf[(d)->len] = 0;                                               \
226 } while (0)
227
228 /* --- @dstr_putm@ --- *
229  *
230  * Arguments:   @dstr *d@ = pointer to a dynamic string block
231  *              @const void *p@ = pointer to a block to append
232  *              @size_t sz@ = size of the block
233  *
234  * Returns:     Appends an arbitrary data block to a string.  No trailing
235  *              null is appended.
236  */
237
238 extern void dstr_putm(dstr */*d*/, const void */*p*/, size_t /*sz*/);
239
240 #define DPUTM(d, p, sz) do {                                            \
241   DENSURE((d), (sz));                                                   \
242   memcpy((d)->buf + (d)->len, (p), (sz));                               \
243   (d)->len += (sz);                                                     \
244 } while (0)
245
246 /* --- @dstr_tidy@ --- *
247  *
248  * Arguments:   @dstr *d@ = pointer to a dynamic string block
249  *
250  * Returns:     ---
251  *
252  * Use:         Reduces the amount of memory used by a string.  A trailing
253  *              null byte is added, as for @dstr_putz@.
254  */
255
256 extern void dstr_tidy(dstr */*d*/);
257
258 /* --- @dstr_putline@ --- *
259  *
260  * Arguments:   @dstr *d@ = pointer to a dynamic string block
261  *              @FILE *fp@ = a stream to read from
262  *
263  * Returns:     The number of characters read into the buffer, or @EOF@ if
264  *              end-of-file was reached before any characters were read.
265  *
266  * Use:         Appends the next line from the given input stream to the
267  *              string.  A trailing newline is not added; a trailing null
268  *              byte is appended, as for @dstr_putz@.
269  */
270
271 extern int dstr_putline(dstr */*d*/, FILE */*fp*/);
272
273 /* --- @dstr_write@ --- *
274  *
275  * Arguments:   @dstr *d@ = pointer to a dynamic string block
276  *              @FILE *fp@ = a stream to write on
277  *
278  * Returns:     The number of bytes written (as for @fwrite@).
279  *
280  * Use:         Writes a dynamic string to a file.
281  */
282
283 extern size_t dstr_write(dstr */*d*/, FILE */*fp*/);
284
285 /*----- That's all, folks -------------------------------------------------*/
286
287 #ifdef __cplusplus
288   }
289 #endif
290
291 #endif