📄 trio.c
字号:
*/
varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned;
}
else
{
/* Used for the I<bits> modifiers */
varsize = parameters[i].varsize;
}
parameters[i].flags &= ~FLAGS_ALL_VARSIZES;
if (varsize <= (int)sizeof(int))
;
else if (varsize <= (int)sizeof(long))
parameters[i].flags |= FLAGS_LONG;
#if defined(QUALIFIER_INTMAX_T)
else if (varsize <= (int)sizeof(trio_longlong_t))
parameters[i].flags |= FLAGS_QUAD;
else
parameters[i].flags |= FLAGS_INTMAX_T;
#else
else
parameters[i].flags |= FLAGS_QUAD;
#endif
}
#endif /* defined(QUALIFIER_VARSIZE) */
#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER)
if (parameters[i].flags & FLAGS_SIZE_T)
parameters[i].data.number.as_unsigned = (argarray == NULL)
? (trio_uintmax_t)va_arg(*arglist, size_t)
: (trio_uintmax_t)(*((size_t *)argarray[num]));
else
#endif
#if defined(QUALIFIER_PTRDIFF_T)
if (parameters[i].flags & FLAGS_PTRDIFF_T)
parameters[i].data.number.as_unsigned = (argarray == NULL)
? (trio_uintmax_t)va_arg(*arglist, ptrdiff_t)
: (trio_uintmax_t)(*((ptrdiff_t *)argarray[num]));
else
#endif
#if defined(QUALIFIER_INTMAX_T)
if (parameters[i].flags & FLAGS_INTMAX_T)
parameters[i].data.number.as_unsigned = (argarray == NULL)
? (trio_uintmax_t)va_arg(*arglist, trio_intmax_t)
: (trio_uintmax_t)(*((trio_intmax_t *)argarray[num]));
else
#endif
if (parameters[i].flags & FLAGS_QUAD)
parameters[i].data.number.as_unsigned = (argarray == NULL)
? (trio_uintmax_t)va_arg(*arglist, trio_ulonglong_t)
: (trio_uintmax_t)(*((trio_ulonglong_t *)argarray[num]));
else if (parameters[i].flags & FLAGS_LONG)
parameters[i].data.number.as_unsigned = (argarray == NULL)
? (trio_uintmax_t)va_arg(*arglist, long)
: (trio_uintmax_t)(*((long *)argarray[num]));
else
{
if (argarray == NULL)
parameters[i].data.number.as_unsigned = (trio_uintmax_t)va_arg(*arglist, int);
else
{
if (parameters[i].type == FORMAT_CHAR)
parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((char *)argarray[num]));
else if (parameters[i].flags & FLAGS_SHORT)
parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((short *)argarray[num]));
else
parameters[i].data.number.as_unsigned = (trio_uintmax_t)(*((int *)argarray[num]));
}
}
}
break;
case FORMAT_PARAMETER:
/*
* The parameter for the user-defined specifier is a pointer,
* whereas the rest (width, precision, base) uses an integer.
*/
if (parameters[i].flags & FLAGS_USER_DEFINED)
parameters[i].data.pointer = (argarray == NULL)
? va_arg(*arglist, trio_pointer_t )
: argarray[num];
else
parameters[i].data.number.as_unsigned = (argarray == NULL)
? (trio_uintmax_t)va_arg(*arglist, int)
: (trio_uintmax_t)(*((int *)argarray[num]));
break;
case FORMAT_DOUBLE:
if (TYPE_SCAN == type)
{
if (parameters[i].flags & FLAGS_LONGDOUBLE)
parameters[i].data.longdoublePointer = (argarray == NULL)
? va_arg(*arglist, trio_long_double_t *)
: (trio_long_double_t *)argarray[num];
else
{
if (parameters[i].flags & FLAGS_LONG)
parameters[i].data.doublePointer = (argarray == NULL)
? va_arg(*arglist, double *)
: (double *)argarray[num];
else
parameters[i].data.doublePointer = (argarray == NULL)
? (double *)va_arg(*arglist, float *)
: (double *)((float *)argarray[num]);
}
}
else
{
if (parameters[i].flags & FLAGS_LONGDOUBLE)
parameters[i].data.longdoubleNumber = (argarray == NULL)
? va_arg(*arglist, trio_long_double_t)
: (trio_long_double_t)(*((trio_long_double_t *)argarray[num]));
else
{
if (argarray == NULL)
parameters[i].data.longdoubleNumber =
(trio_long_double_t)va_arg(*arglist, double);
else
{
if (parameters[i].flags & FLAGS_SHORT)
parameters[i].data.longdoubleNumber =
(trio_long_double_t)(*((float *)argarray[num]));
else
parameters[i].data.longdoubleNumber =
(trio_long_double_t)(*((double *)argarray[num]));
}
}
}
break;
#if defined(FORMAT_ERRNO)
case FORMAT_ERRNO:
parameters[i].data.errorNumber = save_errno;
break;
#endif
default:
break;
}
} /* for all specifiers */
return num;
}
/*************************************************************************
*
* FORMATTING
*
************************************************************************/
/*************************************************************************
* TrioWriteNumber
*
* Description:
* Output a number.
* The complexity of this function is a result of the complexity
* of the dependencies of the flags.
*/
TRIO_PRIVATE void
TrioWriteNumber
TRIO_ARGS6((self, number, flags, width, precision, base),
trio_class_t *self,
trio_uintmax_t number,
trio_flags_t flags,
int width,
int precision,
int base)
{
BOOLEAN_T isNegative;
BOOLEAN_T isNumberZero;
BOOLEAN_T isPrecisionZero;
BOOLEAN_T ignoreNumber;
char buffer[MAX_CHARS_IN(trio_uintmax_t) * (1 + MAX_LOCALE_SEPARATOR_LENGTH) + 1];
char *bufferend;
char *pointer;
TRIO_CONST char *digits;
int i;
int length;
char *p;
int count;
assert(VALID(self));
assert(VALID(self->OutStream));
assert(((base >= MIN_BASE) && (base <= MAX_BASE)) || (base == NO_BASE));
digits = (flags & FLAGS_UPPER) ? internalDigitsUpper : internalDigitsLower;
if (base == NO_BASE)
base = BASE_DECIMAL;
isNumberZero = (number == 0);
isPrecisionZero = (precision == 0);
ignoreNumber = (isNumberZero
&& isPrecisionZero
&& !((flags & FLAGS_ALTERNATIVE) && (base == BASE_OCTAL)));
if (flags & FLAGS_UNSIGNED)
{
isNegative = FALSE;
flags &= ~FLAGS_SHOWSIGN;
}
else
{
isNegative = ((trio_intmax_t)number < 0);
if (isNegative)
number = -((trio_intmax_t)number);
}
if (flags & FLAGS_QUAD)
number &= (trio_ulonglong_t)-1;
else if (flags & FLAGS_LONG)
number &= (unsigned long)-1;
else
number &= (unsigned int)-1;
/* Build number */
pointer = bufferend = &buffer[sizeof(buffer) - 1];
*pointer-- = NIL;
for (i = 1; i < (int)sizeof(buffer); i++)
{
*pointer-- = digits[number % base];
number /= base;
if (number == 0)
break;
if ((flags & FLAGS_QUOTE) && TrioFollowedBySeparator(i + 1))
{
/*
* We are building the number from the least significant
* to the most significant digit, so we have to copy the
* thousand separator backwards
*/
length = internalThousandSeparatorLength;
if (((int)(pointer - buffer) - length) > 0)
{
p = &internalThousandSeparator[length - 1];
while (length-- > 0)
*pointer-- = *p--;
}
}
}
if (! ignoreNumber)
{
/* Adjust width */
width -= (bufferend - pointer) - 1;
}
/* Adjust precision */
if (NO_PRECISION != precision)
{
precision -= (bufferend - pointer) - 1;
if (precision < 0)
precision = 0;
flags |= FLAGS_NILPADDING;
}
/* Calculate padding */
count = (! ((flags & FLAGS_LEFTADJUST) || (precision == NO_PRECISION)))
? precision
: 0;
/* Adjust width further */
if (isNegative || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
width--;
if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
{
switch (base)
{
case BASE_BINARY:
case BASE_HEX:
width -= 2;
break;
case BASE_OCTAL:
if (!(flags & FLAGS_NILPADDING) || (count == 0))
width--;
break;
default:
break;
}
}
/* Output prefixes spaces if needed */
if (! ((flags & FLAGS_LEFTADJUST) ||
((flags & FLAGS_NILPADDING) && (precision == NO_PRECISION))))
{
while (width-- > count)
self->OutStream(self, CHAR_ADJUST);
}
/* width has been adjusted for signs and alternatives */
if (isNegative)
self->OutStream(self, '-');
else if (flags & FLAGS_SHOWSIGN)
self->OutStream(self, '+');
else if (flags & FLAGS_SPACE)
self->OutStream(self, ' ');
/* Prefix is not written when the value is zero */
if ((flags & FLAGS_ALTERNATIVE) && !isNumberZero)
{
switch (base)
{
case BASE_BINARY:
self->OutStream(self, '0');
self->OutStream(self, (flags & FLAGS_UPPER) ? 'B' : 'b');
break;
case BASE_OCTAL:
if (!(flags & FLAGS_NILPADDING) || (count == 0))
self->OutStream(self, '0');
break;
case BASE_HEX:
self->OutStream(self, '0');
self->OutStream(self, (flags & FLAGS_UPPER) ? 'X' : 'x');
break;
default:
break;
} /* switch base */
}
/* Output prefixed zero padding if needed */
if (flags & FLAGS_NILPADDING)
{
if (precision == NO_PRECISION)
precision = width;
while (precision-- > 0)
{
self->OutStream(self, '0');
width--;
}
}
if (! ignoreNumber)
{
/* Output the number itself */
while (*(++pointer))
{
self->OutStream(self, *pointer);
}
}
/* Output trailing spaces if needed */
if (flags & FLAGS_LEFTADJUST)
{
while (width-- > 0)
self->OutStream(self, CHAR_ADJUST);
}
}
/*************************************************************************
* TrioWriteStringCharacter
*
* Description:
* Output a single character of a string
*/
TRIO_PRIVATE void
TrioWriteStringCharacter
TRIO_ARGS3((self, ch, flags),
trio_class_t *self,
int ch,
trio_flags_t flags)
{
if (flags & FLAGS_ALTERNATIVE)
{
if (! isprint(ch))
{
/*
* Non-printable characters are converted to C escapes or
* \number, if no C escape exists.
*/
self->OutStream(self, CHAR_BACKSLASH);
switch (ch)
{
case '\007': self->OutStream(self, 'a'); break;
case '\b': self->OutStream(self, 'b'); break;
case '\f': self->OutStream(self, 'f'); break;
case '\n': self->OutStream(self, 'n'); break;
case '\r': self->OutStream(self, 'r'); break;
case '\t': self->OutStream(self, 't'); break;
case '\v': self->OutStream(self, 'v'); break;
case '\\': self->OutStream(self, '\\'); break;
default:
self->OutStream(self, 'x');
TrioWriteNumber(self, (trio_uintmax_t)ch,
FLAGS_UNSIGNED | FLAGS_NILPADDING,
2, 2, BASE_HEX);
break;
}
}
else if (ch == CHAR_BACKSLASH)
{
self->OutStream(self, CHAR_BACKSLASH);
self->OutStream(self, CHAR_BACKSLASH);
}
else
{
self->OutStream(self, ch);
}
}
else
{
self->OutStream(self, ch);
}
}
/*************************************************************************
* TrioWriteString
*
* Description:
* Output a string
*/
TRIO_PRIVATE void
TrioWriteString
TRIO_ARGS5((self, string, flags, width, precision),
trio_class_t *self,
TRIO_CONST char *string,
trio_flags_t flags,
int width,
int precision)
{
int length;
int ch;
assert(VALID(self));
assert(VALID(self->OutStream));
if (string == NULL)
{
string = internalNullString;
length = sizeof(internalNullString) - 1;
/* Disable quoting for the null pointer */
flags &= (~FLAGS_QUOTE);
width = 0;
}
else
{
length = trio_length(string);
}
if ((NO_PRECISION != precision) &&
(precision < length))
{
length = precision;
}
width -= length;
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
if (! (flags & FLAGS_LEFTADJUST))
{
while (width-- > 0)
self->OutStream(self, CHAR_ADJUST);
}
while (length-- > 0)
{
/* The ctype parameters must be an unsigned char (or EOF) */
ch = (int)((unsigned char)(*string++));
TrioWriteStringCharacter(self, ch, flags);
}
if (flags & FLAGS_LEFTADJUST)
{
while (width-- > 0)
self->OutStream(self, CHAR_ADJUST);
}
if (flags & FLAGS_QUOTE)
self->OutStream(self, CHAR_QUOTE);
}
/*************************************************************************
* TrioWriteWideStringCharacter
*
* Description:
* Output a wide string as a multi-byte sequence
*/
#if TRIO_WIDECHAR
TRIO_PRIVATE int
TrioWriteWideStringCharacter
TRIO_ARGS4((self, wch, flags, width),
trio_class_t *self,
trio_wchar_t wch,
trio_flags_t flags,
int width)
{
int size;
int i;
int ch;
char *string;
char buffer[MB_LEN_MAX + 1];
if (width == NO_WIDTH)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -