isundil 2 سال پیش
کامیت
1fd3a3e2e4
18فایلهای تغییر یافته به همراه1237 افزوده شده و 0 حذف شده
  1. 4 0
      .gitignore
  2. 39 0
      Makefile
  3. 36 0
      ft_aprintf.c
  4. 54 0
      ft_dprintf.c
  5. 30 0
      ft_printf.c
  6. 21 0
      ft_printf.h
  7. 75 0
      ft_printf_internal.h
  8. 51 0
      ft_sprintf.c
  9. 237 0
      main.c
  10. 21 0
      printFdBuffer.c
  11. 69 0
      printfC.c
  12. 144 0
      printfDecimal.c
  13. 199 0
      printfDi.c
  14. 11 0
      printfN.c
  15. 106 0
      printfParams.c
  16. 10 0
      printfPercent.c
  17. 91 0
      printfWrite.c
  18. 39 0
      printfouxX.c

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+
+/printf
+*.o
+

+ 39 - 0
Makefile

@@ -0,0 +1,39 @@
+
+SRC=	ft_printf.c		\
+		ft_dprintf.c	\
+		ft_sprintf.c	\
+		ft_aprintf.c	\
+		printfParams.c	\
+		printfPercent.c	\
+		printfDi.c		\
+		printfouxX.c	\
+		printfC.c		\
+		printfN.c		\
+		printfDecimal.c	\
+		printfWrite.c	\
+		printFdBuffer.c	\
+		main.c
+
+OBJ=	$(SRC:.c=.o)
+
+NAME=	printf
+
+CFLAGS=	-W -Wall -Wextra -Werror -g3
+
+LDFLAGS=-g3
+
+$(NAME):	all
+
+all: $(OBJ)
+	$(CC) $(OBJ) $(LDFLAGS) -o $(NAME)
+
+clean:
+	$(RM) $(NAME)
+
+fclean:	clean
+	$(RM) $(OBJ)
+
+re:	fclean all
+
+.PHONY:	all clean fclean re
+

+ 36 - 0
ft_aprintf.c

@@ -0,0 +1,36 @@
+
+#include "ft_printf_internal.h"
+
+int ft_aprintf(char** output, char* format, ...)
+{
+    va_list args;
+    int result;
+
+    va_start(args, format);
+    result = ft_vaprintf(output, format, args);
+    va_end(args);
+    return result;
+}
+
+int ft_vaprintf(char** output, char* format, va_list args)
+{
+    struct printf_data params;
+
+    params.fd = -1;
+    params.written = 0;
+    params.inputBuffer = format;
+    params.outputBuffer = NULL;
+    params.bufferMaxSize = 0;
+    params.realloc = 1;
+    params.fdBuffer = NULL;
+    params.bufferPos = 0;
+    while (*params.inputBuffer)
+    {
+        if (doPrintf(&params, args) < 0)
+            return -1;
+    }
+    flushBuffer(&params);
+    *output = params.outputBuffer;
+    return params.written;
+}
+

+ 54 - 0
ft_dprintf.c

@@ -0,0 +1,54 @@
+
+#include <stdlib.h>
+#include "ft_printf_internal.h"
+
+int doPrintf(struct printf_data* params, va_list args)
+{
+    int to;
+    int syscallReturn;
+
+    to = 0;
+    while (params->inputBuffer[to] && params->inputBuffer[to] != '%')
+    {
+        ++to;
+    }
+    if (to)
+    {
+        syscallReturn = printfWrite(params, params->inputBuffer, to);
+        if (syscallReturn < 0)
+            return syscallReturn;
+        params->inputBuffer += to;
+    }
+    if (*params->inputBuffer == '%')
+    {
+        params->inputBuffer++;
+        syscallReturn = expandParams(params, args);
+        if (syscallReturn < 0)
+            return syscallReturn;
+        return 0;
+    }
+    return 0;
+}
+
+int ft_vdprintf(int fd, char* format, va_list args)
+{
+    struct printf_data params;
+
+    params.fd = fd;
+    params.written = 0;
+    params.inputBuffer = format;
+    params.outputBuffer = NULL;
+    params.realloc = 0;
+    params.fdBuffer = (char*) malloc(sizeof(*params.fdBuffer) * PRINTF_FD_BUFFER_LEN);
+    params.bufferMaxSize = PRINTF_FD_BUFFER_LEN;
+    params.bufferPos = 0;
+    while (*params.inputBuffer)
+    {
+        if (doPrintf(&params, args) < 0)
+            return -1;
+    }
+    flushBuffer(&params);
+    free(params.fdBuffer);
+    return params.written;
+}
+

