chiark / gitweb /
codec/{base32,hex}.h: Include `codec.h'.
[mLib] / buf / lbuf.h
1 /* -*-c-*-
2  *
3  * Block-to-line buffering
4  *
5  * (c) 1999 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
12  * mLib is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * mLib is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with mLib; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 #ifndef MLIB_LBUF_H
29 #define MLIB_LBUF_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Line buffering ----------------------------------------------------*
36  *
37  * The line buffer accepts as input arbitrary-sized lumps of data and
38  * converts them, by passing them to a client-supplied function, into a
39  * sequence of lines.  It's particularly useful when performing multiplexed
40  * network I/O.  It's not normally acceptable to block while waiting for the
41  * rest of a text line to arrive, for example.  The line buffer stores the
42  * start of the line until the rest of it arrives later.
43  *
44  * A line is a piece of text terminated by either a linefeed or a carriage-
45  * return/linefeed pair.  (The former is there to cope with Unix; the latter
46  * copes with Internet-format line ends.)
47  *
48  * There's a limit to the size of lines that the buffer can cope with.  It's
49  * not hard to remove this limit, but it's probably a bad idea in a lot of
50  * cases, because it'd allow a remote user to gobble arbitrary amounts of
51  * your memory.  If a line exceeds the limit, it is truncated: the initial
52  * portion of the line is processed normally, and the remaining portion is
53  * simply discarded.
54  *
55  * Lines extracted from the input data are passed, one at a time, to a
56  * `handler function', along with a caller-supplied pointer argument to
57  * provide the handler with some context.  The line read is null-terminated
58  * and does not include the trailing newline characters.  It is legal for a
59  * handler function to modify the string it is passed.  However, writing
60  * beyond the terminating null byte is not allowed.  An end-of-file condition
61  * is signalled to the handler by passing it a null pointer rather than the
62  * address of a string.
63  *
64  * A complexity arises because of the concept of a `disabled' buffer.
65  * Disablement is really a higher-level concept, but it turns out to be
66  * important to implement it here.  It's useful for a line handler function
67  * to `disable' itself, so that it doesn't get called any more.  For example,
68  * this might happen if it encouters an error, or when it finishes reading
69  * everything it wanted to read.  The line buffer needs to be `in the loop'
70  * so that it stops attempting to flush any further lines stored in its
71  * buffer towards a handler function which isn't ready to accept them.
72  * Buffers are initially enabled, although higher- level buffering systems
73  * might well disable them immediately for their own purposes.
74  */
75
76 /*----- Header files ------------------------------------------------------*/
77
78 #include <stddef.h>
79
80 #ifndef MLIB_ARENA_H
81 #  include "arena.h"
82 #endif
83
84 /*----- Data structures ---------------------------------------------------*/
85
86 /* --- The buffer structure --- *
87  *
88  * The only thing that's safe to fiddle with in here is the @lbuf_enable@
89  * flag.  Only higher-level buffering systems should be playing with even
90  * that.
91  */
92
93 struct lbuf;
94
95 typedef void lbuf_func(char */*s*/, size_t /*len*/, void */*p*/);
96
97 typedef struct lbuf {
98   lbuf_func *func;                      /* Handler function */
99   void *p;                              /* Argument for handler */
100   size_t len;                           /* Length of data in buffer */
101   size_t sz;                            /* Buffer size */
102   unsigned delim;                       /* Delimiter to look for */
103   unsigned f;                           /* Various useful state flags */
104   arena *a;                             /* Memory allocation arena */
105   char *buf;                            /* The actual buffer */
106 } lbuf;
107
108 #define LBUF_CR 1u                      /* Read a carriage return */
109 #define LBUF_ENABLE 2u                  /* Buffer is currently enabled */
110 #define LBUF_CLOSE 4u                   /* Buffer is now closed */
111
112 enum {
113   LBUF_CRLF = 256,
114   LBUF_STRICTCRLF = 257
115 };
116
117 /*----- Functions provided ------------------------------------------------*/
118
119 /* --- @lbuf_flush@ --- *
120  *
121  * Arguments:   @lbuf *b@ = pointer to buffer block
122  *              @char *p@ = pointer to where to start searching
123  *              @size_t len@ = length of new material added
124  *
125  * Returns:     ---
126  *
127  * Use:         Flushes any complete lines in a line buffer.  New material
128  *              is assumed to have been added starting at @p@.  If @p@ is
129  *              null, then the scan starts at the beginning of the buffer,
130  *              and the size of data already in the buffer is used in place
131  *              of @len@.
132  *
133  *              It is assumed that the buffer is initially enabled.  You
134  *              shouldn't be contributing data to a disabled buffer anyway.
135  *              However, the buffer handler may at some point disable itself,
136  *              and @lbuf_flush@ can cope with this eventuality.  Any pending
137  *              data is left at the start of the buffer and can be flushed
138  *              out by calling @lbuf_flush(b, 0, 0)@ if the buffer is ever
139  *              re-enabled.
140  */
141
142 extern void lbuf_flush(lbuf */*b*/, char */*p*/, size_t /*len*/);
143
144 /* --- @lbuf_close@ --- *
145  *
146  * Arguments:   @lbuf *b@ = pointer to buffer block
147  *
148  * Returns:     ---
149  *
150  * Use:         Empties the buffer of any data currently lurking in it, and
151  *              informs the client that this has happened.  It's assumed that
152  *              the buffer is enabled: you shouldn't be reading close events
153  *              on disabled buffers.
154  */
155
156 extern void lbuf_close(lbuf */*b*/);
157
158 /* --- @lbuf_free@ --- *
159  *
160  * Arguments:   @lbuf *b@ = pointer to buffer block
161  *              @char **p@ = output pointer to free space
162  *
163  * Returns:     Free buffer size.
164  *
165  * Use:         Returns the free portion of a line buffer.  Data can then be
166  *              written to this portion, and split out into lines by calling
167  *              @lbuf_flush@.
168  */
169
170 extern size_t lbuf_free(lbuf */*b*/, char **/*p*/);
171
172 /* --- @lbuf_snarf@ --- *
173  *
174  * Arguments:   @lbuf *b@ = pointer to buffer block
175  *              @const void *p@ = pointer to input data buffer
176  *              @size_t sz@ = size of data in input buffer
177  *
178  * Returns:     ---
179  *
180  * Use:         Snarfs the data from the input buffer and spits it out as
181  *              lines.  This interface ignores the complexities of dealing
182  *              with disablement: you should be using @lbuf_free@ to
183  *              contribute data if you want to cope with that.
184  */
185
186 extern void lbuf_snarf(lbuf */*b*/, const void */*p*/, size_t /*sz*/);
187
188 /* --- @lbuf_setsize@ --- *
189  *
190  * Arguments:   @lbuf *b@ = pointer to buffer block
191  *              @size_t sz@ = requested maximum line size
192  *
193  * Returns:     ---
194  *
195  * Use:         Allocates a buffer of the requested size reading lines.
196  */
197
198 extern void lbuf_setsize(lbuf */*b*/, size_t /*sz*/);
199
200 /* --- @lbuf_init@ --- *
201  *
202  * Arguments:   @lbuf *b@ = pointer to buffer block
203  *              @lbuf_func *func@ = handler function
204  *              @void *p@ = argument pointer for @func@
205  *
206  * Returns:     ---
207  *
208  * Use:         Initializes a line buffer block.  Any recognized lines are
209  *              passed to @func@ for processing.
210  */
211
212 extern void lbuf_init(lbuf */*b*/, lbuf_func */*func*/, void */*p*/);
213
214 /* --- @lbuf_destroy@ --- *
215  *
216  * Arguments:   @lbuf *b@ = pointer to buffer block
217  *
218  * Returns:     ---
219  *
220  * Use:         Deallocates a line buffer and frees any resources it owned.
221  */
222
223 extern void lbuf_destroy(lbuf */*b*/);
224
225 /*----- That's all, folks -------------------------------------------------*/
226
227 #ifdef __cplusplus
228   }
229 #endif
230
231 #endif