/* */
/* ************************************************************************** */
-#include <stdlib.h> // malloc, free
-#include <stdarg.h> // va_*
+#include <stdlib.h> // malloc, free
+#include <stdarg.h> // va_*
#include <unistd.h> // write
#include "libft.h"
return (len);
}
-typedef struct s_flags
+typedef struct s_flags
{
int alt_mode;
int zero_pad;
int sign_show;
} t_flags;
-typedef struct s_conv
+typedef struct s_conv
{
t_flags flags;
int minwidth;
flags.zero_pad = 0;
flags.left_adjust = 0;
flags.sign_allign = 0;
- flags.sign_show = 0;
+ flags.sign_show = 0;
while (1)
{
if (**format == '#')
return (1);
}
+intptr_t ft_abs(intptr_t n)
+{
+ if (n < 0)
+ return (-n);
+ else
+ return (n);
+}
char *ft_itoa_base(intptr_t n, const char *base)
{
int size;
- size_t base_len;
+ int base_len;
char *res;
if (!valid_base(base))
res[size--] = '\0';
while (n != 0)
{
- res[size--] = base[abs(n % base_len)];
+ res[size--] = base[ft_abs(n % base_len)];
n /= base_len;
}
return (res);
return (conv);
}
-typedef struct s_printed
+typedef struct s_to_print
{
char *left_pad;
char sign;
char *zero_pad;
char *main_part;
char *right_pad;
-} t_printed;
+} t_to_print;
char *create_alt(t_conv conv)
{
if (conv.type == 'p')
return (ft_strdup("0x"));
- else if (conv.flag.alt_mode)
+ else if (conv.flags.alt_mode)
{
if (conv.type == 'o')
return (ft_strdup("0"));
void create_main(char *str, t_conv conv, t_to_print *tp)
{
- if (conv.type == 'd' || conv.type == 'i')
+ if (conv.type == 'd' || conv.type == 'i')
{
if (*str == '-')
{
}
else
{
- tp->main_part = ft_strfup(str);
+ tp->main_part = ft_strdup(str);
if (conv.flags.sign_show)
tp->sign = '+';
else if (conv.flags.sign_allign)
tp->sign = ' ';
}
}
- else if (conv.type == 's' && conv.prec < ft_strlen(str))
+ else if (conv.type == 's'
+ && (size_t)conv.prec < ft_strlen(str) && conv.prec >= 0)
+ tp->main_part = ft_strndup(str, conv.prec);
+ else
+ tp->main_part = ft_strdup(str);
+ return ;
+}
+
+void init_printed(t_to_print *tp)
+{
+ tp->left_pad = NULL;
+ tp->sign = '\0';
+ tp->zero_pad = NULL;
+ tp->main_part = NULL;
+ tp->right_pad = NULL;
+ return ;
+}
+
+char *rep_char(char c, int n)
+{
+ char *res;
+
+ if (n < 0)
+ n = 0;
+ res = malloc(++n);
+ if (res == NULL)
+ return (res);
+ res[--n] = '\0';
+ while (n > 0)
+ res[--n] = c;
+ return (res);
+}
+
+void lengthen_by_zeros(char **str, int n)
+{
+ char *temp;
+ size_t size;
+
+ if (n <= 0)
+ return ;
+ temp = *str;
+ size = ft_strlen(temp) + n + 1;
+ *str = malloc(size);
+ if (*str == NULL)
{
- tp->main_part = malloc((conv.prec + 1) * sizeof(char));
- if (tp.main_part == NULL)
- return ();
- ft_strlcpy(tp->main_part, str, conv.prec + 1);
+ free(temp);
+ return ;
+ }
+ ft_strlcpy(*str, temp, size);
+ free(temp);
+ while (n > 0)
+ (*str)[size - (n--) - 1] = '0';
+ (*str)[size - 1] = '\0';
+ return ;
+}
+
+void create_padding(t_to_print *tp, t_conv conv)
+{
+ size_t len;
+
+ len = ft_strlen(tp->main_part);
+ tp->zero_pad = rep_char('0', conv.prec - len);
+ len += ft_strlen(tp->zero_pad) + ft_strlen(tp->alt) + (tp->sign != '\0');
+ if (conv.flags.left_adjust)
+ {
+ tp->right_pad = rep_char(' ', conv.minwidth - len);
+ tp->left_pad = ft_strdup("");
}
else
- tp->main_part = ft_strdup(str);
- return ();
+ {
+ tp->right_pad = ft_strdup("");
+ if (!conv.flags.zero_pad || conv.type == 's')
+ tp->left_pad = rep_char(' ', conv.minwidth - len);
+ else if (conv.flags.zero_pad)
+ {
+ tp->left_pad = ft_strdup("");
+ lengthen_by_zeros(&(tp->zero_pad), conv.minwidth - len);
+ }
+ }
+ return ;
}
-t_printed formated(char *str, t_conv conv)
+t_to_print formated(char *str, t_conv conv)
{
t_to_print res;
init_printed(&res);
create_main(str, conv, &res);
res.alt = create_alt(conv);
-
+ create_padding(&res, conv);
+ return (res);
+}
+
+int valid_toprint(t_to_print tp)
+{
+ return (tp.left_pad && tp.zero_pad && tp.main_part && tp.right_pad);
+}
+
+size_t to_print_len(t_to_print tp)
+{
+ size_t len;
+
+ len = 0;
+ len += ft_strlen(tp.left_pad);
+ len += (tp.sign != '\0');
+ len += ft_strlen(tp.alt);
+ len += ft_strlen(tp.zero_pad);
+ len += ft_strlen(tp.main_part);
+ len += ft_strlen(tp.right_pad);
+ return (len);
}
int handle_conversion(const char **format, va_list *args)
{
t_conv conv;
- char *str;
- int len;
+ char *temp;
t_to_print to_print;
++(*format);
ft_putstr_fd(to_print.alt, 1);
ft_putstr_fd(to_print.main_part, 1);
ft_putstr_fd(to_print.right_pad, 1);
- return (len);
+ return (to_print_len(to_print));
}
int ft_printf(const char *format, ...)
va_list args;
int res;
+ res = 0;
va_start(args, format);
while (*format)
{
res += print_ordinary(&format);
if (!*format)
- break;
+ break ;
res += handle_conversion(&format, &args);
}
va_end(args);