Add a new flag, SBUF_INCLUDENUL, and new get/set/clear functions for flags.

The SBUF_INCLUDENUL flag causes the nulterm byte at the end of the string
to be counted in the length of the data.  If copying the data using the
sbuf_data() and sbuf_len() functions, or if writing it automatically with
a drain function, the net effect is that the nulterm byte is copied along
with the rest of the data.
This commit is contained in:
Ian Lepore 2015-03-14 16:02:11 +00:00
parent df57ec4933
commit f4d281428f
3 changed files with 57 additions and 2 deletions

View file

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd April 11, 2013
.Dd March 14, 2015
.Dt SBUF 9
.Os
.Sh NAME
@ -34,6 +34,9 @@
.Nm sbuf_new_auto ,
.Nm sbuf_new_for_sysctl ,
.Nm sbuf_clear ,
.Nm sbuf_get_flags ,
.Nm sbuf_set_flags ,
.Nm sbuf_clear_flags ,
.Nm sbuf_setpos ,
.Nm sbuf_bcat ,
.Nm sbuf_bcopyin ,
@ -67,6 +70,12 @@
.Ft void
.Fn sbuf_clear "struct sbuf *s"
.Ft int
.Fn sbuf_get_flags "struct sbuf *s"
.Ft void
.Fn sbuf_set_flags "struct sbuf *s" "int flags"
.Ft void
.Fn sbuf_clear_flags "struct sbuf *s" "int flags"
.Ft int
.Fn sbuf_setpos "struct sbuf *s" "int pos"
.Ft int
.Fn sbuf_bcat "struct sbuf *s" "const void *buf" "size_t len"
@ -159,6 +168,8 @@ Attempting to extend the sbuf beyond this size results in an overflow condition.
.It Dv SBUF_AUTOEXTEND
This indicates that the storage buffer may be extended as necessary, so long
as resources allow, to hold additional data.
.It Dv SBUF_INCLUDENUL
This causes the final nulterm byte to be counted in the length of the data.
.El
.Pp
Note that if
@ -211,6 +222,18 @@ function invalidates the contents of the
and resets its position to zero.
.Pp
The
.Fn sbuf_get_flags
function returns the current user flags.
The
.Fn sbuf_set_flags
and
.Fn sbuf_get_flags
functions set or clear one or more user flags, respectively.
The user flags are described under the
.Fn sbuf_new
function.
.Pp
The
.Fn sbuf_setpos
function sets the
.Fa sbuf Ns 's

View file

@ -262,6 +262,28 @@ sbuf_uionew(struct sbuf *s, struct uio *uio, int *error)
}
#endif
int
sbuf_get_flags(struct sbuf *s)
{
return (s->s_flags & SBUF_USRFLAGMSK);
}
void
sbuf_clear_flags(struct sbuf *s, int flags)
{
s->s_flags &= ~(flags & SBUF_USRFLAGMSK);
}
void
sbuf_set_flags(struct sbuf *s, int flags)
{
s->s_flags |= (flags & SBUF_USRFLAGMSK);
}
/*
* Clear an sbuf and reset its position.
*/
@ -697,11 +719,13 @@ sbuf_finish(struct sbuf *s)
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
s->s_buf[s->s_len] = '\0';
if (s->s_flags & SBUF_INCLUDENUL)
s->s_len++;
if (s->s_drain_func != NULL) {
while (s->s_len > 0 && s->s_error == 0)
s->s_error = sbuf_drain(s);
}
s->s_buf[s->s_len] = '\0';
SBUF_SETFLAG(s, SBUF_FINISHED);
#ifdef _KERNEL
return (s->s_error);
@ -743,6 +767,10 @@ sbuf_len(struct sbuf *s)
if (s->s_error != 0)
return (-1);
/* If finished, nulterm is already in len, else add one. */
if ((s->s_flags & (SBUF_INCLUDENUL | SBUF_FINISHED)) == SBUF_INCLUDENUL)
return (s->s_len + 1);
return (s->s_len);
}

View file

@ -48,6 +48,7 @@ struct sbuf {
ssize_t s_len; /* current length of string */
#define SBUF_FIXEDLEN 0x00000000 /* fixed length buffer (default) */
#define SBUF_AUTOEXTEND 0x00000001 /* automatically extend buffer */
#define SBUF_INCLUDENUL 0x00000002 /* nulterm byte is counted in len */
#define SBUF_USRFLAGMSK 0x0000ffff /* mask of flags the user may specify */
#define SBUF_DYNAMIC 0x00010000 /* s_buf must be freed */
#define SBUF_FINISHED 0x00020000 /* set by sbuf_finish() */
@ -64,6 +65,9 @@ __BEGIN_DECLS
struct sbuf *sbuf_new(struct sbuf *, char *, int, int);
#define sbuf_new_auto() \
sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND)
int sbuf_get_flags(struct sbuf *);
void sbuf_clear_flags(struct sbuf *, int);
void sbuf_set_flags(struct sbuf *, int);
void sbuf_clear(struct sbuf *);
int sbuf_setpos(struct sbuf *, ssize_t);
int sbuf_bcat(struct sbuf *, const void *, size_t);