]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: buffers: add a new b_move() function
authorWilly Tarreau <w@1wt.eu>
Sat, 22 Dec 2018 18:19:50 +0000 (19:19 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 24 Dec 2018 10:45:00 +0000 (11:45 +0100)
This function will be used to move parts of a buffer to another place
in the same buffer, even if the parts overlap. In order to keep things
under reasonable control, it only uses a length and absolute offsets
for the source and destination, and doesn't consider head nor data.

doc/internals/buffer-api.txt
include/common/buf.h

index 7938f4c9a3c4c199c05a38fe2690d8c4dc1a2ae8..13881f7eb51e4f28e923f07f4fef4e55306132e1 100644 (file)
@@ -443,6 +443,11 @@ b_putblk()          | buffer *buf      | tries to append block <blk> at the end
                     |                  | available. It returns the number of
                     |                  | bytes really copied
 --------------------+------------------+---------------------------------------
+b_move()            | buffer *buf      | moves block (src,len) left or right
+                    | size_t src       | by <shift> bytes, supporting wrapping
+                    | size_t len       | and overlapping.
+                    | size_t shift     |
+--------------------+------------------+---------------------------------------
 b_rep_blk()         | buffer *buf      | writes the block <blk> at position
                     | char *pos        | <pos> which must be in buffer <b>, and
                     | char *end        | moves the part between <end> and the
index cc670bf38c91ebf6ec28a58e2fcb7cdaec592513..d495a19cf730a94be7fedf7ffd8b6ddecacab897 100644 (file)
@@ -564,6 +564,63 @@ static inline size_t b_xfer(struct buffer *dst, struct buffer *src, size_t count
        return ret;
 }
 
+/* Moves <len> bytes from absolute position <src> of buffer <b> by <shift>
+ * bytes, while supporting wrapping of both the source and the destination.
+ * The position is relative to the buffer's origin and may overlap with the
+ * target position. The <shift>'s absolute value must be strictly lower than
+ * the buffer's size. The main purpose is to aggregate data block during
+ * parsing while removing unused delimiters. The buffer's length is not
+ * modified, and the caller must take care of size adjustments and holes by
+ * itself.
+ */
+static inline void b_move(const struct buffer *b, size_t src, size_t len, ssize_t shift)
+{
+       char  *orig = b_orig(b);
+       size_t size = b_size(b);
+       size_t dst  = src + size + shift;
+       size_t cnt;
+
+       if (dst >= size)
+               dst -= size;
+
+       if (shift < 0) {
+               /* copy from left to right */
+               for (; (cnt = len); len -= cnt) {
+                       if (cnt > size - src)
+                               cnt = size - src;
+                       if (cnt > size - dst)
+                               cnt = size - dst;
+
+                       memmove(orig + dst, orig + src, cnt);
+                       dst += cnt;
+                       src += cnt;
+                       if (dst >= size)
+                               dst -= size;
+                       if (src >= size)
+                               src -= size;
+               }
+       }
+       else if (shift > 0) {
+               /* copy from right to left */
+               for (; (cnt = len); len -= cnt) {
+                       size_t src_end = src + len;
+                       size_t dst_end = dst + len;
+
+                       if (dst_end > size)
+                               dst_end -= size;
+                       if (src_end > size)
+                               src_end -= size;
+
+                       if (cnt > dst_end)
+                               cnt = dst_end;
+                       if (cnt > src_end)
+                               cnt = src_end;
+
+                       memmove(orig + dst_end - cnt, orig + src_end - cnt, cnt);
+               }
+       }
+}
+
 /* b_rep_blk() : writes the block <blk> at position <pos> which must be in
  * buffer <b>, and moves the part between <end> and the buffer's tail just
  * after the end of the copy of <blk>. This effectively replaces the part