svn commit: r212365 - head/sys/kern

Matthew D Fleming mdf at FreeBSD.org
Thu Sep 9 16:51:52 UTC 2010


Author: mdf
Date: Thu Sep  9 16:51:52 2010
New Revision: 212365
URL: http://svn.freebsd.org/changeset/base/212365

Log:
  Refactor sbuf code so that most uses of sbuf_extend() are in a new
  sbuf_put_byte().  This makes it easier to add drain functionality when a
  buffer would overflow as there are fewer code points.
  
  Reviewed by:	phk

Modified:
  head/sys/kern/subr_sbuf.c

Modified: head/sys/kern/subr_sbuf.c
==============================================================================
--- head/sys/kern/subr_sbuf.c	Thu Sep  9 16:27:02 2010	(r212364)
+++ head/sys/kern/subr_sbuf.c	Thu Sep  9 16:51:52 2010	(r212365)
@@ -272,27 +272,59 @@ sbuf_setpos(struct sbuf *s, int pos)
 }
 
 /*
+ * Append a byte 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(int c, struct sbuf *s)
+{
+
+	assert_sbuf_integrity(s);
+	assert_sbuf_state(s, 0);
+
+	if (SBUF_HASOVERFLOWED(s))
+		return;
+	if (SBUF_FREESPACE(s) <= 0) {
+		if (sbuf_extend(s, 1) < 0) {
+			SBUF_SETFLAG(s, SBUF_OVERFLOWED);
+			return;
+		}
+	}
+	s->s_buf[s->s_len++] = c;
+}
+
+/*
+ * Append a non-NUL character to an sbuf.  This prototype signature is
+ * suitable for use with kvprintf(9).
+ */
+static void
+sbuf_putc_func(int c, void *arg)
+{
+
+	if (c != '\0')
+		sbuf_put_byte(c, arg);
+}
+
+/*
  * Append a byte string to an sbuf.
  */
 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);
 
 	if (SBUF_HASOVERFLOWED(s))
 		return (-1);
-	for (; len; len--) {
-		if (!SBUF_HASROOM(s) && sbuf_extend(s, len) < 0)
-			break;
-		s->s_buf[s->s_len++] = *str++;
-	}
-	if (len > 0) {
-		SBUF_SETFLAG(s, SBUF_OVERFLOWED);
-		return (-1);
-	}
+	for (; str < end; str++) {
+		sbuf_put_byte(*str, s);
+		if (SBUF_HASOVERFLOWED(s))
+			return (-1);
+ 	}
 	return (0);
 }
 
@@ -352,13 +384,9 @@ sbuf_cat(struct sbuf *s, const char *str
 		return (-1);
 
 	while (*str != '\0') {
-		if (!SBUF_HASROOM(s) && sbuf_extend(s, strlen(str)) < 0)
-			break;
-		s->s_buf[s->s_len++] = *str++;
-	}
-	if (*str != '\0') {
-		SBUF_SETFLAG(s, SBUF_OVERFLOWED);
-		return (-1);
+		sbuf_put_byte(*str, s);
+		if (SBUF_HASOVERFLOWED(s))
+			return (-1);
 	}
 	return (0);
 }
@@ -417,6 +445,23 @@ sbuf_cpy(struct sbuf *s, const char *str
 /*
  * Format the given argument list and append the resulting string to an sbuf.
  */
+#ifdef _KERNEL
+int
+sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
+{
+
+	assert_sbuf_integrity(s);
+	assert_sbuf_state(s, 0);
+
+	KASSERT(fmt != NULL,
+	    ("%s called with a NULL format string", __func__));
+
+	(void)kvprintf(fmt, sbuf_putc_func, s, 10, ap);
+	if (SBUF_HASOVERFLOWED(s))
+		return (-1);
+	return (0);
+}
+#else /* !_KERNEL */
 int
 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
 {
@@ -432,6 +477,12 @@ sbuf_vprintf(struct sbuf *s, const char 
 	if (SBUF_HASOVERFLOWED(s))
 		return (-1);
 
+	/*
+	 * For the moment, there is no way to get vsnprintf(3) to hand
+	 * back a character at a time, to push everything into
+	 * sbuf_putc_func() as was done for the kernel.
+	 */
+
 	do {
 		va_copy(ap_copy, ap);
 		len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1,
@@ -462,6 +513,7 @@ sbuf_vprintf(struct sbuf *s, const char 
 		return (-1);
 	return (0);
 }
+#endif /* _KERNEL */
 
 /*
  * Format the given arguments and append the resulting string to an sbuf.
@@ -485,17 +537,9 @@ int
 sbuf_putc(struct sbuf *s, int c)
 {
 
-	assert_sbuf_integrity(s);
-	assert_sbuf_state(s, 0);
-
+	sbuf_putc_func(c, s);
 	if (SBUF_HASOVERFLOWED(s))
 		return (-1);
-	if (!SBUF_HASROOM(s) && sbuf_extend(s, 1) < 0) {
-		SBUF_SETFLAG(s, SBUF_OVERFLOWED);
-		return (-1);
-	}
-	if (c != '\0')
-		s->s_buf[s->s_len++] = c;
 	return (0);
 }
 


More information about the svn-src-all mailing list