+ 30 - 0
ft_printf.c

@@ -0,0 +1,30 @@
+
+#include "ft_printf_internal.h"
+
+int ft_dprintf(int fd, char* format, ...)
+{
+    va_list args;
+    int result;
+
+    va_start(args, format);
+    result = ft_vdprintf(fd, format, args);
+    va_end(args);
+    return result;
+}
+
+int ft_printf(char* format, ...)
+{
+    va_list args;
+    int result;
+
+    va_start(args, format);
+    result = ft_vdprintf(1, format, args);
+    va_end(args);
+    return result;
+}
+
+int ft_vprintf(char* format, va_list args)
+{
+    return ft_vdprintf(1, format, args);
+}
+

+ 21 - 0
ft_printf.h

@@ -0,0 +1,21 @@
+
+#ifndef __FT_PRINTF_H__
+#define __FT_PRINTF_H__
+
+#include <stdarg.h>
+
+int ft_printf(char* format, ...);
+int ft_dprintf(int fd, char* format, ...);
+int ft_vprintf(char* format, va_list args);
+int ft_vdprintf(int fd, char* format, va_list args);
+
+int ft_sprintf(char* output, char* format, ...);
+int ft_snprintf(char* output, int bufLen, char* format, ...);
+int ft_vsprintf(char* output, char* format, va_list args);
+int ft_vsnprintf(char* output, int bufLen, char* format, va_list args);
+
+int ft_aprintf(char** output, char* format, ...);
+int ft_vaprintf(char** output, char* format, va_list args);
+
+#endif
+

+ 75 - 0
ft_printf_internal.h

@@ -0,0 +1,75 @@
+
+#ifndef __FT_PRINTF_INT_H__
+#define __FT_PRINTF_INT_H__
+
+#include <stddef.h>
+#include <stdarg.h>
+
+#define DEC_ALPHABET "0123456789"
+#define OCT_ALPHABET "01234567"
+#define HEx_ALPHABET "0123456789abcdef"
+#define HEX_ALPHABET "0123456789ABCDEF"
+
+#define PRINTF_FD_BUFFER_LEN 126
+#define PRINTF_OUTPUT_BUFFER_INCREMENT 1024
+
+struct printf_data
+{
+    int fd;
+    size_t written;
+    char* inputBuffer;
+    char* outputBuffer;
+    size_t bufferMaxSize;
+    size_t bufferPos;
+    char* fdBuffer;
+    int realloc;
+};
+
+#define PRINTF_FLAG_ALTERNATE_FORM 1
+#define PRINTF_FLAG_ZERO_PAD 2
+#define PRINTF_FLAG_LEFT_PADDING 4
+#define PRINTF_FLAG_SIGNED_PAD 8
+#define PRINTF_FLAG_SIGNED_SIGN 16
+#define PRINTF_FLAG_THD_GROUP 32
+
+struct printf_format_params
+{
+    int flags;
+    int width;
+    int precision;
+    int length;
+    int (*typeName)(struct printf_data* data, struct printf_format_params* format, va_list arg);
+};
+
+typedef int (*printf_typeName)(struct printf_data* data, struct printf_format_params* format, va_list args);
+
+void flushBuffer(struct printf_data* data);
+int printfWrite(struct printf_data* data, const char* buff, size_t len);
+int printfString(struct printf_data* data, struct printf_format_params* format, const char* str);
+int appendToFdBuffer(struct printf_data* data, const char* buf, size_t len);
+int doPrintf(struct printf_data* params, va_list args);
+int printfNumber(struct printf_data* data, struct printf_format_params* format, long long int number, char decimalCount, const char* alphabet);
+
+int pad(struct printf_data* data, struct printf_format_params* format, int written);
+
+int printf_percent(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_di(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_u(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_o(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_X(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_x(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_c(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_p(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_n(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_m(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_s(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_f(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_F(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_a(struct printf_data* data, struct printf_format_params* format, va_list args);
+int printf_A(struct printf_data* data, struct printf_format_params* format, va_list args);
+int expandParams(struct printf_data* params, va_list args);
+
+#endif
+
+#include "ft_printf.h"
+

+ 51 - 0
ft_sprintf.c

@@ -0,0 +1,51 @@
+
+#include "ft_printf_internal.h"
+
+int ft_sprintf(char* output, char* format, ...)
+{
+    va_list args;
+    int result;
+
+    va_start(args, format);
+    result = ft_vsnprintf(output, -1, format, args);
+    va_end(args);
+    return result;
+}
+
+int ft_snprintf(char* output, int bufLen, char* format, ...)
+{
+    va_list args;
+    int result;
+
+    va_start(args, format);
+    result = ft_vsnprintf(output, bufLen, format, args);
+    va_end(args);
+    return result;
+}
+
+int ft_vsprintf(char* output, char* format, va_list args)
+{
+    return ft_vsnprintf(output, -1, format, args);
+}
+
+int ft_vsnprintf(char* output, int bufLen, char* format, va_list args)
+{
+    struct printf_data params;
+
+    params.fd = -1;
+    params.written = 0;
+    params.inputBuffer = format;
+    params.outputBuffer = output;
+    params.bufferMaxSize = bufLen;
+    params.realloc = 0;
+    params.fdBuffer = NULL;
+    params.bufferPos = 0;
+    while (*params.inputBuffer)
+    {
+        if (doPrintf(&params, args) < 0)
+            return -1;
+    }
+    flushBuffer(&params);
+    return params.written;
+}
+

+ 237 - 0
main.c

@@ -0,0 +1,237 @@
+
+#include <math.h>
+#include <errno.h>
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include "ft_printf.h"
+
+#define N__PRINTF(str) printf("%d: P>"str" -> %n", __LINE__, &tmp); printf("%d\n", tmp);
+#define N_fPRINTF(str) ft_printf("%d: M>"str" -> %n", __LINE__, &tmp); ft_printf("%d\n", tmp); ft_aprintf(&buffer, "%d: A>"str, __LINE__); ft_printf("%s\n\n", buffer); if (buffer) free(buffer); buffer = NULL;
+#define __PRINTF(str, args...) printf("%d: P>"str" -> %n", __LINE__, args, &tmp); printf("%d\n", tmp);
+#define _fPRINTF(str, args...) ft_printf("%d: M>"str" -> %n", __LINE__, args, &tmp); ft_printf("%d\n", tmp); ft_aprintf(&buffer, "%d: A>"str, __LINE__, args); ft_printf("%s\n\n", buffer); if (buffer) free(buffer); buffer = NULL;
+
+#define TEST_FLOATS(LETTER) \
+    __PRINTF("number %+"LETTER, 42.12345);\
+    _fPRINTF("number %+"LETTER, 42.12345);\
+    __PRINTF("number % "LETTER, 44.12345);\
+    _fPRINTF("number % "LETTER, 44.12345);\
+    __PRINTF("number % 4"LETTER, 45.12345);\
+    _fPRINTF("number % 4"LETTER, 45.12345);\
+    __PRINTF("number %04"LETTER, 46.12345);\
+    _fPRINTF("number %04"LETTER, 46.12345);\
+    __PRINTF("number % 04"LETTER, 47.12345);\
+    _fPRINTF("number % 04"LETTER, 47.12345);\
+    __PRINTF("number %-+"LETTER, 48.12345);\
+    _fPRINTF("number %-+"LETTER, 48.12345);\
+    __PRINTF("number %-+"LETTER, 49.12345);\
+    _fPRINTF("number %-+"LETTER, 49.12345);\
+    __PRINTF("number %- "LETTER, 50.12345);\
+    _fPRINTF("number %- "LETTER, 50.12345);\
+    __PRINTF("number %- 4"LETTER"|", 51.12345);\
+    _fPRINTF("number %- 4"LETTER"|", 51.12345);\
+    __PRINTF("number %+"LETTER, -42.12345);\
+    _fPRINTF("number %+"LETTER, -42.12345);\
+    __PRINTF("number %+"LETTER, -43.12345);\
+    _fPRINTF("number %+"LETTER, -43.12345);\
+    __PRINTF("number % "LETTER, -44.12345);\
+    _fPRINTF("number % "LETTER, -44.12345);\
+    __PRINTF("number % 4"LETTER, -45.12345);\
+    _fPRINTF("number % 4"LETTER, -45.12345);\
+    __PRINTF("number %04"LETTER, -46.12345);\
+    _fPRINTF("number %04"LETTER, -46.12345);\
+    __PRINTF("number % 04"LETTER, -47.12345);\
+    _fPRINTF("number % 04"LETTER, -47.12345);\
+    __PRINTF("number %-+"LETTER, -48.12345);\
+    _fPRINTF("number %-+"LETTER, -48.12345);\
+    __PRINTF("number %-+"LETTER, -49.12345);\
+    _fPRINTF("number %-+"LETTER, -49.12345);\
+    __PRINTF("number %- "LETTER, -50.12345);\
+    _fPRINTF("number %- "LETTER, -50.12345);\
+    __PRINTF("number %- 4"LETTER"|", -51.12345);\
+    _fPRINTF("number %- 4"LETTER"|", -51.12345);\
+    __PRINTF("number %+.3"LETTER, 42.12345);\
+    _fPRINTF("number %+.3"LETTER, 42.12345);\
+    __PRINTF("number % .3"LETTER, 44.12345);\
+    _fPRINTF("number % .3"LETTER, 44.12345);\
+    __PRINTF("number % 4.3"LETTER, 45.12345);\
+    _fPRINTF("number % 4.3"LETTER, 45.12345);\
+    __PRINTF("number %04.3"LETTER, 46.12345);\
+    _fPRINTF("number %04.3"LETTER, 46.12345);\
+    __PRINTF("number % 04.3"LETTER, 47.12345);\
+    _fPRINTF("number % 04.3"LETTER, 47.12345);\
+    __PRINTF("number %-+.3"LETTER, 48.12345);\
+    _fPRINTF("number %-+.3"LETTER, 48.12345);\
+    __PRINTF("number %-+.3"LETTER, 49.12345);\
+    _fPRINTF("number %-+.3"LETTER, 49.12345);\
+    __PRINTF("number %- .3"LETTER, 50.12345);\
+    _fPRINTF("number %- .3"LETTER, 50.12345);\
+    __PRINTF("number %- 4"LETTER"|", 51.12345);\
+    _fPRINTF("number %- 4"LETTER"|", 51.12345);\
+    __PRINTF("number %+.3"LETTER, -42.12345);\
+    _fPRINTF("number %+.3"LETTER, -42.12345);\
+    __PRINTF("number %+.3"LETTER, -43.12345);\
+    _fPRINTF("number %+.3"LETTER, -43.12345);\
+    __PRINTF("number % .3"LETTER, -44.12345);\
+    _fPRINTF("number % .3"LETTER, -44.12345);\
+    __PRINTF("number % 4.3"LETTER, -45.12345);\
+    _fPRINTF("number % 4.3"LETTER, -45.12345);\
+    __PRINTF("number %04.3"LETTER, -46.12345);\
+    _fPRINTF("number %04.3"LETTER, -46.12345);\
+    __PRINTF("number % 04.3"LETTER, -47.12345);\
+    _fPRINTF("number % 04.3"LETTER, -47.12345);\
+    __PRINTF("number %-+.3"LETTER, -48.12345);\
+    _fPRINTF("number %-+.3"LETTER, -48.12345);\
+    __PRINTF("number %-+.3"LETTER, -49.12345);\
+    _fPRINTF("number %-+.3"LETTER, -49.12345);\
+    __PRINTF("number %- .3"LETTER, -50.12345);\
+    _fPRINTF("number %- .3"LETTER, -50.12345);\
+    __PRINTF("number %- 4"LETTER"|", -51.12345);\
+    _fPRINTF("number %- 4"LETTER"|", -51.12345);\
+    __PRINTF("number %.1"LETTER"|", -51.99);\
+    _fPRINTF("number %.1"LETTER"|", -51.99);\
+    __PRINTF("number %"LETTER"|", NAN);\
+    _fPRINTF("number %"LETTER"|", NAN);\
+    __PRINTF("number %"LETTER"|", INFINITY);\
+    _fPRINTF("number %"LETTER"|", INFINITY);\
+    __PRINTF("number %"LETTER"|", -NAN);\
+    _fPRINTF("number %"LETTER"|", -NAN);\
+    __PRINTF("number %"LETTER"|", -INFINITY);\
+    _fPRINTF("number %"LETTER"|", -INFINITY);
+
+
+int main()
+{
+    int tmp =0;
+    char* buffer = NULL;
+
+    N__PRINTF("test");
+    N_fPRINTF("test");
+    N__PRINTF("te%%st");
+    N_fPRINTF("te%%st");
+    N__PRINTF("te%%%%st");
+    N_fPRINTF("te%%%%st");
+
+    __PRINTF("number %+d", 42);
+    _fPRINTF("number %+d", 42);
+    __PRINTF("number %+d", 43);
+    _fPRINTF("number %+d", 43);
+    __PRINTF("number % d", 44);
+    _fPRINTF("number % d", 44);
+    __PRINTF("number % 4d", 45);
+    _fPRINTF("number % 4d", 45);
+    __PRINTF("number %04d", 46);
+    _fPRINTF("number %04d", 46);
+    __PRINTF("number % 04d", 47);
+    _fPRINTF("number % 04d", 47);
+    __PRINTF("number %-+d", 48);
+    _fPRINTF("number %-+d", 48);
+    __PRINTF("number %-+d", 49);
+    _fPRINTF("number %-+d", 49);
+    __PRINTF("number %- d", 50);
+    _fPRINTF("number %- d", 50);
+    __PRINTF("number %- 4d|", 51);
+    _fPRINTF("number %- 4d|", 51);
+    __PRINTF("number %+d", -42);
+    _fPRINTF("number %+d", -42);
+    __PRINTF("number %+d", -43);
+    _fPRINTF("number %+d", -43);
+    __PRINTF("number % d", -44);
+    _fPRINTF("number % d", -44);
+    __PRINTF("number % 4d", -45);
+    _fPRINTF("number % 4d", -45);
+    __PRINTF("number %04d", -46);
+    _fPRINTF("number %04d", -46);
+    __PRINTF("number % 04d", -47);
+    _fPRINTF("number % 04d", -47);
+    __PRINTF("number %-+d", -48);
+    _fPRINTF("number %-+d", -48);
+    __PRINTF("number %-+d", -49);
+    _fPRINTF("number %-+d", -49);
+    __PRINTF("number %- d", -50);
+    _fPRINTF("number %- d", -50);
+    __PRINTF("number %- 4d|", -51);
+    _fPRINTF("number %- 4d|", -51);
+    __PRINTF("number %+d", 0);
+    _fPRINTF("number %+d", 0);
+    __PRINTF("number %+d", 0);
+    _fPRINTF("number %+d", 0);
+    __PRINTF("number % d", 0);
+    _fPRINTF("number % d", 0);
+    __PRINTF("number % 4d", 0);
+    _fPRINTF("number % 4d", 0);
+    __PRINTF("number %04d", 0);
+    _fPRINTF("number %04d", 0);
+    __PRINTF("number % 04d", 0);
+    _fPRINTF("number % 04d", 0);
+    __PRINTF("number %-+d", 0);
+    _fPRINTF("number %-+d", 0);
+    __PRINTF("number %-+d", 0);
+    _fPRINTF("number %-+d", 0);
+    __PRINTF("number %- d", 0);
+    _fPRINTF("number %- d", 0);
+    __PRINTF("number %- 4d|", 0);
+    _fPRINTF("number %- 4d|", 0);
+    __PRINTF("number %- 4d|", INT_MIN);
+    _fPRINTF("number %- 4d|", INT_MIN);
+
+    __PRINTF("number %o", 0);
+    _fPRINTF("number %o", 0);
+    __PRINTF("number %u", 0);
+    _fPRINTF("number %u", 0);
+    __PRINTF("number %x", 0);
+    _fPRINTF("number %x", 0);
+    __PRINTF("number %12o", UINT_MAX);
+    _fPRINTF("number %12o", UINT_MAX);
+    __PRINTF("number %12u", UINT_MAX);
+    _fPRINTF("number %12u", UINT_MAX);
+    __PRINTF("number %12X", UINT_MAX);
+    _fPRINTF("number %12X", UINT_MAX);
+    __PRINTF("number %12x", UINT_MAX);
+    _fPRINTF("number %12x", UINT_MAX);
+    __PRINTF("number %#12o", UINT_MAX);
+    _fPRINTF("number %#12o", UINT_MAX);
+    __PRINTF("number %#12X", UINT_MAX);
+    _fPRINTF("number %#12X", UINT_MAX);
+    __PRINTF("number %#12x", UINT_MAX);
+    _fPRINTF("number %#12x", UINT_MAX);
+    _fPRINTF("number %'+012d", 123456789);
+    _fPRINTF("number %'+012d", 1234567);
+
+    __PRINTF("char %c", 'e');
+    _fPRINTF("char %c", 'e');
+    __PRINTF("char %3c", 'e');
+    _fPRINTF("char %3c", 'e');
+
+    __PRINTF("ptr %18s", "e");
+    _fPRINTF("ptr %18s", "e");
+    buffer = NULL;
+    __PRINTF("ptr %18s", buffer);
+    _fPRINTF("ptr %18s", (char*)NULL);
+
+    __PRINTF("ptr %18p", "e");
+    _fPRINTF("ptr %18p", "e");
+    __PRINTF("ptr %18p", NULL);
+    _fPRINTF("ptr %18p", NULL);
+
+    errno = 7;
+    N__PRINTF("errno %30m");
+    N_fPRINTF("errno %30m");
+    __PRINTF("str %18s", "test");
+    _fPRINTF("str %18s", "test");
+    __PRINTF("str %5.3s", "test");
+    _fPRINTF("str %5.3s", "test");
+
+    TEST_FLOATS("f");
+    TEST_FLOATS("F");
+    /*
+    TEST_FLOATS("a");
+    TEST_FLOATS("A");
+    TEST_FLOATS("e");
+    TEST_FLOATS("E");
+    TEST_FLOATS("g");
+    TEST_FLOATS("G");
+    */
+    return 0;
+}
+

+ 21 - 0
printFdBuffer.c

@@ -0,0 +1,21 @@
+
+#include <unistd.h>
+#include <sys/param.h>
+#include <string.h>
+#include "ft_printf_internal.h"
+
+int appendToFdBuffer(struct printf_data* data, const char* buf, size_t len)
+{
+    size_t sizeToWrite = MIN(data->bufferMaxSize - data->bufferPos, len);
+    memcpy(&data->fdBuffer[data->bufferPos], buf, sizeToWrite);
+    data->bufferPos += sizeToWrite;
+    if (data->bufferPos == data->bufferMaxSize)
+    {
+        int result = write(data->fd, data->fdBuffer, data->bufferMaxSize);
+        if (result < 0)
+            return result;
+        data->bufferPos = 0;
+    }
+    return sizeToWrite;
+}
+

+ 69 - 0
printfC.c

@@ -0,0 +1,69 @@
+
+#include <errno.h>
+#include <string.h>
+#include "ft_printf_internal.h"
+
+int padString(struct printf_data* data, int len)
+{
+    int padLen = 0;
+    int sysCallRet;
+
+    while (len > 0)
+    {
+        sysCallRet = printfWrite(data, " ", 1);
+        if (sysCallRet < 0)
+            return sysCallRet;
+        padLen += sysCallRet;
+        --len;
+    }
+    return padLen;
+}
+
+int printf_c(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    char c = (char) va_arg(args, int);
+    int len = format->width -1;
+    int padLen = 0;
+    int sysCallRet;
+
+    padLen = padString(data, len);
+    if (padLen < 0)
+        return padLen;
+    sysCallRet = printfWrite(data, &c, 1);
+    if (sysCallRet < 0)
+        return sysCallRet;
+    return sysCallRet + padLen;
+}
+
+int printfString(struct printf_data* data, struct printf_format_params* format, const char* str)
+{
+    int len = strlen(str);
+    int pad = format->width;
+
+    if (format->precision >= 0 && len > format->precision)
+        len = format->precision;
+    if (pad >= 0)
+        pad = pad - len;
+    pad = padString(data, pad);
+    if (pad < 0)
+        return pad;
+    len = printfWrite(data, str, len);
+    if (len < 0)
+        return len;
+    return pad + len;
+}
+
+int printf_s(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    const char* str = va_arg(args, const char*);
+    return printfString(data, format, str == NULL ? "(null)" : str);
+}
+
+int printf_m(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    (void) args;
+    return printfString(data, format, strerror(errno));
+}
+
+
+

+ 144 - 0
printfDecimal.c

@@ -0,0 +1,144 @@
+
+#include <string.h>
+#include <math.h>
+#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);
+}
+

+ 199 - 0
printfDi.c

@@ -0,0 +1,199 @@
+
+#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);
+}
+

+ 11 - 0
printfN.c

@@ -0,0 +1,11 @@
+
+#include "ft_printf_internal.h"
+
+int printf_n(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    int* output = va_arg(args, int*);
+    (void) format;
+    *output = data->written;
+    return 0;
+}
+

+ 106 - 0
printfParams.c

@@ -0,0 +1,106 @@
+
+#include "ft_printf_internal.h"
+
+int consumeFlags(struct printf_data* params)
+{
+    int flags;
+    int status;
+
+    status = 1;
+    flags = 0;
+    while (*params->inputBuffer && status)
+    {
+        if (*params->inputBuffer == '#')
+            flags |= PRINTF_FLAG_ALTERNATE_FORM;
+        else if (*params->inputBuffer == '0')
+            flags |= PRINTF_FLAG_ZERO_PAD;
+        else if (*params->inputBuffer == '-')
+            flags |= PRINTF_FLAG_LEFT_PADDING;
+        else if (*params->inputBuffer == ' ')
+            flags |= PRINTF_FLAG_SIGNED_PAD;
+        else if (*params->inputBuffer == '+')
+            flags |= PRINTF_FLAG_SIGNED_SIGN;
+        else if (*params->inputBuffer == '\'')
+            flags |= PRINTF_FLAG_THD_GROUP;
+        else
+            status = 0;
+        if (status)
+            params->inputBuffer++;
+    }
+    return flags;
+}
+
+int consumeNumber(struct printf_data* params)
+{
+    int result;
+
+    result = 0;
+    while (*params->inputBuffer >= '0' && *params->inputBuffer <= '9')
+    {
+        result = result * 10 + (*params->inputBuffer - '0');
+        params->inputBuffer++;
+    }
+    return result;
+}
+
+printf_typeName consumeTypename(struct printf_data* data)
+{
+    if (*data->inputBuffer == '%')
+        return printf_percent;
+    if (*data->inputBuffer == 'd' || *data->inputBuffer == 'i')
+        return printf_di;
+    if (*data->inputBuffer == 'u')
+        return printf_u;
+    if (*data->inputBuffer == 'o')
+        return printf_o;
+    if (*data->inputBuffer == 'x')
+        return printf_x;
+    if (*data->inputBuffer == 'X')
+        return printf_X;
+    if (*data->inputBuffer == 'c')
+        return printf_c;
+    if (*data->inputBuffer == 'p')
+        return printf_p;
+    if (*data->inputBuffer == 'n')
+        return printf_n;
+    if (*data->inputBuffer == 'm')
+        return printf_m;
+    if (*data->inputBuffer == 's')
+        return printf_s;
+    if (*data->inputBuffer == 'f')
+        return printf_f;
+    if (*data->inputBuffer == 'F')
+        return printf_F;
+    if (*data->inputBuffer == 'a')
+        return printf_a;
+    if (*data->inputBuffer == 'A')
+        return printf_A;
+    return NULL;
+}
+
+int expandParams(struct printf_data* params, va_list args)
+{
+    struct printf_format_params format;
+    char* buffer = params->inputBuffer;
+
+    format.flags = consumeFlags(params);
+    format.width = -1;
+    format.precision = -1;
+    if (*params->inputBuffer >= '0' && *params->inputBuffer <= '9')
+        format.width = consumeNumber(params);
+    if (*params->inputBuffer == '.')
+    {
+        ++params->inputBuffer;
+        format.precision = consumeNumber(params);
+    }
+    /* LENGTH MODIFIERS NOT SUPPORTED */
+    format.typeName = consumeTypename(params);
+    if (format.typeName)
+    {
+        params->inputBuffer++;
+        return format.typeName(params, &format, args);
+    }
+    params->inputBuffer = buffer;
+    return printf_percent(params, &format, args);
+}
+

+ 10 - 0
printfPercent.c

@@ -0,0 +1,10 @@
+
+#include "ft_printf_internal.h"
+
+int printf_percent(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    (void) format;
+    (void) args;
+    return printfWrite(data, "%", 1);
+}
+

+ 91 - 0
printfWrite.c

@@ -0,0 +1,91 @@
+
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "ft_printf_internal.h"
+
+int expandBuffer(struct printf_data* data, int size)
+{
+    if (!data->realloc)
+        return -1;
+    int finalSize = ((size / PRINTF_OUTPUT_BUFFER_INCREMENT) +1) * PRINTF_OUTPUT_BUFFER_INCREMENT;
+    char* newBuffer = (char*) malloc(sizeof(*newBuffer) * finalSize);
+    if (!newBuffer)
+        return -1;
+    if (data->outputBuffer)
+    {
+        memcpy(newBuffer, data->outputBuffer, data->bufferMaxSize);
+        free(data->outputBuffer);
+    }
+    data->outputBuffer = newBuffer;
+    data->bufferMaxSize = finalSize;
+    return 0;
+}
+
+int appendToBuffer(struct printf_data* data, const char* buf, size_t len)
+{
+    int sizeToWrite = MIN(len, data->bufferMaxSize - data->written);
+    int totalWritten = data->written;
+
+    if (!data->outputBuffer && !data->realloc)
+        return -1;
+    if (data->outputBuffer)
+    {
+        memcpy(&data->outputBuffer[data->written], buf, sizeToWrite);
+        data->written += sizeToWrite;
+        len -= sizeToWrite;
+        buf += sizeToWrite;
+    }
+    if (len > 0)
+    {
+        if (expandBuffer(data, data->bufferMaxSize + len) == -1)
+            return -1;
+        sizeToWrite = MIN(len, data->bufferMaxSize - data->written);
+        memcpy(&data->outputBuffer[data->written], buf, sizeToWrite);
+        data->written += sizeToWrite;
+    }
+    return data->written - totalWritten;
+}
+
+void flushBuffer(struct printf_data* data)
+{
+    if (data->outputBuffer)
+    {
+        appendToBuffer(data, "", 1);
+        if (data->realloc && data->written != data->bufferMaxSize)
+        {
+            char* newBuf = (char*) malloc(sizeof(*newBuf) * data->written);
+            memcpy(newBuf, data->outputBuffer, data->written);
+            free(data->outputBuffer);
+            data->outputBuffer = newBuf;
+        }
+    }
+    if (data->fdBuffer && data->bufferPos)
+    {
+        write(data->fd, data->fdBuffer, data->bufferPos);
+    }
+}
+
+int printfWrite(struct printf_data* data, const char* buf, size_t len)
+{
+    if (data->outputBuffer || data->realloc)
+        return appendToBuffer(data, buf, len);
+    if (data->fdBuffer)
+    {
+        int totalLen = len;
+        while (len > 0)
+        {
+            int result = appendToFdBuffer(data, buf, len);
+            if (result < 0)
+                return result;
+            len -= result;
+        }
+        data->written += totalLen;
+        return totalLen;
+    }
+    int written = write(data->fd, buf, len);
+    data->written += written;
+    return written;
+}
+

+ 39 - 0
printfouxX.c

@@ -0,0 +1,39 @@
+
+#include "ft_printf_internal.h"
+
+int printf_u(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    return printfNumber(data, format, va_arg(args, unsigned int), 0, DEC_ALPHABET);
+}
+
+int printf_o(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    return printfNumber(data, format, va_arg(args, unsigned int), 0, OCT_ALPHABET);
+}
+
+int printf_X(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    return printfNumber(data, format, va_arg(args, unsigned int), 0, HEX_ALPHABET);
+}
+
+int printf_x(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    return printfNumber(data, format, va_arg(args, unsigned int), 0, HEx_ALPHABET);
+}
+
+int printf_p(struct printf_data* data, struct printf_format_params* format, va_list args)
+{
+    int result;
+    int oldFlags = format->flags;
+    void* ptr = va_arg(args, void*);
+
+    if (!ptr)
+        return printfString(data, format, "(nil)");
+    format->flags |= PRINTF_FLAG_ALTERNATE_FORM;
+    format->typeName = printf_x;
+    result = printfNumber(data, format, (unsigned long long) ptr, 0, HEx_ALPHABET);
+    format->typeName = printf_p;
+    format->flags = oldFlags;
+    return result;
+}
+