chiark / gitweb /
Makefile for manual page installation. Subtle and complicated.
[mLib] / man / lbuf.3
CommitLineData
05fbeb03 1.\" -*-nroff-*-
2.TH lbuf 3 "6 July 1999" mLib
3.SH "NAME"
4lbuf \- split lines out of asynchronously received blocks
5.\" @lbuf_flush
6.\" @lbuf_close
7.\" @lbuf_free
8.\" @lbuf_snarf
9.\" @lbuf_init
10.SH "SYNOPSIS"
11.nf
12.B "#include <mLib/lbuf.h>"
13
14.BI "void lbuf_flush(lbuf *" b ", char *" p ", size_t " len );
15.BI "void lbuf_close(lbuf *" b );
16.BI "size_t lbuf_free(lbuf *" b ", char **" p );
17.BI "void lbuf_snarf(lbuf *" b ", const void *" p ", size_t " sz );
18.BI "void lbuf_init(lbuf *" b ,
19.BI " void (*" func ")(char *" s ", void *" p ),
20.BI " void *" p );
21.fi
22.SH "DESCRIPTION"
23The declarations in
24.B <mLib/lbuf.h>
25implement a handy object called a
26.IR "line buffer" .
27Given unpredictably-sized chunks of data, the line buffer extracts
28completed lines of text and passes them to a caller-supplied function.
29This is useful in nonblocking network servers, for example: the server
30can feed input from a client into a line buffer as it arrives and deal
31with completed text lines as they appear without having to wait for
32newline characters.
33.PP
34The state of a line buffer is stored in an object of type
35.BR lbuf .
36This is a structure which must be allocated by the caller. The
37structure should normally be considered opaque (see the section on
38.B Disablement
39for an exception to this).
40.SS "Initialization and finalization"
41The function
42.B lbuf_init
43initializes a line buffer ready for use. It is given three arguments:
44.TP
45.I b
46A pointer to the block of memory to use for the line buffer. This is
47all the memory the line buffer requires.
48.TP
49.I func
50The
51.I line-handler
52function to which the line buffer should pass completed lines of text.
53.TP
54.I p
55A pointer argument to be passed to the function when a completed line of
56text arrives.
57.PP
58Since the line buffer requires no memory except for the actual
59.B lbuf
60object, and doesn't hook itself onto anything else, it can just be
61thrown away when you don't want it any more. No explicit finalization
62is required.
63.SS "Inserting data into the buffer"
64There are two interfaces for inserting data into the buffer. One's much
65simpler than the other, although it's less expressive.
66.PP
67The simple interface is
68.BR lbuf_snarf .
69This function is given three arguments: a pointer
70.I b
71to a line buffer structure; a pointer
72.I p
73 to a chunk of data to read; and the size
74.I sz
75of the chunk of data. The data is pushed through the line buffer and
76any complete lines are passed on to the line handler.
77.PP
78The complex interface is the pair of functions
79.I lbuf_free
80and
81.IR lbuf_flush .
82.PP
83The
84.B lbuf_free
85function returns the address and size of a free portion of the line
86buffer's memory into which data may be written. The function is passed
87the address
88.I l
89of the line buffer. Its result is the size of the free area, and it
90writes the base address of this free space to the location pointed to by
91the argument
92.IR p .
93The caller's data must be written to ascending memory locations starting
94at
95.BI * p
96and no data may be written beyond the end of the free space. However,
97it isn't necessary to completely fill the buffer.
98.PP
99Once the free area has had some data written to it,
100.B lbuf_flush
101is called to examine the new data and break it into text lines. This is
102given three arguments:
103.TP
104.I b
105The address of the line buffer.
106.TP
107.I p
108The address at which the new data has been written. This must be the
109base address returned from
110.BR lbuf_free .
111.TP
112.I len
113The number of bytes which have been written to the buffer.
114.PP
115The
116.B lbuf_flush
117function breaks the new data into lines as described below, and passes
118each one in turn to the line-handler function.
119.PP
120The
121.B lbuf_snarf
122function is trivially implemented in terms of the more complex
123.B lbuf_free / lbuf_flush
124interface.
125.SS "Line breaking"
126The line buffer considers a line to end with either a simple linefeed
127character (the normal Unix convention) or a carriage-return/linefeed
128pair (the Internet convention).
129.PP
130The line buffer has a fixed amount of memory available to it. This is
131deliberate, to prevent a trivial attack whereby a remote user sends a
132stream of data containing no newline markers, wasting the server's
133memory. Instead, the buffer will truncate overly long lines (silently)
134and return only the initial portion. It will ignore the rest of the
135line completely.
136.SS "Line-handler functions"
137Completed lines, as already said, are passed to the caller's
138line-handler function. The function is given two arguments:
139the address
140.I s
141of the line which has just been read, and the pointer
142.I p
143which was set up in the call to
144.B lbuf_init .
145The line passed is null-terminated, and has had its trailing newline
146stripped. The area of memory in which the string is located may be
147overwritten by the line-handler function, although writing beyond the
148terminating zero byte is not permitted.
149.PP
150The line pointer argument
151.I s
152may be null to signify end-of-file. See the next section.
153.SS "Flushing the remaining data"
154When the client program knows that there's no more data arriving (for
155example, an end-of-file condition exists on its data source) it should
156call the function
157.BR lbuf_close
158to flush out the remaining data in the buffer as one last (improperly
159terminated) line. This will pass the remaining text to the line
160handler, if there is any, and then call the handler one final time with
161a null pointer rather than the address of a text line to inform it of
162the end-of-file.
163.SS "Disablement"
164The line buffer is intended to be used in higher-level program objects,
165such as the buffer selector described in
166.BR selbuf (3).
167Unfortunately, a concept from this high level needs to exist at the line
168buffer level, which complicates the description somewhat. The idea is
169that, when a line-handler attached to some higher-level object decides
170that it's read enough, it can
171.I disable
172the object so that it doesn't see any more data.
173.PP
174Clearly, since an
175.B lbuf_flush
176call can emit more than one line, so it must be aware that the line
177handler isn't interested in any more lines. However, this fact must
178also be signalled to the higher-level object so that it can detach
179itself from its data source.
180.PP
181Rather than invent some complex interface for this, the line buffer
182exports one of its structure members,
183.BR flags .
184A higher-level object wishing to disable the line buffer simply clears
185the bit
186.B LBUF_ENABLE
187in the flags word.
188.PP
189Disabling a buffer causes an immediate return from
190.BR lbuf_flush .
191However, it is not permitted for the functions
192.B lbuf_flush
193or
194.B lbuf_close
195to be called on a disabled buffer. (This condition isn't checked for;
196it'll just do the wrong thing.) Furthermore, the
197.B lbuf_snarf
198function does not handle disablement at all, because it would complicate
199the interface so much that it wouldn't have any advantage over the more
200general
201.BR lbuf_free / lbuf_flush .
202.SH "SEE ALSO"
203.BR selbuf (3),
204.BR mLib (3).
205.SH "AUTHOR"
206Mark Wooding, <mdw@nsict.org>