Moved number() closer to vsnprintf() because it'll need the put_*() functions
once it's fixed. Renamed some variables. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5407 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -79,81 +79,6 @@ do_div(uint64 *_number, uint32 base)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
|
||||||
number(char *str, long long num, unsigned base, int size, int precision, int type)
|
|
||||||
{
|
|
||||||
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
|
|
||||||
char c, sign, tmp[66];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (type & LARGE)
|
|
||||||
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
||||||
if (type & LEFT)
|
|
||||||
type &= ~ZEROPAD;
|
|
||||||
if (base < 2 || base > 36)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
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) {
|
|
||||||
if (base == 16)
|
|
||||||
size -= 2;
|
|
||||||
else if (base == 8)
|
|
||||||
size--;
|
|
||||||
}
|
|
||||||
i = 0;
|
|
||||||
if (num == 0)
|
|
||||||
tmp[i++] = '0';
|
|
||||||
else while (num != 0)
|
|
||||||
tmp[i++] = digits[do_div(&num, base)];
|
|
||||||
|
|
||||||
if (i > precision)
|
|
||||||
precision = i;
|
|
||||||
size -= precision;
|
|
||||||
|
|
||||||
if (!(type&(ZEROPAD + LEFT))) {
|
|
||||||
while (size-- > 0)
|
|
||||||
*str++ = ' ';
|
|
||||||
}
|
|
||||||
if (sign)
|
|
||||||
*str++ = sign;
|
|
||||||
|
|
||||||
if (type & SPECIAL) {
|
|
||||||
if (base == 8)
|
|
||||||
*str++ = '0';
|
|
||||||
else if (base == 16) {
|
|
||||||
*str++ = '0';
|
|
||||||
*str++ = digits[33];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(type & LEFT))
|
|
||||||
while (size-- > 0)
|
|
||||||
*str++ = c;
|
|
||||||
while (i < precision--)
|
|
||||||
*str++ = '0';
|
|
||||||
while (i-- > 0)
|
|
||||||
*str++ = tmp[i];
|
|
||||||
while (size-- > 0)
|
|
||||||
*str++ = ' ';
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
put_padding(char **_buffer, size_t *_bytesLeft, int32 count)
|
put_padding(char **_buffer, size_t *_bytesLeft, int32 count)
|
||||||
{
|
{
|
||||||
@@ -236,14 +161,89 @@ put_character(char **_buffer, size_t *_bytesLeft, char c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
number(char *str, long long num, unsigned base, int size, int precision, int type)
|
||||||
|
{
|
||||||
|
const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
char c, sign, tmp[66];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (type & LARGE)
|
||||||
|
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
if (type & LEFT)
|
||||||
|
type &= ~ZEROPAD;
|
||||||
|
if (base < 2 || base > 36)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (base == 16)
|
||||||
|
size -= 2;
|
||||||
|
else if (base == 8)
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
if (num == 0)
|
||||||
|
tmp[i++] = '0';
|
||||||
|
else while (num != 0)
|
||||||
|
tmp[i++] = digits[do_div(&num, base)];
|
||||||
|
|
||||||
|
if (i > precision)
|
||||||
|
precision = i;
|
||||||
|
size -= precision;
|
||||||
|
|
||||||
|
if (!(type&(ZEROPAD + LEFT))) {
|
||||||
|
while (size-- > 0)
|
||||||
|
*str++ = ' ';
|
||||||
|
}
|
||||||
|
if (sign)
|
||||||
|
*str++ = sign;
|
||||||
|
|
||||||
|
if (type & SPECIAL) {
|
||||||
|
if (base == 8)
|
||||||
|
*str++ = '0';
|
||||||
|
else if (base == 16) {
|
||||||
|
*str++ = '0';
|
||||||
|
*str++ = digits[33];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(type & LEFT))
|
||||||
|
while (size-- > 0)
|
||||||
|
*str++ = c;
|
||||||
|
while (i < precision--)
|
||||||
|
*str++ = '0';
|
||||||
|
while (i-- > 0)
|
||||||
|
*str++ = tmp[i];
|
||||||
|
while (size-- > 0)
|
||||||
|
*str++ = ' ';
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
vsnprintf(char *buffer, size_t bytesLeft, const char *fmt, va_list args)
|
vsnprintf(char *buffer, size_t bytesLeft, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
uint64 num;
|
uint64 num;
|
||||||
int base;
|
int base;
|
||||||
char *str;
|
char *string;
|
||||||
int flags; /* flags to number() */
|
int flags; /* flags to number() */
|
||||||
int field_width; /* width of output field */
|
int fieldWidth; /* width of output field */
|
||||||
int precision;
|
int precision;
|
||||||
/* min. # of digits for integers; max number of chars for from string */
|
/* min. # of digits for integers; max number of chars for from string */
|
||||||
int qualifier; /* 'h', 'l', or 'L' for integer fields */
|
int qualifier; /* 'h', 'l', or 'L' for integer fields */
|
||||||
@@ -251,9 +251,9 @@ vsnprintf(char *buffer, size_t bytesLeft, const char *fmt, va_list args)
|
|||||||
bytesLeft--;
|
bytesLeft--;
|
||||||
// make space for the terminating '\0' byte
|
// make space for the terminating '\0' byte
|
||||||
|
|
||||||
for (str = buffer; fmt[0] && bytesLeft > 0; fmt++) {
|
for (string = buffer; format[0] && bytesLeft > 0; format++) {
|
||||||
if (fmt[0] != '%') {
|
if (format[0] != '%') {
|
||||||
if (!put_character(&str, &bytesLeft, fmt[0]))
|
if (!put_character(&string, &bytesLeft, format[0]))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -264,8 +264,8 @@ vsnprintf(char *buffer, size_t bytesLeft, const char *fmt, va_list args)
|
|||||||
flags = 0;
|
flags = 0;
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
++fmt; /* this also skips first '%' */
|
++format; /* this also skips first '%' */
|
||||||
switch (fmt[0]) {
|
switch (format[0]) {
|
||||||
case '-': flags |= LEFT; goto repeat;
|
case '-': flags |= LEFT; goto repeat;
|
||||||
case '+': flags |= PLUS; goto repeat;
|
case '+': flags |= PLUS; goto repeat;
|
||||||
case ' ': flags |= SPACE; goto repeat;
|
case ' ': flags |= SPACE; goto repeat;
|
||||||
@@ -275,15 +275,15 @@ vsnprintf(char *buffer, size_t bytesLeft, const char *fmt, va_list args)
|
|||||||
|
|
||||||
/* get field width */
|
/* get field width */
|
||||||
|
|
||||||
field_width = -1;
|
fieldWidth = -1;
|
||||||
if (isdigit(*fmt))
|
if (isdigit(*format))
|
||||||
field_width = skip_atoi(&fmt);
|
fieldWidth = skip_atoi(&format);
|
||||||
else if (fmt[0] == '*') {
|
else if (format[0] == '*') {
|
||||||
++fmt;
|
++format;
|
||||||
/* it's the next argument */
|
/* it's the next argument */
|
||||||
field_width = va_arg(args, int);
|
fieldWidth = va_arg(args, int);
|
||||||
if (field_width < 0) {
|
if (fieldWidth < 0) {
|
||||||
field_width = -field_width;
|
fieldWidth = -fieldWidth;
|
||||||
flags |= LEFT;
|
flags |= LEFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,12 +291,12 @@ vsnprintf(char *buffer, size_t bytesLeft, const char *fmt, va_list args)
|
|||||||
/* get the precision */
|
/* get the precision */
|
||||||
|
|
||||||
precision = -1;
|
precision = -1;
|
||||||
if (fmt[0] == '.') {
|
if (format[0] == '.') {
|
||||||
++fmt;
|
++format;
|
||||||
if (isdigit(*fmt))
|
if (isdigit(*format))
|
||||||
precision = skip_atoi(&fmt);
|
precision = skip_atoi(&format);
|
||||||
else if (fmt[0] == '*') {
|
else if (format[0] == '*') {
|
||||||
++fmt;
|
++format;
|
||||||
/* it's the next argument */
|
/* it's the next argument */
|
||||||
precision = va_arg(args, int);
|
precision = va_arg(args, int);
|
||||||
}
|
}
|
||||||
@@ -307,22 +307,20 @@ vsnprintf(char *buffer, size_t bytesLeft, const char *fmt, va_list args)
|
|||||||
/* get the conversion qualifier */
|
/* get the conversion qualifier */
|
||||||
|
|
||||||
qualifier = -1;
|
qualifier = -1;
|
||||||
if (fmt[0] == 'h' || fmt[0] == 'l' || fmt[0] == 'L') {
|
if (format[0] == 'h' || format[0] == 'l' || format[0] == 'L')
|
||||||
qualifier = fmt[0];
|
qualifier = *format++;
|
||||||
++fmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* default base */
|
/* default base */
|
||||||
base = 10;
|
base = 10;
|
||||||
|
|
||||||
switch (fmt[0]) {
|
switch (format[0]) {
|
||||||
case 'c':
|
case 'c':
|
||||||
if (!(flags & LEFT) && !put_padding(&str, &bytesLeft, field_width))
|
if (!(flags & LEFT) && !put_padding(&string, &bytesLeft, fieldWidth))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
put_character(&str, &bytesLeft, (char)va_arg(args, int));
|
put_character(&string, &bytesLeft, (char)va_arg(args, int));
|
||||||
|
|
||||||
if ((flags & LEFT) != 0 && !put_padding(&str, &bytesLeft, field_width))
|
if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft, fieldWidth))
|
||||||
goto out;
|
goto out;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -336,37 +334,37 @@ vsnprintf(char *buffer, size_t bytesLeft, const char *fmt, va_list args)
|
|||||||
|
|
||||||
length = strnlen(argument, precision);
|
length = strnlen(argument, precision);
|
||||||
|
|
||||||
if (!(flags & LEFT) && !put_padding(&str, &bytesLeft, field_width))
|
if (!(flags & LEFT) && !put_padding(&string, &bytesLeft, fieldWidth))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!put_string(&str, &bytesLeft, argument, length))
|
if (!put_string(&string, &bytesLeft, argument, length))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if ((flags & LEFT) != 0 && !put_padding(&str, &bytesLeft, field_width))
|
if ((flags & LEFT) != 0 && !put_padding(&string, &bytesLeft, fieldWidth))
|
||||||
goto out;
|
goto out;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (field_width == -1) {
|
if (fieldWidth == -1) {
|
||||||
field_width = 2*sizeof(void *);
|
fieldWidth = 2*sizeof(void *);
|
||||||
flags |= ZEROPAD;
|
flags |= ZEROPAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDo: fix me!
|
// ToDo: fix me!
|
||||||
str[0] = '0';
|
string[0] = '0';
|
||||||
str[1] = 'x';
|
string[1] = 'x';
|
||||||
str = number(str + 2, (uint32)va_arg(args, void *), 16,
|
string = number(string + 2, (uint32)va_arg(args, void *), 16,
|
||||||
field_width, precision, flags);
|
fieldWidth, precision, flags);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
if (qualifier == 'l') {
|
if (qualifier == 'l') {
|
||||||
long *ip = va_arg(args, long *);
|
long *ip = va_arg(args, long *);
|
||||||
*ip = (str - buffer);
|
*ip = (string - buffer);
|
||||||
} else {
|
} else {
|
||||||
int *ip = va_arg(args, int *);
|
int *ip = va_arg(args, int *);
|
||||||
*ip = (str - buffer);
|
*ip = (string - buffer);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -388,13 +386,13 @@ vsnprintf(char *buffer, size_t bytesLeft, const char *fmt, va_list args)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (fmt[0] != '%')
|
if (format[0] != '%')
|
||||||
put_character(&str, &bytesLeft, '%');
|
put_character(&string, &bytesLeft, '%');
|
||||||
|
|
||||||
if (!fmt[0])
|
if (!format[0])
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
put_character(&str, &bytesLeft, fmt[0]);
|
put_character(&string, &bytesLeft, format[0]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,23 +401,23 @@ vsnprintf(char *buffer, size_t bytesLeft, const char *fmt, va_list args)
|
|||||||
else if (qualifier == 'l') {
|
else if (qualifier == 'l') {
|
||||||
num = va_arg(args, unsigned long);
|
num = va_arg(args, unsigned long);
|
||||||
if (flags & SIGN)
|
if (flags & SIGN)
|
||||||
num = (long) num;
|
num = (long)num;
|
||||||
} else if (qualifier == 'h') {
|
} else if (qualifier == 'h') {
|
||||||
num = (unsigned short) va_arg(args, int);
|
num = (unsigned short)va_arg(args, int);
|
||||||
if (flags & SIGN)
|
if (flags & SIGN)
|
||||||
num = (short) num;
|
num = (short)num;
|
||||||
} else if (flags & SIGN)
|
} else if (flags & SIGN)
|
||||||
num = va_arg(args, int);
|
num = va_arg(args, int);
|
||||||
else
|
else
|
||||||
num = va_arg(args, unsigned int);
|
num = va_arg(args, unsigned int);
|
||||||
|
|
||||||
// ToDo: fix me!
|
// ToDo: fix me!
|
||||||
str = number(str, num, base, field_width, precision, flags);
|
string = number(string, num, base, fieldWidth, precision, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
*str = '\0';
|
*string = '\0';
|
||||||
return str - buffer;
|
return string - buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user