basic functions to make

This commit is contained in:
mcolonna 2024-04-23 14:52:17 +02:00
parent 1a34e2f64b
commit a0ad80a375
52 changed files with 2964 additions and 3 deletions

View file

@ -0,0 +1,57 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* conversions.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/11 16:45:39 by mcolonna #+# #+# */
/* Updated: 2024/02/12 13:31:08 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef CONVERSIONS_H
# define CONVERSIONS_H
# include <stdlib.h>
# include <stdarg.h>
// Does a specific conversion.
// - flags: the flags of the conversion
// - args: the args given to ft_printf
// Return the number of chars written.
// ERROR: returns -1.
typedef int (t_put_function)(va_list args);
// Represents a possible conversion.
// Ex: {'c', &put_char} is the conversion to write a char.
// .name: Code to identify the conversion
// 'c' would mean you have to use it with "%c"
// .put_function: Function called with the argument to write the data.
// - flags: The flags to modify the way the content is wrote.
// - content: The arguments of printf.
// Returned value: The number of chars wrote, -1 if error.
typedef struct s_conversion
{
char name;
t_put_function *put_function;
} t_conversion;
// 'c' conversion.
int put_char(va_list args);
// 's' conversion.
int put_str(va_list args);
// '%' conversion.
int put_percent(va_list args);
// 'd' and 'i' conversions (it's the same).
int put_decimal(va_list args);
// 'u' conversion.
int put_unsigned(va_list args);
// 'x' conversion.
int put_hex_lower(va_list args);
// 'X' conversion.
int put_hex_upper(va_list args);
// 'p' conversion.
int put_pointer(va_list args);
#endif

View file

@ -0,0 +1,25 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* do_conversion.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/13 14:25:00 by mcolonna #+# #+# */
/* Updated: 2023/11/20 15:19:10 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef DO_CONVERSION_H
# define DO_CONVERSION_H
# include <stdarg.h>
// Do a conversion specified by its name.
// - args: arguments given to ft_printf()
// - name: name of the conversion
// Returns the number of chars written.
// ERROR: returns -1.
int do_conversion(va_list args, char name);
#endif

View file

@ -0,0 +1,38 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* stream.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/26 18:11:25 by mcolonna #+# #+# */
/* Updated: 2024/02/12 13:27:20 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef STREAM_H
# define STREAM_H
// Represents a stream.
// Allows to read a string char by char and remembering the position.
typedef struct s_stream_2
{
const char *str;
int i;
} t_stream_2;
// Return a new malloced t_stream_2 pointer, or NULL if malloc error.
t_stream_2 *stream_2_new(const char *str);
// Get the current char of the stream, '\0' if the string is finished.
char stream_2_getchar(t_stream_2 *stream);
// Goes to the next char (never after a '\0').
// Returns 1 if it isn't the end, or else 0.
int stream_2_next(t_stream_2 *stream);
// Returns 1 if it isn't the end, or else 0.
int stream_2_continues(t_stream_2 *stream);
// Skip 'n' chars.
void stream_2_skip(t_stream_2 *stream, int n);
// Return a pointer to the current char.
char *stream_2_pointer(t_stream_2 *stream);
#endif

View file

@ -0,0 +1,18 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* tf_printf.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/16 16:50:23 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:35:21 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef TF_PRINTF_H
# define TF_PRINTF_H
int tf_printf(const char *format, ...);
#endif

View file

@ -0,0 +1,36 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* utils.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/13 14:31:39 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:57:29 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef UTILS_H
# define UTILS_H
# include "stream.h"
char *ft_strjoin(char const *s1, char const *s2);
// Cast an int to a string (0 or /[1-9][0-9]*/).
// - n: number
char *ft_itoa(int n);
// Cast an unsigned int to a string (0 or /-?[1-9][0-9]*/).
// - n: number
char *ft_utoa(unsigned int n);
// Cast an unsigned int to a string in a specified base.
// - n: number
// - base: base chars (example: "01233456789abcdef")
char *ft_utoa_base(unsigned long n, const char *base);
// atoi for a stream.
unsigned int stream_atoi(t_stream_2 *stream);
#endif

View file

@ -0,0 +1,72 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* conversions1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/11 16:53:07 by mcolonna #+# #+# */
/* Updated: 2024/02/12 13:25:57 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "conversions.h"
#include "utils.h"
#include "libtf.h"
#include <unistd.h>
int put_char(va_list args)
{
const char c = va_arg(args, int);
write(1, &c, 1);
return (1);
}
int put_str(va_list args)
{
char *str;
str = va_arg(args, char *);
if (!str)
str = "(null)";
write(1, str, str_len(str));
return (str_len(str));
}
int put_percent(va_list args)
{
(void)args;
write(1, "%", 1);
return (1);
}
int put_decimal(va_list args)
{
char *str;
int r;
int arg;
arg = va_arg(args, int);
str = ft_itoa(arg);
if (!str)
return (-1);
write(1, str, str_len(str));
r = str_len(str);
free(str);
return (r);
}
int put_unsigned(va_list args)
{
char *str;
int r;
str = ft_utoa(va_arg(args, unsigned int));
if (!str)
return (-1);
write(1, str, str_len(str));
r = str_len(str);
free(str);
return (r);
}

View file

@ -0,0 +1,68 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* conversions2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/18 13:21:09 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:58:11 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "conversions.h"
#include "utils.h"
#include "libtf.h"
#include <unistd.h>
int put_hex_lower(va_list args)
{
char *str;
int r;
r = 0;
str = ft_utoa_base(va_arg(args, unsigned int), "0123456789abcdef");
if (!str)
return (-1);
write(1, str, str_len(str));
r += str_len(str);
free(str);
return (r);
}
int put_hex_upper(va_list args)
{
char *str;
int r;
r = 0;
str = ft_utoa_base(va_arg(args, unsigned int), "0123456789ABCDEF");
if (!str)
return (-1);
write(1, str, str_len(str));
r += str_len(str);
free(str);
return (r);
}
int put_pointer(va_list args)
{
void *arg;
char *str;
int r;
arg = va_arg(args, void *);
if (!arg)
{
write(1, "(nil)", 5);
return (5);
}
write(1, "0x", 2);
str = ft_utoa_base((unsigned long)arg, "0123456789abcdef");
if (!str)
return (-1);
write(1, str, str_len(str));
r = 2 + str_len(str);
free(str);
return (r);
}

View file

@ -0,0 +1,40 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* do_conversion.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/13 14:14:36 by mcolonna #+# #+# */
/* Updated: 2024/02/12 13:30:36 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "do_conversion.h"
#include "conversions.h"
int do_conversion(va_list args, char name)
{
static const t_conversion conversions[] = {
{'c', &put_char},
{'s', &put_str},
{'%', &put_percent},
{'d', &put_decimal},
{'i', &put_decimal},
{'u', &put_unsigned},
{'x', &put_hex_lower},
{'X', &put_hex_upper},
{'p', &put_pointer},
{'\0', NULL}
};
int i;
i = 0;
while (conversions[i].name)
{
if (conversions[i].name == name)
return (conversions[i].put_function(args));
i++;
}
return (-1);
}

View file

@ -0,0 +1,66 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_itoa.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/03 13:51:10 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:13:37 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdlib.h>
static char get_digit_at(long pos_n, int i, int nb_len)
{
int w;
long ten_power;
w = nb_len - i - 1;
ten_power = 1;
while (w--)
ten_power *= 10;
return ('0' + pos_n / ten_power % 10);
}
static int get_nb_len(long pos_n)
{
int r;
long ten_powers;
r = 1;
ten_powers = 10;
while (pos_n >= ten_powers)
{
r++;
ten_powers *= 10;
}
return (r);
}
char *ft_itoa(int n)
{
long pos_n;
int sign;
int nb_len;
char *dest;
int i;
sign = (n >= 0) - (n < 0);
pos_n = (long)n * sign;
nb_len = get_nb_len(pos_n);
dest = malloc(((sign == -1) + nb_len + 1) * sizeof(char));
if (!dest)
return (NULL);
i = 0;
if (sign == -1)
dest[i++] = '-';
while (i - (sign == -1) < nb_len)
{
dest[i] = get_digit_at(pos_n, i - (sign == -1), nb_len);
i++;
}
dest[i] = '\0';
return (dest);
}

View file

@ -0,0 +1,42 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ft_strjoin.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/03 11:31:45 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:13:04 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdlib.h>
#include "libtf.h"
char *ft_strjoin(char const *s1, char const *s2)
{
int len;
char *dest;
int i;
int j;
len = str_len(s1) + str_len(s2);
dest = malloc((len + 1) * sizeof(char));
if (!dest)
return (NULL);
i = 0;
while (s1[i])
{
dest[i] = s1[i];
i++;
}
j = 0;
while (s2[j])
{
dest[i] = s2[j];
i++;
j++;
}
dest[i] = '\0';
return (dest);
}

View file

@ -0,0 +1,51 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* stream1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/26 18:15:47 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:05:01 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "stream.h"
#include <stdlib.h>
t_stream_2 *stream_2_new(const char *str)
{
t_stream_2 *r;
r = malloc(sizeof(t_stream_2));
if (!r)
return (NULL);
r->str = str;
r->i = 0;
return (r);
}
char stream_2_getchar(t_stream_2 *stream)
{
return (stream->str[stream->i]);
}
int stream_2_next(t_stream_2 *stream)
{
if (stream_2_continues(stream))
stream->i++;
return (stream_2_continues(stream));
}
int stream_2_continues(t_stream_2 *stream)
{
if (stream_2_getchar(stream))
return (1);
else
return (0);
}
char *stream_2_pointer(t_stream_2 *stream)
{
return ((char *)stream->str + stream->i);
}

View file

@ -0,0 +1,19 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* stream2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/26 18:15:47 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:06:27 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "stream.h"
void stream_2_skip(t_stream_2 *stream, int n)
{
while (n-- && stream_2_continues(stream))
stream_2_next(stream);
}

View file

@ -0,0 +1,71 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* tf_printf.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/11 16:07:21 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:36:08 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "tf_printf.h"
#include "stream.h"
#include "do_conversion.h"
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
// Print the escaped string (with %) from str at i.
// str[i] must be a '%'.
// Return the number of chars wrote.
// Return a negative value if error.
static int print_esc(va_list args, t_stream_2 *stream)
{
int r;
stream_2_next(stream);
r = do_conversion(args, stream_2_getchar(stream));
stream_2_next(stream);
return (r);
}
// Count the number of chars until a '%' or the end of the string.
static int txt_len(const char *str)
{
int i;
i = 0;
while (str[i] && str[i] != '%')
i++;
return (i);
}
int tf_printf(const char *str, ...)
{
va_list args;
t_stream_2 *stream;
int count;
int len;
va_start(args, str);
stream = stream_2_new(str);
if (!stream)
return (-1);
count = 0;
while (stream_2_continues(stream))
{
len = txt_len(stream_2_pointer(stream));
write(1, stream_2_pointer(stream), len);
stream_2_skip(stream, len);
count += len;
if (!stream_2_getchar(stream))
break ;
len = print_esc(args, stream);
if (len == -1)
return (free(stream), -1);
count += len;
}
return (free(stream), count);
}

View file

@ -0,0 +1,85 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* utils1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/20 16:26:46 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:59:05 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "utils.h"
#include "libtf.h"
#include "unistd.h"
#include <stdlib.h>
char *ft_utoa(unsigned int n)
{
char first_digit[2];
char *tmp;
char *r;
if (n >= 1000000000)
first_digit[0] = n / 1000000000 + '0';
else
first_digit[0] = '\0';
first_digit[1] = '\0';
tmp = ft_itoa(n % 1000000000);
if (!tmp)
return (NULL);
r = ft_strjoin(first_digit, tmp);
free(tmp);
return (r);
}
static char get_digit_at(
unsigned long n, int i, int nb_len, const char *base)
{
int w;
long long base_power;
const int base_len = str_len(base);
w = nb_len - i - 1;
base_power = 1;
while (w--)
base_power *= base_len;
return (base[n / base_power % base_len]);
}
static int get_nb_len(unsigned long n, const char *base)
{
int r;
const int base_len = str_len(base);
r = 0;
while (n > 0)
{
n /= (unsigned long long)base_len;
r++;
}
if (r == 0)
r = 1;
return (r);
}
char *ft_utoa_base(unsigned long n, const char *base)
{
int nb_len;
char *dest;
int i;
nb_len = get_nb_len(n, base);
dest = malloc((nb_len + 1) * sizeof(char));
if (!dest)
return (NULL);
i = 0;
while (i < nb_len)
{
dest[i] = get_digit_at(n, i, nb_len, base);
i++;
}
dest[i] = '\0';
return (dest);
}

View file

@ -0,0 +1,43 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* utils2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/20 16:26:46 by mcolonna #+# #+# */
/* Updated: 2024/02/12 12:06:57 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "utils.h"
#include "stream.h"
#include "unistd.h"
#include <stdlib.h>
static int is_in(char c, char *chars)
{
int i;
i = 0;
while (chars[i])
{
if (c == chars[i])
return (1);
i++;
}
return (0);
}
unsigned int stream_2_atoi(t_stream_2 *stream)
{
int r;
r = 0;
while (is_in(stream_2_getchar(stream), "0123456789"))
{
r = r * 10 + (stream_2_getchar(stream) - '0');
stream_2_next(stream);
}
return (r);
}