unicode: Avoid copying the decomposition data when not necessary.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a646e4e6f2
commit
cd8eaef47e
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue