Commit 8a37450d authored by Alexandre Julliard's avatar Alexandre Julliard

'used' should be set even if we are only computing the necessary

buffer size.
parent f25efa06
...@@ -76,33 +76,53 @@ static inline int is_valid_sbcs_mapping( const struct sbcs_table *table, int fla ...@@ -76,33 +76,53 @@ static inline int is_valid_sbcs_mapping( const struct sbcs_table *table, int fla
} }
/* query necessary dst length for src string */ /* query necessary dst length for src string */
static inline int get_length_sbcs( const struct sbcs_table *table, int flags, static int get_length_sbcs( const struct sbcs_table *table, int flags,
const WCHAR *src, unsigned int srclen ) const WCHAR *src, unsigned int srclen, int *used )
{ {
unsigned int ret = srclen;
if (flags & WC_COMPOSITECHECK)
{
const unsigned char * const uni2cp_low = table->uni2cp_low; const unsigned char * const uni2cp_low = table->uni2cp_low;
const unsigned short * const uni2cp_high = table->uni2cp_high; const unsigned short * const uni2cp_high = table->uni2cp_high;
int ret, tmp;
WCHAR composed; WCHAR composed;
for (ret = 0; srclen > 1; ret++, srclen--, src++) if (!used) used = &tmp; /* avoid checking on every char */
*used = 0;
for (ret = 0; srclen; ret++, src++, srclen--)
{ {
if (!(composed = compose(src))) continue; WCHAR wch = *src;
/* check if we should skip the next char */ unsigned char ch;
/* in WC_DEFAULTCHAR and WC_DISCARDNS mode, we always skip */ if ((flags & WC_COMPOSITECHECK) && (srclen > 1) && (composed = compose(src)))
/* the next char no matter if the composition is valid or not */ {
if (!(flags & (WC_DEFAULTCHAR|WC_DISCARDNS))) /* now check if we can use the composed char */
ch = uni2cp_low[uni2cp_high[composed >> 8] + (composed & 0xff)];
if (is_valid_sbcs_mapping( table, flags, composed, ch ))
{
/* we have a good mapping, use it */
src++;
srclen--;
continue;
}
/* no mapping for the composed char, check the other flags */
if (flags & WC_DEFAULTCHAR) /* use the default char instead */
{ {
unsigned char ch = uni2cp_low[uni2cp_high[composed >> 8] + (composed & 0xff)]; *used = 1;
if (!is_valid_sbcs_mapping( table, flags, composed, ch )) continue; src++; /* skip the non-spacing char */
srclen--;
continue;
} }
if (flags & WC_DISCARDNS) /* skip the second char of the composition */
{
src++; src++;
srclen--; srclen--;
} }
if (srclen) ret++; /* last char */ /* WC_SEPCHARS is the default */
}
if (!*used)
{
ch = uni2cp_low[uni2cp_high[wch >> 8] + (wch & 0xff)];
*used = !is_valid_sbcs_mapping( table, flags, wch, ch );
}
} }
return ret; return ret;
} }
...@@ -238,15 +258,15 @@ static inline int is_valid_dbcs_mapping( const struct dbcs_table *table, int fla ...@@ -238,15 +258,15 @@ static inline int is_valid_dbcs_mapping( const struct dbcs_table *table, int fla
/* query necessary dst length for src string */ /* query necessary dst length for src string */
static int get_length_dbcs( const struct dbcs_table *table, int flags, static int get_length_dbcs( const struct dbcs_table *table, int flags,
const WCHAR *src, unsigned int srclen, const WCHAR *src, unsigned int srclen,
const char *defchar ) const char *defchar, int *used )
{ {
const unsigned short * const uni2cp_low = table->uni2cp_low; const unsigned short * const uni2cp_low = table->uni2cp_low;
const unsigned short * const uni2cp_high = table->uni2cp_high; const unsigned short * const uni2cp_high = table->uni2cp_high;
WCHAR defchar_value = table->info.def_char; WCHAR defchar_value = table->info.def_char;
WCHAR composed; WCHAR composed;
int len; int len, tmp;
if (!defchar && !(flags & WC_COMPOSITECHECK)) if (!defchar && !used && !(flags & WC_COMPOSITECHECK))
{ {
for (len = 0; srclen; srclen--, src++, len++) for (len = 0; srclen; srclen--, src++, len++)
{ {
...@@ -256,6 +276,8 @@ static int get_length_dbcs( const struct dbcs_table *table, int flags, ...@@ -256,6 +276,8 @@ static int get_length_dbcs( const struct dbcs_table *table, int flags,
} }
if (defchar) defchar_value = defchar[1] ? ((defchar[0] << 8) | defchar[1]) : defchar[0]; if (defchar) defchar_value = defchar[1] ? ((defchar[0] << 8) | defchar[1]) : defchar[0];
if (!used) used = &tmp; /* avoid checking on every char */
*used = 0;
for (len = 0; srclen; len++, srclen--, src++) for (len = 0; srclen; len++, srclen--, src++)
{ {
unsigned short res; unsigned short res;
...@@ -278,6 +300,7 @@ static int get_length_dbcs( const struct dbcs_table *table, int flags, ...@@ -278,6 +300,7 @@ static int get_length_dbcs( const struct dbcs_table *table, int flags,
if (flags & WC_DEFAULTCHAR) /* use the default char instead */ if (flags & WC_DEFAULTCHAR) /* use the default char instead */
{ {
if (defchar_value & 0xff00) len++; if (defchar_value & 0xff00) len++;
*used = 1;
src++; /* skip the non-spacing char */ src++; /* skip the non-spacing char */
srclen--; srclen--;
continue; continue;
...@@ -291,7 +314,11 @@ static int get_length_dbcs( const struct dbcs_table *table, int flags, ...@@ -291,7 +314,11 @@ static int get_length_dbcs( const struct dbcs_table *table, int flags,
} }
res = uni2cp_low[uni2cp_high[wch >> 8] + (wch & 0xff)]; res = uni2cp_low[uni2cp_high[wch >> 8] + (wch & 0xff)];
if (!is_valid_dbcs_mapping( table, flags, wch, res )) res = defchar_value; if (!is_valid_dbcs_mapping( table, flags, wch, res ))
{
res = defchar_value;
*used = 1;
}
if (res & 0xff00) len++; if (res & 0xff00) len++;
} }
return len; return len;
...@@ -399,15 +426,18 @@ int cp_wcstombs( const union cptable *table, int flags, ...@@ -399,15 +426,18 @@ int cp_wcstombs( const union cptable *table, int flags,
{ {
if (table->info.char_size == 1) if (table->info.char_size == 1)
{ {
if (!dstlen) return get_length_sbcs( &table->sbcs, flags, src, srclen );
if (flags || defchar || used) if (flags || defchar || used)
{
if (!dstlen) return get_length_sbcs( &table->sbcs, flags, src, srclen, used );
return wcstombs_sbcs_slow( &table->sbcs, flags, src, srclen, return wcstombs_sbcs_slow( &table->sbcs, flags, src, srclen,
dst, dstlen, defchar, used ); dst, dstlen, defchar, used );
}
if (!dstlen) return srclen;
return wcstombs_sbcs( &table->sbcs, src, srclen, dst, dstlen ); return wcstombs_sbcs( &table->sbcs, src, srclen, dst, dstlen );
} }
else /* mbcs */ else /* mbcs */
{ {
if (!dstlen) return get_length_dbcs( &table->dbcs, flags, src, srclen, defchar ); if (!dstlen) return get_length_dbcs( &table->dbcs, flags, src, srclen, defchar, used );
if (flags || defchar || used) if (flags || defchar || used)
return wcstombs_dbcs_slow( &table->dbcs, flags, src, srclen, return wcstombs_dbcs_slow( &table->dbcs, flags, src, srclen,
dst, dstlen, defchar, used ); dst, dstlen, defchar, used );
......
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