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

Frédéric Delanoy frederic.delanoy at gmail.com
Thu Oct 6 11:50:32 CDT 2011


Also use common console/file handling where possible

Changes: Merged "cmd: Simplify WCMD_fgets" patch
try2: fix typo
---
 programs/cmd/batch.c |   54 ++++++++++++++++++++++++++-----------------------
 1 files changed, 29 insertions(+), 25 deletions(-)

diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 79bb009..a276d3e 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -188,38 +188,42 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where, WCHAR **end) {
 
 WCHAR *WCMD_fgets(WCHAR *buf, int noChars, HANDLE h)
 {
-  DWORD bytes, charsRead;
+  DWORD charsRead;
   BOOL status;
-  WCHAR *p;
+  LARGE_INTEGER filepos;
+  int i;
 
   /* 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 (WCMD_is_console_handle(h)) {
-    status = ReadConsoleW(h, buf, noChars, &charsRead, NULL);
-    if (!status) return NULL;
-    if (buf[charsRead-2] == '\r')
-      buf[charsRead-2] = '\0'; /* Strip \r\n */
-    else {
-      /* Truncate */
-      buf[noChars-1] = '\0';
-    }
-    return p;
+  if (!WCMD_is_console_handle(h)) {
+    /* Save current file position */
+    filepos.QuadPart = 0;
+    SetFilePointerEx(h, filepos, &filepos, FILE_CURRENT);
   }
 
-  /* TODO: More intelligent buffering for reading lines from files */
-  do {
-    status = WCMD_ReadFile(h, buf, 1, &bytes);
-    if ((status == 0) || ((bytes == 0) && (buf == p))) return NULL;
-    if (*buf == '\n') bytes = 0;
-    else if (*buf != '\r') {
-      buf++;
-      noChars--;
-    }
-    *buf = '\0';
-  } while ((bytes == 1) && (noChars > 1));
-  return p;
+  status = WCMD_ReadFile(h, buf, noChars, &charsRead);
+  if (!status || charsRead == 0) return NULL;
+
+  /* Find first EOL */
+  for (i = 0; i < charsRead; i++) {
+    if (buf[i] == '\n' || buf[i] == '\r')
+      break;
+  }
+
+  if (!WCMD_is_console_handle(h) && 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);
+  }
+
+  /* Truncate at EOL (or end of buffer) */
+  if (i == noChars)
+    i--;
+
+  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