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

buffer size.
This commit is contained in:
Alexandre Julliard 2002-04-11 17:36:09 +00:00
parent f25efa0660
commit 8a37450d82
1 changed files with 55 additions and 25 deletions

View File

@ -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 */
static inline int get_length_sbcs( const struct sbcs_table *table, int flags,
const WCHAR *src, unsigned int srclen )
static int get_length_sbcs( const struct sbcs_table *table, int flags,
const WCHAR *src, unsigned int srclen, int *used )
{
unsigned int ret = srclen;
const unsigned char * const uni2cp_low = table->uni2cp_low;
const unsigned short * const uni2cp_high = table->uni2cp_high;
int ret, tmp;
WCHAR composed;
if (flags & WC_COMPOSITECHECK)
if (!used) used = &tmp; /* avoid checking on every char */
*used = 0;
for (ret = 0; srclen; ret++, src++, srclen--)
{
const unsigned char * const uni2cp_low = table->uni2cp_low;
const unsigned short * const uni2cp_high = table->uni2cp_high;
WCHAR composed;
WCHAR wch = *src;
unsigned char ch;
for (ret = 0; srclen > 1; ret++, srclen--, src++)
if ((flags & WC_COMPOSITECHECK) && (srclen > 1) && (composed = compose(src)))
{
if (!(composed = compose(src))) continue;
/* check if we should skip the next char */
/* in WC_DEFAULTCHAR and WC_DISCARDNS mode, we always skip */
/* 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 ))
{
unsigned char ch = uni2cp_low[uni2cp_high[composed >> 8] + (composed & 0xff)];
if (!is_valid_sbcs_mapping( table, flags, composed, ch )) continue;
/* we have a good mapping, use it */
src++;
srclen--;
continue;
}
src++;
srclen--;
/* no mapping for the composed char, check the other flags */
if (flags & WC_DEFAULTCHAR) /* use the default char instead */
{
*used = 1;
src++; /* skip the non-spacing char */
srclen--;
continue;
}
if (flags & WC_DISCARDNS) /* skip the second char of the composition */
{
src++;
srclen--;
}
/* 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 );
}
if (srclen) ret++; /* last char */
}
return ret;
}
@ -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 */
static int get_length_dbcs( const struct dbcs_table *table, int flags,
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_high = table->uni2cp_high;
WCHAR defchar_value = table->info.def_char;
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++)
{
@ -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 (!used) used = &tmp; /* avoid checking on every char */
*used = 0;
for (len = 0; srclen; len++, srclen--, src++)
{
unsigned short res;
@ -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 (defchar_value & 0xff00) len++;
*used = 1;
src++; /* skip the non-spacing char */
srclen--;
continue;
@ -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)];
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++;
}
return len;
@ -399,15 +426,18 @@ int cp_wcstombs( const union cptable *table, int flags,
{
if (table->info.char_size == 1)
{
if (!dstlen) return get_length_sbcs( &table->sbcs, flags, src, srclen );
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,
dst, dstlen, defchar, used );
}
if (!dstlen) return srclen;
return wcstombs_sbcs( &table->sbcs, src, srclen, dst, dstlen );
}
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)
return wcstombs_dbcs_slow( &table->dbcs, flags, src, srclen,
dst, dstlen, defchar, used );