chiark / gitweb /
Minor edits.
[mLib] / man / dstr.3
CommitLineData
b6b9d458 1.\" -*-nroff-*-
2.de VS
3.sp 1
d66d7727 4.RS
b6b9d458 5.nf
6.ft B
7..
8.de VE
9.ft R
10.fi
11.RE
12.sp 1
13..
08da152e 14.de hP
b6b9d458 15.IP
16.ft B
17\h'-\w'\\$1\ 'u'\\$1\ \c
18.ft P
19..
20.ie t .ds o \(bu
21.el .ds o o
08da152e 22.TH dstr 3 "8 May 1999" "mLib"
b6b9d458 23dstr \- a simple dynamic string type
08da152e 24.\" @dstr_create
25.\" @dstr_destroy
26.\" @dstr_reset
27.\" @dstr_ensure
28.\" @dstr_tidy
29.\"
30.\" @dstr_putc
31.\" @dstr_putz
32.\" @dstr_puts
33.\" @dstr_putf
34.\" @dstr_putd
35.\" @dstr_putm
36.\" @dstr_putline
37.\" @dstr_write
38.\"
e49a7995 39.\" @DSTR_INIT
08da152e 40.\" @DCREATE
41.\" @DDESTROY
42.\" @DRESET
43.\" @DENSURE
44.\" @DPUTC
45.\" @DPUTZ
46.\" @DPUTS
47.\" @DPUTD
48.\" @DPUTM
49.\" @DWRITE
50.\"
b6b9d458 51.SH SYNOPSIS
52.nf
53.B "#include <mLib/dstr.h>"
54
55.BI "void dstr_create(dstr *" d );
56.BI "void dstr_destroy(dstr *" d );
57.BI "void dstr_reset(dstr *" d );
58
59.BI "void dstr_ensure(dstr *" d ", size_t " sz );
60.BI "void dstr_tidy(dstr *" d );
61
62.BI "void dstr_putc(dstr *" d ", char " ch );
63.BI "void dstr_putz(dstr *" d );
64.BI "void dstr_puts(dstr *" d ", const char *" s );
65.BI "int dstr_vputf(dstr *" d ", va_list " ap );
d2a91066 66.BI "int dstr_putf(dstr *" d ", ...);"
b6b9d458 67.BI "void dstr_putd(dstr *" d ", const dstr *" p );
68.BI "void dstr_putm(dstr *" d ", const void *" p ", size_t " sz );
69.BI "int dstr_putline(dstr *" d ", FILE *" fp );
70.BI "size_t dstr_write(const dstr *" d ", FILE *" fp );
71
e49a7995 72.BI "dstr " d " = DSTR_INIT;"
b6b9d458 73.BI "void DCREATE(dstr *" d );
74.BI "void DDESTROY(dstr *" d );
75.BI "void DRESET(dstr *" d );
76.BI "void DENSURE(dstr *" d ", size_t " sz );
08da152e 77.BI "void DPUTC(dstr *" c ", char " ch );
b6b9d458 78.BI "void DPUTZ(dstr *" d );
79.BI "void DPUTS(dstr *" d ", const char *" s );
80.BI "void DPUTD(dstr *" d ", const dstr *" p );
81.BI "void DPUTM(dstr *" d ", const void *" p ", size_t " sz );
82.BI "size_t DWRITE(const dstr *" d ", FILE *" fp );
83.fi
750e4b6c 84.SH DESCRIPTION
b6b9d458 85The header
86.B dstr.h
87declares a type for representing dynamically extending strings, and a
88small collection of useful operations on them. None of the operations
89returns a failure result on an out-of-memory condition; instead, the
90exception
91.B EXC_NOMEM
92is raised.
93.PP
94Many of the functions which act on dynamic strings have macro
95equivalents. These equivalent macros may evaluate their arguments
96multiple times.
750e4b6c 97.SS "Underlying type"
b6b9d458 98A
99.B dstr
100object is a small structure with the following members:
101.VS
102typedef struct dstr {
103 char *buf; /* Pointer to string buffer */
104 size_t sz; /* Size of the buffer */
105 size_t len; /* Length of the string */
106} dstr;
107.VE
108The
109.B buf
110member points to the actual character data in the string. The data may
111or may not be null terminated, depending on what operations have
112recently been performed on it. None of the
113.B dstr
114functions depend on the string being null-terminated; indeed, all of
115them work fine on strings containing arbitrary binary data. You can
116force null-termination by calling the
117.B dstr_putz
118function, or the
119.B DPUTZ
120macro.
121.PP
122The
123.B sz
124member describes the current size of the buffer. This reflects the
125maximum possible length of string that can be represented in
126.B buf
127without allocating a new buffer.
128.PP
129The
130.B len
131member describes the current length of the string. It is the number of
132bytes in the string which are actually interesting. The length does
133.I not
134include a null-terminating byte, if there is one.
135.PP
136The following invariants are maintained by
137.B dstr
138and must hold when any function is called:
08da152e 139.hP \*o
b6b9d458 140If
141.B sz
142is nonzero, then
143.B buf
144points to a block of memory of length
145.BR sz .
146If
147.B sz
148is zero, then
149.B buf
150is a null pointer.
08da152e 151.hP \*o
b6b9d458 152At all times,
153.BI sz " >= " len\fR.
154.PP
d2a91066 155Note that there is no equivalent of the standard C distinction between
b6b9d458 156the empty string (a pointer to an array of characters whose first
d2a91066 157element is zero) and the nonexistent string (a null pointer). Any
b6b9d458 158.B dstr
159whose
160.B len
161is zero is an empty string.
750e4b6c 162.SS "Creation and destruction"
b6b9d458 163The caller is responsible for allocating the
164.B dstr
165structure. It can be initialized in any of the following ways:
08da152e 166.hP \*o
b6b9d458 167Using the macro
168.B DSTR_INIT
169as an initializer in the declaration of the object.
08da152e 170.hP \*o
b6b9d458 171Passing its address to the
172.B dstr_create
173function.
08da152e 174.hP \*o
b6b9d458 175Passing its address to the (equivalent)
176.B DCREATE
177macro.
178.PP
179The initial value of a
180.B dstr
181is the empty string.
182.PP
183The additional storage space for a string's contents may be reclaimed by
184passing it to the
185.B dstr_destroy
186function, or the
187.B DDESTROY
188macro. After destruction, a string's value is reset to the empty
189string:
190.I "it's still a valid"
191.BR dstr .
192However, once a string has been destroyed, it's safe to deallocate the
193underlying
194.B dstr
195object.
196.PP
197The
198.B dstr_reset
199function empties a string
200.I without
201deallocating any memory. Therefore appending more characters is quick,
d2a91066 202because the old buffer is still there and doesn't need to be allocated.
b6b9d458 203Calling
204.VS
205dstr_reset(d);
206.VE
d2a91066 207is equivalent to directly assigning
b6b9d458 208.VS
209d->len = 0;
210.VE
211There's also a macro
212.B DRESET
213which does the same job as the
214.B dstr_reset
215function.
750e4b6c 216.SS "Extending a string"
b6b9d458 217All memory allocation for strings is done by the function
218.BR dstr_ensure .
219Given a pointer
220.I d
221to a
222.B dstr
223and a size
224.IR sz ,
225the function ensures that there are at least
226.I sz
227unused bytes in the string's buffer. The current algorithm for
228extending the buffer is fairly unsophisticated, but seems to work
229relatively well \- see the source if you really want to know what it's
230doing.
231.PP
232Extending a string never returns a failure result. Instead, if there
233isn't enough memory for a longer string, the exception
234.B EXC_NOMEM
235is raised. See
08da152e 236.BR exc (3)
b6b9d458 237for more information about
238.BR mLib 's
239exception handling system.
240.PP
241Note that if an ensure operation needs to reallocate a string buffer,
242any pointers you've taken into the string become invalid.
243.PP
244There's a macro
245.B DENSURE
246which does a quick inline check to see whether there's enough space in
247a string's buffer. This saves a procedure call when no reallocation
248needs to be done. The
249.B DENSURE
250macro is called in the same way as the
251.B dstr_ensure
252function.
253.PP
254The function
255.B dstr_tidy
256`trims' a string's buffer so that it's just large enough for the string
257contents and a null terminating byte. This might raise an exception due
258to lack of memory. (There are two possible ways this might happen.
d2a91066 259Firstly, the underlying allocator might just be brain-damaged enough to
b6b9d458 260fail on reducing a block's size. Secondly, tidying an empty string with no
261buffer allocated for it causes allocation of a buffer large enough for
262the terminating null byte.)
750e4b6c 263.SS "Contributing data to a string"
b6b9d458 264There are a collection of functions which add data to a string. All of
265these functions add their new data to the
266.I end
267of the string. This is good, because programs usually build strings
268left-to-right. If you want to do something more clever, that's up to
269you.
270.PP
271Several of these functions have equivalent macros which do the main work
272inline. (There still might need to be a function call if the buffer
273needs to be extended.)
274.PP
275Any of these functions might extend the string, causing pointers into
276the string buffer to be invalidated. If you don't want that to happen,
277pre-ensure enough space before you start.
278.PP
279The simplest function is
280.B dstr_putc
281which appends a single character
282.I ch
283to the end of the string. It has a macro equivalent called
284.BR DPUTC .
285.PP
286The function
287.B dstr_putz
288places a zero byte at the end of the string. It does
289.I not
290affect the string's length, so any other data added to the string will
291overwrite the null terminator. This is useful if you want to pass your
292string to one of the standard C library string-handling functions. The
293macro
294.B DPUTZ
295does the same thing.
296.PP
297The function
298.B dstr_puts
299writes a C-style null-terminated string to the end of a dynamic string.
300A terminating zero byte is also written, as if
301.B dstr_putz
302were called. The macro
303.B DPUTS
304does the same job.
305.PP
306The function
307.B dstr_putf
308works similarly to the standard
309.BR sprintf (3)
310function. It accepts a
311.BR print (3)-style
312format string and an arbitrary number of arguments to format and writes
313the resulting text to the end of a dynamic string, returning the number
314of characters so written. A terminating zero byte is also appended.
315The formatting is intended to be convenient and safe rather than
316efficient, so don't expect blistering performance. Similarly, there may
317be differences between the formatting done by
318.B dstr_putf
319and
320.BR sprintf (3)
321because the former has to do most of its work itself. In particular,
322.B dstr_putf
323doesn't (and probably never will) understand the
324.RB ` n$ '
d2a91066 325positional parameter notation accepted by many Unix C libraries. There
b6b9d458 326is no macro equivalent of
327.BR dstr_putf .
328.PP
329The function
330.B dstr_vputf
331provides access to the `guts' of
332.BR dstr_putf :
333given a format string and a
334.B va_list
335pointer, it will format the arguments according to the format string,
336just as
337.B dstr_putf
338does.
339.PP
340The function
341.B dstr_putd
342appends the contents of one dynamic string to another. A null
343terminator is also appended. The macro
344.B DPUTD
345does the same thing.
346.PP
347The function
348.B dstr_putm
349puts an arbitrary block of memory, addressed by
350.IR p ,
351with length
352.I sz
353bytes, at the end of a dynamic string. No terminating null is appended:
354it's assumed that if you're playing with arbitrary chunks of memory then
355you're probably not going to be using the resulting data as a normal
356text string. The macro
357.B DPUTM
358works the same way.
359.PP
360The function
361.B dstr_putline
362reads a line from an input stream
363.I fp
364and appends it to a string. If an error occurs, or end-of-file is
365encountered, before any characters have been read, then
366.B dstr_putline
367returns the value
750e4b6c 368.B EOF
369and does not extend the string. Otherwise, it reads until it encounters
370a newline character, an error, or end-of-file, and returns the number of
371characters read. If reading was terminated by a newline character, the
372newline character is
b6b9d458 373.I not
374inserted in the buffer. A terminating null is appended, as by
375.BR dstr_putz .
750e4b6c 376.SS "Other functions"
b6b9d458 377The
378.B dstr_write
379function writes a string to an output stream
380.IR fp .
381It returns the number of characters written, or
382.B 0
383if an error occurred before the first write. No newline character is
384written to the stream, unless the string actually contains one already.
385The macro
386.B DWRITE
387is equivalent.
388.SH "SECURITY CONSIDERATIONS"
d2a91066 389The implementation of the
b6b9d458 390.B dstr
391functions is designed to do string handling in security-critical
392programs. However, there may be bugs in the code somewhere. In
393particular, the
394.B dstr_putf
f1583053 395functions are quite complicated, and could do with some checking by
b6b9d458 396independent people who know what they're doing.
08da152e 397.SH "SEE ALSO"
398.BR exc (3),
399.BR mLib (3).
b6b9d458 400.SH AUTHOR
401Mark Wooding, <mdw@nsict.org>