From: Christopher Faulet Date: Tue, 6 Feb 2024 06:57:51 +0000 (+0100) Subject: MEDIUM: buf: Add b_getline() and b_getdelim() functions X-Git-Tag: v3.0-dev7~61 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1380b972855cae7307041c81518034f1ba1ba9f2;p=thirdparty%2Fhaproxy.git MEDIUM: buf: Add b_getline() and b_getdelim() functions These functions are very similar to co_getline() and co_getdelim(). The first one retrieves the longest part of the buffer that is composed exclusively of characters not in the a delimiter set. The second one stops on LF only and thus returns a line. --- diff --git a/include/haproxy/buf.h b/include/haproxy/buf.h index 6118cc47f3..ad22e6f1ff 100644 --- a/include/haproxy/buf.h +++ b/include/haproxy/buf.h @@ -435,6 +435,121 @@ static inline size_t b_getblk_nc(const struct buffer *buf, const char **blk1, si return 1; } +/* Locates the longest part of the buffer that is composed exclusively of + * characters not in the set, and delimited by one of these characters, + * and returns the initial part and the first of such delimiters. A single + * escape character in may be specified so that when not 0 and found, + * the character that follows it is never taken as a delimiter. Note that + * cannot contain the zero byte, hence this function is not usable with + * byte zero as a delimiter. + * + * Return values : + * >0 : number of bytes read. Includes the sep if present before len or end. + * =0 : no sep before end found. is left undefined. + * + * The buffer is left unaffected. Unused buffers are left in an undefined state. + */ +static inline size_t b_getdelim(const struct buffer *buf, size_t offset, size_t count, + char *str, size_t len, const char *delim, char escape) +{ + uchar delim_map[256 / 8]; + int found, escaped; + uint pos, bit; + size_t ret, max; + uchar b; + char *p; + + ret = 0; + p = b_peek(buf, offset); + + max = len; + if (!count || offset+count > b_data(buf)) + goto out; + if (max > count) { + max = count; + str[max-1] = 0; + } + + /* create the byte map */ + memset(delim_map, 0, sizeof(delim_map)); + while ((b = *delim)) { + pos = b >> 3; + bit = b & 7; + delim_map[pos] |= 1 << bit; + delim++; + } + + found = escaped = 0; + while (max) { + *str++ = b = *p; + ret++; + max--; + + if (escape && (escaped || *p == escape)) { + escaped = !escaped; + goto skip; + } + + pos = b >> 3; + bit = b & 7; + if (delim_map[pos] & (1 << bit)) { + found = 1; + break; + } + skip: + p = b_next(buf, p); + } + + if (ret > 0 && !found) + ret = 0; + out: + if (max) + *str = 0; + return ret; +} + +/* Gets one text line out of aa buffer. + * Return values : + * >0 : number of bytes read. Includes the \n if present before len or end. + * =0 : no '\n' before end found. is left undefined. + * + * The buffer is left unaffected. Unused buffers are left in an undefined state. + */ +static inline size_t b_getline(const struct buffer *buf, size_t offset, size_t count, + char *str, size_t len) +{ + size_t ret, max; + char *p; + + ret = 0; + p = b_peek(buf, offset); + + max = len; + if (!count || offset+count > b_data(buf)) + goto out; + if (max > count) { + max = count; + str[max-1] = 0; + } + + while (max) { + *str++ = *p; + ret++; + max--; + + if (*p == '\n') + break; + p = b_next(buf, p); + } + + if (ret > 0 && *(str-1) != '\n') + ret = 0; + out: + if (max) + *str = 0; + return ret; +} + /*********************************************/ /* Functions used to modify the buffer state */