summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmeric Brun <ebrun@haproxy.com>2020-10-05 14:35:21 +0200
committerWilly Tarreau <w@1wt.eu>2020-10-07 17:17:27 +0200
commit6d75616951b260456f96f370210432b3108891b0 (patch)
treef39ec6efa97d198e331c443ceac0bf34fe9d17b6
parent2897644ae5cdfde7a91271b3c4c7d879ed336be3 (diff)
downloadhaproxy-6d75616951b260456f96f370210432b3108891b0.tar.gz
MINOR: channel: new getword and getchar functions on channel.
This patch adds two new functions to get a char or a word from a channel.
-rw-r--r--include/haproxy/channel.h2
-rw-r--r--src/channel.c74
2 files changed, 76 insertions, 0 deletions
diff --git a/include/haproxy/channel.h b/include/haproxy/channel.h
index 3cd3bb3b1..de51d0467 100644
--- a/include/haproxy/channel.h
+++ b/include/haproxy/channel.h
@@ -47,7 +47,9 @@ int ci_getline_nc(const struct channel *chn, char **blk1, size_t *len1, char **b
int ci_getblk_nc(const struct channel *chn, char **blk1, size_t *len1, char **blk2, size_t *len2);
int ci_insert_line2(struct channel *c, int pos, const char *str, int len);
int co_inject(struct channel *chn, const char *msg, int len);
+int co_getchar(const struct channel *chn, char *c);
int co_getline(const struct channel *chn, char *str, int len);
+int co_getword(const struct channel *chn, char *str, int len, char sep);
int co_getblk(const struct channel *chn, char *blk, int len, int offset);
int co_getline_nc(const struct channel *chn, const char **blk1, size_t *len1, const char **blk2, size_t *len2);
int co_getblk_nc(const struct channel *chn, const char **blk1, size_t *len1, const char **blk2, size_t *len2);
diff --git a/src/channel.c b/src/channel.c
index a139eada1..ba8ab638a 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -175,6 +175,57 @@ int ci_putblk(struct channel *chn, const char *blk, int len)
return len;
}
+/* Gets one text word out of a channel's buffer from a stream interface.
+ * Return values :
+ * >0 : number of bytes read. Includes the sep if present before len or end.
+ * =0 : no sep before end found. <str> is left undefined.
+ * <0 : no more bytes readable because output is shut.
+ * The channel status is not changed. The caller must call co_skip() to
+ * update it. The line separator 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 line separator.
+ */
+int co_getword(const struct channel *chn, char *str, int len, char sep)
+{
+ int ret, max;
+ char *p;
+
+ ret = 0;
+ max = len;
+
+ /* closed or empty + imminent close = -1; empty = 0 */
+ if (unlikely((chn->flags & CF_SHUTW) || channel_is_empty(chn))) {
+ if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW))
+ ret = -1;
+ goto out;
+ }
+
+ p = co_head(chn);
+
+ if (max > co_data(chn)) {
+ max = co_data(chn);
+ str[max-1] = 0;
+ }
+ while (max) {
+ *str++ = *p;
+ ret++;
+ max--;
+
+ if (*p == sep)
+ break;
+ p = b_next(&chn->buf, p);
+ }
+ if (ret > 0 && ret < len &&
+ (ret < co_data(chn) || channel_may_recv(chn)) &&
+ *(str-1) != sep &&
+ !(chn->flags & (CF_SHUTW|CF_SHUTW_NOW)))
+ ret = 0;
+ out:
+ if (max)
+ *str = 0;
+ return ret;
+}
+
/* Gets one text line out of a channel's buffer from a stream interface.
* Return values :
* >0 : number of bytes read. Includes the \n if present before len or end.
@@ -226,6 +277,29 @@ int co_getline(const struct channel *chn, char *str, int len)
return ret;
}
+/* Gets one char of data from a channel's buffer,
+ * Return values :
+ * 1 : number of bytes read, equal to requested size.
+ * =0 : not enough data available. <c> is left undefined.
+ * <0 : no more bytes readable because output is shut.
+ * The channel status is not changed. The caller must call co_skip() to
+ * update it.
+ */
+int co_getchar(const struct channel *chn, char *c)
+{
+ if (chn->flags & CF_SHUTW)
+ return -1;
+
+ if (unlikely(co_data(chn) == 0)) {
+ if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW))
+ return -1;
+ return 0;
+ }
+
+ *c = *(co_head(chn));
+ return 1;
+}
+
/* Gets one full block of data at once from a channel's buffer, optionally from
* a specific offset. Return values :
* >0 : number of bytes read, equal to requested size.