mirror of
https://codeberg.org/la-chouette/minishell.git
synced 2025-12-06 07:28:09 +01:00
133 lines
3.6 KiB
C
133 lines
3.6 KiB
C
|
|
/* ************************************************************************** */
|
||
|
|
/* */
|
||
|
|
/* ::: :::::::: */
|
||
|
|
/* ft_printf_parsing.c :+: :+: :+: */
|
||
|
|
/* +:+ +:+ +:+ */
|
||
|
|
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
|
||
|
|
/* +#+#+#+#+#+ +#+ */
|
||
|
|
/* 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);
|
||
|
|
}
|