@@@ man wip
[mLib] / struct / dstr.c
CommitLineData
0875b58f 1/* -*-c-*-
2 *
0875b58f 3 * Handle dynamically growing strings
4 *
5 * (c) 1998 Straylight/Edgeware
6 */
7
d4efbcd9 8/*----- Licensing notice --------------------------------------------------*
0875b58f 9 *
10 * This file is part of the mLib utilities library.
11 *
12 * mLib is free software; you can redistribute it and/or modify
c846879c 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.
d4efbcd9 16 *
0875b58f 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
c846879c 20 * GNU Library General Public License for more details.
d4efbcd9 21 *
c846879c 22 * You should have received a copy of the GNU Library General Public
0bd98442 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.
0875b58f 26 */
27
0875b58f 28/*----- Header files ------------------------------------------------------*/
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include "alloc.h"
35#include "dstr.h"
adec5584 36#include "growbuf.h"
0875b58f 37
38/*----- Tunable constants -------------------------------------------------*/
39
002eaee3 40/*
3ca4c9f8 41 * If the buffer is empty, it is set to @DSTR_INITSZ@ bytes in size.
42 * Otherwise, it's set to the next power of two that's large enough. This is
43 * memory-hungry, but efficient.
44 */
45
f8509853 46#define DSTR_INITSZ 64 /* Initial buffer size */
3ca4c9f8 47
0875b58f 48/*----- Main code ---------------------------------------------------------*/
49
50/* --- @dstr_create@ --- *
51 *
52 * Arguments: @dstr *d@ = pointer to a dynamic string block
53 *
54 * Returns: ---
55 *
96c5fe33 56 * Use: Initializes a dynamic string.
0875b58f 57 */
58
fb467548 59void dstr_create(dstr *d) { DCREATE(d); }
0875b58f 60
61/* --- @dstr_destroy@ --- *
62 *
63 * Arguments: @dstr *d@ = pointer to a dynamic string block
64 *
65 * Returns: ---
66 *
67 * Use: Reclaims the space used by a dynamic string.
68 */
69
fb467548 70void dstr_destroy(dstr *d) { DDESTROY(d); }
0875b58f 71
72/* --- @dstr_reset@ --- *
73 *
c6e0eaf0 74 * Arguments: @dstr *d@ = pointer to a dynamic string block
0875b58f 75 *
76 * Returns: ---
77 *
78 * Use: Resets a string so that new data gets put at the beginning.
79 */
80
fb467548 81void dstr_reset(dstr *d) { DRESET(d); }
0875b58f 82
83/* --- @dstr_ensure@ --- *
84 *
85 * Arguments: @dstr *d@ = pointer to a dynamic string block
86 * @size_t sz@ = amount of free space to ensure
87 *
88 * Returns: ---
89 *
90 * Use: Ensures that at least @sz@ bytes are available in the
91 * given string.
92 */
93
94void dstr_ensure(dstr *d, size_t sz)
adec5584 95 { GROWBUF_EXTEND(d->a, d->buf, d->sz, d->len + sz, DSTR_INITSZ, 1); }
0875b58f 96
97/* --- @dstr_putc@ --- *
98 *
99 * Arguments: @dstr *d@ = pointer to a dynamic string block
2be33c7c 100 * @int ch@ = character to append
0875b58f 101 *
102 * Returns: ---
103 *
104 * Use: Appends a character to a string.
105 */
106
2be33c7c 107void dstr_putc(dstr *d, int ch) { DPUTC(d, ch); }
0875b58f 108
109/* --- @dstr_putz@ --- *
110 *
111 * Arguments: @dstr *d@ = pointer to a dynamic string block
112 *
113 * Returns: ---
114 *
115 * Use: Appends a null byte to a string. The null byte does not
116 * contribute to the string's length, and will be overwritten
117 * by subsequent `put' operations.
118 */
119
fb467548 120void dstr_putz(dstr *d) { DPUTZ(d); }
0875b58f 121
122/* --- @dstr_puts@ --- *
123 *
124 * Arguments: @dstr *d@ = pointer to a dynamic string block
125 * @const char *s@ = pointer to string to append
126 *
127 * Returns: ---
128 *
129 * Use: Appends a character string to a string. A trailing null
130 * byte is added, as for @dstr_putz@.
131 */
132
fb467548 133void dstr_puts(dstr *d, const char *s) { DPUTS(d, s); }
0875b58f 134
135/* --- @dstr_putd@ --- *
136 *
137 * Arguments: @dstr *d@ = pointer to a dynamic string block
138 * @const dstr *s@ = pointer to a dynamic string to append
139 *
140 * Returns: ---
141 *
142 * Use: Appends a dynamic string to a string. A trailing null
143 * byte is added, as for @dstr_putz@.
144 */
145
fb467548 146void dstr_putd(dstr *d, const dstr *s) { DPUTD(d, s); }
0875b58f 147
148/* --- @dstr_putm@ --- *
149 *
150 * Arguments: @dstr *d@ = pointer to a dynamic string block
151 * @const void *p@ = pointer to a block to append
152 * @size_t sz@ = size of the block
153 *
154 * Returns: Appends an arbitrary data block to a string. No trailing
155 * null is appended.
156 */
157
fb467548 158void dstr_putm(dstr *d, const void *p, size_t sz) { DPUTM(d, p, sz); }
0875b58f 159
160/* --- @dstr_tidy@ --- *
161 *
162 * Arguments: @dstr *d@ = pointer to a dynamic string block
163 *
164 * Returns: ---
165 *
166 * Use: Reduces the amount of memory used by a string. A trailing
167 * null byte is added, as for @dstr_putz@.
168 */
169
170void dstr_tidy(dstr *d)
171{
b5ea4de3 172 d->buf = x_realloc(d->a, d->buf, d->len + 1, d->sz);
f8509853 173 d->buf[d->len] = 0;
0875b58f 174 d->sz = d->len + 1;
175}
176
177/* --- @dstr_putline@ --- *
178 *
179 * Arguments: @dstr *d@ = pointer to a dynamic string block
180 * @FILE *fp@ = a stream to read from
181 *
182 * Returns: The number of characters read into the buffer, or @EOF@ if
183 * end-of-file was reached before any characters were read.
184 *
185 * Use: Appends the next line from the given input stream to the
186 * string. A trailing newline is not added; a trailing null
187 * byte is appended, as for @dstr_putz@.
188 */
189
190int dstr_putline(dstr *d, FILE *fp)
191{
192 size_t left = d->sz - d->len;
193 size_t off = d->len;
194 int rd = 0;
195 int ch;
196
197 for (;;) {
198
0875b58f 199 /* --- Read the next byte --- */
200
201 ch = getc(fp);
202
203 /* --- End-of-file when no characters read is special --- */
204
205 if (ch == EOF && !rd)
206 return (EOF);
207
f8509853 208 /* --- Make sure there's some buffer space --- */
209
210 if (!left) {
9994cbdc 211 d->len = off;
f8509853 212 dstr_ensure(d, 1);
213 left = d->sz - off;
214 }
215
0875b58f 216 /* --- End-of-file or newline ends the loop --- */
217
218 if (ch == EOF || ch == '\n') {
219 d->buf[off] = 0;
220 d->len = off;
221 return rd;
222 }
223
224 /* --- Append the character and continue --- */
225
226 d->buf[off++] = ch;
227 left--; rd++;
228 }
229}
230
231/* --- @dstr_write@ --- *
232 *
233 * Arguments: @dstr *d@ = pointer to a dynamic string block
234 * @FILE *fp@ = a stream to write on
235 *
236 * Returns: The number of bytes written (as for @fwrite@).
237 *
238 * Use: Writes a dynamic string to a file.
239 */
240
fb467548 241size_t dstr_write(const dstr *d, FILE *fp) { return (DWRITE(d, fp)); }
0875b58f 242
243/*----- That's all, folks -------------------------------------------------*/