chiark / gitweb /
Hack if there is no @_SC_OPEN_MAX@ or @OPEN_MAX@.
[mLib] / lbuf.c
diff --git a/lbuf.c b/lbuf.c
index 63eb4471bbd8c8023661d63c71117412a9dea258..8b930763d34016a31ead58ad95a39b1fd2de318f 100644 (file)
--- a/lbuf.c
+++ b/lbuf.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: lbuf.c,v 1.2 1999/05/17 20:36:08 mdw Exp $
+ * $Id: lbuf.c,v 1.5 2001/02/03 16:23:33 mdw Exp $
  *
  * Block-to-line buffering
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: lbuf.c,v $
+ * Revision 1.5  2001/02/03 16:23:33  mdw
+ * Bug fix: handle a disable during a close-induced flush without dumping
+ * core.
+ *
+ * Revision 1.4  2000/06/17 10:38:14  mdw
+ * Add support for variable buffer sizes.
+ *
+ * Revision 1.3  1999/05/22 13:38:50  mdw
+ * Fix bug which discarded initial portions of incomplete lines.
+ *
  * Revision 1.2  1999/05/17 20:36:08  mdw
  * Make the magical constants for the buffer flags uppercase.
  *
 
 /*----- Header files ------------------------------------------------------*/
 
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include "alloc.h"
+#include "arena.h"
 #include "lbuf.h"
 
 /*----- Main code ---------------------------------------------------------*/
@@ -78,6 +91,11 @@ void lbuf_flush(lbuf *b, char *p, size_t len)
   char *base;                          /* Base address of current line */
   int cr;                              /* Carriage return state */
 
+  if (b->f & LBUF_CLOSE) {
+    b->func(0, b->p);
+    return;
+  }
+
   /* --- Initialize variables as necessary --- */
 
   if (!p) {
@@ -91,7 +109,7 @@ void lbuf_flush(lbuf *b, char *p, size_t len)
 
   /* --- Clear @base@ if I'm discarding an overlong line --- */
 
-  if (b->len == sizeof(b->buf))
+  if (b->len == b->sz)
     base = 0;
   else
     base = b->buf;
@@ -148,7 +166,7 @@ void lbuf_flush(lbuf *b, char *p, size_t len)
 
   if (base) {
     size_t len = l - base;
-    if (len == sizeof(b->buf)) {
+    if (len == b->sz) {
       b->buf[len - 1] = 0;
       b->func(base, b->p);
     } else if (base != b->buf)
@@ -170,15 +188,20 @@ void lbuf_flush(lbuf *b, char *p, size_t len)
  * Use:                Empties the buffer of any data currently lurking in it, and
  *             informs the client that this has happened.  It's assumed that
  *             the buffer is enabled: you shouldn't be reading close events
- *             on disabled buffers.
+ *             on disabled buffers.  The buffer, if allocated, is freed.
  */
 
 void lbuf_close(lbuf *b)
 {
-  if (b->len && b->len != sizeof(b->buf)) {
+  if (b->len && b->len != b->sz) {
     b->buf[b->len] = 0;
     b->func(b->buf, b->p);
   }
+  if (b->buf) {
+    x_free(b->a, b->buf);
+    b->buf = 0;
+  }
+  b->f |= LBUF_CLOSE;
   if (b->f & LBUF_ENABLE)
     b->func(0, b->p);
 }
@@ -192,7 +215,8 @@ void lbuf_close(lbuf *b)
  *
  * Use:                Returns the free portion of a line buffer.  Data can then be
  *             written to this portion, and split out into lines by calling
- *             @lbuf_flush@.
+ *             @lbuf_flush@.  A buffer is allocated if none currently
+ *             exists.
  */
 
 size_t lbuf_free(lbuf *b, char **p)
@@ -201,18 +225,20 @@ size_t lbuf_free(lbuf *b, char **p)
    *
    * If a line from the file wouldn't fit in the buffer, I truncate it and
    * return what would fit.  The rest of the line ought to be discarded.
-   * This condition is signalled by @len = sizeof(buf)@, and means that the
-   * entire buffer is OK to be trashed.  In other cases, @len@ is the amount
-   * of space currently occupied in the buffer.  This special case is the
-   * reason this routine exists.
+   * This condition is signalled by @len = b->sz@, and means that the entire
+   * buffer is OK to be trashed.  In other cases, @len@ is the amount of
+   * space currently occupied in the buffer.  This special case is the reason
+   * this routine exists.
    */
 
-  if (b->len == 0 || b->len == sizeof(b->buf)) {
+  if (b->len != 0 && b->len != b->sz) {
     *p = b->buf + b->len;
-    return (sizeof(b->buf) - b->len);
+    return (b->sz - b->len);
   } else {
+    if (!b->buf)
+      b->buf = x_alloc(b->a, b->sz);
     *p = b->buf;
-    return (sizeof(b->buf));
+    return (b->sz);
   }
 }
 
@@ -233,7 +259,7 @@ size_t lbuf_free(lbuf *b, char **p)
 void lbuf_snarf(lbuf *b, const void *p, size_t sz)
 {
   const char *pp = p;
-  while (sz) {
+  while (sz && (b->f & LBUF_ENABLE)) {
     size_t bsz;
     char *bp;
 
@@ -247,6 +273,28 @@ void lbuf_snarf(lbuf *b, const void *p, size_t sz)
   }
 }
 
+/* --- @lbuf_setsize@ --- *
+ *
+ * Arguments:  @lbuf *b@ = pointer to buffer block
+ *             @size_t sz@ = requested maximum line size
+ *
+ * Returns:    ---
+ *
+ * Use:                Modifies the size of the buffer associated with the block.
+ *             It is an error to resize a buffer while it contains data.
+ */
+
+void lbuf_setsize(lbuf *b, size_t sz)
+{
+  if (b->buf)
+  assert(((void)"Buffer in use in lbuf_setsize",
+        b->len == 0 || b->len == b->sz));
+  if (b->buf)
+    x_free(b->a, b->buf);
+  b->sz = sz;
+  b->buf = 0;
+}
+
 /* --- @lbuf_init@ --- *
  *
  * Arguments:  @lbuf *b@ = pointer to buffer block
@@ -256,7 +304,9 @@ void lbuf_snarf(lbuf *b, const void *p, size_t sz)
  * Returns:    ---
  *
  * Use:                Initializes a line buffer block.  Any recognized lines are
- *             passed to @func@ for processing.
+ *             passed to @func@ for processing.  No buffer is initially
+ *             allocated; this is done when the buffer is actually required
+ *             for the first time.
  */
 
 void lbuf_init(lbuf *b,
@@ -267,6 +317,26 @@ void lbuf_init(lbuf *b,
   b->p = p;
   b->len = 0;
   b->f = LBUF_ENABLE;
+  b->buf = 0;
+  b->a = arena_global;
+  lbuf_setsize(b, 256);
+}
+
+/* --- @lbuf_destroy@ --- *
+ *
+ * Arguments:  @lbuf *b@ = pointer to buffer block
+ *
+ * Returns:    ---
+ *
+ * Use:                Deallocates a line buffer and frees any resources it owned.
+ */
+
+void lbuf_destroy(lbuf *b)
+{
+  if (b->buf) {
+    x_free(b->a, b->buf);
+    b->buf = 0;
+  }
 }
 
 /*----- That's all, folks -------------------------------------------------*/