]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Simplify the line reader:
authorJoerg Sonnenberger <joerg.sonnenberger@gmail.com>
Sat, 20 Feb 2010 22:59:56 +0000 (17:59 -0500)
committerJoerg Sonnenberger <joerg.sonnenberger@gmail.com>
Sat, 20 Feb 2010 22:59:56 +0000 (17:59 -0500)
- Do not allocate a buffer in advance, it will be reallocated on the
first round anyway.
- Allocate one more byte to allow always terminating the buffer.
- Use strcpsn to compute the end of line. This slightly changes the
behavior for NUL in text lines as they are no longer truncated.

SVN-Revision: 1929

libarchive_fe/line_reader.c

index 4af60de4c07e7116b49465a4cbbd9de0b2aa28f4..2d197d3dfb0381f619cbac76fefa24f38a64635b 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2008 Tim Kientzle
+ * Copyright (c) 2010 Joerg Sonnenberger
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -74,14 +75,20 @@ lafe_line_reader(const char *pathname, int nullSeparator)
        if (lr->f == NULL)
                lafe_errc(1, errno, "Couldn't open %s", pathname);
        lr->buff_length = 8192;
-       lr->buff = malloc(lr->buff_length);
-       if (lr->buff == NULL)
-               lafe_errc(1, ENOMEM, "Can't read %s", pathname);
-       lr->line_start = lr->line_end = lr->buff_end = lr->buff;
+       lr->line_start = lr->line_end = lr->buff_end = lr->buff = NULL;
 
        return (lr);
 }
 
+static void
+lafe_line_reader_find_eol(struct lafe_line_reader *lr)
+{
+
+       lr->line_end += strcspn(lr->line_end,
+           lr->nullSeparator ? "" : "\x0d\x0a");
+       *lr->line_end = '\0'; /* Noop if line_end == buff_end */
+}
+
 const char *
 lafe_line_reader_next(struct lafe_line_reader *lr)
 {
@@ -91,36 +98,21 @@ lafe_line_reader_next(struct lafe_line_reader *lr)
        for (;;) {
                /* If there's a line in the buffer, return it immediately. */
                while (lr->line_end < lr->buff_end) {
-                       if (lr->nullSeparator) {
-                               if (*lr->line_end == '\0') {
-                                       line_start = lr->line_start;
-                                       lr->line_start = lr->line_end + 1;
-                                       lr->line_end = lr->line_start;
-                                       return (line_start);
-                               }
-                       } else if (*lr->line_end == '\x0a' || *lr->line_end == '\x0d') {
-                               *lr->line_end = '\0';
-                               line_start = lr->line_start;
-                               lr->line_start = lr->line_end + 1;
-                               lr->line_end = lr->line_start;
-                               if (line_start[0] != '\0')
-                                       return (line_start);
-                       }
-                       lr->line_end++;
+                       line_start = lr->line_start;
+                       lr->line_start = ++lr->line_end;
+                       lafe_line_reader_find_eol(lr);
+
+                       if (lr->nullSeparator || line_start[0] != '\0')
+                               return (line_start);
                }
 
                /* If we're at end-of-file, process the final data. */
                if (lr->f == NULL) {
-                       /* If there's more text, return one last line. */
-                       if (lr->line_end > lr->line_start) {
-                               *lr->line_end = '\0';
-                               line_start = lr->line_start;
-                               lr->line_start = lr->line_end + 1;
-                               lr->line_end = lr->line_start;
-                               return (line_start);
-                       }
-                       /* Otherwise, we're done. */
-                       return (NULL);
+                       if (lr->line_start == lr->buff_end)
+                               return (NULL); /* No more text */
+                       line_start = lr->line_start;
+                       lr->line_start = lr->buff_end;
+                       return (line_start);
                }
 
                /* Buffer only has part of a line. */
@@ -138,7 +130,11 @@ lafe_line_reader_next(struct lafe_line_reader *lr)
                                lafe_errc(1, ENOMEM,
                                    "Line too long in %s", lr->pathname);
                        lr->buff_length = new_buff_size;
-                       p = realloc(lr->buff, new_buff_size);
+                       /*
+                        * Allocate one extra byte to allow terminating
+                        * the buffer.
+                        */
+                       p = realloc(lr->buff, new_buff_size + 1);
                        if (p == NULL)
                                lafe_errc(1, ENOMEM,
                                    "Line too long in %s", lr->pathname);
@@ -151,6 +147,8 @@ lafe_line_reader_next(struct lafe_line_reader *lr)
                bytes_wanted = lr->buff + lr->buff_length - lr->buff_end;
                bytes_read = fread(lr->buff_end, 1, bytes_wanted, lr->f);
                lr->buff_end += bytes_read;
+               *lr->buff_end = '\0'; /* Always terminate buffer */
+               lafe_line_reader_find_eol(lr);
 
                if (ferror(lr->f))
                        lafe_errc(1, errno, "Can't read %s", lr->pathname);