| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- #include <string.h>
- #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);
- }
|