]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] buffers: add peekchar and peekline functions for stream interfaces
authorWilly Tarreau <w@1wt.eu>
Tue, 1 Sep 2009 04:41:32 +0000 (06:41 +0200)
committerWilly Tarreau <w@1wt.eu>
Sat, 19 Sep 2009 12:53:47 +0000 (14:53 +0200)
The buffer_si_peekline() function is sort of a fgets() to be used from a
stream interface. It returns a complete line whenever possible, and does
not update the buffer's pointer, so that the reader is free to consume
what it wants to.

buffer_si_peekchar() only returns one character, and also needs a call
to buffer_skip() once the character is definitely consumed.

include/proto/buffers.h
src/buffers.c

index d4ae20b92ad5ed7cdb7f90e72fd48eb4386662fc..544db654f5ba417b49e3f334d4fbda8bffb036d8 100644 (file)
@@ -347,8 +347,26 @@ static inline void buffer_skip(struct buffer *buf, int len)
        buf->send_max -= len;
 }
 
+/*
+ * Return one char from the buffer. If the buffer is empty and closed, return -1.
+ * If the buffer is just empty, return -2. The buffer's pointer is not advanced,
+ * it's up to the caller to call buffer_skip(buf, 1) when it has consumed the char.
+ * Also note that this function respects the send_max limit.
+ */
+static inline int buffer_si_peekchar(struct buffer *buf)
+{
+       if (buf->send_max)
+               return *buf->w;
+
+       if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW))
+               return -1;
+       else
+               return -2;
+}
+
 int buffer_write(struct buffer *buf, const char *msg, int len);
 int buffer_feed(struct buffer *buf, const char *str, int len);
+int buffer_si_peekline(struct buffer *buf, char *str, int len);
 int buffer_replace(struct buffer *b, char *pos, char *end, const char *str);
 int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len);
 int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len);
index 6d406c515b484ca9fa641fe0ca5ef713d9e9cb47..edda45954fa0227e2001fac357b8359632d01267 100644 (file)
@@ -119,6 +119,55 @@ int buffer_feed(struct buffer *buf, const char *str, int len)
        return -1;
 }
 
+/* Get one text line out of a buffer from a stream interface.
+ * Return values :
+ *   >0 : number of bytes read. Includes the \n if present before len or end.
+ *   =0 : no '\n' before end found. <buf> is undefined.
+ *   <0 : no more bytes readable + shutdown set.
+ * The buffer status is not changed. The caller must call buffer_skip() to
+ * update it. The '\n' is waited for as long as neither the buffer nor the
+ * output are full. If either of them is full, the string may be returned
+ * as is, without the '\n'.
+ */
+int buffer_si_peekline(struct buffer *buf, char *str, int len)
+{
+       int ret, max;
+       char *p;
+
+       ret = 0;
+       max = len;
+       if (!buf->send_max) {
+               if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW))
+                       ret = -1;
+               goto out;
+       }
+
+       p = buf->w;
+
+       if (max > buf->send_max) {
+               max = buf->send_max;
+               str[max] = 0;
+       }
+       while (max) {
+               *str++ = *p;
+               ret++;
+               max--;
+
+               if (*p == '\n')
+                       break;
+               p++;
+               if (p == buf->data + buf->size)
+                       p = buf->data;
+       }
+       if (*p != '\n' && ret < len && ret < buf->max_len &&
+          !(buf->flags & (BF_SHUTW|BF_SHUTW_NOW)))
+               ret = 0;
+ out:
+       if (max)
+               *str = 0;
+       return ret;
+}
+
 /*
  * this function writes the string <str> at position <pos> which must be in buffer <b>,
  * and moves <end> just after the end of <str>.