In streamout(): fix a number of formatting bugs, round floats, fix issue with large unsigned values that were treated as signed, simplify some code.

svn path=/trunk/; revision=49516
This commit is contained in:
Timo Kreuzer 2010-11-07 10:06:00 +00:00
parent 2f7608101c
commit 7d0aa25a0f

View file

@ -145,7 +145,7 @@ format_float(
} }
/* CHECKME: Windows seems to handle a max of 17 digits(?) */ /* CHECKME: Windows seems to handle a max of 17 digits(?) */
num_digits = precision <= 17 ? precision : 17; num_digits = precision <= 17 ? precision: 17;
/* Handle sign */ /* Handle sign */
if (fpval < 0) if (fpval < 0)
@ -173,20 +173,19 @@ format_float(
} }
else else
{ {
val64 = (__int64)fpval;
fpval -= val64;
fpval *= pow(10., precision); fpval *= pow(10., precision);
val64 = (__int64)(fpval + 0.5);
while (num_digits--) while (num_digits-- > 0)
{ {
*--(*string) = digits[(__int64)fpval % 10]; *--(*string) = digits[val64 % 10];
fpval /= 10; val64 /= 10;
} }
} }
*--(*string) = _T('.'); *--(*string) = _T('.');
/* Gather digits in reverse order */ /* Digits before the decimal point */
do do
{ {
*--(*string) = digits[val64 % base]; *--(*string) = digits[val64 % base];
@ -286,7 +285,7 @@ streamout(FILE *stream, const TCHAR *format, va_list argptr)
int base, len, prefixlen, fieldwidth, precision, padding; int base, len, prefixlen, fieldwidth, precision, padding;
int written = 1, written_all = 0; int written = 1, written_all = 0;
unsigned int flags; unsigned int flags;
__int64 val64; unsigned __int64 val64;
buffer[BUFFER_SIZE] = '\0'; buffer[BUFFER_SIZE] = '\0';
@ -297,8 +296,9 @@ streamout(FILE *stream, const TCHAR *format, va_list argptr)
/* Check for end of format string */ /* Check for end of format string */
if (chr == _T('\0')) break; if (chr == _T('\0')) break;
/* Check for 'normal' character */ /* Check for 'normal' character or double % */
if (chr != _T('%')) if ((chr != _T('%')) ||
(chr = *format++) == _T('%'))
{ {
/* Write the character to the stream */ /* Write the character to the stream */
if ((written = streamout_char(stream, chr)) == -1) return -1; if ((written = streamout_char(stream, chr)) == -1) return -1;
@ -306,26 +306,17 @@ streamout(FILE *stream, const TCHAR *format, va_list argptr)
continue; continue;
} }
/* Check for escaped % character */
if (*format == _T('%'))
{
/* Write % to the stream */
if ((written = streamout_char(stream, _T('%'))) == -1) return -1;
written_all += written;
continue;
}
/* Handle flags */ /* Handle flags */
flags = 0; flags = 0;
while (1) while (1)
{ {
chr = *format++;
if (chr == _T('-')) flags |= FLAG_ALIGN_LEFT; if (chr == _T('-')) flags |= FLAG_ALIGN_LEFT;
else if (chr == _T('+')) flags |= FLAG_FORCE_SIGN; else if (chr == _T('+')) flags |= FLAG_FORCE_SIGN;
else if (chr == _T(' ')) flags |= FLAG_FORCE_SIGNSP; else if (chr == _T(' ')) flags |= FLAG_FORCE_SIGNSP;
else if (chr == _T('0')) flags |= FLAG_PAD_ZERO; else if (chr == _T('0')) flags |= FLAG_PAD_ZERO;
else if (chr == _T('#')) flags |= FLAG_SPECIAL; else if (chr == _T('#')) flags |= FLAG_SPECIAL;
else break; else break;
chr = *format++;
} }
/* Handle field width modifier */ /* Handle field width modifier */
@ -505,13 +496,14 @@ streamout(FILE *stream, const TCHAR *format, va_list argptr)
/* Use external function, one for kernel one for user mode */ /* Use external function, one for kernel one for user mode */
format_float(chr, flags, precision, &string, &prefix, &argptr); format_float(chr, flags, precision, &string, &prefix, &argptr);
len = _tcslen(string); len = _tcslen(string);
precision = 0;
break; break;
case _T('d'): case _T('d'):
case _T('i'): case _T('i'):
val64 = va_arg_f(argptr, flags); val64 = (__int64)va_arg_f(argptr, flags);
if (val64 < 0) if ((__int64)val64 < 0)
{ {
val64 = -val64; val64 = -val64;
prefix = _T("-"); prefix = _T("-");
@ -526,12 +518,9 @@ streamout(FILE *stream, const TCHAR *format, va_list argptr)
case _T('o'): case _T('o'):
base = 8; base = 8;
if (flags & FLAG_SPECIAL) prefix = _T("0"); if (flags & FLAG_SPECIAL) prefix = _T("0");
goto case_unsigned;
/* Fall through */ /* Fall through */
case _T('u'):
val64 = (unsigned __int64)va_arg_fu(argptr, flags);
goto case_number;
case _T('p'): case _T('p'):
precision = 2 * sizeof(void*); precision = 2 * sizeof(void*);
flags &= ~FLAG_PAD_ZERO; flags &= ~FLAG_PAD_ZERO;
@ -543,27 +532,31 @@ streamout(FILE *stream, const TCHAR *format, va_list argptr)
/* Fall through */ /* Fall through */
case _T('x'): case _T('x'):
val64 = (unsigned __int64)va_arg_fu(argptr, flags);
base = 16; base = 16;
if (flags & FLAG_SPECIAL) if (flags & FLAG_SPECIAL)
{ {
prefix = &digits[16]; prefix = &digits[16];
} }
case _T('u'):
case_unsigned:
val64 = va_arg_fu(argptr, flags);
case_number: case_number:
#ifdef _UNICODE #ifdef _UNICODE
flags |= FLAG_WIDECHAR; flags |= FLAG_WIDECHAR;
#else #else
flags &= ~FLAG_WIDECHAR; flags &= ~FLAG_WIDECHAR;
#endif #endif
if (precision < 0) precision = 1;
/* Gather digits in reverse order */ /* Gather digits in reverse order */
do while (val64)
{ {
*--string = digits[val64 % base]; *--string = digits[val64 % base];
val64 /= base; val64 /= base;
precision--; precision--;
} }
while (val64);
len = _tcslen(string); len = _tcslen(string);
break; break;
@ -578,11 +571,12 @@ streamout(FILE *stream, const TCHAR *format, va_list argptr)
prefixlen = prefix ? _tcslen(prefix) : 0; prefixlen = prefix ? _tcslen(prefix) : 0;
if (precision < 0) precision = 0; if (precision < 0) precision = 0;
padding = fieldwidth - len - prefixlen - precision; padding = fieldwidth - len - prefixlen - precision;
if (padding < 0) padding = 0;
/* Optional left space padding */ /* Optional left space padding */
if ((flags & (FLAG_ALIGN_LEFT | FLAG_PAD_ZERO)) == 0) if ((flags & (FLAG_ALIGN_LEFT | FLAG_PAD_ZERO)) == 0)
{ {
while (padding-- > 0) for (; padding > 0; padding--)
{ {
if ((written = streamout_char(stream, _T(' '))) == -1) return -2; if ((written = streamout_char(stream, _T(' '))) == -1) return -2;
written_all += written; written_all += written;