mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 09:16:17 +00:00
- Implement LCMapStringA/W (based on Wine, +55 passed tests)
- Fix CompareStringA/W (+6 passed tests) svn path=/trunk/; revision=37571
This commit is contained in:
parent
7d4a8b9e1c
commit
0c2971975e
4 changed files with 2173 additions and 96 deletions
|
@ -57,6 +57,7 @@
|
|||
<file>actctx.c</file>
|
||||
<file>atom.c</file>
|
||||
<file>chartype.c</file>
|
||||
<file>collation.c</file>
|
||||
<file>casemap.c</file>
|
||||
<file>comm.c</file>
|
||||
<file>computername.c</file>
|
||||
|
@ -75,6 +76,7 @@
|
|||
<file>perfcnt.c</file>
|
||||
<file>recovery.c</file>
|
||||
<file>res.c</file>
|
||||
<file>sortkey.c</file>
|
||||
<file>stubs.c</file>
|
||||
<file>sysinfo.c</file>
|
||||
<file>time.c</file>
|
||||
|
|
1657
reactos/dll/win32/kernel32/misc/collation.c
Normal file
1657
reactos/dll/win32/kernel32/misc/collation.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -35,6 +35,10 @@
|
|||
|
||||
//static RTL_CRITICAL_SECTION LocalesListLock;
|
||||
|
||||
extern int wine_fold_string(int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen);
|
||||
extern int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen);
|
||||
extern int wine_compare_string(int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
|
@ -61,6 +65,8 @@ static const WCHAR szLangGroupsKeyName[] = {
|
|||
'L','a','n','g','u','a','g','e',' ','G','r','o','u','p','s',0
|
||||
};
|
||||
|
||||
extern const unsigned int CollationTable[];
|
||||
|
||||
/******************************************************************************
|
||||
* @implemented
|
||||
* RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
|
||||
|
@ -1869,8 +1875,6 @@ FoldStringA_exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
extern int wine_fold_string( int flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen );
|
||||
|
||||
/*************************************************************************
|
||||
* FoldStringW (KERNEL32.@)
|
||||
*
|
||||
|
@ -1908,9 +1912,8 @@ INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen,
|
|||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
* @implemented (Synced to Wine-22112008)
|
||||
*/
|
||||
/* Synced to Wine-22112008 */
|
||||
int
|
||||
STDCALL
|
||||
CompareStringA (
|
||||
|
@ -1975,88 +1978,8 @@ CompareStringA (
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
LANG_CompareUnicodeString(
|
||||
LPCWSTR s1,
|
||||
ULONG len1,
|
||||
LPCWSTR s2,
|
||||
ULONG len2,
|
||||
DWORD Flags
|
||||
)
|
||||
{
|
||||
WCHAR c1, c2;
|
||||
|
||||
while (len1 > 0 && len2 > 0)
|
||||
{
|
||||
if (Flags & NORM_IGNORESYMBOLS)
|
||||
{
|
||||
int skip = 0;
|
||||
/* FIXME: not tested */
|
||||
if (iswctype(*s1, _SPACE | _PUNCT))
|
||||
{
|
||||
s1++;
|
||||
len1--;
|
||||
skip = 1;
|
||||
}
|
||||
if (iswctype(*s2, _SPACE | _PUNCT))
|
||||
{
|
||||
s2++;
|
||||
len2--;
|
||||
skip = 1;
|
||||
}
|
||||
if (skip) continue;
|
||||
}
|
||||
|
||||
/* hyphen and apostrophe are treated differently depending on
|
||||
* whether SORT_STRINGSORT specified or not
|
||||
*/
|
||||
if (!(Flags & SORT_STRINGSORT))
|
||||
{
|
||||
if (*s1 == '-' || *s1 == '\'')
|
||||
{
|
||||
if (*s2 != '-' && *s2 != '\'')
|
||||
{
|
||||
s1++;
|
||||
len1--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (*s2 == '-' || *s2 == '\'')
|
||||
{
|
||||
s2++;
|
||||
len2--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (Flags & NORM_IGNORECASE)
|
||||
{
|
||||
c1 = len1-- ? RtlUpcaseUnicodeChar(*s1++) : 0;
|
||||
c2 = len2-- ? RtlUpcaseUnicodeChar(*s2++) : 0;
|
||||
if (!c1 || !c2 || c1 != c2)
|
||||
return c1 - c2;
|
||||
}
|
||||
else
|
||||
{
|
||||
c1 = len1-- ? *s1++ : 0;
|
||||
c2 = len2-- ? *s2++ : 0;
|
||||
if (!c1 || !c2 || c1 != c2)
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) (len1 - len2);
|
||||
}
|
||||
|
||||
static int
|
||||
LANG_GetRealLength(const WCHAR *str, int len)
|
||||
{
|
||||
while (len && !str[len - 1]) len--;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented (Synced to Wine-22/11/2008)
|
||||
*/
|
||||
int
|
||||
STDCALL
|
||||
|
@ -2092,10 +2015,7 @@ CompareStringW (
|
|||
if (cchCount1 < 0) cchCount1 = wcslen(lpString1);
|
||||
if (cchCount2 < 0) cchCount2 = wcslen(lpString2);
|
||||
|
||||
cchCount1 = LANG_GetRealLength(lpString1, cchCount1);
|
||||
cchCount2 = LANG_GetRealLength(lpString2, cchCount2);
|
||||
|
||||
Result = LANG_CompareUnicodeString(lpString1, cchCount1, lpString2, cchCount2, dwCmpFlags);
|
||||
Result = wine_compare_string(dwCmpFlags, lpString1, cchCount1, lpString2, cchCount2);
|
||||
|
||||
if (Result) /* need to translate result */
|
||||
return (Result < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
|
||||
|
@ -2571,9 +2491,8 @@ IsValidLocale(LCID Locale,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
int
|
||||
STDCALL
|
||||
|
@ -2586,19 +2505,76 @@ LCMapStringA (
|
|||
int cchDest
|
||||
)
|
||||
{
|
||||
WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
|
||||
LPWSTR srcW, dstW;
|
||||
INT ret = 0, srclenW, dstlenW;
|
||||
UINT locale_cp = CP_ACP;
|
||||
|
||||
if (!lpSrcStr || !cchSrc || cchDest < 0)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
if (!(dwMapFlags & LOCALE_USE_CP_ACP)) locale_cp = get_lcid_codepage(Locale);
|
||||
|
||||
srclenW = MultiByteToWideChar(locale_cp, 0, lpSrcStr, cchSrc, bufW, 260);
|
||||
if (srclenW)
|
||||
srcW = bufW;
|
||||
else
|
||||
{
|
||||
srclenW = MultiByteToWideChar(locale_cp, 0, lpSrcStr, cchSrc, NULL, 0);
|
||||
srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
|
||||
if (!srcW)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
MultiByteToWideChar(locale_cp, 0, lpSrcStr, cchSrc, srcW, srclenW);
|
||||
}
|
||||
|
||||
if (dwMapFlags & LCMAP_SORTKEY)
|
||||
{
|
||||
if (lpSrcStr == lpDestStr)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
goto map_string_exit;
|
||||
}
|
||||
ret = wine_get_sortkey(dwMapFlags, srcW, srclenW, lpDestStr, cchDest);
|
||||
if (ret == 0)
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
goto map_string_exit;
|
||||
}
|
||||
|
||||
if (dwMapFlags & SORT_STRINGSORT)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
goto map_string_exit;
|
||||
}
|
||||
|
||||
dstlenW = LCMapStringW(Locale, dwMapFlags, srcW, srclenW, NULL, 0);
|
||||
if (!dstlenW)
|
||||
goto map_string_exit;
|
||||
|
||||
dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
|
||||
if (!dstW)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto map_string_exit;
|
||||
}
|
||||
|
||||
LCMapStringW(Locale, dwMapFlags, srcW, srclenW, dstW, dstlenW);
|
||||
ret = WideCharToMultiByte(locale_cp, 0, dstW, dstlenW, lpDestStr, cchDest, NULL, NULL);
|
||||
HeapFree(GetProcessHeap(), 0, dstW);
|
||||
|
||||
map_string_exit:
|
||||
if (srcW != bufW) HeapFree(GetProcessHeap(), 0, srcW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
int
|
||||
STDCALL
|
||||
|
@ -2611,6 +2587,8 @@ LCMapStringW (
|
|||
int cchDest
|
||||
)
|
||||
{
|
||||
LPWSTR dst_ptr;
|
||||
|
||||
if (!lpSrcStr || !cchSrc || cchDest < 0)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
|
@ -2629,8 +2607,98 @@ LCMapStringW (
|
|||
|
||||
if (!cchDest) lpDestStr = NULL;
|
||||
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
Locale = ConvertDefaultLocale(Locale);
|
||||
|
||||
if (dwMapFlags & LCMAP_SORTKEY)
|
||||
{
|
||||
INT ret;
|
||||
if (lpSrcStr == lpDestStr)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cchSrc < 0) cchSrc = wcslen(lpSrcStr);
|
||||
|
||||
ret = wine_get_sortkey(dwMapFlags, lpSrcStr, cchSrc, (char *)lpDestStr, cchDest);
|
||||
if (ret == 0)
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
|
||||
if (dwMapFlags & SORT_STRINGSORT)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cchSrc < 0) cchSrc = wcslen(lpSrcStr) + 1;
|
||||
|
||||
if (!lpDestStr) /* return required string length */
|
||||
{
|
||||
INT len;
|
||||
|
||||
for (len = 0; cchSrc; lpSrcStr++, cchSrc--)
|
||||
{
|
||||
WCHAR wch = *lpSrcStr;
|
||||
/* tests show that win2k just ignores NORM_IGNORENONSPACE,
|
||||
* and skips white space and punctuation characters for
|
||||
* NORM_IGNORESYMBOLS.
|
||||
*/
|
||||
if ((dwMapFlags & NORM_IGNORESYMBOLS) && (iswctype(wch, _SPACE | _PUNCT)))
|
||||
continue;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
if (dwMapFlags & LCMAP_UPPERCASE)
|
||||
{
|
||||
for (dst_ptr = lpDestStr; cchSrc && cchDest; lpSrcStr++, cchSrc--)
|
||||
{
|
||||
WCHAR wch = *lpSrcStr;
|
||||
if ((dwMapFlags & NORM_IGNORESYMBOLS) && (iswctype(wch, _SPACE | _PUNCT)))
|
||||
continue;
|
||||
*dst_ptr++ = towupper(wch);
|
||||
cchDest--;
|
||||
}
|
||||
}
|
||||
else if (dwMapFlags & LCMAP_LOWERCASE)
|
||||
{
|
||||
for (dst_ptr = lpDestStr; cchSrc && cchDest; lpSrcStr++, cchSrc--)
|
||||
{
|
||||
WCHAR wch = *lpSrcStr;
|
||||
if ((dwMapFlags & NORM_IGNORESYMBOLS) && (iswctype(wch, _SPACE | _PUNCT)))
|
||||
continue;
|
||||
*dst_ptr++ = towlower(wch);
|
||||
cchDest--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lpSrcStr == lpDestStr)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return 0;
|
||||
}
|
||||
for (dst_ptr = lpDestStr; cchSrc && cchDest; lpSrcStr++, cchSrc--)
|
||||
{
|
||||
WCHAR wch = *lpSrcStr;
|
||||
if ((dwMapFlags & NORM_IGNORESYMBOLS) && (iswctype(wch, _SPACE | _PUNCT)))
|
||||
continue;
|
||||
*dst_ptr++ = wch;
|
||||
cchDest--;
|
||||
}
|
||||
}
|
||||
|
||||
if (cchSrc)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dst_ptr - lpDestStr;
|
||||
}
|
||||
|
||||
|
||||
|
|
350
reactos/dll/win32/kernel32/misc/sortkey.c
Normal file
350
reactos/dll/win32/kernel32/misc/sortkey.c
Normal file
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Unicode sort key generation
|
||||
*
|
||||
* Copyright 2003 Dmitry Timoshkov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include "wine/unicode.h"
|
||||
|
||||
extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
|
||||
extern const unsigned int collation_table[];
|
||||
|
||||
/*
|
||||
* flags - normalization NORM_* flags
|
||||
*
|
||||
* FIXME: 'variable' flag not handled
|
||||
*/
|
||||
int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen)
|
||||
{
|
||||
WCHAR dummy[4]; /* no decomposition is larger than 4 chars */
|
||||
int key_len[4];
|
||||
char *key_ptr[4];
|
||||
const WCHAR *src_save = src;
|
||||
int srclen_save = srclen;
|
||||
|
||||
key_len[0] = key_len[1] = key_len[2] = key_len[3] = 0;
|
||||
for (; srclen; srclen--, src++)
|
||||
{
|
||||
int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/
|
||||
dummy[0] = *src;
|
||||
if (decomposed_len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < decomposed_len; i++)
|
||||
{
|
||||
WCHAR wch = dummy[i];
|
||||
unsigned int ce;
|
||||
|
||||
/* tests show that win2k just ignores NORM_IGNORENONSPACE,
|
||||
* and skips white space and punctuation characters for
|
||||
* NORM_IGNORESYMBOLS.
|
||||
*/
|
||||
if ((flags & NORM_IGNORESYMBOLS) && (iswctype(wch, _SPACE | _PUNCT)))
|
||||
continue;
|
||||
|
||||
if (flags & NORM_IGNORECASE) wch = tolowerW(wch);
|
||||
|
||||
ce = collation_table[collation_table[wch >> 8] + (wch & 0xff)];
|
||||
if (ce != (unsigned int)-1)
|
||||
{
|
||||
if (ce >> 16) key_len[0] += 2;
|
||||
if ((ce >> 8) & 0xff) key_len[1]++;
|
||||
if ((ce >> 4) & 0x0f) key_len[2]++;
|
||||
if (ce & 1)
|
||||
{
|
||||
if (wch >> 8) key_len[3]++;
|
||||
key_len[3]++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
key_len[0] += 2;
|
||||
if (wch >> 8) key_len[0]++;
|
||||
if (wch & 0xff) key_len[0]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dstlen) /* compute length */
|
||||
/* 4 * '\1' + 1 * '\0' + key length */
|
||||
return key_len[0] + key_len[1] + key_len[2] + key_len[3] + 4 + 1;
|
||||
|
||||
if (dstlen < key_len[0] + key_len[1] + key_len[2] + key_len[3] + 4 + 1)
|
||||
return 0; /* overflow */
|
||||
|
||||
src = src_save;
|
||||
srclen = srclen_save;
|
||||
|
||||
key_ptr[0] = dst;
|
||||
key_ptr[1] = key_ptr[0] + key_len[0] + 1;
|
||||
key_ptr[2] = key_ptr[1] + key_len[1] + 1;
|
||||
key_ptr[3] = key_ptr[2] + key_len[2] + 1;
|
||||
|
||||
for (; srclen; srclen--, src++)
|
||||
{
|
||||
int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/
|
||||
dummy[0] = *src;
|
||||
if (decomposed_len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < decomposed_len; i++)
|
||||
{
|
||||
WCHAR wch = dummy[i];
|
||||
unsigned int ce;
|
||||
|
||||
/* tests show that win2k just ignores NORM_IGNORENONSPACE,
|
||||
* and skips white space and punctuation characters for
|
||||
* NORM_IGNORESYMBOLS.
|
||||
*/
|
||||
if ((flags & NORM_IGNORESYMBOLS) && (iswctype(wch, _SPACE | _PUNCT)))
|
||||
continue;
|
||||
|
||||
if (flags & NORM_IGNORECASE) wch = tolowerW(wch);
|
||||
|
||||
ce = collation_table[collation_table[wch >> 8] + (wch & 0xff)];
|
||||
if (ce != (unsigned int)-1)
|
||||
{
|
||||
WCHAR key;
|
||||
if ((key = ce >> 16))
|
||||
{
|
||||
*key_ptr[0]++ = key >> 8;
|
||||
*key_ptr[0]++ = key & 0xff;
|
||||
}
|
||||
/* make key 1 start from 2 */
|
||||
if ((key = (ce >> 8) & 0xff)) *key_ptr[1]++ = key + 1;
|
||||
/* make key 2 start from 2 */
|
||||
if ((key = (ce >> 4) & 0x0f)) *key_ptr[2]++ = key + 1;
|
||||
/* key 3 is always a character code */
|
||||
if (ce & 1)
|
||||
{
|
||||
if (wch >> 8) *key_ptr[3]++ = wch >> 8;
|
||||
if (wch & 0xff) *key_ptr[3]++ = wch & 0xff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*key_ptr[0]++ = 0xff;
|
||||
*key_ptr[0]++ = 0xfe;
|
||||
if (wch >> 8) *key_ptr[0]++ = wch >> 8;
|
||||
if (wch & 0xff) *key_ptr[0]++ = wch & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*key_ptr[0] = '\1';
|
||||
*key_ptr[1] = '\1';
|
||||
*key_ptr[2] = '\1';
|
||||
*key_ptr[3]++ = '\1';
|
||||
*key_ptr[3] = 0;
|
||||
|
||||
return key_ptr[3] - dst;
|
||||
}
|
||||
|
||||
static inline int compare_unicode_weights(int flags, const WCHAR *str1, int len1,
|
||||
const WCHAR *str2, int len2)
|
||||
{
|
||||
unsigned int ce1, ce2;
|
||||
int ret;
|
||||
|
||||
/* 32-bit collation element table format:
|
||||
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||
* case weight - high 4 bit of low 8 bit.
|
||||
*/
|
||||
while (len1 > 0 && len2 > 0)
|
||||
{
|
||||
if (flags & NORM_IGNORESYMBOLS)
|
||||
{
|
||||
int skip = 0;
|
||||
/* FIXME: not tested */
|
||||
if (iswctype(*str1, _SPACE | _PUNCT))
|
||||
{
|
||||
str1++;
|
||||
len1--;
|
||||
skip = 1;
|
||||
}
|
||||
if (iswctype(*str2, _SPACE | _PUNCT))
|
||||
{
|
||||
str2++;
|
||||
len2--;
|
||||
skip = 1;
|
||||
}
|
||||
if (skip) continue;
|
||||
}
|
||||
|
||||
/* hyphen and apostrophe are treated differently depending on
|
||||
* whether SORT_STRINGSORT specified or not
|
||||
*/
|
||||
if (!(flags & SORT_STRINGSORT))
|
||||
{
|
||||
if (*str1 == '-' || *str1 == '\'')
|
||||
{
|
||||
if (*str2 != '-' && *str2 != '\'')
|
||||
{
|
||||
str1++;
|
||||
len1--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (*str2 == '-' || *str2 == '\'')
|
||||
{
|
||||
str2++;
|
||||
len2--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)];
|
||||
ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
|
||||
|
||||
if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1)
|
||||
ret = (ce1 >> 16) - (ce2 >> 16);
|
||||
else
|
||||
ret = *str1 - *str2;
|
||||
|
||||
if (ret) return ret;
|
||||
|
||||
str1++;
|
||||
str2++;
|
||||
len1--;
|
||||
len2--;
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
static inline int compare_diacritic_weights(int flags, const WCHAR *str1, int len1,
|
||||
const WCHAR *str2, int len2)
|
||||
{
|
||||
unsigned int ce1, ce2;
|
||||
int ret;
|
||||
|
||||
/* 32-bit collation element table format:
|
||||
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||
* case weight - high 4 bit of low 8 bit.
|
||||
*/
|
||||
while (len1 > 0 && len2 > 0)
|
||||
{
|
||||
if (flags & NORM_IGNORESYMBOLS)
|
||||
{
|
||||
int skip = 0;
|
||||
/* FIXME: not tested */
|
||||
if (iswctype(*str1, _SPACE | _PUNCT))
|
||||
{
|
||||
str1++;
|
||||
len1--;
|
||||
skip = 1;
|
||||
}
|
||||
if (iswctype(*str2, _SPACE | _PUNCT))
|
||||
{
|
||||
str2++;
|
||||
len2--;
|
||||
skip = 1;
|
||||
}
|
||||
if (skip) continue;
|
||||
}
|
||||
|
||||
ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)];
|
||||
ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
|
||||
|
||||
if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1)
|
||||
ret = ((ce1 >> 8) & 0xff) - ((ce2 >> 8) & 0xff);
|
||||
else
|
||||
ret = *str1 - *str2;
|
||||
|
||||
if (ret) return ret;
|
||||
|
||||
str1++;
|
||||
str2++;
|
||||
len1--;
|
||||
len2--;
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
static inline int compare_case_weights(int flags, const WCHAR *str1, int len1,
|
||||
const WCHAR *str2, int len2)
|
||||
{
|
||||
unsigned int ce1, ce2;
|
||||
int ret;
|
||||
|
||||
/* 32-bit collation element table format:
|
||||
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||
* case weight - high 4 bit of low 8 bit.
|
||||
*/
|
||||
while (len1 > 0 && len2 > 0)
|
||||
{
|
||||
if (flags & NORM_IGNORESYMBOLS)
|
||||
{
|
||||
int skip = 0;
|
||||
/* FIXME: not tested */
|
||||
if (iswctype(*str1, _SPACE | _PUNCT))
|
||||
{
|
||||
str1++;
|
||||
len1--;
|
||||
skip = 1;
|
||||
}
|
||||
if (iswctype(*str2, _SPACE | _PUNCT))
|
||||
{
|
||||
str2++;
|
||||
len2--;
|
||||
skip = 1;
|
||||
}
|
||||
if (skip) continue;
|
||||
}
|
||||
|
||||
ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)];
|
||||
ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
|
||||
|
||||
if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1)
|
||||
ret = ((ce1 >> 4) & 0x0f) - ((ce2 >> 4) & 0x0f);
|
||||
else
|
||||
ret = *str1 - *str2;
|
||||
|
||||
if (ret) return ret;
|
||||
|
||||
str1++;
|
||||
str2++;
|
||||
len1--;
|
||||
len2--;
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
static inline int real_length(const WCHAR *str, int len)
|
||||
{
|
||||
while (len && !str[len - 1]) len--;
|
||||
return len;
|
||||
}
|
||||
|
||||
int wine_compare_string(int flags, const WCHAR *str1, int len1,
|
||||
const WCHAR *str2, int len2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
len1 = real_length(str1, len1);
|
||||
len2 = real_length(str2, len2);
|
||||
|
||||
ret = compare_unicode_weights(flags, str1, len1, str2, len2);
|
||||
if (!ret)
|
||||
{
|
||||
if (!(flags & NORM_IGNORENONSPACE))
|
||||
ret = compare_diacritic_weights(flags, str1, len1, str2, len2);
|
||||
if (!ret && !(flags & NORM_IGNORECASE))
|
||||
ret = compare_case_weights(flags, str1, len1, str2, len2);
|
||||
}
|
||||
return ret;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue