From 4fe7a2ec6c75266cf961537c362f14d2e9814a58 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 1 Sep 2009 06:41:32 +0200 Subject: [PATCH] [MINOR] buffers: add peekchar and peekline functions for stream interfaces 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 | 18 +++++++++++++++ src/buffers.c | 49 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/proto/buffers.h b/include/proto/buffers.h index d4ae20b92..544db654f 100644 --- a/include/proto/buffers.h +++ b/include/proto/buffers.h @@ -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); diff --git a/src/buffers.c b/src/buffers.c index 6d406c515..edda45954 100644 --- a/src/buffers.c +++ b/src/buffers.c @@ -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. 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 at position which must be in buffer , * and moves just after the end of .