git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/9] Add strbuf_printf() to do formatted printing to a strbuf.

From
Kristian Høgsberg <krh@redhat.com>
Date
Sep 6, 2007, 00:23 UTC
Message-ID
<11890382243290-git-send-email-krh@redhat.com>
In-Reply-To
<11890382242333-git-send-email-krh@redhat.com>
Also, expose strbuf_add() and strbuf_add_char() to add raw data to the buffer.
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---
 strbuf.c |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 strbuf.h |    3 ++
 2 files changed, 65 insertions(+), 7 deletions(-)
diff --git a/strbuf.c b/strbuf.c
index e33d06b..2805c11 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -11,16 +11,26 @@ static void strbuf_begin(struct strbuf *sb) {
 	strbuf_init(sb);
 }
 
-static void inline strbuf_add(struct strbuf *sb, int ch) {
-	if (sb->alloc <= sb->len) {
-		sb->alloc = sb->alloc * 3 / 2 + 16;
-		sb->buf = xrealloc(sb->buf, sb->alloc);
-	}
+static void inline strbuf_grow(struct strbuf *sb, size_t extra)
+{
+	ALLOC_GROW(sb->buf, sb->len + extra, sb->alloc);
+}
+
+void strbuf_add(struct strbuf *sb, const char *data, size_t len)
+{
+	strbuf_grow(sb, len);
+	memcpy(sb->buf + sb->len, data, len);
+	sb->len += len;
+}
+
+void strbuf_add_char(struct strbuf *sb, int ch)
+{
+	strbuf_grow(sb, 1);
 	sb->buf[sb->len++] = ch;
 }
 
 static void strbuf_end(struct strbuf *sb) {
-	strbuf_add(sb, 0);
+	strbuf_add_char(sb, 0);
 }
 
 void read_line(struct strbuf *sb, FILE *fp, int term) {
@@ -33,9 +43,54 @@ void read_line(struct strbuf *sb, FILE *fp, int term) {
 	while ((ch = fgetc(fp)) != EOF) {
 		if (ch == term)
 			break;
-		strbuf_add(sb, ch);
+		strbuf_add_char(sb, ch);
 	}
 	if (ch == EOF && sb->len == 0)
 		sb->eof = 1;
 	strbuf_end(sb);
 }
+
+void strbuf_printf(struct strbuf *sb, const char *fmt, ...)
+{
+	char buffer[2048];
+	va_list args;
+	int len, size = 2 * sizeof buffer;
+
+	va_start(args, fmt);
+	len = vsnprintf(buffer, sizeof(buffer), fmt, args);
+	va_end(args);
+
+	if (len > sizeof(buffer)) {
+		/*
+		 * Didn't fit in the buffer, but this vsnprintf at
+		 * least gives us the required length back.  Grow the
+		 * buffer acccordingly and try again.
+		 */
+		strbuf_grow(sb, len);
+		va_start(args, fmt);
+		len = vsnprintf(sb->buf + sb->len,
+				sb->alloc - sb->len, fmt, args);
+		va_end(args);
+	} else if (len >= 0) {
+		/*
+		 * The initial vsnprintf fit in the temp buffer, just
+		 * copy it to the strbuf.
+		 */
+		strbuf_add(sb, buffer, len);
+	} else {
+		/*
+		 * This vnsprintf sucks and just returns -1 when the
+		 * buffer is too small.  Keep doubling the size until
+		 * it fits.
+		 */
+		while (len < 0) {
+			strbuf_grow(sb, size);
+			va_start(args, fmt);
+			len = vsnprintf(sb->buf + sb->len,
+					sb->alloc - sb->len, fmt, args);
+			va_end(args);
+			size *= 2;
+		}
+	}
+}
+
diff --git a/strbuf.h b/strbuf.h
index 74cc012..1e5d09e 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -9,5 +9,8 @@ struct strbuf {
 
 extern void strbuf_init(struct strbuf *);
 extern void read_line(struct strbuf *, FILE *, int);
+extern void strbuf_add(struct strbuf *sb, const char *data, size_t len);
+extern void strbuf_add_char(struct strbuf *sb, int ch);
+extern void strbuf_printf(struct strbuf *sb, const char *fmt, ...);
 
 #endif /* STRBUF_H */
-- 
1.5.2.GIT
Previous: Kristian HøgsbergNext: Kristian Høgsberg
Message 3 of 25 in “Enable wt-status output to a given FILE pointer.”
  1. 1/9 Enable wt-status output to a given FILE pointer.Kristian Høgsberg, Sep 6, 2007
  2. 2/9 Enable wt-status to run against non-standard index file.Kristian Høgsberg, Sep 6, 2007
  3. 3/9 Add strbuf_printf() to do formatted printing to a strbuf.Kristian Høgsberg, Sep 6, 2007
  4. 4/9 Introduce entry point for launching add--interactive.Kristian Høgsberg, Sep 6, 2007
  5. 5/9 Introduce strbuf_read_fd().Kristian Høgsberg, Sep 6, 2007
  6. 6/9 Rewrite launch_editor, create_tag and stripspace to use strbufs.Kristian Høgsberg, Sep 6, 2007
  7. 7/9 Add strbuf_read_path().Kristian Høgsberg, Sep 6, 2007
  8. 8/9 Export rerere() and launch_editor().Kristian Høgsberg, Sep 6, 2007
  9. 9/9 Implement git commit as a builtin command.Kristian Høgsberg, Sep 6, 2007
  10. Johannes SchindelinSep 6, 2007
  11. Kristian HøgsbergSep 17, 2007
  12. Johannes SchindelinSep 17, 2007
  13. Jeff KingSep 17, 2007
  14. Kristian HøgsbergSep 18, 2007
  15. Johannes SchindelinSep 6, 2007
  16. Johannes SchindelinSep 6, 2007
  17. Kristian HøgsbergSep 17, 2007
  18. Johannes SchindelinSep 6, 2007
  19. Kristian HøgsbergSep 17, 2007
  20. Johannes SchindelinSep 17, 2007
  21. Junio C HamanoSep 6, 2007
  22. Pierre HabouzitSep 6, 2007
  23. Pierre HabouzitSep 6, 2007
  24. Johannes SchindelinSep 6, 2007
  25. Kristian HøgsbergSep 17, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.