* The floating point output now correctly honours eventual sign flags,

and actually shows the sign (before, it would just absorb it).
* On calling floating() from vsnprintf(), the order of the "fieldWidth", and
  "flags" parameters were mixed, causing some strange output.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25611 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-05-22 15:38:09 +00:00
parent 15173df4e9
commit 403bfdda6c

View File

@ -1,7 +1,7 @@
/*
* Copyright 2003-2006, Axel Dörfler. All rights reserved.
* Copyright 2003-2008, Axel Dörfler. All rights reserved.
* Distributed under the terms of the MIT license.
*
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
@ -39,8 +39,8 @@ skip_atoi(const char **s)
static uint64
do_div(uint64 *_number, uint32 base)
{
do_div(uint64 *_number, uint32 base)
{
uint64 result = *_number % (uint64)base;
*_number = *_number / (uint64)base;
@ -130,42 +130,53 @@ put_character(char **_buffer, int32 *_bytesLeft, char c)
}
static char
sign_symbol(int flags, bool negative)
{
if ((flags & SIGN) == 0)
return '\0';
if (negative)
return '-';
else if ((flags & PLUS) != 0)
return '+';
else if ((flags & SPACE) != 0)
return ' ';
return '\0';
}
static void
number(char **_string, int32 *_bytesLeft, int64 num, uint32 base, int size,
int precision, int type)
int precision, int flags)
{
const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
char c, sign, tmp[66];
int i;
if (type & LARGE)
if (flags & LARGE)
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (type & LEFT)
type &= ~ZEROPAD;
if (flags & LEFT)
flags &= ~ZEROPAD;
if (base < 2 || base > 36)
return;
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
if (type & SIGN) {
if (num < 0) {
sign = '-';
num = -num;
size--;
} else if (type & PLUS) {
sign = '+';
size--;
} else if (type & SPACE) {
sign = ' ';
size--;
}
}
if (type & SPECIAL) {
c = (flags & ZEROPAD) ? '0' : ' ';
sign = sign_symbol(flags, num < 0);
if (num < 0)
num = -num;
if (sign)
size--;
if ((flags & SPECIAL) != 0) {
if (base == 16)
size -= 2;
else if (base == 8)
size--;
}
i = 0;
if (num == 0)
tmp[i++] = '0';
@ -176,14 +187,14 @@ number(char **_string, int32 *_bytesLeft, int64 num, uint32 base, int size,
precision = i;
size -= precision;
if (!(type & (ZEROPAD + LEFT))) {
if (!(flags & (ZEROPAD + LEFT))) {
put_padding(_string, _bytesLeft, size);
size = 0;
}
if (sign)
put_character(_string, _bytesLeft, sign);
if (type & SPECIAL) {
if ((flags & SPECIAL) != 0) {
if (base == 8)
put_character(_string, _bytesLeft, '0');
else if (base == 16) {
@ -192,7 +203,7 @@ number(char **_string, int32 *_bytesLeft, int64 num, uint32 base, int size,
}
}
if (!(type & LEFT)) {
if (!(flags & LEFT)) {
while (size-- > 0)
put_character(_string, _bytesLeft, c);
}
@ -212,15 +223,17 @@ number(char **_string, int32 *_bytesLeft, int64 num, uint32 base, int size,
It's just here for your convenience so that you can use it for debug output.
*/
static bool
floating(char **_string, int32 *_bytesLeft, double value, int fieldWidth, int flags)
floating(char **_string, int32 *_bytesLeft, double value, int fieldWidth,
int flags)
{
char buffer[66];
bool sign = value < 0.0;
uint64 fraction;
uint64 integer;
int32 length = 0;
char sign;
if (sign)
sign = sign_symbol(flags, value < 0.0);
if (value < 0.0)
value = -value;
fraction = (uint64)(value * 1000) % 1000;
@ -254,6 +267,9 @@ floating(char **_string, int32 *_bytesLeft, double value, int fieldWidth, int fl
if (!(flags & LEFT) && !put_padding(_string, _bytesLeft, fieldWidth))
return false;
if (sign && !put_character(_string, _bytesLeft, sign))
return false;
while (length-- > 0) {
if (!put_character(_string, _bytesLeft, buffer[length]))
return false;
@ -276,7 +292,7 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
char *string;
int flags; /* flags to number() */
int fieldWidth; /* width of output field */
int precision;
int precision;
/* min. # of digits for integers; max number of chars for from string */
int qualifier; /* 'h', 'l', or 'L' for integer fields */
@ -300,7 +316,8 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
flags = 0;
repeat:
++format; /* this also skips first '%' */
format++;
/* this also skips first '%' */
switch (format[0]) {
case '-': flags |= LEFT; goto repeat;
case '+': flags |= PLUS; goto repeat;
@ -315,7 +332,7 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
if (isdigit(*format))
fieldWidth = skip_atoi(&format);
else if (format[0] == '*') {
++format;
format++;
/* it's the next argument */
fieldWidth = va_arg(args, int);
if (fieldWidth < 0) {
@ -328,11 +345,11 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
precision = -1;
if (format[0] == '.') {
++format;
format++;
if (isdigit(*format))
precision = skip_atoi(&format);
else if (format[0] == '*') {
++format;
format++;
/* it's the next argument */
precision = va_arg(args, int);
}
@ -359,12 +376,14 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
switch (format[0]) {
case 'c':
if (!(flags & LEFT) && !put_padding(&string, &bytesLeft, fieldWidth - 1))
if (!(flags & LEFT) && !put_padding(&string, &bytesLeft,
fieldWidth - 1))
goto out;
put_character(&string, &bytesLeft, (char)va_arg(args, int));
if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft, fieldWidth - 1))
if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft,
fieldWidth - 1))
goto out;
continue;
@ -379,13 +398,15 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
length = strnlen(argument, precision);
fieldWidth -= length;
if (!(flags & LEFT) && !put_padding(&string, &bytesLeft, fieldWidth))
if (!(flags & LEFT) && !put_padding(&string, &bytesLeft,
fieldWidth))
goto out;
if (!put_string(&string, &bytesLeft, argument, length))
goto out;
if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft, fieldWidth))
if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft,
fieldWidth))
goto out;
continue;
}
@ -397,7 +418,8 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
case 'G':
{
double value = va_arg(args, double);
if (!floating(&string, &bytesLeft, value, flags, fieldWidth))
if (!floating(&string, &bytesLeft, value, fieldWidth,
flags | SIGN))
goto out;
continue;
}
@ -498,7 +520,7 @@ snprintf(char *buffer, size_t bufferSize, const char *format, ...)
}
int
int
sprintf(char *buffer, const char *format, ...)
{
va_list args;