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