sbuf: Process more than one char at a time

Revamp sbuf_put_byte() to sbuf_put_bytes() in the obvious fashion and
fixup callers.

Add a thin shim around sbuf_put_bytes() with the old ABI to avoid ugly
changes to some callers.

Reviewed by:	jhb, markj
Obtained from:	Dan Sledz
Sponsored by:	EMC / Isilon Storage Division
Differential Revision:	https://reviews.freebsd.org/D3717
This commit is contained in:
cem 2015-09-25 18:37:14 +00:00
parent 048c6e7723
commit d13a26b53a

@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/ctype.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/limits.h>
#include <sys/malloc.h>
#include <sys/systm.h>
#include <sys/uio.h>
@ -42,6 +43,7 @@ __FBSDID("$FreeBSD$");
#else /* _KERNEL */
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@ -383,34 +385,51 @@ sbuf_drain(struct sbuf *s)
}
/*
* Append a byte to an sbuf. This is the core function for appending
* Append bytes to an sbuf. This is the core function for appending
* to an sbuf and is the main place that deals with extending the
* buffer and marking overflow.
*/
static void
sbuf_put_byte(struct sbuf *s, int c)
sbuf_put_bytes(struct sbuf *s, const char *buf, size_t len)
{
size_t n;
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
if (s->s_error != 0)
return;
if (SBUF_FREESPACE(s) <= 0) {
/*
* If there is a drain, use it, otherwise extend the
* buffer.
*/
if (s->s_drain_func != NULL)
(void)sbuf_drain(s);
else if (sbuf_extend(s, 1) < 0)
s->s_error = ENOMEM;
if (s->s_error != 0)
return;
while (len > 0) {
if (SBUF_FREESPACE(s) <= 0) {
/*
* If there is a drain, use it, otherwise extend the
* buffer.
*/
if (s->s_drain_func != NULL)
(void)sbuf_drain(s);
else if (sbuf_extend(s, len > INT_MAX ? INT_MAX : len)
< 0)
s->s_error = ENOMEM;
if (s->s_error != 0)
return;
}
n = SBUF_FREESPACE(s);
if (len < n)
n = len;
memcpy(&s->s_buf[s->s_len], buf, n);
s->s_len += n;
if (SBUF_ISSECTION(s))
s->s_sect_len += n;
len -= n;
buf += n;
}
s->s_buf[s->s_len++] = c;
if (SBUF_ISSECTION(s))
s->s_sect_len++;
}
static void
sbuf_put_byte(struct sbuf *s, char c)
{
sbuf_put_bytes(s, &c, 1);
}
/*
@ -419,19 +438,10 @@ sbuf_put_byte(struct sbuf *s, int c)
int
sbuf_bcat(struct sbuf *s, const void *buf, size_t len)
{
const char *str = buf;
const char *end = str + len;
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
sbuf_put_bytes(s, buf, len);
if (s->s_error != 0)
return (-1);
for (; str < end; str++) {
sbuf_put_byte(s, *str);
if (s->s_error != 0)
return (-1);
}
return (0);
}
@ -485,18 +495,12 @@ sbuf_bcpy(struct sbuf *s, const void *buf, size_t len)
int
sbuf_cat(struct sbuf *s, const char *str)
{
size_t n;
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
n = strlen(str);
sbuf_put_bytes(s, str, n);
if (s->s_error != 0)
return (-1);
while (*str != '\0') {
sbuf_put_byte(s, *str++);
if (s->s_error != 0)
return (-1);
}
return (0);
}