#include #include "ft_printf_internal.h" int numberLen(long long number, int alphabetLen, int alternativeForm, char decimalCount) { int result = 1; if (number < 0) { number *= -1; ++result; } while (number > alphabetLen) { number /= alphabetLen; result++; } if (alternativeForm && alphabetLen == 8) result++; if (alternativeForm && alphabetLen == 16) result += 2; return result + decimalCount; } int doPrintPosNumber(struct printf_data* data, struct printf_format_params* format, char buf[24], int pos) { int result = 0; int sysCallRet; while (pos >= 0) { if (format->flags & PRINTF_FLAG_THD_GROUP && (pos %3) == 2) { sysCallRet = printfWrite(data, "'", 1); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; } sysCallRet = printfWrite(data, &buf[pos], 1); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; --pos; } return result; } int pad(struct printf_data* data, struct printf_format_params* format, int written) { int numberSize = written; int result = 0; int sysCallRet; char padWith = ' '; if (format->width > numberSize) { numberSize = format->width - numberSize; if (format->flags & PRINTF_FLAG_ZERO_PAD) padWith = '0'; while (numberSize > 0) { sysCallRet = printfWrite(data, &padWith, 1); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; --numberSize; } } return result; } int printPosNumber(struct printf_data* data, struct printf_format_params* format, long long posNumber, int written, const char* alphabet, char decimalCount) { char buf[32]; int sysCallRet; int pos = -1; int result = 0; int alphabetLen = strlen(alphabet); if (format->flags & PRINTF_FLAG_ZERO_PAD) { sysCallRet = pad(data, format, written + numberLen(posNumber, alphabetLen, format->flags & PRINTF_FLAG_ALTERNATE_FORM, decimalCount)); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; } if (!posNumber) return result + printfWrite(data, &alphabet[0], 1); while (posNumber > 0) { ++pos; buf[pos] = alphabet[posNumber % alphabetLen]; posNumber /= alphabetLen; } return result + doPrintPosNumber(data, format, buf, pos); } int signPad(struct printf_data* data, struct printf_format_params* format, char isPositiveNumber, int alphabetLen) { int result = 0; int sysCallRet; if (format->flags & PRINTF_FLAG_SIGNED_SIGN && isPositiveNumber) { sysCallRet = printfWrite(data, "+", 1); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; } if (format->flags & PRINTF_FLAG_ALTERNATE_FORM) { char* alternate; if (alphabetLen == 8) alternate = "0"; else if (alphabetLen == 16 && format->typeName == printf_x) alternate = "0x"; else if (alphabetLen == 16 && format->typeName == printf_X) alternate = "0X"; sysCallRet = printfWrite(data, alternate, strlen(alternate)); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; } if (!isPositiveNumber) { sysCallRet = printfWrite(data, "-", 1); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; } return result; } int printfDiPrepend(struct printf_data* data, struct printf_format_params* format, long long number, int alphabetLen, char decimalCount) { int result = 0; int sysCallRet; if (!(format->flags & PRINTF_FLAG_SIGNED_SIGN) && (format->flags & PRINTF_FLAG_SIGNED_PAD) && number >=0) { sysCallRet = printfWrite(data, " ", 1); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; } if (!(format->flags & PRINTF_FLAG_LEFT_PADDING) && !(format->flags & PRINTF_FLAG_ZERO_PAD)) { int _numberLen = numberLen(number, alphabetLen, format->flags & PRINTF_FLAG_ALTERNATE_FORM, decimalCount); sysCallRet = pad(data, format, result + _numberLen); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; } sysCallRet = signPad(data, format, number >= 0, alphabetLen); if (sysCallRet < 0) return sysCallRet; return result + sysCallRet; } int printfNumber(struct printf_data* data, struct printf_format_params* format, long long int number, char decimalLength, const char* alphabet) { int result = 0; int sysCallRet; sysCallRet = printfDiPrepend(data, format, number, strlen(alphabet), decimalLength); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; if (number < 0) number *= -1; sysCallRet = printPosNumber(data, format, number, result, alphabet, decimalLength); if (sysCallRet < 0) return sysCallRet; result += sysCallRet; if (decimalLength == 0 && (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; } /* * * The int argument is converted to signed decimal notation. * The precision, if any, gives the minimum number of digits that must appear; * if the converted value requires fewer digits, it is padded on the left with zeros. * The default precision is 1. * When 0 is printed with an explicit precision 0, the output is empty. * **/ int printf_di(struct printf_data* data, struct printf_format_params* format, va_list args) { return printfNumber(data, format, va_arg(args, int), 0, DEC_ALPHABET); }