Commit 33f9dcb1 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

Move CompareString implementation to libwine_unicode, add a bunch of

CompareString tests.
parent 1bcbd546
...@@ -1971,6 +1971,12 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, ...@@ -1971,6 +1971,12 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen,
} }
} }
if (srclen)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
return dst_ptr - dst; return dst_ptr - dst;
} }
...@@ -1994,7 +2000,7 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, ...@@ -1994,7 +2000,7 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen,
INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen, INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
LPSTR dst, INT dstlen) LPSTR dst, INT dstlen)
{ {
WCHAR bufW[128]; WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
LPWSTR srcW, dstW; LPWSTR srcW, dstW;
INT ret = 0, srclenW, dstlenW; INT ret = 0, srclenW, dstlenW;
UINT locale_cp; UINT locale_cp;
...@@ -2007,7 +2013,7 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen, ...@@ -2007,7 +2013,7 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
locale_cp = get_lcid_codepage(lcid); locale_cp = get_lcid_codepage(lcid);
srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 128); srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 260);
if (srclenW) if (srclenW)
srcW = bufW; srcW = bufW;
else else
...@@ -2040,6 +2046,9 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen, ...@@ -2040,6 +2046,9 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
} }
dstlenW = LCMapStringW(lcid, flags, srcW, srclenW, NULL, 0); dstlenW = LCMapStringW(lcid, flags, srcW, srclenW, NULL, 0);
if (!dstlenW)
goto map_string_exit;
dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR)); dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
if (!dstW) if (!dstW)
{ {
...@@ -2172,7 +2181,7 @@ INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen, ...@@ -2172,7 +2181,7 @@ INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen,
INT WINAPI CompareStringW(LCID lcid, DWORD style, INT WINAPI CompareStringW(LCID lcid, DWORD style,
LPCWSTR str1, INT len1, LPCWSTR str2, INT len2) LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
{ {
INT ret, len; INT ret;
if (!str1 || !str2) if (!str1 || !str2)
{ {
...@@ -2180,19 +2189,24 @@ INT WINAPI CompareStringW(LCID lcid, DWORD style, ...@@ -2180,19 +2189,24 @@ INT WINAPI CompareStringW(LCID lcid, DWORD style,
return 0; return 0;
} }
if (len1 < 0) len1 = lstrlenW(str1); if( style & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|
if (len2 < 0) len2 = lstrlenW(str2); SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|0x10000000) )
{
SetLastError(ERROR_INVALID_FLAGS);
return 0;
}
len = (len1 < len2) ? len1 : len2; if (style & 0x10000000)
ret = (style & NORM_IGNORECASE) ? strncmpiW(str1, str2, len) : FIXME("Ignoring unknown style 0x10000000\n");
strncmpW(str1, str2, len);
if (len1 < 0) len1 = strlenW(str1);
if (len2 < 0) len2 = strlenW(str2);
ret = wine_compare_string(style, str1, len1, str2, len2);
if (ret) /* need to translate result */ if (ret) /* need to translate result */
return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN; return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
return CSTR_EQUAL;
if (len1 == len2) return CSTR_EQUAL;
/* the longer one is lexically greater */
return (len1 < len2) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
} }
/****************************************************************************** /******************************************************************************
...@@ -2216,7 +2230,8 @@ INT WINAPI CompareStringW(LCID lcid, DWORD style, ...@@ -2216,7 +2230,8 @@ INT WINAPI CompareStringW(LCID lcid, DWORD style,
INT WINAPI CompareStringA(LCID lcid, DWORD style, INT WINAPI CompareStringA(LCID lcid, DWORD style,
LPCSTR str1, INT len1, LPCSTR str2, INT len2) LPCSTR str1, INT len1, LPCSTR str2, INT len2)
{ {
WCHAR buf1W[128], buf2W[128]; WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
WCHAR *buf2W = buf1W + 130;
LPWSTR str1W, str2W; LPWSTR str1W, str2W;
INT len1W, len2W, ret; INT len1W, len2W, ret;
UINT locale_cp; UINT locale_cp;
...@@ -2226,13 +2241,12 @@ INT WINAPI CompareStringA(LCID lcid, DWORD style, ...@@ -2226,13 +2241,12 @@ INT WINAPI CompareStringA(LCID lcid, DWORD style,
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return 0; return 0;
} }
if (len1 < 0) len1 = strlen(str1); if (len1 < 0) len1 = strlen(str1);
if (len2 < 0) len2 = strlen(str2); if (len2 < 0) len2 = strlen(str2);
locale_cp = get_lcid_codepage(lcid); locale_cp = get_lcid_codepage(lcid);
len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 128); len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 130);
if (len1W) if (len1W)
str1W = buf1W; str1W = buf1W;
else else
...@@ -2246,7 +2260,7 @@ INT WINAPI CompareStringA(LCID lcid, DWORD style, ...@@ -2246,7 +2260,7 @@ INT WINAPI CompareStringA(LCID lcid, DWORD style,
} }
MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W); MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W);
} }
len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 128); len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 130);
if (len2W) if (len2W)
str2W = buf2W; str2W = buf2W;
else else
......
...@@ -64,7 +64,7 @@ static BOOL WINAPI SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags) ...@@ -64,7 +64,7 @@ static BOOL WINAPI SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
char str1[3], str2[3]; char str1[3], str2[3];
str1[0] = LOBYTE(ch1); str1[0] = LOBYTE(ch1);
if (IsDBCSLeadByte(ch1)) if (IsDBCSLeadByte(str1[0]))
{ {
str1[1] = HIBYTE(ch1); str1[1] = HIBYTE(ch1);
str1[2] = '\0'; str1[2] = '\0';
...@@ -73,7 +73,7 @@ static BOOL WINAPI SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags) ...@@ -73,7 +73,7 @@ static BOOL WINAPI SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
str1[1] = '\0'; str1[1] = '\0';
str2[0] = LOBYTE(ch2); str2[0] = LOBYTE(ch2);
if (IsDBCSLeadByte(ch2)) if (IsDBCSLeadByte(str2[0]))
{ {
str2[1] = HIBYTE(ch2); str2[1] = HIBYTE(ch2);
str2[2] = '\0'; str2[2] = '\0';
......
...@@ -156,33 +156,37 @@ static const StrFromTimeIntervalResult StrFromTimeInterval_results[] = { ...@@ -156,33 +156,37 @@ static const StrFromTimeIntervalResult StrFromTimeInterval_results[] = {
static void test_StrChrA(void) static void test_StrChrA(void)
{ {
char string[129]; char string[129];
int count; WORD count;
ok(!StrChrA(NULL,'\0'), "found a character in a NULL string!"); /* this test crashes on win2k SP4 */
/*ok(!StrChrA(NULL,'\0'), "found a character in a NULL string!");*/
for (count = 32; count < 128; count++) for (count = 32; count < 128; count++)
string[count] = count; string[count] = (char)count;
string[128] = '\0'; string[128] = '\0';
for (count = 32; count < 128; count++) for (count = 32; count < 128; count++)
{ {
LPSTR result = StrChrA(string+32, count); LPSTR result = StrChrA(string+32, count);
ok(result - string == count, "found char %d in wrong place", count); ok(result - string == count,
"found char '%c' in wrong place: got %d, expected %d\n",
count, result - string, count);
} }
for (count = 32; count < 128; count++) for (count = 32; count < 128; count++)
{ {
LPSTR result = StrChrA(string+count+1, count); LPSTR result = StrChrA(string+count+1, count);
ok(!result, "found char not in the string"); ok(!result, "found char '%c' not in the string\n", count);
} }
} }
static void test_StrChrW(void) static void test_StrChrW(void)
{ {
WCHAR string[16385]; WCHAR string[16385];
int count; WORD count;
ok(!StrChrW(NULL,'\0'), "found a character in a NULL string!"); /* this test crashes on win2k SP4 */
/*ok(!StrChrW(NULL,'\0'), "found a character in a NULL string!");*/
for (count = 32; count < 16384; count++) for (count = 32; count < 16384; count++)
string[count] = count; string[count] = count;
...@@ -204,12 +208,13 @@ static void test_StrChrW(void) ...@@ -204,12 +208,13 @@ static void test_StrChrW(void)
static void test_StrChrIA(void) static void test_StrChrIA(void)
{ {
char string[129]; char string[129];
int count; WORD count;
ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!"); /* this test crashes on win2k SP4 */
/*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");*/
for (count = 32; count < 128; count++) for (count = 32; count < 128; count++)
string[count] = count; string[count] = (char)count;
string[128] = '\0'; string[128] = '\0';
for (count = 'A'; count <= 'X'; count++) for (count = 'A'; count <= 'X'; count++)
...@@ -230,9 +235,10 @@ static void test_StrChrIA(void) ...@@ -230,9 +235,10 @@ static void test_StrChrIA(void)
static void test_StrChrIW(void) static void test_StrChrIW(void)
{ {
WCHAR string[129]; WCHAR string[129];
int count; WORD count;
ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!"); /* this test crashes on win2k SP4 */
/*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");*/
for (count = 32; count < 128; count++) for (count = 32; count < 128; count++)
string[count] = count; string[count] = count;
...@@ -256,12 +262,13 @@ static void test_StrChrIW(void) ...@@ -256,12 +262,13 @@ static void test_StrChrIW(void)
static void test_StrRChrA(void) static void test_StrRChrA(void)
{ {
char string[129]; char string[129];
int count; WORD count;
ok(!StrRChrA(NULL, NULL,'\0'), "found a character in a NULL string!"); /* this test crashes on win2k SP4 */
/*ok(!StrRChrA(NULL, NULL,'\0'), "found a character in a NULL string!");*/
for (count = 32; count < 128; count++) for (count = 32; count < 128; count++)
string[count] = count; string[count] = (char)count;
string[128] = '\0'; string[128] = '\0';
for (count = 32; count < 128; count++) for (count = 32; count < 128; count++)
...@@ -285,31 +292,34 @@ static void test_StrRChrA(void) ...@@ -285,31 +292,34 @@ static void test_StrRChrA(void)
static void test_StrRChrW(void) static void test_StrRChrW(void)
{ {
WCHAR string[16385]; WCHAR string[129];
int count; WORD count;
ok(!StrRChrW(NULL, NULL,'\0'), "found a character in a NULL string!"); /* this test crashes on win2k SP4 */
/*ok(!StrRChrW(NULL, NULL,'\0'), "found a character in a NULL string!");*/
for (count = 32; count < 16384; count++) for (count = 32; count < 128; count++)
string[count] = count; string[count] = count;
string[16384] = '\0'; string[128] = '\0';
for (count = 32; count < 16384; count++) for (count = 32; count < 128; count++)
{ {
LPWSTR result = StrRChrW(string+32, NULL, count); LPWSTR result = StrRChrW(string+32, NULL, count);
ok(result - string == count, "found char %d in wrong place", count); ok(result - string == count,
"found char %d in wrong place: got %d, expected %d\n",
count, result - string, count);
} }
for (count = 32; count < 16384; count++) for (count = 32; count < 128; count++)
{ {
LPWSTR result = StrRChrW(string+count+1, NULL, count); LPWSTR result = StrRChrW(string+count+1, NULL, count);
ok(!result, "found char not in the string"); ok(!result, "found char %d not in the string\n", count);
} }
for (count = 32; count < 16384; count++) for (count = 32; count < 128; count++)
{ {
LPWSTR result = StrRChrW(string+count+1, string + 127, count); LPWSTR result = StrRChrW(string+count+1, string + 127, count);
ok(!result, "found char not in the string"); ok(!result, "found char %d not in the string\n", count);
} }
} }
...@@ -455,6 +465,8 @@ static void test_StrDupA() ...@@ -455,6 +465,8 @@ static void test_StrDupA()
static void test_StrFormatByteSize64A(void) static void test_StrFormatByteSize64A(void)
{ {
/* this test fails on locales which do not use '.' as a decimal separator */
#if 0
char szBuff[256]; char szBuff[256];
const StrFormatSizeResult* result = StrFormatSize_results; const StrFormatSizeResult* result = StrFormatSize_results;
...@@ -462,10 +474,13 @@ static void test_StrFormatByteSize64A(void) ...@@ -462,10 +474,13 @@ static void test_StrFormatByteSize64A(void)
{ {
StrFormatByteSize64A(result->value, szBuff, 256); StrFormatByteSize64A(result->value, szBuff, 256);
ok(!strcmp(result->byte_size_64, szBuff), "Formatted %lld wrong", result->value); ok(!strcmp(result->byte_size_64, szBuff),
"Formatted %lx%08lx wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->byte_size_64);
result++; result++;
} }
#endif
} }
static void test_StrFormatKBSizeW(void) static void test_StrFormatKBSizeW(void)
...@@ -480,8 +495,9 @@ static void test_StrFormatKBSizeW(void) ...@@ -480,8 +495,9 @@ static void test_StrFormatKBSizeW(void)
{ {
StrFormatKBSizeW(result->value, szBuffW, 256); StrFormatKBSizeW(result->value, szBuffW, 256);
WideCharToMultiByte(0,0,szBuffW,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR),0,0); WideCharToMultiByte(0,0,szBuffW,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR),0,0);
ok(!strcmp(result->kb_size, szBuff), "Formatted %lld wrong", ok(!strcmp(result->kb_size, szBuff),
result->value); "Formatted %lx%08lx wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
result++; result++;
} }
#endif #endif
...@@ -489,6 +505,7 @@ static void test_StrFormatKBSizeW(void) ...@@ -489,6 +505,7 @@ static void test_StrFormatKBSizeW(void)
static void test_StrFormatKBSizeA(void) static void test_StrFormatKBSizeA(void)
{ {
/* this test fails on locales which do not use '.' as a decimal separator */
#if 0 #if 0
char szBuff[256]; char szBuff[256];
const StrFormatSizeResult* result = StrFormatSize_results; const StrFormatSizeResult* result = StrFormatSize_results;
...@@ -497,8 +514,9 @@ static void test_StrFormatKBSizeA(void) ...@@ -497,8 +514,9 @@ static void test_StrFormatKBSizeA(void)
{ {
StrFormatKBSizeA(result->value, szBuff, 256); StrFormatKBSizeA(result->value, szBuff, 256);
ok(!strcmp(result->kb_size, szBuff), "Formatted %lld wrong", ok(!strcmp(result->kb_size, szBuff),
result->value); "Formatted %lx%08lx wrong: got %s, expected %s\n",
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
result++; result++;
} }
#endif #endif
......
...@@ -74,6 +74,7 @@ extern int wine_cp_wcstombs( const union cptable *table, int flags, ...@@ -74,6 +74,7 @@ extern int wine_cp_wcstombs( const union cptable *table, int flags,
extern int wine_utf8_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen ); extern int wine_utf8_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen );
extern int wine_utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int dstlen ); extern int wine_utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int dstlen );
extern int wine_compare_string( int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2 );
extern int wine_get_sortkey( int flags, const WCHAR *src, int srclen, char *dst, int dstlen ); extern int wine_get_sortkey( int flags, const WCHAR *src, int srclen, char *dst, int dstlen );
extern int wine_fold_string( int flags, const WCHAR *src, int srclen , WCHAR *dst, int dstlen ); extern int wine_fold_string( int flags, const WCHAR *src, int srclen , WCHAR *dst, int dstlen );
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "wine/unicode.h" #include "wine/unicode.h"
extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen); extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
extern const unsigned int collation_table[];
/* /*
* flags - normalization NORM_* flags * flags - normalization NORM_* flags
...@@ -28,7 +29,6 @@ extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen); ...@@ -28,7 +29,6 @@ extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
*/ */
int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen) int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen)
{ {
extern const unsigned int collation_table[];
WCHAR dummy[4]; /* no decomposition is larger than 4 chars */ WCHAR dummy[4]; /* no decomposition is larger than 4 chars */
int key_len[4]; int key_len[4];
char *key_ptr[4]; char *key_ptr[4];
...@@ -38,7 +38,8 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst ...@@ -38,7 +38,8 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
key_len[0] = key_len[1] = key_len[2] = key_len[3] = 0; key_len[0] = key_len[1] = key_len[2] = key_len[3] = 0;
for (; srclen; srclen--, src++) for (; srclen; srclen--, src++)
{ {
int decomposed_len = get_decomposition(*src, dummy, 4); int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/
dummy[0] = *src;
if (decomposed_len) if (decomposed_len)
{ {
int i; int i;
...@@ -62,18 +63,18 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst ...@@ -62,18 +63,18 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
if (ce >> 16) key_len[0] += 2; if (ce >> 16) key_len[0] += 2;
if ((ce >> 8) & 0xff) key_len[1]++; if ((ce >> 8) & 0xff) key_len[1]++;
if ((ce >> 4) & 0x0f) key_len[2]++; if ((ce >> 4) & 0x0f) key_len[2]++;
/*if (ce & 1) if (ce & 1)
{ {
if (wch >> 8) key_len[3]++; if (wch >> 8) key_len[3]++;
key_len[3]++; key_len[3]++;
}*/ }
} }
/*else else
{ {
key_len[0] += 2; key_len[0] += 2;
if (wch >> 8) key_len[0]++; if (wch >> 8) key_len[0]++;
if (wch & 0xff) key_len[0]++; if (wch & 0xff) key_len[0]++;
}*/ }
} }
} }
} }
...@@ -95,7 +96,8 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst ...@@ -95,7 +96,8 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
for (; srclen; srclen--, src++) for (; srclen; srclen--, src++)
{ {
int decomposed_len = get_decomposition(*src, dummy, 4); int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/
dummy[0] = *src;
if (decomposed_len) if (decomposed_len)
{ {
int i; int i;
...@@ -127,19 +129,19 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst ...@@ -127,19 +129,19 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
/* make key 2 start from 2 */ /* make key 2 start from 2 */
if ((key = (ce >> 4) & 0x0f)) *key_ptr[2]++ = key + 1; if ((key = (ce >> 4) & 0x0f)) *key_ptr[2]++ = key + 1;
/* key 3 is always a character code */ /* key 3 is always a character code */
/*if (ce & 1) if (ce & 1)
{ {
if (wch >> 8) *key_ptr[3]++ = wch >> 8; if (wch >> 8) *key_ptr[3]++ = wch >> 8;
if (wch & 0xff) *key_ptr[3]++ = wch & 0xff; if (wch & 0xff) *key_ptr[3]++ = wch & 0xff;
}*/ }
} }
/*else else
{ {
*key_ptr[0]++ = 0xff; *key_ptr[0]++ = 0xff;
*key_ptr[0]++ = 0xfe; *key_ptr[0]++ = 0xfe;
if (wch >> 8) *key_ptr[0]++ = wch >> 8; if (wch >> 8) *key_ptr[0]++ = wch >> 8;
if (wch & 0xff) *key_ptr[0]++ = wch & 0xff; if (wch & 0xff) *key_ptr[0]++ = wch & 0xff;
}*/ }
} }
} }
} }
...@@ -152,3 +154,198 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst ...@@ -152,3 +154,198 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
return key_ptr[3] - dst; 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 (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
{
str1++;
len1--;
skip = 1;
}
if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
{
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 (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
{
str1++;
len1--;
skip = 1;
}
if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
{
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 (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
{
str1++;
len1--;
skip = 1;
}
if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
{
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)
{
int real_len = 0;
while (len-- && *str++) real_len++;
return real_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;
}
...@@ -27,7 +27,7 @@ int strcmpiW( const WCHAR *str1, const WCHAR *str2 ) ...@@ -27,7 +27,7 @@ int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
{ {
for (;;) for (;;)
{ {
int ret = toupperW(*str1) - toupperW(*str2); int ret = tolowerW(*str1) - tolowerW(*str2);
if (ret || !*str1) return ret; if (ret || !*str1) return ret;
str1++; str1++;
str2++; str2++;
...@@ -38,7 +38,7 @@ int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n ) ...@@ -38,7 +38,7 @@ int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
{ {
int ret = 0; int ret = 0;
for ( ; n > 0; n--, str1++, str2++) for ( ; n > 0; n--, str1++, str2++)
if ((ret = toupperW(*str1) - toupperW(*str2)) || !*str1) break; if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break;
return ret; return ret;
} }
......
...@@ -12,6 +12,7 @@ EXPORTS ...@@ -12,6 +12,7 @@ EXPORTS
vsprintfW vsprintfW
wine_casemap_lower wine_casemap_lower
wine_casemap_upper wine_casemap_upper
wine_compare_string
wine_cp_enum_table wine_cp_enum_table
wine_cp_get_table wine_cp_get_table
wine_cp_mbstowcs wine_cp_mbstowcs
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment