162 lines
3.5 KiB
C
162 lines
3.5 KiB
C
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* main.c :+: :+: :+: */
|
|
/* +:+ +:+ +:+ */
|
|
/* By: gbaconni@student.42lausanne.ch +#+ +:+ +#+ */
|
|
/* +#+#+#+#+#+ +#+ */
|
|
/* Created: 2022/04/13 06:58:46 by gbaconni #+# #+# */
|
|
/* Updated: 2022/04/29 22:52:28 by gbaconni ### lausanne.ch */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <limits.h>
|
|
|
|
#include "libftprintf/ft_printf.h"
|
|
|
|
int ft_skipchars(const char *s, char *chars)
|
|
{
|
|
int ret;
|
|
int i;
|
|
int hits;
|
|
|
|
ret = 0;
|
|
while (*s != '\0')
|
|
{
|
|
i = 0;
|
|
hits = 0;
|
|
while (chars[i] != '\0')
|
|
hits += (chars[i++] == *s);
|
|
if (hits > 0)
|
|
ret++;
|
|
else
|
|
break ;
|
|
s++;
|
|
}
|
|
return (ret);
|
|
}
|
|
|
|
char *ft_fmtsplit(char **fmt)
|
|
{
|
|
char *format;
|
|
char *start;
|
|
char *end;
|
|
int len;
|
|
|
|
format = NULL;
|
|
start = *fmt;
|
|
end = *fmt;
|
|
if (start == NULL)
|
|
return (NULL);
|
|
if (*end == '%')
|
|
if (*end++ == '%')
|
|
end++;
|
|
while (*end != '\0' && *end != '%')
|
|
end++;
|
|
len = end - start;
|
|
format = (char *) calloc(len + 1, sizeof(char));
|
|
if (format == NULL)
|
|
return (NULL);
|
|
strncpy(format, start, len);
|
|
if (*end == '\0')
|
|
*fmt = NULL;
|
|
else
|
|
*fmt += len;
|
|
return (format);
|
|
}
|
|
|
|
int _printf(int (*f)(const char *restrict, ...), \
|
|
char *format, char *arg)
|
|
{
|
|
int ret;
|
|
char c;
|
|
|
|
ret = 0;
|
|
if (arg == NULL)
|
|
return (ret);
|
|
c = *(format + 1 + ft_skipchars(format + 1, "0123456789# +"));
|
|
if (c == 'c')
|
|
ret = (*f)(format, *arg);
|
|
else if (c == 's')
|
|
ret = (*f)(format, arg);
|
|
else if (c == 'p')
|
|
ret = (*f)(format, (arg)? &arg: NULL);
|
|
else if (c == 'x' || c == 'X')
|
|
ret = (*f)(format, atol(arg));
|
|
else if (c == 'd' || c == 'i' || c == 'u')
|
|
ret = (*f)(format, atoi(arg));
|
|
else
|
|
ret = (*f)(format);
|
|
return (ret);
|
|
}
|
|
|
|
int _sprintf(int (*f)(const char *restrict, ...), \
|
|
char *str, char *format, char *arg)
|
|
{
|
|
int ret;
|
|
char c;
|
|
int fd[3];
|
|
|
|
ret = 0;
|
|
setbuf(stdout, NULL);
|
|
pipe(fd);
|
|
fd[2] = dup(STDOUT_FILENO);
|
|
dup2(fd[1], STDOUT_FILENO);
|
|
ret = _printf((*f), format, arg);
|
|
dup2(fd[2], STDOUT_FILENO);
|
|
fflush(stdout);
|
|
close(fd[1]);
|
|
while (read(fd[0], &c, 1) > 0)
|
|
*str++ = c;
|
|
*str = '\0';
|
|
close(fd[0]);
|
|
return (ret);
|
|
}
|
|
|
|
int assert_printf(char *format, char *arg)
|
|
{
|
|
int ret;
|
|
int ft_ret;
|
|
char out[256];
|
|
char ft_out[256];
|
|
|
|
if (arg == NULL || strcmp(arg, "") == 0)
|
|
arg = NULL;
|
|
ret = _sprintf(printf, out, format, arg);
|
|
printf("%d = printf(\"%s\", '%s')\n%s\n", ret, format, arg, out);
|
|
ft_ret = _sprintf(ft_printf, ft_out, format, arg);
|
|
printf("%d = ft_printf(\"%s\", '%s')\n%s\n\n", ft_ret, format, arg, ft_out);
|
|
assert(ret == ft_ret);
|
|
assert(strcmp(out, ft_out) == 0);
|
|
return (!(ret == ft_ret));
|
|
}
|
|
|
|
int main(int args, char *argv[])
|
|
{
|
|
int ret;
|
|
char *fmt;
|
|
char *format;
|
|
char *arg;
|
|
|
|
ret = 0;
|
|
argv++;
|
|
if (--args < 1)
|
|
return (127);
|
|
fmt = *argv++;
|
|
format = ft_fmtsplit(&fmt);
|
|
while (format != NULL)
|
|
{
|
|
if (*format == '%' && *(format + 1) != '%' && --args)
|
|
arg = *argv++;
|
|
else
|
|
arg = NULL;
|
|
ret |= assert_printf(format, arg);
|
|
free(format);
|
|
format = ft_fmtsplit(&fmt);
|
|
}
|
|
return (ret);
|
|
}
|