diff --git a/include/proto/buffers.h b/include/proto/buffers.h index 5caff85fb..f82e461d5 100644 --- a/include/proto/buffers.h +++ b/include/proto/buffers.h @@ -242,6 +242,19 @@ static inline int buffer_contig_space(const struct buffer *buf) return right - left; } +/* Advances the buffer by bytes, which means that the buffer + * pointer advances, and that as many bytes from in are transferred + * to out. The caller is responsible for ensuring that adv is always + * smaller than or equal to b->i. The BF_OUT_EMPTY flag is updated. + */ +static inline void b_adv(struct buffer *b, unsigned int adv) +{ + b->i -= adv; + b->o += adv; + if (b->o) + b->flags &= ~BF_OUT_EMPTY; + b->p = b_ptr(b, adv); +} /* Return the amount of bytes that can be written into the buffer at once, * excluding the amount of reserved space passed in , which is diff --git a/src/buffers.c b/src/buffers.c index 40aa57a96..2bd24a8c5 100644 --- a/src/buffers.c +++ b/src/buffers.c @@ -42,29 +42,26 @@ unsigned long long buffer_forward(struct buffer *buf, unsigned long long bytes) { unsigned int new_forward; unsigned int forwarded; + unsigned int bytes32; - if (!bytes) - return 0; - if (bytes <= (unsigned long long)buf->i) { - buf->p = b_ptr(buf, (unsigned int)bytes); - buf->o += bytes; - buf->i -= bytes; - buf->flags &= ~BF_OUT_EMPTY; - return bytes; + bytes32 = bytes; + + /* hint: avoid comparisons on long long for the fast case, since if the + * length does not fit in an unsigned it, it will never be forwarded at + * once anyway. + */ + if (bytes <= ~0U) { + if (bytes32 <= buf->i) { + /* OK this amount of bytes might be forwarded at once */ + if (!bytes32) + return 0; + b_adv(buf, bytes32); + return bytes; + } } forwarded = buf->i; - buf->p = bi_end(buf); - buf->o += forwarded; - buf->i = 0; - - if (buf->o) - buf->flags &= ~BF_OUT_EMPTY; - - if (buf->o < buffer_max_len(buf)) - buf->flags &= ~BF_FULL; - else - buf->flags |= BF_FULL; + b_adv(buf, buf->i); /* Note: the case below is the only case where we may return * a byte count that does not fit into a 32-bit number. @@ -211,10 +208,7 @@ int buffer_put_block(struct buffer *buf, const char *blk, int len) fwd = buf->to_forward; buf->to_forward -= fwd; } - buf->o += fwd; - buf->i -= fwd; - buf->p = b_ptr(buf, fwd); - buf->flags &= ~BF_OUT_EMPTY; + b_adv(buf, fwd); } buf->flags &= ~BF_FULL; diff --git a/src/stream_sock.c b/src/stream_sock.c index 038e8c81a..575e24c0b 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -309,10 +309,7 @@ int stream_sock_read(int fd) { fwd = b->to_forward; b->to_forward -= fwd; } - b->o += fwd; - b->i -= fwd; - b->p = b_ptr(b, fwd); - b->flags &= ~BF_OUT_EMPTY; + b_adv(b, fwd); } if (fdtab[fd].state == FD_STCONN)