From fc6e2a8f7018a01ce84e566c252a545a55d5f70c Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Mon, 25 Oct 2010 12:03:12 +0100 Subject: Implement dynstr_readline and dynstr_freadline. This is a very stupid implementation. --- dynstr.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ unittests.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) 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); +} + diff --git a/unittests.c b/unittests.c index b4ad978..32bb270 100644 --- a/unittests.c +++ b/unittests.c @@ -1096,6 +1096,77 @@ static int test_read_reads_string(void) } +static int readline_test(Dynstr *(*callback)(char *filename)) +{ + char tempname[] = "unittest.XXXXXX"; + int fd; + const char cline1[] = "life is too short for str* and mem* in apps\n"; + const char cline2[] = "use dynstr instead!\n"; + Dynstr *lines; + Dynstr *line1; + Dynstr *line2; + Dynstr *result; + + fd = mkstemp(tempname); + if (fd == -1) + abort(); + + line1 = dynstr_new_from_constant_cstring(cline1); + line2 = dynstr_new_from_constant_cstring(cline2); + lines = dynstr_cat(line1, line2, NULL); + if (dynstr_write(fd, lines) != dynstr_len(lines)) + abort(); + close(fd); + + result = callback(tempname); + + FAIL_UNLESS_EQUAL(dynstr_cmp(line1, result), 0); + + dynstr_free(line1); + dynstr_free(line2); + dynstr_free(lines); + dynstr_free(result); + + return true; +} + + +static Dynstr *freadline_callback(char *filename) +{ + FILE *f; + Dynstr *line1; + + f = fopen(filename, "r"); + line1 = dynstr_freadline(f); + fclose(f); + return line1; +} + + +static int test_freadline_reads_first_line(void) +{ + return readline_test(freadline_callback); +} + + +static Dynstr *readline_callback(char *filename) +{ + int fd; + Dynstr *line1; + + fd = open(filename, O_RDONLY, 0); + line1 = dynstr_readline(fd); + close(fd); + return line1; +} + + +static int test_readline_reads_first_line(void) +{ + return readline_test(readline_callback); +} + + static void setup(void) { dynstr_init(); @@ -1186,6 +1257,8 @@ static const struct test tests[] = { TEST(test_write_writes_string), TEST(test_fread_reads_string), TEST(test_read_reads_string), + TEST(test_freadline_reads_first_line), + TEST(test_readline_reads_first_line), }; static const int num_tests = sizeof(tests) / sizeof(tests[0]); -- cgit v1.2.1