'used' should be set even if we are only computing the necessary
buffer size.
This commit is contained in:
parent
f25efa0660
commit
8a37450d82
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue