[RTL]
authorThomas Faber <thomas.faber@reactos.org>
Wed, 12 Oct 2011 11:36:52 +0000 (11:36 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Wed, 12 Oct 2011 11:36:52 +0000 (11:36 +0000)
- Rewrite RtlFindCharInUnicodeString. Fixes timeout in ntdll:rtlstr test.

svn path=/trunk/; revision=54091

reactos/include/ndk/rtlfuncs.h
reactos/include/ndk/rtltypes.h
reactos/lib/rtl/unicode.c

index 0204a01..30a3897 100644 (file)
@@ -2026,7 +2026,7 @@ NTSTATUS
 NTAPI
 RtlFindCharInUnicodeString(
     IN ULONG Flags,
-    IN PUNICODE_STRING SearchString,
+    IN PCUNICODE_STRING SearchString,
     IN PCUNICODE_STRING MatchString,
     OUT PUSHORT Position
 );
index 5f9a99d..67a45b8 100644 (file)
@@ -242,6 +242,8 @@ C_ASSERT(HEAP_CREATE_VALID_MASK == 0x0007F0FF);
 //
 // RtlFindCharInUnicodeString Flags
 //
+#define RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END        1
+#define RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET 2
 #define RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE    4
 
 //
index 8eb7b13..c91d04c 100644 (file)
@@ -2486,6 +2486,31 @@ RtlpEnsureBufferSize(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3)
     return STATUS_NOT_IMPLEMENTED;
 }
 
+static
+BOOLEAN
+RtlpIsCharInUnicodeString(
+    IN WCHAR Char,
+    IN PCUNICODE_STRING MatchString,
+    IN BOOLEAN CaseInSensitive)
+{
+    USHORT i;
+
+    if (CaseInSensitive)
+        Char = RtlUpcaseUnicodeChar(Char);
+
+    for (i = 0; i < MatchString->Length / sizeof(WCHAR); i++)
+    {
+        WCHAR OtherChar = MatchString->Buffer[i];
+        if (CaseInSensitive)
+            OtherChar = RtlUpcaseUnicodeChar(OtherChar);
+
+        if (Char == OtherChar)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
 /*
  * @implemented
  */
@@ -2493,94 +2518,54 @@ NTSTATUS
 NTAPI
 RtlFindCharInUnicodeString(
     IN ULONG Flags,
-    IN PUNICODE_STRING SearchString,
+    IN PCUNICODE_STRING SearchString,
     IN PCUNICODE_STRING MatchString,
     OUT PUSHORT Position)
 {
-    USHORT i, j;
+    BOOLEAN Found;
+    const BOOLEAN WantToFind = (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET) == 0;
+    const BOOLEAN CaseInSensitive = (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE) != 0;
+    INT Length;
+    INT i;
 
-    switch (Flags)
-    {
-        case 0:
-        {
-            for (i = 0; i < SearchString->Length / sizeof(WCHAR); i++)
-            {
-                for (j = 0; j < MatchString->Length / sizeof(WCHAR); j++)
-                {
-                    if (SearchString->Buffer[i] == MatchString->Buffer[j])
-                    {
-                        *Position = (i + 1) * sizeof(WCHAR);
-                        return STATUS_SUCCESS;
-                    }
-                }
-            }
+    DPRINT("RtlFindCharInUnicodeString(%u, '%wZ', '%wZ', %p)\n",
+           Flags, SearchString, MatchString, Position);
 
-            *Position = 0;
-            return STATUS_NOT_FOUND;
-        }
+    /* Parameter checks */
+    if (Position == NULL)
+        return STATUS_INVALID_PARAMETER;
 
-        case 1:
-        {
-            for (i = SearchString->Length / sizeof(WCHAR) - 1; (i + 1) > 0; i--)
-            {
-                for (j = 0; j < MatchString->Length / sizeof(WCHAR); j++)
-                {
-                    if (SearchString->Buffer[i] == MatchString->Buffer[j])
-                    {
-                        *Position = i * sizeof(WCHAR);
-                        return STATUS_SUCCESS;
-                    }
-                }
-            }
+    *Position = 0;
 
-            *Position = 0;
-            return STATUS_NOT_FOUND;
-        }
+    if (Flags & ~(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END |
+                  RTL_FIND_CHAR_IN_UNICODE_STRING_COMPLEMENT_CHAR_SET |
+                  RTL_FIND_CHAR_IN_UNICODE_STRING_CASE_INSENSITIVE))
+        return STATUS_INVALID_PARAMETER;
 
-        case 2:
+    /* Search */
+    Length = SearchString->Length / sizeof(WCHAR);
+    if (Flags & RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END)
+    {
+        for (i = Length - 1; i >= 0; i--)
         {
-            for (i = 0; i < SearchString->Length / sizeof(WCHAR); i++)
+            Found = RtlpIsCharInUnicodeString(SearchString->Buffer[i], MatchString, CaseInSensitive);
+            if (Found == WantToFind)
             {
-                j = 0;
-
-                while (j < MatchString->Length / sizeof(WCHAR) &&
-                       SearchString->Buffer[i] != MatchString->Buffer[j])
-                {
-                    j++;
-                }
-
-                if (j >= MatchString->Length / sizeof(WCHAR))
-                {
-                    *Position = (i + 1) * sizeof(WCHAR);
-                    return STATUS_SUCCESS;
-                }
+                *Position = i * sizeof(WCHAR);
+                return STATUS_SUCCESS;
             }
-
-            *Position = 0;
-            return STATUS_NOT_FOUND;
         }
-
-        case 3:
+    }
+    else
+    {
+        for (i = 0; i < Length; i++)
         {
-            for (i = SearchString->Length / sizeof(WCHAR) - 1; (i + 1) > 0; i--)
+            Found = RtlpIsCharInUnicodeString(SearchString->Buffer[i], MatchString, CaseInSensitive);
+            if (Found == WantToFind)
             {
-                j = 0;
-
-                while (j < MatchString->Length / sizeof(WCHAR) &&
-                       SearchString->Buffer[i] != MatchString->Buffer[j])
-                {
-                    j++;
-                }
-
-                if (j >= MatchString->Length / sizeof(WCHAR))
-                {
-                    *Position = i * sizeof(WCHAR);
-                    return STATUS_SUCCESS;
-                }
+                *Position = (i + 1) * sizeof(WCHAR);
+                return STATUS_SUCCESS;
             }
-
-            *Position = 0;
-            return STATUS_NOT_FOUND;
         }
     }