]> Untitled Git - axy/ft/ft_printf.git/commitdiff
Partial printf parsing impl
author= <=>
Wed, 29 Oct 2025 17:45:34 +0000 (18:45 +0100)
committer= <=>
Wed, 29 Oct 2025 17:45:34 +0000 (18:45 +0100)
Makefile [new file with mode: 0644]
ft_printf.c [new file with mode: 0644]
libftprintf.h [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..4711819
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,27 @@
+NAME=libftprintf.a
+
+SRCS=
+
+OBJS=${SRCS:.c=.o}
+
+CFLAGS=-Wall -Wextra -Werror
+
+CC=cc
+
+all : ${NAME}
+
+%.o : %.c
+       ${CC} ${CFLAGS} -c -o $@ -- $<
+
+${NAME} : ${OBJS}
+       ar -rcs $@ $^
+
+clean : 
+       rm -f ${OBJS} ${BONUS_OBJS}
+
+fclean : clean
+       rm -f ${NAME}
+
+re : fclean all
+
+.PHONY : all clean fclean re
diff --git a/ft_printf.c b/ft_printf.c
new file mode 100644 (file)
index 0000000..3e2d923
--- /dev/null
@@ -0,0 +1,218 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   ft_printf.c                                        :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: agilliar <marvin@42.fr>                    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2025/10/29 14:24:47 by agilliar          #+#    #+#             */
+/*   Updated: 2025/10/29 18:45:02 by agilliar         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+/*
+       Because of variadic argument promotion, we represent an expected char as an int
+*/
+typedef enum e_step
+{
+       STEP_INT,
+       STEP_UNSIGNED,
+       STEP_PTR,
+       STEP_NONE,
+}      t_step;
+
+/*
+       Ditto for t_step
+*/
+typedef union u_step_arg
+{
+       int                     v_int;
+       unsigned        v_uint;
+       void            *v_ptr;
+}      t_step_arg;
+
+typedef enum e_sign_flag
+{
+       SIGN_NEG_ONLY,
+       SIGN_FORCED,
+       SIGN_SPACE,
+}      t_sign_flag;
+
+typedef enum e_justify
+{
+       JUSTIFY_LEFT,
+       JUSTIFY_RIGHT,
+}      t_justify;
+
+typedef enum e_padding_type
+{
+       PADDING_SPACE,
+       PADDING_ZEROS,
+}      t_padding_type;
+
+typedef enum e_specifier
+{
+       SPECIFIER_NONE,
+       SPECIFIER_CHAR,
+       SPECIFIER_STRING,
+       SPECIFIER_VOID_PTR,
+       SPECIFIER_INT,
+       SPECIFIER_UNSIGNED,
+       SPECIFIER_INT_HEX_LOWER,
+       SPECIFIER_INT_HEX_UPPER,
+       SPECIFIER_PERCENT,
+}      t_specifier;
+
+typedef enum e_num_prefix
+{
+       NUM_PREFIX_NONE,
+       NUM_PREFIX_FORMAT;
+}      t_num_prefix;
+
+typedef struct s_format
+{
+       t_specifier             specifier;
+       t_sign_flag             sign_flag;
+       t_justify               justify;
+       t_num_prefix    num_prefix;
+       size_t                  width;
+       s_padding_type  padding_type;
+       size_t                  precision;
+       bool                    enable_precision;
+}      t_format;
+
+int    ft_putformat(const t_format *format, t_step_arg arg);
+
+t_format       ft_format_default(void)
+{
+       t_format        res;
+
+       res.specifier = SPECIFIER_NONE;
+       res.sign_flag = SIGN_NEG_ONLY;
+       res.justify = JUSTIFY_RIGHT;
+       res.num_prefix = NUM_PREFIX_NONE;
+       res.width = 0;
+       res.padding_type PADDING_SPACE;
+       res.precision = 0;
+       res.enable_precision = false;
+       return (res);
+}
+
+size_t ft_parse_num(const char **s)
+{
+       size_t  res;
+
+       res = 0;
+       while (**s >= '0' && **s <= '9')
+               res = res * 10 + '0' - *((*s)++);
+       return (res);
+}
+
+bool   ft_parse_flag(char c, t_format *format)
+{
+       if (c == '-')
+               format->justify = JUSTIFY_LEFT;
+       else if (c == '+')
+               format->sign_flag = SIGN_FORCED;
+       else if (c == ' ')
+               format->sign_flag = SIGN_SPACE;
+       else if (c == '#')
+               format->num_prefix = NUM_PREFIX_FORMAT;
+       else if (c == '0')
+               format->padding_type = PADDING_ZEROS;
+}
+
+t_specifier    ft_parse_specifier(char c)
+{
+       if (c == 'c')
+               return (SPECIFIER_CHAR);
+       if (c == 's')
+               return (SPECIFIER_STRING);
+       if (c == 'p')
+               return (SPECIFIER_VOID_PTR);
+       if (c == 'd' || c == 'i')
+               return (SPECIFIER_INT);
+       if (c == 'u')
+               return (SPECIFIER_UNSIGNED);
+       if (c == 'x')
+               return (SPECIFIER_INT_HEX_LOWER);
+       if (c == 'X')
+               return (SPECIFIER_INT_HEX_UPPER);
+       if (c == '%')
+               return (SPECIFIER_PERCENT);
+       return (SPECIFIER_NONE);
+}
+
+t_format ft_parse_format(const char **format)
+{
+       t_format        res;
+
+       res = ft_format_default();
+       while (ft_parse_flag(**format, &res))
+               format++;
+       res.specifier = ft_parse_specifier(*((*format)++));
+       return (res);
+}
+
+int    ft_print_step(const char **format, t_format *step, t_step_arg arg)
+{
+       int     written;
+
+       if (step->specifier == SPECIFIER_NONE && **format != '%')
+       {
+               if (write(STDOUT_FILENO, (*format)++, 1) != 1)
+                       return (-1);
+               return (1);
+       }
+       if (step->specifier != SPECIFIER_NONE)
+       {
+               written = ft_putformat(step, arg);
+               *step = ft_format_default();
+               return (written);
+       }
+       *step = ft_parse_format(format);
+       return (0);
+}
+
+t_step specifier_to_step(t_specifier spec)
+{
+       if (spec == SPECIFIER_NONE || spec == SPECIFIER_PERCENT)
+               return (STEP_NONE);
+       if (spec == SPECIFIER_STRING || spec == SPECIFIER_VOID_PTR)
+               return (STEP_PTR);
+       if (spec == SPECIFIER_UNSIGNED)
+               return (STEP_UNSIGNED);
+       return (STEP_INT);
+}
+
+int    ft_printf(const char *format, ...)
+{
+       va_list         args;
+       int                     count;
+       int                     written;
+       t_format        step;
+       t_step_arg      arg;
+
+       va_start(args, format);
+       count = 0;
+       step.specifier = SPECIFIER_NONE;
+       while (*format)
+       {
+               written = ft_print_step(&format, &step, arg);
+               if (written < 0)
+                       return (written);
+               count += written;
+               if (specifier_to_step(step.specifier) == STEP_INT)
+                       arg.v_int = va_arg(args, int);
+               if (specifier_to_step(step.specifier) == STEP_UNSIGNED)
+                       arg.v_uint = va_arg(args, unsigned);
+               if (specifier_to_step(step.specifier) == STEP_PTR)
+                       arg.v_ptr = va_arg(args, void *);
+       }
+       return (count);
+}
diff --git a/libftprintf.h b/libftprintf.h
new file mode 100644 (file)
index 0000000..a51f240
--- /dev/null
@@ -0,0 +1,18 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   libftprintf.h                                      :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: agilliar <marvin@42.fr>                    +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2025/10/29 14:21:01 by agilliar          #+#    #+#             */
+/*   Updated: 2025/10/29 14:22:40 by agilliar         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#ifndef LIBFTPRINTF_H
+# define LIBFTPRINTF_H
+
+int    ft_printf(const char *format, ...);
+
+#endif