unicode: Avoid copying the decomposition data when not necessary.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-02-04 10:52:04 +01:00
parent a646e4e6f2
commit cd8eaef47e
8 changed files with 135 additions and 146 deletions

View File

@ -4,7 +4,7 @@
#include "windef.h" #include "windef.h"
static const WCHAR table[6061] = const WCHAR DECLSPEC_HIDDEN nfd_table[6061] =
{ {
/* index */ /* index */
0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0100, 0x0160, 0x0100, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0100, 0x0160, 0x0100,
@ -957,17 +957,3 @@ static const WCHAR table[6061] =
0x05e9, 0x05bc, 0x05ea, 0x05bc, 0x05d5, 0x05b9, 0x05d1, 0x05bf, 0x05e9, 0x05bc, 0x05ea, 0x05bc, 0x05d5, 0x05b9, 0x05d1, 0x05bf,
0x05db, 0x05bf, 0x05e4, 0x05bf 0x05db, 0x05bf, 0x05e4, 0x05bf
}; };
unsigned int DECLSPEC_HIDDEN wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen )
{
unsigned short offset = table[table[ch >> 8] + ((ch >> 4) & 0xf)] + (ch & 0xf);
unsigned short start = table[offset];
unsigned short end = table[offset + 1];
unsigned int len = end - start;
*dst = ch;
if (!len) return 1;
if (dstlen < len) return 0;
memcpy( dst, table + start, len * sizeof(WCHAR) );
return len;
}

View File

