📄 trio.c
字号:
#if TRIO_FEATURE_USER_DEFINED case FORMAT_USER_DEFINED:#endif case FORMAT_POINTER: case FORMAT_COUNT: case FORMAT_UNKNOWN: parameters[i].data.pointer = (argarray == NULL) ? va_arg(arglist, trio_pointer_t ) : argarray[num]; break; case FORMAT_CHAR: case FORMAT_INT:#if TRIO_FEATURE_SCANF if (TYPE_SCAN == type) { if (argarray == NULL) parameters[i].data.pointer = (trio_pointer_t)va_arg(arglist, trio_pointer_t); else { if (parameters[i].type == FORMAT_CHAR) parameters[i].data.pointer = (trio_pointer_t)((char *)argarray[num]); else if (parameters[i].flags & FLAGS_SHORT) parameters[i].data.pointer = (trio_pointer_t)((short *)argarray[num]); else parameters[i].data.pointer = (trio_pointer_t)((int *)argarray[num]); } } else#endif /* TRIO_FEATURE_SCANF */ {#if TRIO_FEATURE_VARSIZE || TRIO_FEATURE_FIXED_SIZE if (parameters[i].flags & (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE)) { if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER) { /* * Variable sizes are mapped onto the fixed sizes, in * accordance with integer promotion. * * Please note that this may not be portable, as we * only guess the size, not the layout of the numbers. * For example, if int is little-endian, and long is * big-endian, then this will fail. */ 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 TRIO_FEATURE_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 /* TRIO_FEATURE_VARSIZE */#if TRIO_FEATURE_SIZE_T || TRIO_FEATURE_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 TRIO_FEATURE_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 TRIO_FEATURE_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;#if TRIO_FEATURE_FLOAT case FORMAT_DOUBLE:# if TRIO_FEATURE_SCANF 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# endif /* TRIO_FEATURE_SCANF */ { 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;#endif /* TRIO_FEATURE_FLOAT */#if TRIO_FEATURE_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 voidTrioWriteNumberTRIO_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;#if TRIO_FEATURE_QUOTE int length; char *p;#endif int count; int digitIndex; 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++) { digitIndex = number % base; *pointer-- = digits[digitIndex]; number /= base; if (number == 0) break;#if TRIO_FEATURE_QUOTE 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--; } }#endif } 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 voidTrioWriteStringCharacterTRIO_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 voidTrioWriteStringTRIO_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;#if TRIO_FEATURE_QUOTE /* Disable quoting for the null pointer */ flags &= (~FLAGS_QUOTE);#endif width = 0; } else { length = trio_length(string); } if ((NO_PRECISION != precision) && (precision < length)) { length = precision; } width -= length;#if TRIO_FEATURE_QUOTE if (flags & FLAGS_QUOTE) self->OutStream(self, CHAR_QUOTE);#endif if (! (flags & FLAGS_LEFTADJUST)) { while (width-- > 0) self->OutS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -