chiark / gitweb /
Pass line length to line handler function. Provide a @typedef@ for
authormdw <mdw>
Sun, 13 Jan 2002 13:33:01 +0000 (13:33 +0000)
committermdw <mdw>
Sun, 13 Jan 2002 13:33:01 +0000 (13:33 +0000)
handler functions.  Allow run-time configuration of line delimiters.

lbuf.c
lbuf.h
man/lbuf.3

diff --git a/lbuf.c b/lbuf.c
index 8b93076..ba18678 100644 (file)
--- a/lbuf.c
+++ b/lbuf.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: lbuf.c,v 1.5 2001/02/03 16:23:33 mdw Exp $
+ * $Id: lbuf.c,v 1.6 2002/01/13 13:32:52 mdw Exp $
  *
  * Block-to-line buffering
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: lbuf.c,v $
+ * Revision 1.6  2002/01/13 13:32:52  mdw
+ * Pass line length to line handler function.  Provide a @typedef@ for
+ * handler functions.  Allow run-time configuration of line delimiters.
+ *
  * Revision 1.5  2001/02/03 16:23:33  mdw
  * Bug fix: handle a disable during a close-induced flush without dumping
  * core.
@@ -92,7 +96,7 @@ void lbuf_flush(lbuf *b, char *p, size_t len)
   int cr;                              /* Carriage return state */
 
   if (b->f & LBUF_CLOSE) {
-    b->func(0, b->p);
+    b->func(0, 0, b->p);
     return;
   }
 
@@ -120,39 +124,36 @@ void lbuf_flush(lbuf *b, char *p, size_t len)
 
     /* --- Quickly discard uninteresting characters --- */
 
-    if (*q != '\r' && *q != '\n') {
-      cr = 0;
-      continue;
-    }
-    if (*q == '\r') {
-      cr = 1;
-      continue;
+    switch (b->delim) {
+      case LBUF_CRLF:
+      case LBUF_STRICTCRLF:
+       if (*q != '\r' && *q != '\n') {
+         cr = 0;
+         continue;
+       }
+       if (*q == '\r') {
+         cr = 1;
+         continue;
+       }
+       if (!cr && b->delim == LBUF_STRICTCRLF)
+         continue;
+       break;
+      default:
+       if (*q != b->delim)
+         continue;
     }
 
-    /* --- Two choices here --- *
-     *
-     * I can either be strict about CRLF line ends, or I can be shoddy
-     * and allow bare LFs.  I'll do the latter, although I oughtn't,
-     * because it makes testing interactively and with Unix text files
-     * easier.
-     */
-
-#ifdef STRICT_CRLF
-    if (!cr)
-      continue;
-#endif 
-
-    /* --- I have a positive ID on a linefeed --- *
+    /* --- I have a positive ID on a delimiter --- *
      *
      * If I'm interested in this string, report it to my owner.
      */
 
     if (base) {
+      len = q - base;
       if (cr)
-       q[-1] = 0;                      /* Exercise: why is this safe? */
-      else
-       *q = 0;
-      b->func(base, b->p);
+       len--;                          /* Exercise: why is this safe? */
+      base[len] = 0;
+      b->func(base, len, b->p);
       if (!(b->f & LBUF_ENABLE)) {
        base = q + 1;
        break;
@@ -165,10 +166,10 @@ void lbuf_flush(lbuf *b, char *p, size_t len)
   /* --- Sift through the aftermath --- */
 
   if (base) {
-    size_t len = l - base;
+    len = l - base;
     if (len == b->sz) {
       b->buf[len - 1] = 0;
-      b->func(base, b->p);
+      b->func(base, len - 1, b->p);
     } else if (base != b->buf)
       memmove(b->buf, base, len);
     b->len = len;
@@ -195,7 +196,7 @@ void lbuf_close(lbuf *b)
 {
   if (b->len && b->len != b->sz) {
     b->buf[b->len] = 0;
-    b->func(b->buf, b->p);
+    b->func(b->buf, b->len, b->p);
   }
   if (b->buf) {
     x_free(b->a, b->buf);
@@ -203,7 +204,7 @@ void lbuf_close(lbuf *b)
   }
   b->f |= LBUF_CLOSE;
   if (b->f & LBUF_ENABLE)
-    b->func(0, b->p);
+    b->func(0, 0, b->p);
 }
 
 /* --- @lbuf_free@ --- *
@@ -298,7 +299,7 @@ void lbuf_setsize(lbuf *b, size_t sz)
 /* --- @lbuf_init@ --- *
  *
  * Arguments:  @lbuf *b@ = pointer to buffer block
- *             @void (*func)(char *s, void *p)@ = handler function
+ *             @lbuf_func *func@ = handler function
  *             @void *p@ = argument pointer for @func@
  *
  * Returns:    ---
@@ -309,14 +310,13 @@ void lbuf_setsize(lbuf *b, size_t sz)
  *             for the first time.
  */
 
-void lbuf_init(lbuf *b,
-              void (*func)(char */*s*/, void */*p*/),
-              void *p)
+void lbuf_init(lbuf *b, lbuf_func *func, void *p)
 {
   b->func = func;
   b->p = p;
   b->len = 0;
   b->f = LBUF_ENABLE;
+  b->delim = LBUF_CRLF;
   b->buf = 0;
   b->a = arena_global;
   lbuf_setsize(b, 256);
diff --git a/lbuf.h b/lbuf.h
index fb04b5f..df8fdff 100644 (file)
--- a/lbuf.h
+++ b/lbuf.h
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: lbuf.h,v 1.6 2001/02/03 16:23:33 mdw Exp $
+ * $Id: lbuf.h,v 1.7 2002/01/13 13:32:52 mdw Exp $
  *
  * Block-to-line buffering
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: lbuf.h,v $
+ * Revision 1.7  2002/01/13 13:32:52  mdw
+ * Pass line length to line handler function.  Provide a @typedef@ for
+ * handler functions.  Allow run-time configuration of line delimiters.
+ *
  * Revision 1.6  2001/02/03 16:23:33  mdw
  * Bug fix: handle a disable during a close-induced flush without dumping
  * core.
  * that.
  */
 
+struct lbuf;
+
+typedef void lbuf_func(char */*s*/, size_t /*len*/, void */*p*/);
+
 typedef struct lbuf {
-  void (*func)(char */*s*/, void */*p*/); /* Handler function */
+  lbuf_func *func;                     /* Handler function */
   void *p;                             /* Argument for handler */
   size_t len;                          /* Length of data in buffer */
   size_t sz;                           /* Buffer size */
+  unsigned delim;                      /* Delimiter to look for */
   unsigned f;                          /* Various useful state flags */
   arena *a;                            /* Memory allocation arena */
   char *buf;                           /* The actual buffer */
@@ -130,6 +139,11 @@ typedef struct lbuf {
 #define LBUF_ENABLE 2u                 /* Buffer is currently enabled */
 #define LBUF_CLOSE 4u                  /* Buffer is now closed */
 
+enum {
+  LBUF_CRLF = 256,
+  LBUF_STRICTCRLF = 257
+};
+
 /*----- Functions provided ------------------------------------------------*/
 
 /* --- @lbuf_flush@ --- *
@@ -216,7 +230,7 @@ extern void lbuf_setsize(lbuf */*b*/, size_t /*sz*/);
 /* --- @lbuf_init@ --- *
  *
  * Arguments:  @lbuf *b@ = pointer to buffer block
- *             @void (*func)(char *s, void *p)@ = handler function
+ *             @lbuf_func *func@ = handler function
  *             @void *p@ = argument pointer for @func@
  *
  * Returns:    ---
@@ -225,9 +239,7 @@ extern void lbuf_setsize(lbuf */*b*/, size_t /*sz*/);
  *             passed to @func@ for processing.
  */
 
-extern void lbuf_init(lbuf */*b*/,
-                     void (*/*func*/)(char */*s*/, void */*p*/),
-                     void */*p*/);
+extern void lbuf_init(lbuf */*b*/, lbuf_func */*func*/, void */*p*/);
 
 /* --- @lbuf_destroy@ --- *
  *
index 87f41a3..b887130 100644 (file)
@@ -18,9 +18,7 @@ lbuf \- split lines out of asynchronously received blocks
 .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 ,
-.BI "               void (*" func ")(char *" s ", void *" p ),
-.BI "               void *" p );
+.BI "void lbuf_init(lbuf *" b ", lbuf_func *" func ", void *" p );
 .BI "void lbuf_destroy(lbuf *" b );
 .fi
 .SH "DESCRIPTION"
@@ -51,10 +49,13 @@ 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 "void (*" func ")(char *" s ", void *" p )
+.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
@@ -138,9 +139,19 @@ function is trivially implemented in terms of the more complex
 .BR lbuf_free / lbuf_flush
 interface.
 .SS "Line breaking"
-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).
+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
@@ -150,10 +161,16 @@ 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.  The function is given two arguments:
-the address
+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, and the pointer
+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 .
@@ -164,7 +181,9 @@ terminating zero byte is not permitted.
 .PP
 The line pointer argument
 .I s
-may be null to signify end-of-file.  See the next section.
+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