@ -42,11 +42,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(nls);
#define CALINFO_MAX_YEAR 2029 #define CALINFO_MAX_YEAR 2029
extern UINT CDECL __wine_get_unix_codepage(void); extern UINT CDECL __wine_get_unix_codepage(void);
extern unsigned int wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen ) DECLSPEC_HIDDEN;
extern WCHAR wine_compose( const WCHAR *str ) DECLSPEC_HIDDEN; extern WCHAR wine_compose( const WCHAR *str ) DECLSPEC_HIDDEN;
extern const unsigned short wctype_table[] DECLSPEC_HIDDEN; extern const unsigned short wctype_table[] DECLSPEC_HIDDEN;
extern const unsigned int collation_table[] DECLSPEC_HIDDEN; extern const unsigned int collation_table[] DECLSPEC_HIDDEN;
extern const unsigned short nfd_table[] DECLSPEC_HIDDEN;
static HANDLE kernel32_handle; static HANDLE kernel32_handle;
@ -675,6 +675,18 @@ static inline WCHAR casemap( const USHORT *table, WCHAR ch )
} }
static const WCHAR *get_decomposition( WCHAR ch, unsigned int *len )
{
unsigned short offset = nfd_table[nfd_table[ch >> 8] + ((ch >> 4) & 0xf)] + (ch & 0xf);
unsigned short start = nfd_table[offset];
unsigned short end = nfd_table[offset + 1];
if ((*len = end - start)) return nfd_table + start;
*len = 1;
return NULL;
}
static UINT get_lcid_codepage( LCID lcid, ULONG flags ) static UINT get_lcid_codepage( LCID lcid, ULONG flags )
{ {
UINT ret = GetACP(); UINT ret = GetACP();
@ -1138,15 +1150,17 @@ static int check_invalid_chars( const CPTABLEINFO *info, const unsigned char *sr
static int mbstowcs_decompose( const CPTABLEINFO *info, const unsigned char *src, int srclen, static int mbstowcs_decompose( const CPTABLEINFO *info, const unsigned char *src, int srclen,
WCHAR *dst, int dstlen ) WCHAR *dst, int dstlen )
{ {
WCHAR ch, dummy[4]; /* no decomposition is larger than 4 chars */ WCHAR ch;
USHORT off; USHORT off;
int len, res; int len;
const WCHAR *decomp;
unsigned int decomp_len;
if (info->DBCSOffsets) if (info->DBCSOffsets)
{ {
if (!dstlen) /* compute length */ if (!dstlen) /* compute length */
{ {
for (len = 0; srclen; srclen--, src++) for (len = 0; srclen; srclen--, src++, len += decomp_len)
{ {
if ((off = info->DBCSOffsets[*src])) if ((off = info->DBCSOffsets[*src]))
{ {
@ -1159,12 +1173,12 @@ static int mbstowcs_decompose( const CPTABLEINFO *info, const unsigned char *src
else ch = info->UniDefaultChar; else ch = info->UniDefaultChar;
} }
else ch = info->MultiByteTable[*src]; else ch = info->MultiByteTable[*src];
len += wine_decompose( 0, ch, dummy, 4 ); get_decomposition( ch, &decomp_len );
} }
return len; return len;
} }
for (len = dstlen; srclen && len; srclen--, src++) for (len = dstlen; srclen && len; srclen--, src++, dst += decomp_len, len -= decomp_len)
{ {
if ((off = info->DBCSOffsets[*src])) if ((off = info->DBCSOffsets[*src]))
{ {
@ -1177,25 +1191,33 @@ static int mbstowcs_decompose( const CPTABLEINFO *info, const unsigned char *src
else ch = info->UniDefaultChar; else ch = info->UniDefaultChar;
} }
else ch = info->MultiByteTable[*src]; else ch = info->MultiByteTable[*src];
if (!(res = wine_decompose( 0, ch, dst, len ))) break;
dst += res; if ((decomp = get_decomposition( ch, &decomp_len )))
len -= res; {
if (len < decomp_len) break;
memcpy( dst, decomp, decomp_len * sizeof(WCHAR) );
}
else *dst = ch;
} }
} }
else else
{ {
if (!dstlen) /* compute length */ if (!dstlen) /* compute length */
{ {
for (len = 0; srclen; srclen--, src++) for (len = 0; srclen; srclen--, src++, len += decomp_len)
len += wine_decompose( 0, info->MultiByteTable[*src], dummy, 4 ); get_decomposition( info->MultiByteTable[*src], &decomp_len );
return len; return len;
} }
for (len = dstlen; srclen && len; srclen--, src++) for (len = dstlen; srclen && len; srclen--, src++, dst += decomp_len, len -= decomp_len)
{ {
if (!(res = wine_decompose( 0, info->MultiByteTable[*src], dst, len ))) break; ch = info->MultiByteTable[*src];
len -= res; if ((decomp = get_decomposition( ch, &decomp_len )))
dst += res; {
if (len < decomp_len) break;
memcpy( dst, decomp, decomp_len * sizeof(WCHAR) );
}
else *dst = ch;
} }
} }
@ -2227,7 +2249,7 @@ static unsigned int get_weight( WCHAR ch, enum weight type )
} }
static void inc_str_pos( const WCHAR **str, int *len, int *dpos, int *dlen ) static void inc_str_pos( const WCHAR **str, int *len, unsigned int *dpos, unsigned int *dlen )
{ {
(*dpos)++; (*dpos)++;
if (*dpos == *dlen) if (*dpos == *dlen)
@ -2242,14 +2264,13 @@ static void inc_str_pos( const WCHAR **str, int *len, int *dpos, int *dlen )
static int compare_weights(int flags, const WCHAR *str1, int len1, static int compare_weights(int flags, const WCHAR *str1, int len1,
const WCHAR *str2, int len2, enum weight type ) const WCHAR *str2, int len2, enum weight type )
{ {
int dpos1 = 0, dpos2 = 0, dlen1 = 0, dlen2 = 0; unsigned int ce1, ce2, dpos1 = 0, dpos2 = 0, dlen1 = 0, dlen2 = 0;
WCHAR dstr1[4], dstr2[4]; const WCHAR *dstr1 = NULL, *dstr2 = NULL;
unsigned int ce1, ce2;
while (len1 > 0 && len2 > 0) while (len1 > 0 && len2 > 0)
{ {
if (!dlen1) dlen1 = wine_decompose( 0, *str1, dstr1, 4 ); if (!dlen1 && !(dstr1 = get_decomposition( *str1, &dlen1 ))) dstr1 = str1;
if (!dlen2) dlen2 = wine_decompose( 0, *str2, dstr2, 4 ); if (!dlen2 && !(dstr2 = get_decomposition( *str2, &dlen2 ))) dstr2 = str2;
if (flags & NORM_IGNORESYMBOLS) if (flags & NORM_IGNORESYMBOLS)
{ {
@ -2308,14 +2329,14 @@ static int compare_weights(int flags, const WCHAR *str1, int len1,
} }
while (len1) while (len1)
{ {
if (!dlen1) dlen1 = wine_decompose( 0, *str1, dstr1, 4 ); if (!dlen1 && !(dstr1 = get_decomposition( *str1, &dlen1 ))) dstr1 = str1;
ce1 = get_weight( dstr1[dpos1], type ); ce1 = get_weight( dstr1[dpos1], type );
if (ce1) break; if (ce1) break;
inc_str_pos( &str1, &len1, &dpos1, &dlen1 ); inc_str_pos( &str1, &len1, &dpos1, &dlen1 );
} }
while (len2) while (len2)
{ {
if (!dlen2) dlen2 = wine_decompose( 0, *str2, dstr2, 4 ); if (!dlen2 && !(dstr2 = get_decomposition( *str2, &dlen2 ))) dstr2 = str2;
ce2 = get_weight( dstr2[dpos2], type ); ce2 = get_weight( dstr2[dpos2], type );
if (ce2) break; if (ce2) break;
inc_str_pos( &str2, &len2, &dpos2, &dlen2 ); inc_str_pos( &str2, &len2, &dpos2, &dlen2 );

View File

@ -83,8 +83,9 @@ static HMODULE kernel32_handle;
static const union cptable *unix_table; /* NULL if UTF8 */ static const union cptable *unix_table; /* NULL if UTF8 */
extern WCHAR wine_compose( const WCHAR *str ) DECLSPEC_HIDDEN; extern WCHAR wine_compose( const WCHAR *str ) DECLSPEC_HIDDEN;
extern unsigned int wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen ) DECLSPEC_HIDDEN;
extern const unsigned short combining_class_table[] DECLSPEC_HIDDEN; extern const unsigned short combining_class_table[] DECLSPEC_HIDDEN;
extern const unsigned short nfd_table[] DECLSPEC_HIDDEN;
extern const unsigned short nfkd_table[] DECLSPEC_HIDDEN;
static NTSTATUS load_string( ULONG id, LANGID lang, WCHAR *buffer, ULONG len ) static NTSTATUS load_string( ULONG id, LANGID lang, WCHAR *buffer, ULONG len )
{ {
@ -153,6 +154,18 @@ static WCHAR casemap_ascii( WCHAR ch )
} }
static const WCHAR *get_decomposition( const unsigned short *table, WCHAR ch, unsigned int *len )
{
unsigned short offset = table[table[ch >> 8] + ((ch >> 4) & 0xf)] + (ch & 0xf);
unsigned short start = table[offset];
unsigned short end = table[offset + 1];
if ((*len = end - start)) return table + start;
*len = 1;
return NULL;
}
static BYTE get_combining_class( WCHAR c ) static BYTE get_combining_class( WCHAR c )
{ {
return combining_class_table[combining_class_table[combining_class_table[c >> 8] + ((c >> 4) & 0xf)] + (c & 0xf)]; return combining_class_table[combining_class_table[combining_class_table[c >> 8] + ((c >> 4) & 0xf)] + (c & 0xf)];
@ -223,20 +236,27 @@ static void canonical_order_string( WCHAR *str, unsigned int len )
} }
static NTSTATUS decompose_string( int flags, const WCHAR *src, int src_len, WCHAR *dst, int *dst_len ) static NTSTATUS decompose_string( int compat, const WCHAR *src, int src_len, WCHAR *dst, int *dst_len )
{ {
int src_pos, dst_pos = 0, decomp_len; const unsigned short *table = compat ? nfkd_table : nfd_table;
int src_pos, dst_pos = 0;
unsigned int decomp_len;
const WCHAR *decomp;
for (src_pos = 0; src_pos < src_len; src_pos++) for (src_pos = 0; src_pos < src_len; src_pos++)
{ {
if (dst_pos == *dst_len) break; if (dst_pos == *dst_len) break;
decomp_len = wine_decompose( flags, src[src_pos], dst + dst_pos, *dst_len - dst_pos ); if ((decomp = get_decomposition( table, src[src_pos], &decomp_len )))
if (decomp_len == 0) break; {
if (dst_pos + decomp_len > *dst_len) break;
memcpy( dst + dst_pos, decomp, decomp_len * sizeof(WCHAR) );
}
else dst[dst_pos] = src[src_pos];
dst_pos += decomp_len; dst_pos += decomp_len;
} }
if (src_pos < src_len) if (src_pos < src_len)
{ {
*dst_len += (src_len - src_pos) * (flags & WINE_DECOMPOSE_COMPAT ? 18 : 3); *dst_len += (src_len - src_pos) * (compat ? 18 : 3);
return STATUS_BUFFER_TOO_SMALL; return STATUS_BUFFER_TOO_SMALL;
} }
canonical_order_string( dst, dst_pos ); canonical_order_string( dst, dst_pos );
@ -1691,7 +1711,7 @@ NTSTATUS WINAPI RtlIsNormalizedString( ULONG form, const WCHAR *str, INT len, BO
*/ */
NTSTATUS WINAPI RtlNormalizeString( ULONG form, const WCHAR *src, INT src_len, WCHAR *dst, INT *dst_len ) NTSTATUS WINAPI RtlNormalizeString( ULONG form, const WCHAR *src, INT src_len, WCHAR *dst, INT *dst_len )
{ {
int flags = 0, compose, compat, buf_len; int compose, compat, buf_len;
WCHAR *buf = NULL; WCHAR *buf = NULL;
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
@ -1721,16 +1741,14 @@ NTSTATUS WINAPI RtlNormalizeString( ULONG form, const WCHAR *src, INT src_len, W
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
if (compat) flags |= WINE_DECOMPOSE_COMPAT; if (!compose) return decompose_string( compat, src, src_len, dst, dst_len );
if (!compose) return decompose_string( flags, src, src_len, dst, dst_len );
buf_len = src_len * 4; buf_len = src_len * 4;
for (;;) for (;;)
{ {
buf = RtlAllocateHeap( GetProcessHeap(), 0, buf_len * sizeof(WCHAR) ); buf = RtlAllocateHeap( GetProcessHeap(), 0, buf_len * sizeof(WCHAR) );
if (!buf) return STATUS_NO_MEMORY; if (!buf) return STATUS_NO_MEMORY;
status = decompose_string( flags, src, src_len, buf, &buf_len ); status = decompose_string( compat, src, src_len, buf, &buf_len );
if (status != STATUS_BUFFER_TOO_SMALL) break; if (status != STATUS_BUFFER_TOO_SMALL) break;
RtlFreeHeap( GetProcessHeap(), 0, buf ); RtlFreeHeap( GetProcessHeap(), 0, buf );
} }

View File

@ -97,9 +97,6 @@ extern int wine_compare_string( int flags, const WCHAR *str1, int len1, const WC
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 );
#define WINE_DECOMPOSE_COMPAT 1
#define WINE_DECOMPOSE_REORDER 2
extern int strcmpiW( const WCHAR *str1, const WCHAR *str2 ); extern int strcmpiW( const WCHAR *str1, const WCHAR *str2 );
extern int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n ); extern int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n );
extern int memicmpW( const WCHAR *str1, const WCHAR *str2, int n ); extern int memicmpW( const WCHAR *str1, const WCHAR *str2, int n );

View File

@ -4,7 +4,7 @@
#include "windef.h" #include "windef.h"
static const WCHAR decomp_table[6061] = const WCHAR DECLSPEC_HIDDEN nfd_table[6061] =
{ {
/* index */ /* index */
0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0100, 0x0160, 0x0100, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0100, 0x0160, 0x0100,
@ -958,7 +958,7 @@ static const WCHAR decomp_table[6061] =
0x05db, 0x05bf, 0x05e4, 0x05bf 0x05db, 0x05bf, 0x05e4, 0x05bf
}; };
static const WCHAR compatmap_table[13479] = const WCHAR DECLSPEC_HIDDEN nfkd_table[13479] =
{ {
/* index */ /* index */
0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0100, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0100,
@ -3039,20 +3039,3 @@ static const WCHAR compatmap_table[13479] =
0x00a3, 0x00ac, 0x0020, 0x0304, 0x00a6, 0x00a5, 0x20a9, 0x2502, 0x00a3, 0x00ac, 0x0020, 0x0304, 0x00a6, 0x00a5, 0x20a9, 0x2502,
0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb
}; };
#include "wine/unicode.h"
unsigned int DECLSPEC_HIDDEN wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen )
{
const WCHAR *table = (flags & WINE_DECOMPOSE_COMPAT) ? compatmap_table : decomp_table;
unsigned short offset = table[table[ch >> 8] + ((ch >> 4) & 0xf)] + (ch & 0xf);
unsigned short start = table[offset];
unsigned short end = table[offset + 1];
unsigned int len = end - start;
*dst = ch;
if (!len) return 1;
if (dstlen < len) return 0;
memcpy( dst, table + start, len * sizeof(WCHAR) );
return len;
}

View File

@ -22,7 +22,18 @@
#include "wine/unicode.h" #include "wine/unicode.h"
extern unsigned int wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen ) DECLSPEC_HIDDEN; extern const unsigned short nfd_table[] DECLSPEC_HIDDEN;
static const WCHAR *get_decomposition( WCHAR ch, unsigned int *len )
{
unsigned short offset = nfd_table[nfd_table[ch >> 8] + ((ch >> 4) & 0xf)] + (ch & 0xf);
unsigned short start = nfd_table[offset];
unsigned short end = nfd_table[offset + 1];
if ((*len = end - start)) return nfd_table + start;
*len = 1;
return NULL;
}
/* check the code whether it is in Unicode Private Use Area (PUA). */ /* check the code whether it is in Unicode Private Use Area (PUA). */
/* MB_ERR_INVALID_CHARS raises an error converting from 1-byte character to PUA. */ /* MB_ERR_INVALID_CHARS raises an error converting from 1-byte character to PUA. */
@ -119,22 +130,24 @@ static int mbstowcs_sbcs_decompose( const struct sbcs_table *table, int flags,
WCHAR *dst, unsigned int dstlen ) WCHAR *dst, unsigned int dstlen )
{ {
const WCHAR * const cp2uni = (flags & MB_USEGLYPHCHARS) ? table->cp2uni_glyphs : table->cp2uni; const WCHAR * const cp2uni = (flags & MB_USEGLYPHCHARS) ? table->cp2uni_glyphs : table->cp2uni;
unsigned int len; const WCHAR *decomp;
unsigned int len, decomp_len;
if (!dstlen) /* compute length */ if (!dstlen) /* compute length */
{ {
WCHAR dummy[4]; /* no decomposition is larger than 4 chars */ for (len = 0; srclen; srclen--, src++, len += decomp_len)
for (len = 0; srclen; srclen--, src++) get_decomposition( cp2uni[*src], &decomp_len );
len += wine_decompose( 0, cp2uni[*src], dummy, 4 );
return len; return len;
} }
for (len = dstlen; srclen && len; srclen--, src++) for (len = dstlen; srclen && len; srclen--, src++, dst += decomp_len, len -= decomp_len)
{ {
unsigned int res = wine_decompose( 0, cp2uni[*src], dst, len ); if ((decomp = get_decomposition( cp2uni[*src], &decomp_len )))
if (!res) break; {
len -= res; if (len < decomp_len) break;
dst += res; memcpy( dst, decomp, decomp_len * sizeof(WCHAR) );
}
else *dst = cp2uni[*src];
} }
if (srclen) return -1; /* overflow */ if (srclen) return -1; /* overflow */
return dstlen - len; return dstlen - len;
@ -221,13 +234,13 @@ static int mbstowcs_dbcs_decompose( const struct dbcs_table *table,
{ {
const WCHAR * const cp2uni = table->cp2uni; const WCHAR * const cp2uni = table->cp2uni;
const unsigned char * const cp2uni_lb = table->cp2uni_leadbytes; const unsigned char * const cp2uni_lb = table->cp2uni_leadbytes;
unsigned int len, res; const WCHAR *decomp;
unsigned int len, decomp_len;
WCHAR ch; WCHAR ch;
if (!dstlen) /* compute length */ if (!dstlen) /* compute length */
{ {
WCHAR dummy[4]; /* no decomposition is larger than 4 chars */ for (len = 0; srclen; srclen--, src++, len += decomp_len)
for (len = 0; srclen; srclen--, src++)
{ {
unsigned char off = cp2uni_lb[*src]; unsigned char off = cp2uni_lb[*src];
if (off && srclen > 1 && src[1]) if (off && srclen > 1 && src[1])
@ -237,12 +250,12 @@ static int mbstowcs_dbcs_decompose( const struct dbcs_table *table,
ch = cp2uni[(off << 8) + *src]; ch = cp2uni[(off << 8) + *src];
} }
else ch = cp2uni[*src]; else ch = cp2uni[*src];
len += wine_decompose( 0, ch, dummy, 4 ); get_decomposition( ch, &decomp_len );
} }
return len; return len;
} }
for (len = dstlen; srclen && len; srclen--, src++) for (len = dstlen; srclen && len; srclen--, src++, dst += decomp_len, len -= decomp_len)
{ {
unsigned char off = cp2uni_lb[*src]; unsigned char off = cp2uni_lb[*src];
if (off && srclen > 1 && src[1]) if (off && srclen > 1 && src[1])
@ -252,9 +265,13 @@ static int mbstowcs_dbcs_decompose( const struct dbcs_table *table,
ch = cp2uni[(off << 8) + *src]; ch = cp2uni[(off << 8) + *src];
} }
else ch = cp2uni[*src]; else ch = cp2uni[*src];
if (!(res = wine_decompose( 0, ch, dst, len ))) break;
dst += res; if ((decomp = get_decomposition( ch, &decomp_len )))
len -= res; {
if (len < decomp_len) break;
memcpy( dst, decomp, decomp_len * sizeof(WCHAR) );
}
else *dst = ch;
} }
if (srclen) return -1; /* overflow */ if (srclen) return -1; /* overflow */
return dstlen - len; return dstlen - len;

View File

@ -19,8 +19,19 @@
*/ */
#include "wine/unicode.h" #include "wine/unicode.h"
extern unsigned int wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen );
extern const unsigned int collation_table[]; extern const unsigned int collation_table[];
extern const unsigned short nfd_table[] DECLSPEC_HIDDEN;
static const WCHAR *get_decomposition( WCHAR ch, unsigned int *len )
{
unsigned short offset = nfd_table[nfd_table[ch >> 8] + ((ch >> 4) & 0xf)] + (ch & 0xf);
unsigned short start = nfd_table[offset];
unsigned short end = nfd_table[offset + 1];
if ((*len = end - start)) return nfd_table + start;
*len = 1;
return NULL;
}
/* /*
* flags - normalization NORM_* flags * flags - normalization NORM_* flags
@ -180,7 +191,7 @@ static unsigned int get_weight(WCHAR ch, enum weight type)
} }
} }
static void inc_str_pos(const WCHAR **str, int *len, int *dpos, int *dlen) static void inc_str_pos(const WCHAR **str, int *len, unsigned int *dpos, unsigned int *dlen)
{ {
(*dpos)++; (*dpos)++;
if (*dpos == *dlen) if (*dpos == *dlen)
@ -194,9 +205,8 @@ static void inc_str_pos(const WCHAR **str, int *len, int *dpos, int *dlen)
static inline int compare_weights(int flags, const WCHAR *str1, int len1, static inline int compare_weights(int flags, const WCHAR *str1, int len1,
const WCHAR *str2, int len2, enum weight type) const WCHAR *str2, int len2, enum weight type)
{ {
int dpos1 = 0, dpos2 = 0, dlen1 = 0, dlen2 = 0; unsigned int ce1, ce2, dpos1 = 0, dpos2 = 0, dlen1 = 0, dlen2 = 0;
WCHAR dstr1[4], dstr2[4]; const WCHAR *dstr1 = NULL, *dstr2 = NULL;
unsigned int ce1, ce2;
/* 32-bit collation element table format: /* 32-bit collation element table format:
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit, * unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
@ -204,8 +214,8 @@ static inline int compare_weights(int flags, const WCHAR *str1, int len1,
*/ */
while (len1 > 0 && len2 > 0) while (len1 > 0 && len2 > 0)
{ {
if (!dlen1) dlen1 = wine_decompose(0, *str1, dstr1, 4); if (!dlen1 && !(dstr1 = get_decomposition( *str1, &dlen1 ))) dstr1 = str1;
if (!dlen2) dlen2 = wine_decompose(0, *str2, dstr2, 4); if (!dlen2 && !(dstr2 = get_decomposition( *str2, &dlen2 ))) dstr2 = str2;
if (flags & NORM_IGNORESYMBOLS) if (flags & NORM_IGNORESYMBOLS)
{ {
@ -264,16 +274,14 @@ static inline int compare_weights(int flags, const WCHAR *str1, int len1,
} }
while (len1) while (len1)
{ {
if (!dlen1) dlen1 = wine_decompose(0, *str1, dstr1, 4); if (!dlen1 && !(dstr1 = get_decomposition( *str1, &dlen1 ))) dstr1 = str1;
ce1 = get_weight(dstr1[dpos1], type); ce1 = get_weight(dstr1[dpos1], type);
if (ce1) break; if (ce1) break;
inc_str_pos(&str1, &len1, &dpos1, &dlen1); inc_str_pos(&str1, &len1, &dpos1, &dlen1);
} }
while (len2) while (len2)
{ {
if (!dlen2) dlen2 = wine_decompose(0, *str2, dstr2, 4); if (!dlen2 && !(dstr2 = get_decomposition( *str2, &dlen2 ))) dstr2 = str2;
ce2 = get_weight(dstr2[dpos2], type); ce2 = get_weight(dstr2[dpos2], type);
if (ce2) break; if (ce2) break;
inc_str_pos(&str2, &len2, &dpos2, &dlen2); inc_str_pos(&str2, &len2, &dpos2, &dlen2);

View File

@ -2380,8 +2380,6 @@ sub dump_decompositions($@)
{ {
my ($name, @decomp) = @_; my ($name, @decomp) = @_;
@decomp = build_decompositions( @decomp );
# first determine all the 16-char subsets that contain something # first determine all the 16-char subsets that contain something
my @filled = (0) x 4096; my @filled = (0) x 4096;
@ -2423,7 +2421,7 @@ sub dump_decompositions($@)
# dump the main index # dump the main index
printf OUTPUT "static const WCHAR %s[%d] =\n", $name, $total + $data_total; printf OUTPUT "\nconst WCHAR DECLSPEC_HIDDEN %s[%d] =\n", $name, $total + $data_total;
printf OUTPUT "{\n /* index */\n"; printf OUTPUT "{\n /* index */\n";
printf OUTPUT "%s", dump_array( 16, 0, @filled_idx ); printf OUTPUT "%s", dump_array( 16, 0, @filled_idx );
printf OUTPUT ",\n /* null sub-index */\n%s", dump_array( 16, 0, ($null_offset) x 16 ); printf OUTPUT ",\n /* null sub-index */\n%s", dump_array( 16, 0, ($null_offset) x 16 );
@ -2471,7 +2469,7 @@ sub dump_decompositions($@)
printf OUTPUT ",\n /* data */\n"; printf OUTPUT ",\n /* data */\n";
printf OUTPUT "%s", dump_array( 16, 0, @data ); printf OUTPUT "%s", dump_array( 16, 0, @data );
printf OUTPUT "\n};\n\n"; printf OUTPUT "\n};\n";
} }
################################################################ ################################################################
@ -2485,50 +2483,11 @@ sub dump_decompose_table($$)
print OUTPUT "/* Unicode char composition */\n"; print OUTPUT "/* Unicode char composition */\n";
print OUTPUT "/* generated from $UNIDATA/UnicodeData.txt */\n"; print OUTPUT "/* generated from $UNIDATA/UnicodeData.txt */\n";
print OUTPUT "/* DO NOT EDIT!! */\n\n"; print OUTPUT "/* DO NOT EDIT!! */\n\n";
print OUTPUT "#include \"windef.h\"\n\n"; print OUTPUT "#include \"windef.h\"\n";
dump_decompositions( $compat ? "decomp_table" : "table", @decomp_table ); dump_decompositions( "nfd_table", build_decompositions( @decomp_table ));
dump_decompositions( "nfkd_table", build_decompositions( @decomp_compat_table )) if $compat;
if ($compat)
{
dump_decompositions( "compatmap_table", @decomp_compat_table );
print OUTPUT <<"EOF";
#include "wine/unicode.h"
unsigned int DECLSPEC_HIDDEN wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen )
{
const WCHAR *table = (flags & WINE_DECOMPOSE_COMPAT) ? compatmap_table : decomp_table;
unsigned short offset = table[table[ch >> 8] + ((ch >> 4) & 0xf)] + (ch & 0xf);
unsigned short start = table[offset];
unsigned short end = table[offset + 1];
unsigned int len = end - start;
*dst = ch;
if (!len) return 1;
if (dstlen < len) return 0;
memcpy( dst, table + start, len * sizeof(WCHAR) );
return len;
}
EOF
}
else
{
print OUTPUT <<"EOF";
unsigned int DECLSPEC_HIDDEN wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen )
{
unsigned short offset = table[table[ch >> 8] + ((ch >> 4) & 0xf)] + (ch & 0xf);
unsigned short start = table[offset];
unsigned short end = table[offset + 1];
unsigned int len = end - start;
*dst = ch;
if (!len) return 1;
if (dstlen < len) return 0;
memcpy( dst, table + start, len * sizeof(WCHAR) );
return len;
}
EOF
}
close OUTPUT; close OUTPUT;
save_file($filename); save_file($filename);
} }