rbuf: adapt to work on ccan/membuf.
[ccan] / ccan / rbuf / rbuf.h
index ab1504a7c910d3d636cf2fd36922294f48fa2c17..7b5306c4a285318b679f23b36242e726fec28dd7 100644 (file)
@@ -5,41 +5,36 @@
 #include <limits.h> // For UCHAR_MAX
 #include <assert.h>
 #include <stdbool.h>
+#include <ccan/membuf/membuf.h>
 
 struct rbuf {
        int fd;
-
-       /* Where to read next. */
-       char *start;
-       /* How much of what is there is valid. */
-       size_t len;
-
-       /* The entire buffer memory we have to work with. */
-       char *buf, *buf_end;
+       MEMBUF(char) m;
 };
 
 /**
  * rbuf_init - set up a buffer.
- * @buf: the struct rbuf.
+ * @rbuf: the struct rbuf.
  * @fd: the file descriptor.
  * @buf: the buffer to use.
  * @buf_max: the size of the buffer.
+ * @expandfn: usually membuf_realloc.
  */
-static inline void rbuf_init(struct rbuf *buf,
-                            int fd, char *buffer, size_t buf_max)
+static inline void rbuf_init(struct rbuf *rbuf,
+                            int fd, char *buffer, size_t buf_max,
+                            void *(*expandfn)(struct membuf *, void *, size_t))
 {
-       buf->fd = fd;
-       buf->start = buf->buf = buffer;
-       buf->len = 0;
-       buf->buf_end = buffer + buf_max;
+       rbuf->fd = fd;
+       membuf_init(&rbuf->m, buffer, buf_max, expandfn);
 }
 
 /**
  * rbuf_open - set up a buffer by opening a file.
- * @buf: the struct rbuf.
+ * @rbuf: the struct rbuf.
  * @filename: the filename
  * @buf: the buffer to use.
  * @buf_max: the size of the buffer.
+ * @expandfn: usually membuf_realloc.
  *
  * Returns false if the open fails.  If @buf_max is 0, then the buffer
  * will be resized to rbuf_good_size() on first rbuf_fill.
@@ -47,10 +42,11 @@ static inline void rbuf_init(struct rbuf *buf,
  * Example:
  *     struct rbuf in;
  *
- *     if (!rbuf_open(&in, "foo", NULL, 0))
+ *     if (!rbuf_open(&in, "foo", NULL, 0, membuf_realloc))
  *             err(1, "Could not open foo");
  */
-bool rbuf_open(struct rbuf *rbuf, const char *name, char *buf, size_t buf_max);
+bool rbuf_open(struct rbuf *rbuf, const char *name, char *buf, size_t buf_max,
+              void *(*expandfn)(struct membuf *, void *, size_t));
 
 /**
  * rbuf_good_size - get a good buffer size for this fd.
@@ -62,73 +58,82 @@ size_t rbuf_good_size(int fd);
 
 /**
  * rbuf_fill - read into a buffer if it's empty.
- * @buf: the struct rbuf
- * @resize: the call to resize the buffer.
+ * @rbuf: the struct rbuf
  *
- * If @resize is needed and is NULL, or returns false, rbuf_read will
- * return NULL (with errno set to ENOMEM).  If a read fails, then NULL
- * is also returned.  If there is nothing more to read, it will return
- * NULL with errno set to 0.  Otherwise, returns @buf->start; @buf->len
- * is the valid length of the buffer.
+ * If @expandfn fails, rbuf_fill will return NULL (with errno set to ENOMEM).
+ * If a read fails, then NULL is also returned.  If there is nothing more to
+ * read, it will return NULL with errno set to 0.  Otherwise, returns first
+ * populated bytes (aka. rbuf_start()); rbuf_len() is the valid length of the
+ * buffer.
  *
  * You need to call rbuf_consume() to mark data in the buffer as
  * consumed.
  *
  * Example:
- *     while (rbuf_fill(&in, realloc)) {
- *             printf("%.*s\n", (int)in.len, in.start);
- *             rbuf_consume(&in, in.len);
+ *     while (rbuf_fill(&in)) {
+ *             printf("%.*s\n", (int)rbuf_len(&in), rbuf_start(&in));
+ *             rbuf_consume(&in, rbuf_len(&in));
  *     }
  *     if (errno)
  *             err(1, "reading foo");
  */
