chiark / gitweb /
Add support for variable buffer sizes.
[mLib] / lbuf.c
diff --git a/lbuf.c b/lbuf.c
index 118250d43f40c3d7d9b93c851d7c0dfa78e22af6..9c0ec229d96c8b20afff38a6ae185ca498e219ea 100644 (file)
--- a/lbuf.c
+++ b/lbuf.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: lbuf.c,v 1.3 1999/05/22 13:38:50 mdw Exp $
+ * $Id: lbuf.c,v 1.4 2000/06/17 10:38:14 mdw Exp $
  *
  * Block-to-line buffering
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: lbuf.c,v $
+ * 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.
  *
 
 /*----- 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 ---------------------------------------------------------*/
@@ -94,7 +100,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;
@@ -151,7 +157,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)
@@ -173,15 +179,19 @@ 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;
+  }
   if (b->f & LBUF_ENABLE)
     b->func(0, b->p);
 }
@@ -195,7 +205,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)
@@ -204,18 +215,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);
   }
 }
 
@@ -236,7 +249,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;
 
@@ -250,6 +263,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
@@ -259,7 +294,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,
@@ -270,6 +307,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 -------------------------------------------------*/