Revision: 1051
Author: [email protected]
Date: Tue Feb  9 06:52:17 2010
Log: Improve NYTP_gets() so that it will also work on compressed input streams.
http://code.google.com/p/perl-devel-nytprof/source/detail?r=1051

Modified:
 /trunk/FileHandle.xs

=======================================
--- /trunk/FileHandle.xs        Mon Feb  8 08:11:41 2010
+++ /trunk/FileHandle.xs        Tue Feb  9 06:52:17 2010
@@ -191,36 +191,6 @@

     return file;
 }
-
-/* This isn't exactly fgets. It will resize the buffer as needed, and returns
-   a pointer to one beyond the read data (usually the terminating '\0'), or
-   NULL if it hit error/EOF */
-
-char *
-NYTP_gets(NYTP_file ifile, char **buffer_p, size_t *len_p) {
-    char *buffer = *buffer_p;
-    size_t len = *len_p;
-    size_t prev_len = 0;
-
-    CROAK_IF_NOT_STDIO(ifile, "NYTP_gets");
-
-    while(fgets(buffer + prev_len, len - prev_len, ifile->file)) {
-       /* We know that there are no '\0' bytes in the part we've already
-          read, so don't bother running strlen() over that part.  */
-       char *end = buffer + prev_len + strlen(buffer + prev_len);
-       if (end[-1] == '\n') {
-           *buffer_p = buffer;
-           *len_p = len;
-           return end;
-       }
-       prev_len = len - 1; /* -1 to take off the '\0' at the end */
-       len *= 2;
-       buffer = saferealloc(buffer, len);
-    }
-    *buffer_p = buffer;
-    *len_p = len;
-    return NULL;
-}

 #ifdef HAS_ZLIB

@@ -337,6 +307,82 @@
     }
     return len;
 }
+
+/* This isn't exactly fgets. It will resize the buffer as needed, and returns
+   a pointer to one beyond the read data (usually the terminating '\0'), or
+   NULL if it hit error/EOF */
+
+char *
+NYTP_gets(NYTP_file ifile, char **buffer_p, size_t *len_p) {
+    char *buffer = *buffer_p;
+    size_t len = *len_p;
+    size_t prev_len = 0;
+
+#ifdef HAS_ZLIB
+    if (FILE_STATE(ifile) == NYTP_FILE_INFLATE) {
+        while (1) {
+ const unsigned char *const p = ifile->large_buffer + ifile->count; + const unsigned int remaining = ((unsigned char *) ifile->zs.next_out) - p;
+            unsigned char *const nl = memchr(p, '\n', remaining);
+            size_t got;
+            size_t want;
+            size_t extra;
+
+            if (nl) {
+                want = nl + 1 - p;
+                extra = want + 1; /* 1 more to add a \0 */
+            } else {
+                want = extra = remaining;
+            }
+
+            if (extra > len - prev_len) {
+                prev_len = len;
+                len += extra;
+                buffer = saferealloc(buffer, len);
+            }
+
+            got = NYTP_read_unchecked(ifile, buffer + prev_len, want);
+            if (got != want)
+ croak("NYTP_gets unexpected short read. got %lu, expected %lu\n",
+                      (unsigned long)got, (unsigned long)want);
+
+            if (nl) {
+                buffer[prev_len + want] = '\0';
+                *buffer_p = buffer;
+                *len_p = len;
+                return buffer + prev_len + want;
+            }
+            if (ifile->zlib_at_eof) {
+                *buffer_p = buffer;
+                *len_p = len;
+                return NULL;
+            }
+            grab_input(ifile);
+        }
+    }
+#endif
+    if (FILE_STATE(ifile) != NYTP_FILE_STDIO) {
+        compressed_io_croak(ifile, "NYTP_gets");
+        return 0;
+    }
+
+    while(fgets(buffer + prev_len, len - prev_len, ifile->file)) {
+        /* We know that there are no '\0' bytes in the part we've already
+           read, so don't bother running strlen() over that part.  */
+        char *end = buffer + prev_len + strlen(buffer + prev_len);
+        if (end[-1] == '\n') {
+            *buffer_p = buffer;
+            *len_p = len;
+            return end;
+        }
+        prev_len = len - 1; /* -1 to take off the '\0' at the end */
+        len *= 2;
+        buffer = saferealloc(buffer, len);
+    }
+    *buffer_p = buffer;
+    *len_p = len;
+    return NULL;
+}


 #ifdef HAS_ZLIB

--
You've received this message because you are subscribed to
the Devel::NYTProf Development User group.

Group hosted at:  http://groups.google.com/group/develnytprof-dev
Project hosted at:  http://perl-devel-nytprof.googlecode.com
CPAN distribution:  http://search.cpan.org/dist/Devel-NYTProf

To post, email:  [email protected]
To unsubscribe, email:  [email protected]

Reply via email to