diff options
author | des <des@FreeBSD.org> | 2001-01-28 00:13:01 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2001-01-28 00:13:01 +0000 |
commit | ba6b6e22f55bc3879df3d7e1ddcf477229670098 (patch) | |
tree | acadf9c9903869d9ab5d644419fb18c697b186d4 | |
parent | 5790cce92db5d94e0d0692cd4d28d5d7e7bb61b6 (diff) | |
download | FreeBSD-src-ba6b6e22f55bc3879df3d7e1ddcf477229670098.zip FreeBSD-src-ba6b6e22f55bc3879df3d7e1ddcf477229670098.tar.gz |
Add sbuf_clear() and sbuf_overflowed().
Move the helper macros from sbuf.h to sbuf.c
Use ints instead of size_ts.
Relax the requirements for sbuf_finish(): it is now possible to finish an
overflowed buffer.
Make sbuf_len() return -1 instead of 0 if the sbuf overflowed.
Requested by: gibbs
-rw-r--r-- | sys/kern/subr_sbuf.c | 62 | ||||
-rw-r--r-- | sys/sys/sbuf.h | 27 |
2 files changed, 57 insertions, 32 deletions
diff --git a/sys/kern/subr_sbuf.c b/sys/kern/subr_sbuf.c index 9e537a8..c59cea7 100644 --- a/sys/kern/subr_sbuf.c +++ b/sys/kern/subr_sbuf.c @@ -38,6 +38,23 @@ MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers"); +/* + * Predicates + */ +#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC) +#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED) +#define SBUF_HASOVERFLOWED(s) ((s)->s_flags & SBUF_OVERFLOWED) +#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1) + +/* + * Set / clear flags + */ +#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0) +#define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0) + +/* + * Debugging support + */ #ifdef INVARIANTS static void assert_sbuf_integrity(struct sbuf *s) @@ -68,8 +85,10 @@ assert_sbuf_state(struct sbuf *s, int state) * big enough to hold at least length characters. */ int -sbuf_new(struct sbuf *s, char *buf, size_t length, int flags) +sbuf_new(struct sbuf *s, char *buf, int length, int flags) { + KASSERT(length >= 0, + ("attempt to create an sbuf of negative length (%d)", length)); KASSERT(flags == 0, (__FUNCTION__ " called with non-zero flags")); KASSERT(s != NULL, @@ -89,10 +108,23 @@ sbuf_new(struct sbuf *s, char *buf, size_t length, int flags) } /* + * Clear an sbuf and reset its position + */ +void +sbuf_clear(struct sbuf *s) +{ + assert_sbuf_integrity(s); + + SBUF_CLEARFLAG(s, SBUF_FINISHED); + SBUF_CLEARFLAG(s, SBUF_OVERFLOWED); + s->s_len = 0; +} + +/* * Set the sbuf's position to an arbitrary value */ int -sbuf_setpos(struct sbuf *s, size_t pos) +sbuf_setpos(struct sbuf *s, int pos) { assert_sbuf_integrity(s); assert_sbuf_state(s, 0); @@ -138,7 +170,7 @@ sbuf_cpy(struct sbuf *s, char *str) assert_sbuf_integrity(s); assert_sbuf_state(s, 0); - s->s_len = 0; + sbuf_clear(s); return (sbuf_cat(s, str)); } @@ -168,7 +200,7 @@ int sbuf_printf(struct sbuf *s, char *fmt, ...) { va_list ap; - size_t len; + int len; assert_sbuf_integrity(s); assert_sbuf_state(s, 0); @@ -212,20 +244,26 @@ sbuf_putc(struct sbuf *s, int c) } /* - * Finish off an sbuf. + * Check if an sbuf overflowed */ int +sbuf_overflowed(struct sbuf *s) +{ + return SBUF_HASOVERFLOWED(s); +} + +/* + * Finish off an sbuf. + */ +void sbuf_finish(struct sbuf *s) { assert_sbuf_integrity(s); assert_sbuf_state(s, 0); - if (SBUF_HASOVERFLOWED(s)) - return (-1); - s->s_buf[s->s_len++] = '\0'; + SBUF_CLEARFLAG(s, SBUF_OVERFLOWED); SBUF_SETFLAG(s, SBUF_FINISHED); - return (0); } /* @@ -237,22 +275,20 @@ sbuf_data(struct sbuf *s) assert_sbuf_integrity(s); assert_sbuf_state(s, SBUF_FINISHED); - if (SBUF_HASOVERFLOWED(s)) - return (NULL); return s->s_buf; } /* * Return the length of the sbuf data. */ -size_t +int sbuf_len(struct sbuf *s) { assert_sbuf_integrity(s); assert_sbuf_state(s, SBUF_FINISHED); if (SBUF_HASOVERFLOWED(s)) - return (0); + return (-1); return s->s_len; } diff --git a/sys/sys/sbuf.h b/sys/sys/sbuf.h index 5995ec1..0244466 100644 --- a/sys/sys/sbuf.h +++ b/sys/sys/sbuf.h @@ -37,8 +37,8 @@ struct sbuf { char *s_buf; /* storage buffer */ struct sbuf *s_next; /* next in chain */ - size_t s_size; /* size of storage buffer */ - size_t s_len; /* current length of string */ + int s_size; /* size of storage buffer */ + int s_len; /* current length of string */ #define SBUF_AUTOEXTEND 0x00000001 /* automatically extend buffer */ #define SBUF_DYNAMIC 0x00010000 /* s_buf must be freed */ #define SBUF_FINISHED 0x00020000 /* set by sbuf_finish() */ @@ -47,30 +47,19 @@ struct sbuf { }; /* - * Predicates - */ -#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC) -#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED) -#define SBUF_HASOVERFLOWED(s) ((s)->s_flags & SBUF_OVERFLOWED) -#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1) - -/* - * Other macros - */ -#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0) - -/* * API functions */ -int sbuf_new(struct sbuf *s, char *buf, size_t length, int flags); -int sbuf_setpos(struct sbuf *s, size_t pos); +int sbuf_new(struct sbuf *s, char *buf, int length, int flags); +void sbuf_clear(struct sbuf *s); +int sbuf_setpos(struct sbuf *s, int pos); int sbuf_cat(struct sbuf *s, char *str); int sbuf_cpy(struct sbuf *s, char *str); int sbuf_printf(struct sbuf *s, char *fmt, ...); int sbuf_putc(struct sbuf *s, int c); -int sbuf_finish(struct sbuf *s); +int sbuf_overflowed(struct sbuf *s); +void sbuf_finish(struct sbuf *s); char *sbuf_data(struct sbuf *s); -size_t sbuf_len(struct sbuf *s); +int sbuf_len(struct sbuf *s); void sbuf_delete(struct sbuf *s); #endif |