summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2010-10-25 12:06:17 +0100
committerLars Wirzenius <liw@liw.fi>2010-10-25 12:06:17 +0100
commit7b7f94de3462845c36b2831719b6448fe173f2f7 (patch)
treeeeda0eccdb2450722179692e063bce4494a9c780
parentfc6e2a8f7018a01ce84e566c252a545a55d5f70c (diff)
downloaddynstr-7b7f94de3462845c36b2831719b6448fe173f2f7.tar.gz
Avoid doing a large number of small allocs in readline_helper.
-rw-r--r--dynstr.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/dynstr.c b/dynstr.c
index de02f79..a77b2b6 100644
--- a/dynstr.c
+++ b/dynstr.c
@@ -376,9 +376,11 @@ static Dynstr *readline_helper(int (*callback)(FILE *, int), FILE *f, int fd)
Dynstr *temp1;
Dynstr *temp2;
int c;
- unsigned char byte;
+ unsigned char buf[1024];
+ size_t buflen;
line = dynstr_new_empty();
+ buflen = 0;
for (;;) {
temp1 = NULL;
@@ -390,19 +392,36 @@ static Dynstr *readline_helper(int (*callback)(FILE *, int), FILE *f, int fd)
else if (c == -2)
break;
- byte = c;
- temp1 = dynstr_new_from_constant_memory(&byte, 1);
+ buf[buflen++] = c;
+ if (buflen == sizeof(buf)) {
+ temp1 = dynstr_new_from_memory(buf, buflen);
+ if (temp1 == NULL)
+ goto error;
+ temp2 = dynstr_cat(line, temp1, NULL);
+ if (temp2 == NULL)
+ goto error;
+ dynstr_free(temp1);
+ dynstr_free(line);
+ line = temp2;
+ buflen = 0;
+ }
+
+ if (c == '\n')
+ break;
+ }
+
+ if (buflen > 0) {
+ temp1 = dynstr_new_from_memory(buf, buflen);
if (temp1 == NULL)
goto error;
temp2 = dynstr_cat(line, temp1, NULL);
+ if (temp2 == NULL)
+ goto error;
dynstr_free(temp1);
dynstr_free(line);
line = temp2;
-
- if (c == '\n')
- break;
}
-
+
return line;
error: