[PATCH 1/4] regedit: Re-implement processRegLinesW()

Hugh McMaster hugh.mcmaster at outlook.com
Thu Mar 16 07:05:00 CDT 2017


Signed-off-by: Hugh McMaster <hugh.mcmaster at outlook.com>
---
 programs/regedit/regproc.c | 163 +++++++++++++++++----------------------------
 1 file changed, 61 insertions(+), 102 deletions(-)

diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c
index 25c0240..f88d863 100644
--- a/programs/regedit/regproc.c
+++ b/programs/regedit/regproc.c
@@ -793,119 +793,78 @@ static void processRegLinesA(FILE *in, char* first_chars)
     HeapFree(GetProcessHeap(), 0, buf);
 }
 
-static void processRegLinesW(FILE *in)
+static WCHAR *get_lineW(FILE *fp, WCHAR **buf)
 {
-    WCHAR* buf           = NULL;  /* line read from input stream */
-    ULONG lineSize       = REG_VAL_BUF_SIZE;
-    size_t CharsInBuf = -1;
+    static size_t size;
+    static WCHAR *next;
+    WCHAR *line;
 
-    WCHAR* s; /* The pointer into buf for where the current fgets should read */
-    WCHAR* line; /* The start of the current line */
-
-    buf = HeapAlloc(GetProcessHeap(), 0, lineSize * sizeof(WCHAR));
-    CHECK_ENOUGH_MEMORY(buf);
-
-    s = buf;
-    line = buf;
-
-    while(!feof(in)) {
-        size_t size_remaining;
-        int size_to_get;
-        WCHAR *s_eol = NULL; /* various local uses */
+    if (!size)
+    {
+        size = REG_VAL_BUF_SIZE;
+        *buf = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+        CHECK_ENOUGH_MEMORY(*buf);
+        **buf = 0;
+        next = *buf;
+    }
+    line = next;
 
-        /* Do we need to expand the buffer ? */
-        assert (s >= buf && s <= buf + lineSize);
-        size_remaining = lineSize - (s-buf);
-        if (size_remaining < 2) /* room for 1 character and the \0 */
+    while (next)
+    {
+        static const WCHAR line_endings[] = {'\r','\n',0};
+        WCHAR *p = strpbrkW(line, line_endings);
+        if (!p)
         {
-            WCHAR *new_buffer;
-            size_t new_size = lineSize + (REG_VAL_BUF_SIZE / sizeof(WCHAR));
-            if (new_size > lineSize) /* no arithmetic overflow */
-                new_buffer = HeapReAlloc (GetProcessHeap(), 0, buf, new_size * sizeof(WCHAR));
-            else
-                new_buffer = NULL;
-            CHECK_ENOUGH_MEMORY(new_buffer);
-            buf = new_buffer;
-            line = buf;
-            s = buf + lineSize - size_remaining;
-            lineSize = new_size;
-            size_remaining = lineSize - (s-buf);
-        }
-
-        /* Get as much as possible into the buffer, terminated either by
-        * eof, error or getting the maximum amount.  Abort on error.
-        */
-        size_to_get = (size_remaining > INT_MAX ? INT_MAX : size_remaining);
-
-        CharsInBuf = fread(s, sizeof(WCHAR), size_to_get - 1, in);
-        s[CharsInBuf] = 0;
-
-        if (CharsInBuf == 0) {
-            if (ferror(in)) {
-                perror ("While reading input");
-                exit (IO_ERROR);
-            } else {
-                assert (feof(in));
-                *s = '\0';
-                /* It is not clear to me from the definition that the
-                * contents of the buffer are well defined on detecting
-                * an eof without managing to read anything.
-                */
+            size_t len, count;
+            len = strlenW(next);
+            MoveMemory(*buf, next, (len + 1) * sizeof(WCHAR));
+            if (size - len < 3)
+            {
+                WCHAR *new_buf = HeapReAlloc(GetProcessHeap(), 0, *buf, (size * 2) * sizeof(WCHAR));
+                CHECK_ENOUGH_MEMORY(new_buf);
+                *buf = new_buf;
+                size *= 2;
+            }
+            if (!(count = fread(*buf + len, sizeof(WCHAR), size - len - 1, fp)))
+            {
+                next = NULL;
+                return *buf;
             }
+            (*buf)[len + count] = 0;
+            next = *buf;
+            line = *buf;
+            continue;
         }
-
-        /* If we didn't read the eol nor the eof go around for the rest */
-        while(1)
+        next = p + 1;
+        if (*p == '\r' && *(p + 1) == '\n') next++;
+        *p = 0;
+        if (*(p - 1) == '\\')
         {
-            const WCHAR line_endings[] = {'\r','\n',0};
-            s_eol = strpbrkW(line, line_endings);
-
-            if(!s_eol) {
-                /* Move the stub of the line to the start of the buffer so
-                 * we get the maximum space to read into, and so we don't
-                 * have to recalculate 'line' if the buffer expands */
-                MoveMemory(buf, line, (strlenW(line)+1) * sizeof(WCHAR));
-                line = buf;
-                s = strchrW(line, '\0');
-                break;
-            }
-
-            /* If it is a comment line then discard it and go around again */
-            if (*line == '#' || *line == ';') {
-                if (*s_eol == '\r' && *(s_eol+1) == '\n')
-                    line = s_eol + 2;
-                else
-                    line = s_eol + 1;
-                continue;
-            }
-
-            /* If there is a concatenating \\ then go around again */
-            if (*(s_eol-1) == '\\') {
-                WCHAR* NextLine = s_eol + 1;
-
-                if(*s_eol == '\r' && *(s_eol+1) == '\n')
-                    NextLine++;
-
-                while(*(NextLine+1) == ' ' || *(NextLine+1) == '\t')
-                    NextLine++;
-
-                MoveMemory(s_eol - 1, NextLine, (CharsInBuf - (NextLine - s) + 1)*sizeof(WCHAR));
-                CharsInBuf -= NextLine - s_eol + 1;
-                continue;
-            }
-
-            /* Remove any line feed.  Leave s_eol on the last \0 */
-            if (*s_eol == '\r' && *(s_eol + 1) == '\n')
-                *s_eol++ = '\0';
-            *s_eol = '\0';
-
-            processRegEntry(line, TRUE);
-            line = s_eol + 1;
+            *(--p) = 0;
+            while (*next && (*next == ' ' || *next == '\t')) next++;
+            MoveMemory(p, next, (strlenW(next) + 1) * sizeof(WCHAR));
+            next = line;
+            continue;
+        }
+        if (*line == ';' || *line == '#')
+        {
+            line = next;
+            continue;
         }
+        return line;
     }
+    size = 0;
+    return NULL;
+}
 
-    closeKey();
+static void processRegLinesW(FILE *fp)
+{
+    WCHAR *buf = NULL, *line;
 
+    while ((line = get_lineW(fp, &buf)))
+        processRegEntry(line, TRUE);
+
+    closeKey();
     HeapFree(GetProcessHeap(), 0, buf);
 }
 
-- 
2.7.4




More information about the wine-patches mailing list