[PATCH 1/2] regedit: Overhaul Unicode line processing

Hugh McMaster hugh.mcmaster at outlook.com
Sun Nov 20 05:33:34 CST 2016


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

diff --git a/programs/regedit/regproc.c b/programs/regedit/regproc.c
index 5e4c2d2..a690a10 100644
--- a/programs/regedit/regproc.c
+++ b/programs/regedit/regproc.c
@@ -584,7 +584,7 @@ static void processSetValue(WCHAR* line, BOOL is_unicode)
  */
 static void processRegEntry(WCHAR* stdInput, BOOL isUnicode)
 {
-    if      ( stdInput[0] == '[')      /* We are reading a new key */
+    if (stdInput[0] == '[') /* We are reading a new key */
     {
         WCHAR* keyEnd;
         closeKey();                    /* Close the previous key */
@@ -600,12 +600,11 @@ static void processRegEntry(WCHAR* stdInput, BOOL isUnicode)
             delete_registry_key(stdInput + 1);
         else if (openKeyW(stdInput) != ERROR_SUCCESS)
             output_message(STRING_OPEN_KEY_FAILED, stdInput);
-    } else if( currentKeyHandle &&
-               (( stdInput[0] == '@') || /* reading a default @=data pair */
-                ( stdInput[0] == '\"'))) /* reading a new value=data pair */
-    {
-        processSetValue(stdInput, isUnicode);
     }
+    else if (currentKeyHandle && (stdInput[0] == '@' || stdInput[0] == '\"'))
+        processSetValue(stdInput, isUnicode); /* process @=data or value=data pairs */
+    else if (stdInput[0] == '#' || stdInput[0] == ';')
+        return; /* skip comment lines */
 }
 
 /******************************************************************************
@@ -731,120 +730,64 @@ 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           = NULL;  /* line read from input stream */
-    ULONG lineSize       = REG_VAL_BUF_SIZE;
-    size_t CharsInBuf = -1;
-
-    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);
+    static size_t size, count, size_remaining, offset = 0;
+    static WCHAR *buf, *s, *line, *p, *next;
 
-    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;
+        s = buf = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+        CHECK_ENOUGH_MEMORY(buf);
+    }
+    while (1)
+    {
+        static const WCHAR line_endings[] = {'\r','\n',0};
 
-        /* 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 */
+        size_remaining = size - (s - buf);
+        if (size_remaining < 3)
         {
-            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);
+            WCHAR *new_buf = HeapReAlloc(GetProcessHeap(), 0, buf, (size * 2) * sizeof(WCHAR));
+            CHECK_ENOUGH_MEMORY(new_buf);
+            buf = new_buf;
+            s = buf + size - size_remaining;
+            size *= 2;
+            size_remaining = size - (s - buf);
         }
+        line = s - offset;
+        count = fread(s, sizeof(WCHAR), size_remaining - 1, fp);
+        s[count] = 0;
+        s += count;
 
-        /* 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.
-                */
-            }
+        p = strpbrkW(line, line_endings);
+        if (!p)
+        {
+            HeapFree(GetProcessHeap(), 0, buf);
+            return NULL;
         }
-
-        /* 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 && isspace(*next)) next++;
+            MoveMemory(p, next, (lstrlenW(next) + 1) * sizeof(WCHAR));
+            continue;
         }
+        offset = s - next;
+        return line;
     }
+}
 
-    closeKey();
+static void processRegLinesW(FILE *fp)
+{
+    WCHAR *line;
 
-    HeapFree(GetProcessHeap(), 0, buf);
+    while ((line = get_lineW(fp)))
+        processRegEntry(line, TRUE);
+    closeKey();
 }
 
 /******************************************************************************
-- 
2.7.4




More information about the wine-patches mailing list