@@@ man wip
[mLib] / buf / lbuf.3
CommitLineData
05fbeb03 1.\" -*-nroff-*-
fbf20b5b 2.TH lbuf 3 "6 July 1999" "Straylight/Edgeware" "mLib utilities library"
05fbeb03 3.SH "NAME"
4lbuf \- split lines out of asynchronously received blocks
5.\" @lbuf_flush
6.\" @lbuf_close
7.\" @lbuf_free
8.\" @lbuf_snarf
31e83d07 9.\" @lbuf_setsize
05fbeb03 10.\" @lbuf_init
31e83d07 11.\" @lbuf_destroy
05fbeb03 12.SH "SYNOPSIS"
13.nf
adec5584 14.ta 2n
05fbeb03 15.B "#include <mLib/lbuf.h>"
d056fbdf 16.PP
4729aa69 17.B "enum {"
adec5584
MW
18.B " LBUF_CRLF,"
19.B " LBUF_STRICTCRLF,"
20.B " ..."
4729aa69
MW
21.B "};"
22.B "#define LBUF_ENABLE ..."
d056fbdf 23.PP
4729aa69 24.B "typedef struct {"
adec5584
MW
25.B " unsigned f;"
26.B " ..."
4729aa69 27.B "} lbuf;"
d056fbdf 28.PP
4729aa69 29.B "typedef void lbuf_func(char *" s ", size_t " len ", void *" p );
d056fbdf 30.PP
05fbeb03 31.BI "void lbuf_flush(lbuf *" b ", char *" p ", size_t " len );
32.BI "void lbuf_close(lbuf *" b );
33.BI "size_t lbuf_free(lbuf *" b ", char **" p );
34.BI "void lbuf_snarf(lbuf *" b ", const void *" p ", size_t " sz );
cededfbe 35.BI "void lbuf_setsize(lbuf *" b ", size_t " sz );
83c63e03 36.BI "void lbuf_init(lbuf *" b ", lbuf_func *" func ", void *" p );
cededfbe 37.BI "void lbuf_destroy(lbuf *" b );
05fbeb03 38.fi
39.SH "DESCRIPTION"
40The declarations in
41.B <mLib/lbuf.h>
42implement a handy object called a
43.IR "line buffer" .
44Given unpredictably-sized chunks of data, the line buffer extracts
45completed lines of text and passes them to a caller-supplied function.
46This is useful in nonblocking network servers, for example: the server
47can feed input from a client into a line buffer as it arrives and deal
48with completed text lines as they appear without having to wait for
49newline characters.
50.PP
51The state of a line buffer is stored in an object of type
52.BR lbuf .
53This is a structure which must be allocated by the caller. The
54structure should normally be considered opaque (see the section on
55.B Disablement
56for an exception to this).
57.SS "Initialization and finalization"
58The function
59.B lbuf_init
60initializes a line buffer ready for use. It is given three arguments:
61.TP
ff76c38f 62.BI "lbuf *" b
31e83d07 63A pointer to the block of memory to use for the line buffer. The line
64buffer will allocate memory to store incoming data automatically: this
65structure just contains bookkeeping information.
05fbeb03 66.TP
83c63e03 67.BI "lbuf_func *" func
05fbeb03 68The
69.I line-handler
70function to which the line buffer should pass completed lines of text.
83c63e03 71See
72.B "Line-handler functions"
73below for a description of this function.
05fbeb03 74.TP
ff76c38f 75.BI "void *" p
05fbeb03 76A pointer argument to be passed to the function when a completed line of
77text arrives.
78.PP
cededfbe 79The amount of memory set aside for reading lines is configurable. It
80may be set by calling
81.B lbuf_setsize
82at any time when the buffer is empty. The default limit is 256 bytes.
83Lines longer than the limit are truncated. By default, the buffer is
84allocated from the current arena,
85.BR arena_global (3);
86this may be changed by altering the buffer's
87.B a
88member to refer to a different arena at any time when the buffer is
89unallocated.
90.PP
91A line buffer must be destroyed after use by calling
92.BR lbuf_destroy ,
93passing it the address of the buffer block.
05fbeb03 94.SS "Inserting data into the buffer"
95There are two interfaces for inserting data into the buffer. One's much
96simpler than the other, although it's less expressive.
97.PP
98The simple interface is
99.BR lbuf_snarf .
100This function is given three arguments: a pointer
101.I b
102to a line buffer structure; a pointer
103.I p
d0053e2e 104to a chunk of data to read; and the size
05fbeb03 105.I sz
106of the chunk of data. The data is pushed through the line buffer and
107any complete lines are passed on to the line handler.
108.PP
109The complex interface is the pair of functions
d0053e2e 110.B lbuf_free
05fbeb03 111and
d0053e2e 112.BR lbuf_flush .
05fbeb03 113.PP
d4efbcd9 114The
05fbeb03 115.B lbuf_free
116function returns the address and size of a free portion of the line
117buffer's memory into which data may be written. The function is passed
d4efbcd9 118the address
31e83d07 119.I b
05fbeb03 120of the line buffer. Its result is the size of the free area, and it
121writes the base address of this free space to the location pointed to by
122the argument
123.IR p .
124The caller's data must be written to ascending memory locations starting
125at
126.BI * p
127and no data may be written beyond the end of the free space. However,
128it isn't necessary to completely fill the buffer.
129.PP
130Once the free area has had some data written to it,
131.B lbuf_flush
132is called to examine the new data and break it into text lines. This is
133given three arguments:
134.TP
ff76c38f 135.BI "lbuf *" b
05fbeb03 136The address of the line buffer.
137.TP
ff76c38f 138.BI "char *" p
05fbeb03 139The address at which the new data has been written. This must be the
140base address returned from
141.BR lbuf_free .
142.TP
ff76c38f 143.BI "size_t " len
05fbeb03 144The number of bytes which have been written to the buffer.
145.PP
146The
147.B lbuf_flush
148function breaks the new data into lines as described below, and passes
149each one in turn to the line-handler function.
150.PP
151The
152.B lbuf_snarf
153function is trivially implemented in terms of the more complex
d0053e2e 154.BR lbuf_free / lbuf_flush
05fbeb03 155interface.
156.SS "Line breaking"
83c63e03 157By default, the line buffer considers a line to end with either a simple
158linefeed character (the normal Unix convention) or a
159carriage-return/linefeed pair (the Internet convention). This can be
160changed by modifying the
161.B delim
162member of the
163.B lbuf
164structure: the default value is
165.BR LBUF_CRLF .
166If set to
167.BR LBUF_STRICTCRLF ,
168only a carriage-return/linefeed pair will terminate a line. Any other
169value is a single character which is considered to be the line terminator.
05fbeb03 170.PP
171The line buffer has a fixed amount of memory available to it. This is
172deliberate, to prevent a trivial attack whereby a remote user sends a
173stream of data containing no newline markers, wasting the server's
174memory. Instead, the buffer will truncate overly long lines (silently)
175and return only the initial portion. It will ignore the rest of the
176line completely.
177.SS "Line-handler functions"
178Completed lines, as already said, are passed to the caller's
4729aa69 179line-handler function. It is given three arguments: the address
05fbeb03 180.I s
83c63e03 181of the line which has just been read; the length
182.I len
183of the line (not including the null terminator), and the pointer
05fbeb03 184.I p
185which was set up in the call to
d0053e2e 186.BR lbuf_init .
05fbeb03 187The line passed is null-terminated, and has had its trailing newline
188stripped. The area of memory in which the string is located may be
189overwritten by the line-handler function, although writing beyond the
190terminating zero byte is not permitted.
191.PP
192The line pointer argument
193.I s
83c63e03 194may be null to signify end-of-file; in this case, the length
195.I len
196will be zero. See the next section.
05fbeb03 197.SS "Flushing the remaining data"
198When the client program knows that there's no more data arriving (for
199example, an end-of-file condition exists on its data source) it should
200call the function
201.BR lbuf_close
202to flush out the remaining data in the buffer as one last (improperly
203terminated) line. This will pass the remaining text to the line
204handler, if there is any, and then call the handler one final time with
205a null pointer rather than the address of a text line to inform it of
206the end-of-file.
207.SS "Disablement"
208The line buffer is intended to be used in higher-level program objects,
209such as the buffer selector described in
210.BR selbuf (3).
211Unfortunately, a concept from this high level needs to exist at the line
212buffer level, which complicates the description somewhat. The idea is
213that, when a line-handler attached to some higher-level object decides
214that it's read enough, it can
215.I disable
216the object so that it doesn't see any more data.
217.PP
218Clearly, since an
219.B lbuf_flush
528c8b4d 220call can emit more than one line, it must be aware that the line handler
221isn't interested in any more lines. However, this fact must also be
222signalled to the higher-level object so that it can detach itself from
223its data source.
05fbeb03 224.PP
225Rather than invent some complex interface for this, the line buffer
3bc42912 226exports one of its structure members, a flags word called
227.BR f .
05fbeb03 228A higher-level object wishing to disable the line buffer simply clears
229the bit
230.B LBUF_ENABLE
3bc42912 231in this flags word.
05fbeb03 232.PP
233Disabling a buffer causes an immediate return from
234.BR lbuf_flush .
235However, it is not permitted for the functions
236.B lbuf_flush
237or
238.B lbuf_close
239to be called on a disabled buffer. (This condition isn't checked for;
240it'll just do the wrong thing.) Furthermore, the
241.B lbuf_snarf
242function does not handle disablement at all, because it would complicate
243the interface so much that it wouldn't have any advantage over the more
244general
245.BR lbuf_free / lbuf_flush .
246.SH "SEE ALSO"
247.BR selbuf (3),
248.BR mLib (3).
249.SH "AUTHOR"
9b5ac6ff 250Mark Wooding, <mdw@distorted.org.uk>