/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* ft_printf_parsing.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: jguelen +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/11/18 10:38:17 by jguelen #+# #+# */ /* Updated: 2025/02/04 10:04:05 by jguelen ### ########.fr */ /* */ /* ************************************************************************** */ #include "ft_printf.h" static t_printf_flags ft_get_flag(char c) { if (c == '0') return (PRINTF_ZEROFLAG); if (c == '-') return (PRINTF_MINUSFLAG); if (c == '#') return (PRINTF_HASHTAGFLAG); if (c == '+') return (PRINTF_PLUSFLAG); if (c == ' ') return (PRINTF_SPACEFLAG); return (PRINTF_NOFLAG); } static t_printf_spec ft_get_spec(char c) { if (c == 'c') return (PRINTF_CHARSPEC); if (c == 's') return (PRINTF_STRINGSPEC); if (c == 'p') return (PRINTF_POINTERSPEC); if (c == 'd' || c == 'i') return (PRINTF_INTSPEC); if (c == 'u') return (PRINTF_UINTSPEC); if (c == 'x') return (PRINTF_HEXA_LOWSPEC); if (c == 'X') return (PRINTF_HEXA_UPSPEC); if (c == '%') return (PRINTF_PERCENTSPEC); return (PRINTF_NOSPEC); } static t_printf_var ft_get_var(t_printf_spec specifier, va_list *arg_list, char c) { t_printf_var var; ft_bzero(&var, sizeof(t_printf_var)); if (specifier == PRINTF_CHARSPEC) var.c = (char)va_arg(*arg_list, int); else if (specifier == PRINTF_STRINGSPEC) var.s = va_arg(*arg_list, char *); else if (specifier == PRINTF_POINTERSPEC) var.p = va_arg(*arg_list, void *); else if (specifier == PRINTF_INTSPEC) var.i = va_arg(*arg_list, int); else if (specifier == PRINTF_UINTSPEC || specifier == PRINTF_HEXA_LOWSPEC || specifier == PRINTF_HEXA_UPSPEC) var.u = va_arg(*arg_list, unsigned int); else var.c = c; return (var); } /*PRINTF_ZEROFLAG only for numerical conv*/ static void ft_getprintf_format(char **s, t_printf_format *format, va_list *arg_list) { char *tmp; tmp = (char *)*s; while (*tmp && ft_strchr(PRINTF_FLAGS, *tmp)) format->flags |= ft_get_flag(*tmp++); if (*tmp == '*' && tmp++) format->minwidth = (long)va_arg(*arg_list, int); else if (ft_isdigit(*tmp)) format->minwidth = ft_printf_atoi(tmp, &tmp); if (*tmp == '.' && tmp++) { format->flags = (format->flags | PRINTF_DOTFLAG) & ~PRINTF_ZEROFLAG; if (*tmp == '*' && tmp++) format->precision = (long)va_arg(*arg_list, int); else if (ft_isdigit(*tmp)) format->precision = ft_printf_atoi(tmp, &tmp); } format->specifier = ft_get_spec(*tmp); if (*tmp) { format->var = ft_get_var(format->specifier, arg_list, *tmp); *s = tmp + 1; } format->total_len = var_len(format); get_prefix_format(format); } int ft_printf_parsing(int fd, char *s, t_printf_format *format, va_list *arg_list) { int len; int i; len = 0; while (*s) { i = 0; while (s[i] && s[i] != '%') i++; i = write(fd, s, i); if (i == -1) return (-1); s += i; len += i; if (*s == '%' && s++) { ft_bzero(format, sizeof(t_printf_format)); ft_getprintf_format(&s, format, arg_list); i = ft_print_printf_format(fd, format); if (((INT_MAX - len) < format->total_len) || (i == -1)) return (-1); len += format->total_len; } } return (len); }