From f1ce5b8b9e485c32267ab53693c51e6b785efd4d Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 19 May 2021 18:06:12 +0200 Subject: [PATCH] ajout de ft_printf a la librairie --- Makefile | 14 +- .../{get_next_line.h => ft_get_next_line.h} | 4 - includes/ft_printf.h | 62 ++++++ includes/libft.h | 60 +++++- srcs/{get_next_line.c => ft_get_next_line.c} | 0 srcs/ft_printf_files/ft_convert.c | 105 +++++++++ srcs/ft_printf_files/ft_flag_transform.c | 199 ++++++++++++++++++ .../ft_printf_files/ft_flag_transform_bonus.c | 75 +++++++ srcs/ft_printf_files/ft_next_word.c | 98 +++++++++ srcs/ft_printf_files/ft_printf.c | 162 ++++++++++++++ 10 files changed, 770 insertions(+), 9 deletions(-) rename includes/{get_next_line.h => ft_get_next_line.h} (95%) create mode 100644 includes/ft_printf.h rename srcs/{get_next_line.c => ft_get_next_line.c} (100%) create mode 100644 srcs/ft_printf_files/ft_convert.c create mode 100644 srcs/ft_printf_files/ft_flag_transform.c create mode 100644 srcs/ft_printf_files/ft_flag_transform_bonus.c create mode 100644 srcs/ft_printf_files/ft_next_word.c create mode 100644 srcs/ft_printf_files/ft_printf.c diff --git a/Makefile b/Makefile index 809fdec..7b496e7 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,8 @@ NAME = libft.a CC = gcc -VPATH = srcs/ +VPATH = srcs/ \ + srcs/ft_printf_files/ IDIR = ./includes _DEP = libft.h @@ -94,8 +95,15 @@ SRCS = ft_memset.c \ ft_arraymap.c \ ft_strmultisplit.c \ \ - get_next_line.c \ - ft_concat_free.c + ft_get_next_line.c \ + ft_concat_free.c \ + \ + ft_printf.c \ + ft_next_word.c \ + ft_convert.c \ + ft_flag_transform.c \ + ft_flag_transform_bonus.c + ODIR = ./builds OBJS = $(SRCS:%.c=$(ODIR)/%.o) diff --git a/includes/get_next_line.h b/includes/ft_get_next_line.h similarity index 95% rename from includes/get_next_line.h rename to includes/ft_get_next_line.h index d8c3d58..23f7cc6 100644 --- a/includes/get_next_line.h +++ b/includes/ft_get_next_line.h @@ -13,10 +13,6 @@ #ifndef GET_NEXT_LINE_H # define GET_NEXT_LINE_H -# include -# include -# include - # ifndef BUFFER_SIZE # define BUFFER_SIZE 1 # endif diff --git a/includes/ft_printf.h b/includes/ft_printf.h new file mode 100644 index 0000000..1f0e1fa --- /dev/null +++ b/includes/ft_printf.h @@ -0,0 +1,62 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_printf.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: hulamy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/02/27 12:07:47 by hulamy #+# #+# */ +/* Updated: 2020/03/12 20:35:10 by hulamy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef FT_PRINTF_H +# define FT_PRINTF_H +# include // to use va_arg + +/* +** ft_printf.c +*/ + +char *specifier(char *s); +int ft_expand_star(int nbr, char **string); +int ft_put_word(char *s, char *type, int size); +char *convert_with_flags(char *s, va_list ap, char *type, int *size); +int ft_printf(char *string, ...); + +/* +** ft_next_word.c +*/ + +int width_precision(char *s); +int word_length(char *s); +char *next_word(char **s); + +/* +** ft_convert.c +*/ + +char *conv_i(char c, long int i); +char *conv_u(char c, unsigned long int i); +char *ft_convert(va_list ap, char *type, char **s); + +/* +** ft_flag_transform.c +*/ + +char *precision_int(char *print, int precision); +char *ft_precision(char *s, char *print, char *type); +char *width_flags(char *print, char *s, int width, int zero); +char *ft_width(char *s, char *print, int *size, char *type); +char *ft_flag_transform(char *s, char *print, char *type, int *size); + +/* +** ft_flag_transform_bonus.c +*/ + +char *ft_plus(char *s, char *print, char *type); +char *ft_sharp(char *s, char *print, char *type); +char *ft_sharp_again(char *s, char *print, char *type); +char *ft_space(char *s, char *print, char *type, int *size); + +#endif diff --git a/includes/libft.h b/includes/libft.h index 893d39a..e4f4338 100644 --- a/includes/libft.h +++ b/includes/libft.h @@ -15,7 +15,9 @@ # include # include # include -# include "get_next_line.h" +# include "ft_get_next_line.h" +# include "ft_printf.h" +# include // to use va_arg in ft_printf void *ft_memset(void *b, int c, size_t len); void ft_bzero(void *s, size_t n); @@ -103,7 +105,61 @@ int ft_issort(int *tab, int length, int (*f)(int, int)); int *ft_arraymap(int *tab, int length, int(*f)(int)); void ft_putnbrendl(int n); void ft_putnbrendl_fd(int n, int fd); -int get_next_line(const int fd, char **line); +int ft_get_next_line(const int fd, char **line); char *ft_concat_free(char *str1, char *str2); + + + + + +# include // to use va_arg + +/* +** ft_printf.c +*/ + +char *specifier(char *s); +int ft_expand_star(int nbr, char **string); +int ft_put_word(char *s, char *type, int size); +char *convert_with_flags(char *s, va_list ap, char *type, int *size); +int ft_printf(char *string, ...); + +/* +** ft_next_word.c +*/ + +int width_precision(char *s); +int word_length(char *s); +char *next_word(char **s); + +/* +** ft_convert.c +*/ + +char *conv_i(char c, long int i); +char *conv_u(char c, unsigned long int i); +char *ft_convert(va_list ap, char *type, char **s); + +/* +** ft_flag_transform.c +*/ + +char *precision_int(char *print, int precision); +char *ft_precision(char *s, char *print, char *type); +char *width_flags(char *print, char *s, int width, int zero); +char *ft_width(char *s, char *print, int *size, char *type); +char *ft_flag_transform(char *s, char *print, char *type, int *size); + +/* +** ft_flag_transform_bonus.c +*/ + +char *ft_plus(char *s, char *print, char *type); +char *ft_sharp(char *s, char *print, char *type); +char *ft_sharp_again(char *s, char *print, char *type); +char *ft_space(char *s, char *print, char *type, int *size); + + + #endif diff --git a/srcs/get_next_line.c b/srcs/ft_get_next_line.c similarity index 100% rename from srcs/get_next_line.c rename to srcs/ft_get_next_line.c diff --git a/srcs/ft_printf_files/ft_convert.c b/srcs/ft_printf_files/ft_convert.c new file mode 100644 index 0000000..644a270 --- /dev/null +++ b/srcs/ft_printf_files/ft_convert.c @@ -0,0 +1,105 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_convert.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: hulamy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/03/12 22:30:05 by hulamy #+# #+# */ +/* Updated: 2020/06/30 00:40:49 by hulamy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* +** -convert the next argument into a string according to the following +** correspondances for diuxXcspefgn : +** [char] [hhd, hhi, c] [int] [d i c] +** [short] [hd, hi] [int] +** [int] [d, i] [int] +** [long] [ld, li] [long] [ld li] +** [long long] [lld, lli] [long] +** [unsigned char] [hhu, hhx, hhX] [unsigned int] [u x X p s] +** [unsigned short] [hu, hx, hX] [unsigned int] +** [unsigned int] [u, x, X, p] [unsigned int] +** [unsigned long] [lu, lx, lX] [unsigned long] [lu lx lX] +** [unsigned long long][llu, llx, llX] [unsigned long] +** [char *] [s, hhn] +** [double] [e, le, f, lf, g, lg] +** [wint_t] [lc] +** [wchar_t] [ls] +** [short *] [hn] +** [int *] [n] +** [long *] [ln] +** [long long *] [lln] +** -'h' and 'hh', are traited just like regular size because of +** default promotion, that promote smaller type than int into int +*/ + +char *conv_i(char c, long int i) +{ + char *s; + + if (c == 'c') + { + s = ft_strdup("0"); + s[0] = i; + return (s); + } + if (c == 'd' || c == 'i') + return (ft_itoa(i)); + return (NULL); +} + +char *conv_u(char c, unsigned long int i) +{ + char *s; + + if (c == 's') + return (i == 0 ? ft_strdup("(null)") : ft_strdup((char *)i)); + s = ft_utoa(i); + if (c == 'u') + return (s); + if (c == 'x' || c == 'p') + return (ft_convertbase_free(s, "0123456789", "0123456789abcdef")); + if (c == 'X') + return (ft_convertbase_free(s, "0123456789", "0123456789ABCDEF")); + return (NULL); +} + +/* +** -first a loop to expand all the stars from width and .precision +** they always expand into int type +** it's done first because those are the first next args on the va_list +** -for each kind of specifier there is finally four kinds of conversion : +** int / long int / unsigned int / unsingned long int +** -the conversion 'uxX' associated with 'l' are converted with lu, but +** also are 'p' and 's', without an 'l' flag, that's why there is this little +** trick on line the line for unsigned int : +** -'uxXps' && 'lps' will make it looks for 'uxX' and for 'l' +** (because it will never find a 'p' or a 's' if there are 'uxX' already) +** or for 'p' and again for 'p', or 's' twice similarly +*/ + +char *ft_convert(va_list ap, char *type, char **s) +{ + char *tmp; + + while (ft_strchr(*s, '*')) + if (!(ft_expand_star(va_arg(ap, int), s))) + return (NULL); + if ((tmp = ft_strchrset(type, "dic")) && ft_strchr(type, 'l')) + return (conv_i(tmp[0], va_arg(ap, long int))); + if ((tmp = ft_strchrset(type, "dic"))) + return (conv_i(tmp[0], va_arg(ap, int))); + if ((tmp = ft_strchrset(type, "uxXps")) && ft_strchrset(type, "lps")) + return (conv_u(tmp[0], va_arg(ap, unsigned long int))); + if ((tmp = ft_strchrset(type, "uxX"))) + return (conv_u(tmp[0], va_arg(ap, unsigned int))); + if (ft_strchr(type, '%')) + return (ft_strdup("%")); + if (ft_strchrset(type, "efgn")) + return (NULL); + return (NULL); +} diff --git a/srcs/ft_printf_files/ft_flag_transform.c b/srcs/ft_printf_files/ft_flag_transform.c new file mode 100644 index 0000000..21a06fc --- /dev/null +++ b/srcs/ft_printf_files/ft_flag_transform.c @@ -0,0 +1,199 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_flag_transform.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: hulamy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/03/12 22:30:28 by hulamy #+# #+# */ +/* Updated: 2020/03/12 22:30:41 by hulamy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* +** -function that modify the string 'print' according to the precision flag : +** if length(s) < precision, add x '0' bfr nbr, but after '-' if negative +*/ + +char *precision_int(char *print, int precision) +{ + int i; + char *tmp; + + i = ft_strlen(print); + if (print[0] == '-') + precision++; + if (precision > i) + { + if (!(tmp = (char *)malloc(sizeof(char) * (precision + 1)))) + return (NULL); + tmp[precision] = '\0'; + if (print[0] == '-') + tmp[0] = '-'; + while (i) + tmp[--precision] = print[--i]; + if (print[0] == '-') + precision++; + while (precision) + tmp[--precision] = '0'; + if (print[0] == '-') + tmp[0] = '-'; + free(print); + print = tmp; + } + return (print); +} + +/* +** -it first verify if there is a precision point, and if so, it execute a +** serie of action listed below, otherwise return print as it is +** ACTIONS : +** -look for a '.' +** -if followed by numbers, extract an int version of those numbers +** -if the '.' is alone, gives value '0' to the int +** -then removes the '.' and the numbers from the %string +** -if flag '0' is present in %string, removes it (actually turn each occurence +** in a '.') +** -and transform 'print' according to the precision : +** -0 if .precision is 0 && print is "0": print nothing +** -1 if type is s: if length(s) > precision, removes end of 'print' to print +** only x chars, with x = precision +** -2 if type is "diouxX": call fonction 'precision_int' that return : +** if length(s) < precision, add x '0' bfr nbr, but after '-' if negative +** -3 if type is "aAeEfF": not covered +** -4 if type is "gG": not covered +** -5 else: error +*/ + +char *ft_precision(char *s, char *print, char *type) +{ + char *tmp; + int precision; + int i; + + if ((tmp = ft_strchr(s, '.'))) + { + precision = ft_atoi(tmp + 1); + while (*s && ft_strchr("#- +'0", *(++s))) + if (*s == '0') + *s = '/'; + i = 0; + if (precision == 0 && !ft_strcmp(print, "0")) + print[0] = '\0'; + else if (ft_strchr(type, 's')) + { + while (i < precision && print[i]) + i++; + if (print[i]) + print[i] = '\0'; + } + else if (ft_strchrset(type, "diouxX")) + print = precision_int(print, precision); + } + return (print); +} + +/* +** -if flag '-' is present, put extra width as ' ' to right of 'print' +** -if flag '0' is present, put extra width as '0' to left of 'print' +** -else, put extra width as ' ' to left of 'print' +*/ + +char *width_flags(char *print, char *s, int width, int zero) +{ + char *tmp; + char *minus; + int len; + + len = ft_strlen(print) + zero; + if (!(tmp = ft_strnew(width))) + return (NULL); + if (ft_strchr(s, '-')) + { + ft_memmove(tmp, print, len); + ft_memset(tmp + len, ' ', width - len); + } + else + { + ft_memset(tmp, (ft_strchr(s, '0')) ? '0' : ' ', width - len); + ft_memmove(ft_strchr(tmp, '\0') + zero, print, ft_strlen(print)); + if (ft_strchr(s, '0') && (minus = ft_strchrset("+-", tmp))) + { + tmp[0] = (minus[0] == '+') ? '+' : '-'; + minus[0] = '0'; + } + } + free(print); + return (tmp); +} + +/* +** -if there is a minimal width field, calculate it and add it to print +** according to the flags '-' and '0' if present +** -in details : +** 0 if print[0] value 0, as it happens for type c with (char)0, save it for +** later in 'zero' +** 1 loop through s, the string starting by '%' and ending by a converter, +** until it has passed all the flags that are not a potentiel width field +** 2 then if it's the end of s, there is no width and print isn't changed, +** otherwise the int 'size' take the value returned by atoi +** in case print isn't changed, 'size' is the length of 'print' +** 3 then if the size of the width shield is bigger than the size of print +** (plus zero in case print is a (char)0), call 'width_flags' that will +** create a new char* to contain the string to print after transformation +** 4 otherwise 'size' is the length of print + zero +*/ + +char *ft_width(char *s, char *print, int *size, char *type) +{ + char *tmp; + int zero; + + tmp = s; + zero = 0; + if (print[0] == '\0' && ft_strchr(type, 'c')) + zero = 1; + while (*tmp != '\0' && ft_strchr("%#- +'0/", *tmp)) + tmp++; + if (*tmp == '\0' || *tmp == '.') + { + *size = ft_strlen(print) + zero; + return (print); + } + *size = ft_atoi(tmp); + tmp[0] = '\0'; + if ((unsigned int)*size > ft_strlen(print) + zero) + print = width_flags(print, s, *size, zero); + else + *size = ft_strlen(print) + zero; + tmp[0] = '1'; + return (print); +} + +/* +** -go through all the transformation flags needs +** -first the precision +** -then if type is int and nbr is positive, add a + to the left, it's flag '+' +** -third the flag "#" +** -fourth, the width +** -then p +** -the case of 'p' is treated without any subtelness because i don't care +*/ + +char *ft_flag_transform(char *s, char *print, char *type, int *size) +{ + print = ft_precision(s, print, type); + print = ft_plus(s, print, type); + print = ft_sharp(s, print, type); + if (ft_strchr(type, 'p')) + { + print = ft_concat_free(ft_strdup("0x"), print); + *size += 2; + } + print = ft_width(s, print, size, type); + print = ft_sharp_again(s, print, type); + print = ft_space(s, print, type, size); + return (print); +} diff --git a/srcs/ft_printf_files/ft_flag_transform_bonus.c b/srcs/ft_printf_files/ft_flag_transform_bonus.c new file mode 100644 index 0000000..f6d773a --- /dev/null +++ b/srcs/ft_printf_files/ft_flag_transform_bonus.c @@ -0,0 +1,75 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_flag_transform_bonus.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: hulamy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/03/12 22:30:50 by hulamy #+# #+# */ +/* Updated: 2020/03/12 22:30:57 by hulamy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_plus(char *s, char *print, char *type) +{ + if (!ft_strchrset(type, "di")) + return (print); + if (ft_strchr(s, '+') && !ft_strchr(print, '-')) + print = ft_concat_free(ft_strdup("+"), print); + return (print); +} + +char *ft_sharp(char *s, char *print, char *type) +{ + if (ft_strchr(s, '#')) + { + if (ft_strchr(type, 'x')) + print = ft_concat_free(ft_strdup("0x"), print); + else + print = ft_concat_free(ft_strdup("0X"), print); + } + return (print); +} + +char *ft_sharp_again(char *s, char *print, char *type) +{ + char *tmp; + + if (!ft_strchr(s, '#')) + return (print); + if (print[0] == '0' && print[1] == '0' && ft_strchrset(type, "xX")) + { + tmp = ft_strchrset("xX", print); + print[1] = tmp[0]; + tmp[0] = '0'; + } + return (print); +} + +char *ft_space(char *s, char *print, char *type, int *size) +{ + int i; + + i = 0; + if (print[0] == ' ' || !ft_strchr(s, ' ') || !ft_strchrset(type, "diuxX")) + return (print); + while (print[i] == ' ') + i++; + if (print[i] == '-' || print[i] == '+') + return (print); + if (ft_strchr(s, '.') || (i == 0 && print[i] != '0')) + { + print = ft_concat_free(ft_strdup(" "), print); + *size += 1; + } + else + print[i] = ' '; + if (ft_strchr(s, '-') && print[*size - 1] == ' ') + { + print[*size] = '\0'; + *size -= 1; + } + return (print); +} diff --git a/srcs/ft_printf_files/ft_next_word.c b/srcs/ft_printf_files/ft_next_word.c new file mode 100644 index 0000000..6980aac --- /dev/null +++ b/srcs/ft_printf_files/ft_next_word.c @@ -0,0 +1,98 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* next_word.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: hulamy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/02/10 13:58:30 by hulamy #+# #+# */ +/* Updated: 2020/02/26 18:24:04 by hulamy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* +** -placed outside of "word_length" for lake of space +** -check if there is a '*' or a number +** -usefull as such for the 'width', and after a check +** for a '.' for the 'precision' flag +*/ + +int width_precision(char *s) +{ + int i; + + i = 0; + if (ft_strchr("*", s[i]) != NULL) + i++; + while (ft_strchr("0123456789", s[i]) != NULL) + i++; + return (i); +} + +/* +** -return the length of the next word to print +** -for that it got through the characters expecting +** in the following order : +** [%][flags][width][.precision][length][specifier] +** knowing that 'flags' can repeat themselves +** -a single '%' is treated as a word of length 1 +** (unlike the real printf) +** -it's written : +** i += width_precision(s + i + 1) + 1; +** instead of : +** i++; +** i += width_precision(s + i); +** to save a line (3 with the brackets) +*/ + +int word_length(char *s) +{ + int i; + + i = 1; + if (s[0] == '\0') + return (0); + if (s[0] != '%') + { + while (s[i] != '%' && s[i] != '\0') + i++; + return (i); + } + while (ft_strchr("#0- +'", s[i]) != NULL) + i++; + i += width_precision(s + i); + if (ft_strchr(".", s[i]) != NULL) + i += width_precision(s + i + 1) + 1; + while (ft_strchr("hl", s[i]) != NULL) + i++; + if (ft_strchr("diuxXcspefgn%", s[i]) != NULL) + i++; + return (i); +} + +/* +** -return the next sequence to be print +** (either a string, or a conversion) +** -a single '%' is an error in real printf +** but is treated as a '%' here +*/ + +char *next_word(char **string) +{ + char *s; + char *word; + int i; + + s = *string; + if (*s == '\0') + return (NULL); + if ((i = word_length(s)) < 0) + return (NULL); + word = (char *)malloc(sizeof(char) * (i + 1)); + word[i] = '\0'; + ft_memmove(word, s, i); + *string += i; + return (word); +} diff --git a/srcs/ft_printf_files/ft_printf.c b/srcs/ft_printf_files/ft_printf.c new file mode 100644 index 0000000..d96f663 --- /dev/null +++ b/srcs/ft_printf_files/ft_printf.c @@ -0,0 +1,162 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_printf.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: hulamy +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/03/12 22:31:29 by hulamy #+# #+# */ +/* Updated: 2020/06/30 00:41:35 by hulamy ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* +** SPECIFIER : +** receive a word as a string, check if it start by '%', and return the +** specifier (diuxXspefgn) and the length (h hh l ll) +** -if s is a string, or is a single '%' +** return NULL (to print is as a string) +** -if s is a double '%%', remove one '%', and +** return NULL (to print is as a string) +** -then s is a conversion, go to the length and specifier +** -copy them in 'string' +** -and remove them from s +** -return the length and specifier in a string +*/ + +char *specifier(char *s) +{ + char *string; + int i; + + if (s[0] != '%' || s[1] == '\0') + return (NULL); + if (s[1] == '%') + { + s[1] = '\0'; + return (NULL); + } + i = 1; + while (ft_strchr("#0- +'0123456789.*", s[i]) != NULL) + i++; + string = ft_strdup(s + i); + while (s[i] != '\0') + { + s[i] = '\0'; + i++; + } + return (string); +} + +/* +** -receive 'i' the number in which '*' will expand +** -turn it into a string +** -calculate the total lentgh of the string '%...' for nbr replacing '*' +** -allocate a new string with this length +** -copy the original str with first '*' expanded into it's corresponding nbr +*/ + +int ft_expand_star(int nbr, char **string) +{ + char *s; + char *n; + int i; + int j; + int k; + + n = ft_itoa(nbr); + if (!(s = ft_memalloc(sizeof(char) * (ft_strlen(n) + ft_strlen(*string))))) + return (0); + i = -1; + j = 0; + k = 0; + while ((*string)[++i] != '\0') + { + s[j] = (*string)[i]; + if (s[j] == '*') + while (n[k] != '\0') + s[j++] = n[k++]; + else + j++; + } + free(n); + free(*string); + *string = s; + return (1); +} + +/* +** print the string +** because of lake of space, it also free 'type' +*/ + +int ft_put_word(char *s, char *type, int size) +{ + int i; + + i = 0; + while (i < size) + write(1, &(s[i++]), 1); + free(type); + free(s); + return (i); +} + +/* +** because of lake of space... +** -1 expand the specifier according to its type and its length +** and put in a string 'print' +** -2 transform 'print' according to the flags +*/ + +char *convert_with_flags(char *s, va_list ap, char *type, int *size) +{ + char *print; + + if (!(print = ft_convert(ap, type, &s))) + return (NULL); + if (!(print = ft_flag_transform(s, print, type, size))) + return (NULL); + free(s); + return (print); +} + +/* +** -printf receive a string to print with a variadic number of arguments +** -it will go in a loop through each 'words' +** -a word is either a string containing no '%' or a conversion starting by '%' +** -if it's a string it's printed right away +** -if it's a conversion it will call convert_with_flags for some actions : +** -1 expand the specifier according to its type and its length +** and put in a string 'print' +** -2 transform 'print' according to the flags +*/ + +int ft_printf(char *string, ...) +{ + char *s; + char *type; + int length; + int size; + va_list ap; + + length = 0; + va_start(ap, string); + while ((s = next_word(&string)) != NULL) + { + if ((type = specifier(s)) == NULL) + length += ft_put_word(s, type, ft_strlen(s)); + else + { + size = 0; + if (!(s = convert_with_flags(s, ap, type, &size))) + return (-1); + length += ft_put_word(s, type, size); + } + } + free(s); + va_end(ap); + return (length); +}