[PATCH] Add strbuf_fread, use it in fast-import.c.
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 <madcoder@debian.org>
---
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