.\" -*-nroff-*- .TH lbuf 3 "6 July 1999" "Straylight/Edgeware" "mLib utilities library" .SH "NAME" lbuf \- split lines out of asynchronously received blocks .\" @lbuf_flush .\" @lbuf_close .\" @lbuf_free .\" @lbuf_snarf .\" @lbuf_setsize .\" @lbuf_init .\" @lbuf_destroy .SH "SYNOPSIS" .nf .B "#include " .BI "void lbuf_flush(lbuf *" b ", char *" p ", size_t " len ); .BI "void lbuf_close(lbuf *" b ); .BI "size_t lbuf_free(lbuf *" b ", char **" p ); .BI "void lbuf_snarf(lbuf *" b ", const void *" p ", size_t " sz ); .BI "void lbuf_setsize(lbuf *" b ", size_t " sz ); .BI "void lbuf_init(lbuf *" b ", lbuf_func *" func ", void *" p ); .BI "void lbuf_destroy(lbuf *" b ); .fi .SH "DESCRIPTION" The declarations in .B implement a handy object called a .IR "line buffer" . Given unpredictably-sized chunks of data, the line buffer extracts completed lines of text and passes them to a caller-supplied function. This is useful in nonblocking network servers, for example: the server can feed input from a client into a line buffer as it arrives and deal with completed text lines as they appear without having to wait for newline characters. .PP The state of a line buffer is stored in an object of type .BR lbuf . This is a structure which must be allocated by the caller. The structure should normally be considered opaque (see the section on .B Disablement for an exception to this). .SS "Initialization and finalization" The function .B lbuf_init initializes a line buffer ready for use. It is given three arguments: .TP .BI "lbuf *" b A pointer to the block of memory to use for the line buffer. The line buffer will allocate memory to store incoming data automatically: this structure just contains bookkeeping information. .TP .BI "lbuf_func *" func The .I line-handler function to which the line buffer should pass completed lines of text. See .B "Line-handler functions" below for a description of this function. .TP .BI "void *" p A pointer argument to be passed to the function when a completed line of text arrives. .PP The amount of memory set aside for reading lines is configurable. It may be set by calling .B lbuf_setsize at any time when the buffer is empty. The default limit is 256 bytes. Lines longer than the limit are truncated. By default, the buffer is allocated from the current arena, .BR arena_global (3); this may be changed by altering the buffer's .B a member to refer to a different arena at any time when the buffer is unallocated. .PP A line buffer must be destroyed after use by calling .BR lbuf_destroy , passing it the address of the buffer block. .SS "Inserting data into the buffer" There are two interfaces for inserting data into the buffer. One's much simpler than the other, although it's less expressive. .PP The simple interface is .BR lbuf_snarf . This function is given three arguments: a pointer .I b to a line buffer structure; a pointer .I p to a chunk of data to read; and the size .I sz of the chunk of data. The data is pushed through the line buffer and any complete lines are passed on to the line handler. .PP The complex interface is the pair of functions .B lbuf_free and .BR lbuf_flush . .PP The .B lbuf_free function returns the address and size of a free portion of the line buffer's memory into which data may be written. The function is passed the address .I b of the line buffer. Its result is the size of the free area, and it writes the base address of this free space to the location pointed to by the argument .IR p . The caller's data must be written to ascending memory locations starting at .BI * p and no data may be written beyond the end of the free space. However, it isn't necessary to completely fill the buffer. .PP Once the free area has had some data written to it, .B lbuf_flush is called to examine the new data and break it into text lines. This is given three arguments: .TP .BI "lbuf *" b The address of the line buffer. .TP .BI "char *" p The address at which the new data has been written. This must be the base address returned from .BR lbuf_free . .TP .BI "size_t " len The number of bytes which have been written to the buffer. .PP The .B lbuf_flush function breaks the new data into lines as described below, and passes each one in turn to the line-handler function. .PP The .B lbuf_snarf function is trivially implemented in terms of the more complex .BR lbuf_free / lbuf_flush interface. .SS "Line breaking" By default, the line buffer considers a line to end with either a simple linefeed character (the normal Unix convention) or a carriage-return/linefeed pair (the Internet convention). This can be changed by modifying the .B delim member of the .B lbuf structure: the default value is .BR LBUF_CRLF . If set to .BR LBUF_STRICTCRLF , only a carriage-return/linefeed pair will terminate a line. Any other value is a single character which is considered to be the line terminator. .PP The line buffer has a fixed amount of memory available to it. This is deliberate, to prevent a trivial attack whereby a remote user sends a stream of data containing no newline markers, wasting the server's memory. Instead, the buffer will truncate overly long lines (silently) and return only the initial portion. It will ignore the rest of the line completely. .SS "Line-handler functions" Completed lines, as already said, are passed to the caller's line-handler function. This function has the signature .IP .B "void" .IB func "(char *" s ", size_t " len ", void *" p ); .PP It is given three arguments: the address .I s of the line which has just been read; the length .I len of the line (not including the null terminator), and the pointer .I p which was set up in the call to .BR lbuf_init . The line passed is null-terminated, and has had its trailing newline stripped. The area of memory in which the string is located may be overwritten by the line-handler function, although writing beyond the terminating zero byte is not permitted. .PP The line pointer argument .I s may be null to signify end-of-file; in this case, the length .I len will be zero. See the next section. .SS "Flushing the remaining data" When the client program knows that there's no more data arriving (for example, an end-of-file condition exists on its data source) it should call the function .BR lbuf_close to flush out the remaining data in the buffer as one last (improperly terminated) line. This will pass the remaining text to the line handler, if there is any, and then call the handler one final time with a null pointer rather than the address of a text line to inform it of the end-of-file. .SS "Disablement" The line buffer is intended to be used in higher-level program objects, such as the buffer selector described in .BR selbuf (3). Unfortunately, a concept from this high level needs to exist at the line buffer level, which complicates the description somewhat. The idea is that, when a line-handler attached to some higher-level object decides that it's read enough, it can .I disable the object so that it doesn't see any more data. .PP Clearly, since an .B lbuf_flush call can emit more than one line, it must be aware that the line handler isn't interested in any more lines. However, this fact must also be signalled to the higher-level object so that it can detach itself from its data source. .PP Rather than invent some complex interface for this, the line buffer exports one of its structure members, a flags word called .BR f . A higher-level object wishing to disable the line buffer simply clears the bit .B LBUF_ENABLE in this flags word. .PP Disabling a buffer causes an immediate return from .BR lbuf_flush . However, it is not permitted for the functions .B lbuf_flush or .B lbuf_close to be called on a disabled buffer. (This condition isn't checked for; it'll just do the wrong thing.) Furthermore, the .B lbuf_snarf function does not handle disablement at all, because it would complicate the interface so much that it wouldn't have any advantage over the more general .BR lbuf_free / lbuf_flush . .SH "SEE ALSO" .BR selbuf (3), .BR mLib (3). .SH "AUTHOR" Mark Wooding,