-void *rbuf_fill(struct rbuf *rbuf, void *(*resize)(void *buf, size_t len));
+void *rbuf_fill(struct rbuf *rbuf);
 
 /**
  * rbuf_consume - helper to use up data in a buffer.
- * @buf: the struct rbuf
+ * @rbuf: the struct rbuf
  * @len: the length (from @buf->start) you used.
  *
  * After rbuf_fill() you should indicate the data you've used with
  * rbuf_consume().  That way rbuf_fill() will know if it has anything
  * to do.
  */
-static inline void rbuf_consume(struct rbuf *buf, size_t len)
+static inline void rbuf_consume(struct rbuf *rbuf, size_t len)
+{
+       membuf_consume(&rbuf->m, len);
+}
+
+/**
+ * rbuf_len - helper to determine how many bytes in rbuf
+ * @rbuf: the struct rbuf
+ */
+static inline size_t rbuf_len(const struct rbuf *rbuf)
+{
+       return membuf_num_elems(&rbuf->m);
+}
+
+/**
+ * rbuf_start - helper to get pointert to unconsumed bytes in rbuf
+ * @rbuf: the struct rbuf
+ */
+static inline char *rbuf_start(const struct rbuf *rbuf)
 {
-       buf->len -= len;
-       buf->start += len;
+       return membuf_elems(&rbuf->m);
 }
 
 /**
  * rbuf_fill_all - read rest of file into a buffer.
- * @buf: the struct rbuf
- * @resize: the call to resize the buffer.
+ * @rbuf: the struct rbuf
  *
- * If @resize is needed and is NULL, or returns false, rbuf_read_all
- * will return NULL (with errno set to ENOMEM).  If a read fails,
- * then NULL is also returned, otherwise returns @buf->start.
+ * If a read or @expandfn fails then NULL returned, otherwise returns
+ * @rbuf->start.
  *
  * Example:
- *     if (!rbuf_fill_all(&in, realloc)) {
- *             if (errno)
- *                     err(1, "reading foo");
- *     }
+ *     if (!rbuf_fill_all(&in))
+ *             err(1, "reading foo");
  */
-void *rbuf_fill_all(struct rbuf *rbuf, void *(*resize)(void *buf, size_t len));
+void *rbuf_fill_all(struct rbuf *rbuf);
 
 /**
  * rbuf_read_str - fill into a buffer up to a terminator, and consume string.
- * @buf: the struct rbuf
+ * @rbuf: the struct rbuf
  * @term: the character to terminate the read.
- * @resize: the call to resize the buffer.
  *
- * If @resize is needed and is NULL, or returns false, rbuf_read_str
- * will return NULL (with errno set to ENOMEM).  If a read fails,
- * then NULL is also returned, otherwise the next string.  It
- * replaces the terminator @term (if any) with NUL, otherwise NUL
+ * If a read or @expandfn fails, then NULL is returned, otherwise the next
+ * string.  It replaces the terminator @term (if any) with NUL, otherwise NUL
  * is placed after EOF.  If you need to, you can tell this has happened
- * because the nul terminator will be at @buf->start (normally it will
- * be at @buf->start - 1).
+ * because the nul terminator will be at rbuf_start(@rbuf) (normally it will be
+ * at rbuf_start(@rbuf) - 1).
  *
  * If there is nothing remaining to be read, NULL is returned with
  * errno set to 0, unless @term is NUL, in which case it returns the
@@ -140,7 +145,7 @@ void *rbuf_fill_all(struct rbuf *rbuf, void *(*resize)(void *buf, size_t len));
  * Example:
  *     char *line;
  *
- *     line = rbuf_read_str(&in, '\n', realloc);
+ *     line = rbuf_read_str(&in, '\n');
  *     if (!line) {
  *             if (errno)
  *                     err(1, "reading foo");
@@ -150,7 +155,20 @@ void *rbuf_fill_all(struct rbuf *rbuf, void *(*resize)(void *buf, size_t len));
  *             printf("First line is %s\n", line);
  *
  */
-char *rbuf_read_str(struct rbuf *rbuf, char term,
-                   void *(*resize)(void *buf, size_t len));
+char *rbuf_read_str(struct rbuf *rbuf, char term);
 
+/**
+ * rbuf_cleanup - reset rbuf, return buffer for freeing.
+ * @rbuf: the struct rbuf
+ *
+ * The rbuf will be empty after this, and crash if you try to use it.
+ * You can rbuf_init() it again, however.
+ *
+ * Example:
+ *     free(rbuf_cleanup(&in));
+ */
+static inline char *rbuf_cleanup(struct rbuf *rbuf)
+{
+       return membuf_cleanup(&rbuf->m);
+}
 #endif /* CCAN_RBUF_H */