]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: buffer: add a function to match against string patterns
authorWilly Tarreau <w@1wt.eu>
Fri, 22 Sep 2017 13:02:54 +0000 (15:02 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 19 Oct 2017 13:01:07 +0000 (15:01 +0200)
In order to match known patterns in wrapping buffer, we'll introduce new
string manipulation functions for buffers. The new function b_isteq()
relies on an ist string for the pattern and compares it against any
location in the buffer relative to <p>. The second function bi_eat()
is specially designed to match input contents.

include/common/buffer.h

index ada43d92fb1bfeedfe96844fee79376ad0799a7a..8050b1a36f869830700cc377b98b5375f5ced202 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <common/chunk.h>
 #include <common/config.h>
+#include <common/ist.h>
 #include <common/memory.h>
 
 
@@ -567,6 +568,56 @@ static inline void offer_buffers(void *from, unsigned int threshold)
        __offer_buffer(from, threshold);
 }
 
+/*************************************************************************/
+/* functions used to manipulate strings and blocks with wrapping buffers */
+/*************************************************************************/
+
+/* returns > 0 if the first <n> characters of buffer <b> starting at
+ * offset <o> relative to b->p match <ist>. (empty strings do match). It is
+ * designed to be use with reasonably small strings (ie matches a single byte
+ * per iteration). This function is usable both with input and output data. To
+ * be used like this depending on what to match :
+ * - input contents  :  b_isteq(b, 0, b->i, ist);
+ * - output contents :  b_isteq(b, -b->o, b->o, ist);
+ * Return value :
+ *   >0 : the number of matching bytes
+ *   =0 : not enough bytes (or matching of empty string)
+ *   <0 : non-matching byte found
+ */
+static inline int b_isteq(const struct buffer *b, unsigned int o, size_t n, const struct ist ist)
+{
+       struct ist r = ist;
+       const char *p;
+       const char *end = b->data + b->size;
+
+       if (n < r.len)
+               return 0;
+
+       p = b_ptr(b, o);
+       while (r.len--) {
+               if (*p++ != *r.ptr++)
+                       return -1;
+               if (unlikely(p == end))
+                       p = b->data;
+       }
+       return ist.len;
+}
+
+/* "eats" string <ist> from the input region of buffer <b>. Wrapping data is
+ * explicitly supported. It matches a single byte per iteration so strings
+ * should remain reasonably small. Returns :
+ *   > 0 : number of bytes matched and eaten
+ *   = 0 : not enough bytes (or matching an empty string)
+ *   < 0 : non-matching byte found
+ */
+static inline int bi_eat(struct buffer *b, const struct ist ist)
+{
+       int ret = b_isteq(b, 0, b->i, ist);
+       if (ret > 0)
+               bi_del(b, ret);
+       return ret;
+}
+
 #endif /* _COMMON_BUFFER_H */
 
 /*