Subject: [PATCH] Add strbuf_fread, use it in fast-import.c.

From: Pierre Habouzit <[email-masked]>
Date: Tue, 4 Sep 2007 10:48:00 +0200

This is a good proof of concept that combined with strbuf_detach it often
helps improving readability a lot, while remaining as efficient as before.

Signed-off-by: Pierre Habouzit <[email-masked]>
---
 fast-import.c |   26 ++++++++++----------------
 strbuf.c      |   12 ++++++++++++
 strbuf.h      |    3 +++
 3 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/fast-import.c b/fast-import.c
index ab3927b..2d8daeb 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1638,20 +1638,15 @@ static void cmd_mark(void)
 
 static void *cmd_data (size_t *size)
 {
-	size_t length;
-	char *buffer;
+	struct strbuf buffer = STRBUF_INIT;
 
 	if (prefixcmp(command_buf.buf, "data "))
 		die("Expected 'data n' command, found: %s", command_buf.buf);
 
 	if (!prefixcmp(command_buf.buf + 5, "<<")) {
 		char *term = xstrdup(command_buf.buf + 5 + 2);
-		size_t sz = 8192, term_len = command_buf.len - 5 - 2;
-		length = 0;
-		buffer = xmalloc(sz);
+		size_t term_len = command_buf.len - 5 - 2;
 
-		/* XXX possible memory leak ? */
-		strbuf_detach(&command_buf);
 		for (;;) {
 			read_line(&command_buf, stdin, '\n');
 			if (command_buf.eof)
@@ -1659,19 +1654,18 @@ static void *cmd_data (size_t *size)
 			if (term_len == command_buf.len
 				&& !strcmp(term, command_buf.buf))
 				break;
-			ALLOC_GROW(buffer, length + command_buf.len + 1, sz);
-			memcpy(buffer + length, command_buf.buf, command_buf.len);
-			length += command_buf.len;
-			buffer[length++] = '\n';
+			strbuf_addbuf(&buffer, &command_buf);
+			strbuf_addch(&buffer, '\n');
 		}
 		free(term);
 	}
 	else {
-		size_t n = 0;
+		size_t n = 0, length;
+
 		length = strtoul(command_buf.buf + 5, NULL, 10);
-		buffer = xmalloc(length);
+
 		while (n < length) {
-			size_t s = fread(buffer + n, 1, length - n, stdin);
+			size_t s = strbuf_fread(&buffer, length - n, stdin);
 			if (!s && feof(stdin))
 				die("EOF in data (%lu bytes remaining)",
 					(unsigned long)(length - n));
@@ -1680,8 +1674,8 @@ static void *cmd_data (size_t *size)
 	}
 
 	skip_optional_lf();
-	*size = length;
-	return buffer;
+	*size = buffer.len;
+	return strbuf_detach(&buffer);
 }
 
 static int validate_raw_date(const char *src, char *result, int maxlen)
diff --git a/strbuf.c b/strbuf.c
index 86d5965..693fbcf 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -58,6 +58,18 @@ void strbuf_addvf(struct strbuf *sb, const char *fmt, va_list ap)
 	sb->buf[sb->len] = '\0';
 }
 
+size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f) {
+	size_t res;
+
+	strbuf_ensure(sb, size);
+	res = fread(sb->buf + sb->len, 1, size, f);
+	if (res > 0) {
+		sb->len += res;
+		sb->buf[sb->len] = '\0';
+	}
+	return res;
+}
+
 void read_line(struct strbuf *sb, FILE *fp, int term) {
 	int ch;
 	if (feof(fp)) {
diff --git a/strbuf.h b/strbuf.h
index ee72419..20c5255 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -42,6 +42,9 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...) {
 	va_end(ap);
 }
 
+
+extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
+
 extern void read_line(struct strbuf *, FILE *, int);
 
 #endif /* STRBUF_H */
-- 
1.5.3