[3/4] cmd: Avoid reading char by char from files (try 2)

Frédéric Delanoy frederic.delanoy at gmail.com
Tue Oct 4 07:41:03 CDT 2011


---
 programs/cmd/batch.c |   42 ++++++++++++++++++++++++++----------------
 1 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 0afca4a..f65bf54 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -188,14 +188,12 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where, WCHAR **end) {
 
 WCHAR *WCMD_fgets(WCHAR *buf, int noChars, HANDLE h, const BOOL is_console_handle)
 {
-  DWORD bytes, charsRead;
+  DWORD charsRead;
   BOOL status;
-  WCHAR *p;
 
   /* We can't use the native f* functions because of the filename syntax differences
      between DOS and Unix. Also need to lose the LF (or CRLF) from the line. */
 
-  p = buf;
   if (is_console_handle) {
     status = ReadConsoleW(h, buf, noChars, &charsRead, NULL);
     if (!status) return NULL;
@@ -205,21 +203,33 @@ WCHAR *WCMD_fgets(WCHAR *buf, int noChars, HANDLE h, const BOOL is_console_handl
       /* Truncate */
       buf[noChars-1] = '\0';
     }
-    return p;
-  }
+  } else {
+    LARGE_INTEGER filepos;
+    int i;
+
+    /* Save current file position */
+    filepos.QuadPart = 0;
+    SetFilePointerEx(h, filepos, &filepos, FILE_CURRENT);
+
+    status = WCMD_ReadFile(h, buf, noChars, &charsRead, CMD_HT_FILE);
+    if (!status || charsRead == 0) return NULL;
+    for (i = 0; i < charsRead; i++) {
+        if (buf[i] == '\n' || buf[i] == '\r')
+            break;
+    }
 
-  /* TODO: More intelligent buffering for reading lines from files */
-  do {
-    status = WCMD_ReadFile(h, s, 1, &bytes, CMD_HT_FILE);
-    if ((status == 0) || ((bytes == 0) && (buf == p))) return NULL;
-    if (*buf == '\n') bytes = 0;
-    else if (*buf != '\r') {
-      buf++;
-      noChars--;
+    if (i != charsRead) {
+      /* Sets file pointer to the start of the next line, if any */
+      filepos.QuadPart += i + 1 + (buf[i] == '\r' ? 1 : 0);
+      SetFilePointerEx(h, filepos, NULL, FILE_BEGIN);
+    } else {
+      /* File pointer positioned correctly already; truncate at the correct place */
+      i--;
     }
-    *buf = '\0';
-  } while ((bytes == 1) && (noChars > 1));
-  return p;
+    buf[i] = '\0';
+  }
+
+  return buf;
 }
 
 /* WCMD_splitpath - copied from winefile as no obvious way to use it otherwise */
-- 
1.7.7




More information about the wine-patches mailing list