#include #include #include "ft_printf_internal.h" char getDecimalCount(struct printf_format_params* format, long double* number, char alphabetLen) { int result = 7; int i; int sign = signbit(*number) ? -1 : 1; int nextDecimal; if (format->precision >=0) return format->precision +1; *number *= sign; i = 0; while (i <= result) { *number = *number * alphabetLen; ++i; } nextDecimal = (int) ((*number - (long long) *number) * alphabetLen); *number = (long long) *number; if (nextDecimal >= alphabetLen/2) (*number)++; while (i) { *number = *number / alphabetLen; --i; } *number *= sign; return result; } int printfDecimalSpecial(struct printf_data* data, char isNegative, const char* str) { int sign = 0; int sysCallRet; if (isNegative) sign = printfWrite(data, "-", 1); if (sign < 0) return sign; sysCallRet = printfWrite(data, str, 3); if (sysCallRet < 0) return sysCallRet; return sysCallRet + sign; } int printDecimals(struct printf_data* data, char decimalToPrint, long double number, const char* alphabet) { int sysCallRet; int result; int alphabetLen = strlen(alphabet); if (decimalToPrint < 0) return 0; if (number < 0) number *= -1; sysCallRet = printfWrite(data, ".", 1); if (sysCallRet < 0) return sysCallRet; result = sysCallRet; decimalToPrint--; while (decimalToPrint) { number = (number - (int) number) * alphabetLen; sysCallRet = printfWrite(data, &alphabet[(int)number], 1); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; decimalToPrint--; } return result; } int doPrintfF(struct printf_data* data, struct printf_format_params* format, long double number, const char* alphabet) { int result; int decimalToPrint = getDecimalCount(format, &number, strlen(alphabet)); int sysCallRet; result = printfNumber(data, format, (long long) number, decimalToPrint, alphabet); if (result < 0) return result; sysCallRet = printDecimals(data, decimalToPrint, number, alphabet); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; if ((format->flags & PRINTF_FLAG_LEFT_PADDING) && !(format->flags & PRINTF_FLAG_ZERO_PAD)) { sysCallRet = pad(data, format, result); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; } return result; } int printf_f(struct printf_data* data, struct printf_format_params* format, va_list args) { double number = va_arg(args, double); if (isnan(number)) return printfDecimalSpecial(data, signbit(number), "nan"); if (!isfinite(number)) return printfDecimalSpecial(data, signbit(number), "inf"); return doPrintfF(data, format, number, DEC_ALPHABET); } int printf_F(struct printf_data* data, struct printf_format_params* format, va_list args) { double number = va_arg(args, double); if (isnan(number)) return printfDecimalSpecial(data, signbit(number), "NAN"); if (!isfinite(number)) return printfDecimalSpecial(data, signbit(number), "INF"); return doPrintfF(data, format, number, DEC_ALPHABET); } int printf_a(struct printf_data* data, struct printf_format_params* format, va_list args) { double number = va_arg(args, double); if (isnan(number)) return printfDecimalSpecial(data, signbit(number), "nan"); if (!isfinite(number)) return printfDecimalSpecial(data, signbit(number), "inf"); format->flags |= PRINTF_FLAG_ALTERNATE_FORM; format->typeName = printf_x; return doPrintfF(data, format, number, HEx_ALPHABET); } int printf_A(struct printf_data* data, struct printf_format_params* format, va_list args) { double number = va_arg(args, double); if (isnan(number)) return printfDecimalSpecial(data, signbit(number), "NAN"); if (!isfinite(number)) return printfDecimalSpecial(data, signbit(number), "INF"); format->flags |= PRINTF_FLAG_ALTERNATE_FORM; format->typeName = printf_X; return doPrintfF(data, format, number, HEX_ALPHABET); }