summaryrefslogtreecommitdiff
path: root/dynstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'dynstr.c')
-rw-r--r--dynstr.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/dynstr.c b/dynstr.c
index 246c16f..de02f79 100644
--- a/dynstr.c
+++ b/dynstr.c
@@ -369,3 +369,87 @@ Dynstr *dynstr_read(int file, size_t size)
return read_helper(read_callback, NULL, file, size);
}
+
+static Dynstr *readline_helper(int (*callback)(FILE *, int), FILE *f, int fd)
+{
+ Dynstr *line;
+ Dynstr *temp1;
+ Dynstr *temp2;
+ int c;
+ unsigned char byte;
+
+ line = dynstr_new_empty();
+
+ for (;;) {
+ temp1 = NULL;
+ temp2 = NULL;
+
+ c = callback(f, fd);
+ if (c == -1)
+ goto error;
+ else if (c == -2)
+ break;
+
+ byte = c;
+ temp1 = dynstr_new_from_constant_memory(&byte, 1);
+ if (temp1 == NULL)
+ goto error;
+ temp2 = dynstr_cat(line, temp1, NULL);
+ dynstr_free(temp1);
+ dynstr_free(line);
+ line = temp2;
+
+ if (c == '\n')
+ break;
+ }
+
+ return line;
+
+error:
+ dynstr_free(line);
+ dynstr_free(temp1);
+ dynstr_free(temp2);
+ return NULL;
+}
+
+
+static int freadline_callback(FILE *f, int fd)
+{
+ int c;
+
+ c = getc(f);
+ if (c == EOF && ferror(f))
+ return -1;
+ else if (c == EOF)
+ return -2;
+ else
+ return c;
+}
+
+
+Dynstr *dynstr_freadline(FILE *file)
+{
+ return readline_helper(freadline_callback, file, -1);
+}
+
+
+static int readline_callback(FILE *f, int fd)
+{
+ unsigned char c;
+ int n;
+
+ n = read(fd, &c, 1);
+ if (n == 0)
+ return -2;
+ else if (n == -1)
+ return -1;
+ else
+ return c;
+}
+
+
+Dynstr *dynstr_readline(int file)
+{
+ return readline_helper(readline_callback, NULL, file);
+}
+