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

@ -5,15 +5,16 @@ SRCS = src/
# include directory
INCLUDES = include/
# .c files in src/ without the extension
CODE =
CODE = main
# directories to 'make'
LIBRARIES =
LIBRARIES = libtf
# .a files to include
LIBRARIES_FILES =
LIBRARIES_FILES = libtf/libtf.a
# to use with the flags -L and -l
LIBRARIES_LINK =
# to use with the flag -l
LINK =
# flags to add to the compiler
MORE_FLAGS +=
##### END OF THE INTERESTING PART #####

46
include/include.h Normal file
View file

@ -0,0 +1,46 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* include.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/23 14:15:12 by mcolonna #+# #+# */
/* Updated: 2024/04/23 14:54:39 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef INCLUDE_H
# define INCLUDE_H
# include <stdbool.h>
// Represents a call to a program (the program name and its arguments)
typedef struct s_call
{
char *program; // path of the program to call.
int argc; // number of arguments given (including the program's name)
char **argv; // arguments given (including the program's name)
} t_call;
// Represents a command given by the user.
typedef struct s_command
{
bool error; // true means an error occured in interpret_command().
t_call *calls; // all calls to programs.
int input_fd; // fd to use with '<' redirection (0 by default)
int output_fd; // fd to use with '>' redirection (1 by default)
} t_command;
// Show the prompt and ask a command to the user.
// Return the command.
char *ask_command(void);
// Return the t_command representing the command given by the user.
// If error, return a t_command wth the value .error = true.
t_command parse_command(char *command);
// Execute the command given. Return the exit status.
int execute_command(t_command command);
#endif

58
libtf/Makefile Normal file
View file

@ -0,0 +1,58 @@
# The interesting part
NAME = libtf
SRCS = src/
INCLUDES = ./ include/
CODE = \
mem mem_utils str1 str2 str3 str_stream str_char1 \
str_char2 str_stream_more str_streamstr print \
list1 list2 error data read_line read_line_utils
PRINTF_CODE = \
conversions1 conversions2 do_conversion ft_itoa tf_printf \
ft_strjoin stream1 stream2 utils1 utils2
PRINTF_SRCS = tf_printf/src/
PRINTF_INCLUDES = ./ tf_printf/include/
WHAT = LIBTF v9
USED = malloc() free() write()
# It works and I probably won't change it for the rest of my life
C_FILES = $(addsuffix .c,$(addprefix $(SRCS),$(CODE)))
O_FILES = $(addsuffix .o,$(addprefix $(SRCS),$(CODE)))
PRINTF_C_FILES = $(addsuffix .c,$(addprefix $(PRINTF_SRCS),$(PRINTF_CODE)))
PRINTF_O_FILES = $(addsuffix .o,$(addprefix $(PRINTF_SRCS),$(PRINTF_CODE)))
ifdef DEBUG
CC = cc -Wall -Wextra -Werror -g
FINISH_MSG = "| $(WHAT) compiled! (debug)"
else
CC = cc -Wall -Wextra -Werror
FINISH_MSG = "| $(WHAT) compiled!"
endif
AR = ar rcs
all : $(NAME)
@echo $(FINISH_MSG)
@echo "| Functions used: $(USED)"
debug :
make DEBUG=yes
$(NAME) : $(O_FILES) $(PRINTF_O_FILES)
$(AR) $(addsuffix .a, $(NAME)) $(O_FILES) $(PRINTF_O_FILES)
$(O_FILES) : %.o : %.c
$(CC) $(addprefix -I ,$(INCLUDES)) -c $< -o $@
clean :
rm -f $(O_FILES) $(PRINTF_O_FILES)
fclean : clean
rm -f $(addsuffix .a, $(NAME))
re : fclean all
printf : $(PRINTF_O_FILES)
$(AR) $(addsuffix .a, $(NAME)) $(PRINTF_O_FILES)
$(PRINTF_O_FILES) : %.o : %.c
$(CC) $(addprefix -I ,$(PRINTF_INCLUDES)) -c $< -o $@
.PHONY : all clean fclean re printf

28
libtf/dev/Makefile Normal file
View file

@ -0,0 +1,28 @@
ALL_BASE=mem str print list error str2 data str3 read mem2
ALL_TOTAL=$(ALL_BASE) printf
COMP=cc -Wall -Werror -Wextra -g -I ../
help :
@echo ""
@echo "RULES: all $(ALL_TOTAL)"
@echo ""
../libtf.a :
make -C ../ fclean debug
$(ALL_BASE) : ../libtf.a
$(COMP) -o $@.out $@.c ../libtf.a
printf : ../libtf.a
$(COMP) -o printf.out -Wno-error=format -Wformat=0 printf.c ../libtf.a
all : $(ALL_TOTAL)
clean :
rm $(addsuffix .out,$(ALL_TOTAL))
fclean : clean
.PHONY : help ../libtf.a $(ALL_TOTAL)

24
libtf/dev/data.c Normal file
View file

@ -0,0 +1,24 @@
#include "libtf.h"
#include <stdio.h>
int main()
{
char data1[] = "can't the future just wait?";
data_cpy(data1 + 17, data1 + 22, 4);
printf("can't the future wait wait? = %s\n", data1);
char data2[] = "0123456789";
data_cpy(data2 + 3, data2 + 2, 7);
printf("0122345678 = %s\n", data2);
char data3[] = "0123456789";
data_cpy(data3 + 2, data3 + 3, 7);
printf("0134567899 = %s\n", data3);
char data4[] = "0123456789";
data_cpy(data4 + 2, data4 + 2, 7);
printf("0123456789 = %s\n", data4);
data_cpy(data4 + 2, data4 + 4, 0);
printf("0123456789 = %s\n", data4);
}

14
libtf/dev/error.c Normal file
View file

@ -0,0 +1,14 @@
#include "libtf.h"
#include <stdio.h>
int main(void)
{
printf("(null) = %s\n", err_get());
printf("(null) = %s\n", err_get());
err_remember("msg1");
printf("msg1 = %s\n", err_get());
printf("(null) = %s\n", err_get());
err_remember("msg2");
printf("msg2 = %s\n", err_get());
printf("(null) = %s\n", err_get());
}

55
libtf/dev/list.c Normal file
View file

@ -0,0 +1,55 @@
#include "libtf.h"
#include <stdio.h>
void err(t_const_string msg)
{
printf("error: %s\n", msg);
}
int main()
{
t_memclass mc = mem_newclass(&err);
int tab[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
t_list list = list_createempty(mc);
for (int i = 0; i < 5; i++)
list_add(&err, &list, &tab[i]);
for (int i = 5; i < 10; i++)
list_revadd(&err, &list, &tab[i]);
printf("9 8 7 6 5 0 1 2 3 4 = ");
for (int i = 0; i < 10; i++)
printf("%i ", *(int *)list_get(&err, &list, i));
printf("\n10 = %i\n", list_getsize(&list));
list_rotate(&list);
printf("8 7 6 5 0 1 2 3 4 9 = ");
for (int i = 0; i < 10; i++)
printf("%i ", *(int *)list_get(&err, &list, i));
list_revrotate(&list);
printf("\n9 8 7 6 5 0 1 2 3 4 = ");
for (int i = 0; i < 10; i++)
printf("%i ", *(int *)list_get(&err, &list, i));
printf("\n\n2 index errors:\n");
list_get(&err, &list, -1);
list_get(&err, &list, 10);
printf("10 = %i\n", list_getsize(&list));
printf("\n");
for (int i = 9; i > 4; i--)
{
int value = *(int *)list_pop(&err, &list);
printf("%i = %i\n", i, value);
}
printf("5 = %i\n", list_getsize(&list));
for (int i = 4; i >= 0; i--)
{
int value = *(int *)list_revpop(&err, &list);
printf("%i = %i\n", i, value);
}
printf("0 = %i\n", list_getsize(&list));
printf("\n2 empty list errors:\n");
list_pop(&err, &list);
list_revpop(&err, &list);
mem_freeall(mc);
printf("\nMust have no leaks\n");
}

50
libtf/dev/mem.c Normal file
View file

@ -0,0 +1,50 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* mem.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/18 11:23:58 by mcolonna #+# #+# */
/* Updated: 2024/01/15 14:38:30 by marvin ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
#include <stdio.h>
void err(const char *msg)
{
printf("error: %s\n", msg);
}
int main(void)
{
t_memclass mc1, mc2, mc3;
char *a, *b, *c;
(void)(a); (void)(b); (void)(c);
mc1 = mem_newclass(&err);
mem_freeall(mc1);
mc2 = mem_newclass(&err);
a = mem_alloc(&err, mc2, 2);
mem_freeall(mc2);
mc3 = mem_newclass(&err);
a = mem_alloc(&err, mc3, 2);
b = mem_alloc(&err, mc3, 2);
c = mem_alloc(&err, mc3, 2);
mem_free(b);
b = mem_alloc(&err, mc3, 2);
mem_free(b);
mem_freeall(mc3);
t_memclass mc4;
mc4 = mem_newclass(&err);
a = mem_alloc(&err, mc4, 2);
b = mem_alloc(&err, mc4, 2);
c = mem_alloc(&err, mc4, 2);
mem_free(a);
mem_free(b);
mem_free(c);
mem_freeall(mc4);
}

44
libtf/dev/mem2.c Normal file
View file

@ -0,0 +1,44 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* mem2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/18 11:23:58 by mcolonna #+# #+# */
/* Updated: 2024/03/11 13:44:48 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
#include <stdio.h>
void err(const char *msg)
{
printf("error: %s\n", msg);
}
int main(void)
{
t_memclass mc1, mc2, mc3;
mc1 = mem_newclass(err);
mem_alloc(err, mc1, 4);
mem_alloc(err, mc1, 6);
mc2 = mem_subclass(err, mc1);
mem_alloc(err, mc2, 8);
mc3 = mem_subclass(err, mc2);
mem_alloc(err, mc3, 8);
mem_alloc(err, mc3, 5);
mem_freeall(mc1);
mc1 = mem_newclass(err);
mem_alloc(err, mc1, 4);
mem_alloc(err, mc1, 6);
mc2 = mem_subclass(err, mc1);
mem_alloc(err, mc2, 8);
mc3 = mem_subclass(err, mc2);
mem_alloc(err, mc3, 8);
mem_alloc(err, mc3, 5);
mem_freeall(mc3);
mem_freeall(mc1);
}

7
libtf/dev/print.c Normal file
View file

@ -0,0 +1,7 @@
#include "libtf.h"
int main()
{
print_str(NULL, 1, "Hello ");
print_line(NULL, 1, "World!");
}

105
libtf/dev/printf.c Normal file
View file

@ -0,0 +1,105 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* printf.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/16 17:55:23 by mcolonna #+# #+# */
/* Updated: 2024/02/12 13:03:35 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdio.h>
#include "libtf.h"
#define TEST(...)\
test(printf(__VA_ARGS__)); \
test(tf_printf(__VA_ARGS__)); \
printf("---\n");
void title(const char *str)
{
fflush(stdout);
while (str[0] == '\t')
{
printf(" ");
str = str + 1;
}
printf("\e[3m %s \e[0m\n", str);
fflush(stdout);
}
void test(int r)
{
fflush(stdout);
printf(" (%d)\n", r);
fflush(stdout);
}
int main(void)
{
int p;
void* n = NULL;
title("Basic strings");
TEST("Hello world!");
TEST("he");
TEST("YEYEYEYEYEYEEY");
title("All conversions");
title("\t%c");
TEST("%c", '4');
TEST("%c", '#');
TEST("%c", '\0');
title("\t%s");
TEST("%s", "42");
TEST("%s", "");
TEST("%s", (char *)n);
title("\t%p");
TEST("%p", &p);
TEST("%p", n);
TEST("%p", n - 42);
title("\t%d");
TEST("%d", 42);
TEST("%d", 393820202);
TEST("%d", 0);
TEST("%d", -42);
TEST("%d", -3838383);
title("\t%i");
TEST("%i", 42);
TEST("%i", 393820202);
TEST("%i", 0);
TEST("%i", -42);
TEST("%i", -3838383);
title("\t%u");
TEST("%u", 42);
TEST("%u", 0);
TEST("%u", 3893838);
title("\t%x");
TEST("%x", 42);
TEST("%x", 0);
TEST("%x", 3893838);
title("\t%X");
TEST("%X", 42);
TEST("%X", 0);
TEST("%X", 3893838);
title("\t%%");
TEST("%%");
title("Combinations");
TEST("The %d %s!", 42, "School");
TEST("%d + %d + %d", 1, 1, 3);
TEST("%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
'T', 'h', 'e', ' ',
'4', '2', ' ',
'S', 'c', 'h', 'o', 'o', 'l', '!');
TEST("%c%c = %s = %d = %i", '4', '2', "42", 42, 42);
TEST("%p / %p", &p, n);
TEST("%i = %u = %d = %X = %x", 42, 42, 42, 42, 42);
TEST("%i = %d", -42, -42);
TEST("%d%% < %d%%", 99, 100);
TEST("%c %s %p %d %i %u %x %X %%", '4', "42", n + 42, 42, 42, 42, 42, 42);
TEST("%c %s %p %d %i %u %x %X %%", '\0', (char *)n, n, 0, 0, 0, 0, 0);
}

33
libtf/dev/read.c Normal file
View file

@ -0,0 +1,33 @@
#include "libtf.h"
#define LINE tf_printf("Line: \"%s\"\n", read_line(err, mc, fd))
void err(t_const_string msg)
{
tf_printf("[error: %s]\n", msg);
}
int main()
{
t_memclass mc = mem_newclass(err);
int fd;
tf_printf("2 bad value errors:\n");
fd = -2;
LINE;
fd = 32767;
LINE;
tf_printf("1 file error:\n");
fd = 100;
LINE;
tf_printf("Copy what you say for 5 lines:\n");
fd = 0;
LINE;
LINE;
LINE;
LINE;
LINE;
mem_freeall(mc);
}

86
libtf/dev/str.c Normal file
View file

@ -0,0 +1,86 @@
#include "libtf.h"
#include <stdio.h>
void err(t_const_string msg)
{
printf("error: %s\n", msg);
}
int main()
{
t_memclass mc = mem_newclass(&err);
printf("Must spell 'Hello world!':\n");
t_const_string str = "Hello world!";
t_stream streaaam;
streamstr_init(&streaaam, str);
t_stream *stream = &streaaam;
while(stream_read(stream))
{
printf("read: %c\n", stream_read(stream));
printf("pop: %c\n", stream_pop(stream));
}
printf("\nChar\tw or 2?\tDigit?\tUpper?\tLower?\tAlpha?\tAlphanum?\n");
const char chars[] = {'a','w','W','2','d','{','\0'};
for (int i = 0; i < 7; i++)
printf("%c\t%i\t%i\t%i\t%i\t%i\t%i\n",
chars[i],
char_isin(chars[i], "w2"),
char_isdigit(chars[i]),
char_isupper(chars[i]),
char_islower(chars[i]),
char_isalpha(chars[i]),
char_isalphanum(chars[i])
);
printf("\nMust say nothing:\n");
stream = streamstr_alloc(&err, mc, " 98 2 ,,. 655yolo");
stream_skip(stream, " .,");
if (stream_readuint(&err, stream) != 98)
err("damn 1");
stream_skip(stream, " .,");
if (stream_readuint(&err, stream) != 2)
err("damn 2");
stream_skip(stream, " .,");
if (stream_readuint(&err, stream) != 655)
err("damn");
printf("\nMust get 2 value errors:\n");
stream_readuint(&err, stream);
stream = streamstr_alloc(&err, mc, "2878979367836578265278276537");
stream_readuint(&err, stream);
printf("\nstr to int:\n");
printf("'%s' = %i\n", "23", str_touint(&err, "23"));
printf("'%s' = %i\n", "0", str_touint(&err, "0"));
printf("bad value = ");
str_touint(&err, "-42");
printf("bad value = ");
str_touint(&err, " 17");
printf("bad value = ");
str_touint(&err, "17 ");
printf("bad value = ");
str_touint(&err, "");
printf("bad value = ");
str_touint(&err, "17b");
printf("bad value = ");
str_touint(&err, "b17");
printf("bad value = ");
str_touint(&err, "+42");
printf("'%s' = %i\n", "23", str_toint(&err, "23"));
printf("'%s' = %i\n", "0", str_toint(&err, "0"));
printf("'%s' = %i\n", "-42", str_toint(&err, "-42"));
printf("bad value = ");
str_toint(&err, " 17");
printf("bad value = ");
str_toint(&err, "17 ");
printf("bad value = ");
str_toint(&err, "");
printf("bad value = ");
str_toint(&err, "17b");
printf("bad value = ");
str_toint(&err, "b17");
printf("'%s' = %i\n", "+42", str_toint(&err, "+42"));
printf("\nMust have no leak with valgrind.\n");
mem_freeall(mc);
}

28
libtf/dev/str2.c Normal file
View file

@ -0,0 +1,28 @@
#include "libtf.h"
#include <stdio.h>
void err(t_const_string msg)
{
printf("<error %s>\n", msg);
}
int main(void)
{
t_memclass mc = mem_newclass(&err);
t_string *arr;
arr = str_split(err, mc, " Hello \nworld\n \n ! ", "\n ");
printf("'Hello' = '%s'\n", arr[0]);
printf("'world' = '%s'\n", arr[1]);
printf("'!' = '%s'\n", arr[2]);
printf("'(null)' = '%s'\n", arr[3]);
arr = str_split(err, mc, "\n\n\n\n ", "\n ");
printf("'(null)' = '%s'\n", arr[0]);
arr = str_split(err, mc, "", "\n ");
printf("'(null)' = '%s'\n", arr[0]);
arr = str_split(err, mc, "yo", "\n ");
printf("'yo' = '%s'\n", arr[0]);
printf("'(null)' = '%s'\n", arr[1]);
mem_freeall(mc);
}

35
libtf/dev/str3.c Normal file
View file

@ -0,0 +1,35 @@
#include "libtf.h"
#include <limits.h>
#include <stdio.h>
int main()
{
t_memclass mc = mem_newclass(err_remember);
char *yo = "Hello ";
char *we = "world!";
printf("%s\n", str_join(err_remember, mc, yo, we));
printf("%i = %s\n", 0, str_inttostr(err_remember, mc, 0));
printf("%i = %s\n", 7, str_inttostr(err_remember, mc, 7));
printf("%i = %s\n", 3892, str_inttostr(err_remember, mc, 3892));
printf("%i = %s\n", -1, str_inttostr(err_remember, mc, -1));
printf("%i = %s\n", -90430, str_inttostr(err_remember, mc, -90430));
printf("%i = %s\n", INT_MAX, str_inttostr(err_remember, mc, INT_MAX));
printf("%i = %s\n", INT_MIN, str_inttostr(err_remember, mc, INT_MIN));
printf("%u = %s\n", 0, str_uinttostr(err_remember, mc, 0));
printf("%u = %s\n", 7, str_uinttostr(err_remember, mc, 7));
printf("%u = %s\n", 3892, str_uinttostr(err_remember, mc, 3892));
printf("%u = %s\n", INT_MAX, str_uinttostr(err_remember, mc, INT_MAX));
printf("%u = %s\n", UINT_MAX, str_uinttostr(err_remember, mc, UINT_MAX));
printf("%i = %i\n", 1, str_eq("", ""));
printf("%i = %i\n", 0, str_eq("one", ""));
printf("%i = %i\n", 0, str_eq("", "two"));
printf("%i = %i\n", 0, str_eq("one", "two"));
printf("%i = %i\n", 1, str_eq("one", "one"));
printf("%i = %i\n", 0, str_eq("onetwo", "one"));
printf("%i = %i\n", 0, str_eq("one", "onetwo"));
mem_freeall(mc);
}

45
libtf/include/mem_utils.h Normal file
View file

@ -0,0 +1,45 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* mem_utils.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/18 16:37:23 by mcolonna #+# #+# */
/* Updated: 2024/03/12 16:06:59 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef MEM_UTILS_H
# define MEM_UTILS_H
# include "libtf.h"
# include <stdlib.h>
typedef struct s_memclass_in t_memclass_in;
typedef struct s_element t_element;
typedef struct s_element
{
void *address;
t_memclass_in *subclass;
t_element *previous;
t_element *next;
t_memclass_in *mc;
} t_element;
typedef struct s_memclass_in
{
t_element *first;
t_element *parent_element;
} t_memclass_in;
void *create_address_with_element(t_element *element, size_t size);
t_element *get_address_element(void *address);
void free_address_with_element(void *address);
void freeelement(t_element *el);
#endif

View file

@ -0,0 +1,62 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* read_line_utils.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/30 15:36:49 by mcolonna #+# #+# */
/* Updated: 2024/03/25 14:21:52 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef READ_LINE_UTILS_H
# define READ_LINE_UTILS_H
# include "libtf.h"
# ifndef BUFFER_SIZE
# define BUFFER_SIZE 1000
# endif
# define NB_FILE_DESCRIPTORS 4096
typedef struct s_buf
{
t_memclass mc;
int size;
char str[BUFFER_SIZE];
} t_buf;
typedef struct s_string2
{
int size;
char *str;
} t_string2;
typedef struct s_errmc
{
t_err *err;
t_memclass mc;
} t_errmc;
// NULL if error.
// Return a pointer to free. Nothing if error.
int create_empty_buf(t_buf **result);
// -1 if error, or else 1.
// string->str will be freed, the new string->str will be to free.
// If error, no free or malloc is done.
int append_to_string(
t_string2 *string, char *to_append, int to_append_size);
// Return 0 if error, or else 1.
// *result (and its "str" value) to free. Nothing to free if error.
int create_empty_string(t_string2 **result);
// Free string->str and string.
void free_string(t_string2 **string);
t_errmc setget_errmc(t_err err, t_memclass mc);
#endif

22
libtf/include/str_utils.h Normal file
View file

@ -0,0 +1,22 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* str_utils.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/02/09 17:13:15 by mcolonna #+# #+# */
/* Updated: 2024/02/09 17:13:39 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef STR_UTILS_H
# define STR_UTILS_H
typedef struct s_two_strings
{
t_const_string str;
t_const_string charset;
} t_two_strings;
#endif

392
libtf/libtf.h Normal file
View file

@ -0,0 +1,392 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* libtf.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/18 11:07:59 by mcolonna #+# #+# */
/* Updated: 2024/03/11 12:12:03 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef LIBTF_H
# define LIBTF_H
# include <stddef.h>
# include <stdbool.h>
///// STR (part1) /////
/**
* t_string variables are char* which ends with '\0'.
*/
typedef char *t_string;
/**
* Same but the chars are constant.
*/
typedef const char *t_const_string;
///// ERR /////
// Functions who can raise an error must accept a t_err function
// and call it if an error occurs.
/**
* Function called when there's an error.
* The argument identifies what type of error is it (can be NULL).
* In this library, the possible arguments are:
* - "alloc error" Error when allocating memory.
* - "bad value" The value given to the function is bad.
* - "errno" The error is defined in errno.
* - "empty list" The list is empty and it shouldn't be.
*/
typedef void (t_err)(t_const_string);
/**
* Keep the error in memory to get it later with get_error().
*/
void err_remember(t_const_string msg);
/**
* If err_remember was called before, return the message of the error
* then drop it. Return NULL if there is no error to get.
*/
t_const_string err_get(void);
///// MEM /////
// Awesome malloc manager. When you alloc an address, you have to assign
// a t_memclass (mc) to it. Then, you can free every address assigned to
// a mc using mem_freeall(), or you can free the addresses one by one
// using mem_free() (you still have to use mem_freeall() to free the mc).
/**
* Represent a class of allocs.
* Must be created by mem_newclass() and freed by mem_freeall()
* Don't use after being freed.
*/
typedef void *t_memclass;
/**
* Create a t_memclass.
* Possible errors: "alloc error"
* Return NULL on error.
*/
t_memclass mem_newclass(t_err *err);
/**
* Create a t_memclass and add it to parent.
* It means if we freeall(parent), this mc is freeall too.
* Possible errors: "alloc error"
* Return NULL on error.
*/
t_memclass mem_subclass(t_err *err, t_memclass parent);
/**
* Alloc memory of the class 'mc' and of the size 'size'.
* If mc is NULL, do nothing.
* Possible errors: "alloc error"
* Return NULL on error.
*/
void *mem_alloc(t_err *err, t_memclass mc, size_t size);
/**
* Free all the memory of the specified class.
* 'mc' becomes unusable.
*/
void mem_freeall(t_memclass mc);
/**
* Free a pointer. If pointer is NULL, do nothing.
* /!\ Must use it only with address alloced with mem_alloc!!
*/
void mem_free(void *pointer);
///// STR (part2) /////
/**
* Return the length of the string.
*/
int str_len(t_const_string str);
/**
* Clone the string.
* Possible errors: "alloc error"
* Return NULL on error.
*/
t_string str_dup(t_err *err, t_memclass mc, t_const_string str);
/**
* Check if the char is in the given charset.
* Return always false if c is '\0'.
*/
bool char_isin(char c, t_const_string charset);
/**
* Check if the char is a digit ([0-9]).
*/
bool char_isdigit(char c);
/**
* Check if the char is an uppercase letter ([A-Z]).
*/
bool char_isupper(char c);
/**
* Check if the char is a lowercase letter ([a-z]).
*/
bool char_islower(char c);
/**
* Check if the char is a letter ([A-Za-z]).
*/
bool char_isalpha(char c);
/**
* Check if the char is a letter or a digit ([A-Za-z0-9]).
*/
bool char_isalphanum(char c);
/**
* Allows reading a string char by char.
*/
typedef struct s_stream
{
char (*_read)(const void **);
char (*_pop)(const void **);
const void *_data;
} t_stream;
/**
* Create a stream from a string.
* Possible errors: "alloc error"
* Return NULL on error.
*/
t_stream *streamstr_alloc(
t_err *err, t_memclass mc, t_const_string str);
/**
* Set 'stream' to a new stream using 'str'.
*/
void streamstr_init(t_stream *stream, t_const_string str);
/**
* Return the current char of the stream, or \0 if it's the end.
*/
char stream_read(t_stream *stream);
/**
* Return the current char of the stream, or \0 if it's the end.
* Go to the next char if it isn't the end.
*/
char stream_pop(t_stream *stream);
/**
* Skip specified chars in stream.
* For example if the stream is at "21012321" and charset is "012",
* it will skip the first '0', '1' and '2's to be at "321".
*/
void stream_skip(t_stream *stream, t_const_string charset);
/**
* Read an unsigned int in decimal, until a non-digit or the end of the stream.
* If there is no digit, or if it overflows the length of a unsigned int, err
* is called with "bad value" and 0 is returned.
* Possible errors: "bad value"
* Return 0 on error.
*/
unsigned int stream_readuint(t_err *err, t_stream *stream);
/**
* Read a signed int in decimal, until a non-digit or the end of the stream.
* If there is no digit, '+' or '-', or if it overflows the length of a signed
* int, err is called with "bad value" and -1 is returned.
* Possible errors: "bad value"
* Return 0 on error.
*/
int stream_readint(t_err *err, t_stream *stream);
/**
* Cast a string to an unsigned int in decimal.
* The string must match /[0-9]+/, and the result must not overflow the limits
* of a unsigned int. If it isn't respected, err is called with "bad value"
* and 0 is returned.
* Possible errors: "bad value"
* Return 0 on error.
*/
unsigned int str_touint(t_err *err, t_const_string str);
/**
* Cast a string to a signed int in decimal.
* The string must match /[-+]?[0-9]+/, and the result must not overflow the
* limits of an int. If it isn't respected, err is called with "bad value" and
* -1 is returned.
* Possible errors: "bad value"
* Return -1 on error.
*/
int str_toint(t_err *err, t_const_string str);
/**
* Split the given string by the given separators in charset.
* Return a list of strings ended by NULL, no empty string.
* Possible errors: "alloc error"
* Return NULL on error.
*/
t_string *str_split(
t_err *err, t_memclass mc, t_const_string str,
t_const_string charset);
/**
* Return a mem_alloc'd concatenation of the two strings.
* Possible errors: "alloc error"
* Return NULL on error.
*/
t_string str_join(t_err *err, t_memclass mc, t_const_string str1,
t_const_string str2);
/**
* Write an int as an str in decimal.
* Possible errors: "alloc error"
* Return NULL on error.
*/
t_string str_inttostr(t_err *err, t_memclass mc, int n);
/**
* Write an unsigned int as an str in decimal.
* Possible errors: "alloc error"
* Return NULL on error.
*/
t_string str_uinttostr(t_err *err, t_memclass mc, unsigned int n);
/**
* Return true if the strings are the same.
*/
bool str_eq(t_const_string str1, t_const_string str2);
///// IO /////
/**
* Write a string on fd.
* Possible errors: "errno"
*/
void print_str(t_err *err, int fd, t_const_string str);
/**
* Write a string on fd and finish it with a \n.
* Possible errors: "errno"
*/
void print_line(t_err *err, int fd, t_const_string str);
/**
* Conversions: %c %s %p %d %i %u %x %X %%
* Return -1 on error.
*/
int tf_printf(t_const_string format, ...);
/**
* Return the next line of the 'fd', including the '\n' if it exists.
* 'fd' must be between 0 and 4095 included.
* Possible error: "alloc error", "bad value", "errno"
* Return NULL if error, BUT it's not the only case it could return NULL!
* To avoid leaks and problems, must be called until it returns NULL.
*/
t_const_string read_line(t_err err, t_memclass mc, int fd);
///// LIST /////
/**
* Represents an element of a t_list.
* - value: mem_alloc'd pointer to the value of the element.
* - next: next element in the list, or NULL if it's the end of the list.
* - previous: previous element in the list, or NULL if it's the beginning of the
* list.
*/
typedef struct s_list_element
{
void *value;
struct s_list_element *next;
struct s_list_element *previous;
} t_list_element;
/**
* Represents a list.
* - first: first element of the list, or NULL if the list is empty.
* - last: last element of the list, or NULL if the list is empty.
* - size: number of elements in the list.
* - mc: memclass of the elements and their values.
* [!] All those fields must stay coherent.
*/
typedef struct s_list
{
t_list_element *first;
t_list_element *last;
int size;
t_memclass mc;
} t_list;
/**
* Create an empty list.
* The mc is saved to be used y list_addelement. You must do mem_freeall(mc)
* after finishing using the list.
*/
t_list list_createempty(t_memclass mc);
/**
* Add an element to the start of the list.
* The element is alloc'd with the mc of the list.
* Possible errors: "alloc error"
*/
void list_revadd(t_err *err, t_list *list, void *value);
/**
* Add an element to the end of the list.
* The element is alloc'd with the mc of the list.
* err is called with "alloc error" if the alloc doesn't work.
* Possible errors: "alloc error"
*/
void list_add(t_err *err, t_list *list, void *value);
/**
* Get the value at the specified index.
* Possible errors: "alloc error"
* Return NULL on error.
*/
void *list_get(t_err *err, const t_list *list, int index);
/**
* Return the last value from the list and remove it.
* Possible errors: "empty list"
* Return NULL on error.
*/
void *list_revpop(t_err *err, t_list *list);
/**
* Return the first value from the list and remove it.
* Possible errors: "empty list"
* Return NULL on error.
*/
void *list_pop(t_err *err, t_list *list);
/**
* Return the size of the list.
*/
int list_getsize(const t_list *list);
/**
* Move the first element to the end of the list.
* Does nothing if empty.
*/
void list_rotate(t_list *list);
/**
* Move the last element to the beginning of the list.
* Does nothing if empty.
*/
void list_revrotate(t_list *list);
///// DATA /////
/**
* Copy 'size' bytes of content from src to dest.
* The ranges CAN overlap.
*/
void data_cpy(void *dest, const void *src, size_t size);
#endif

37
libtf/src/data.c Normal file
View file

@ -0,0 +1,37 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* data.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/02/09 17:36:23 by mcolonna #+# #+# */
/* Updated: 2024/02/13 17:03:23 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include <stddef.h>
void data_cpy(void *dest, const void *src, size_t size)
{
unsigned int i;
if (dest < src)
{
i = 0;
while (i < size)
{
((char *)dest)[i] = ((char *)src)[i];
i++;
}
}
else
{
i = size;
while (i > 0)
{
i--;
((char *)dest)[i] = ((char *)src)[i];
}
}
}

33
libtf/src/error.c Normal file
View file

@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* error.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/02/06 18:47:37 by mcolonna #+# #+# */
/* Updated: 2024/02/06 19:08:01 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
static t_const_string pop_msg(t_const_string msg)
{
static t_const_string value = NULL;
t_const_string tmp;
tmp = value;
value = msg;
return (tmp);
}
void err_remember(t_const_string msg)
{
pop_msg(msg);
}
t_const_string err_get(void)
{
return (pop_msg(NULL));
}

102
libtf/src/list1.c Normal file
View file

@ -0,0 +1,102 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* list1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/10 15:36:25 by mcolonna #+# #+# */
/* Updated: 2024/02/13 17:02:25 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
t_list list_createempty(t_memclass mc)
{
t_list r;
r.first = NULL;
r.last = NULL;
r.size = 0;
r.mc = mc;
return (r);
}
void list_add(t_err *err, t_list *list, void *value)
{
t_list_element *new_element;
new_element = mem_alloc(err, list->mc, sizeof(t_list_element));
if (!new_element)
return ;
new_element->value = value;
new_element->next = NULL;
new_element->previous = list->last;
if (list->last)
{
list->last->next = new_element;
list->last = new_element;
}
else
{
list->first = new_element;
list->last = new_element;
}
list->size++;
}
void list_revadd(t_err *err, t_list *list, void *value)
{
t_list_element *new_element;
new_element = mem_alloc(err, list->mc, sizeof(t_list_element));
if (!new_element)
return ;
new_element->value = value;
new_element->next = list->first;
new_element->previous = NULL;
if (list->first)
{
list->first->previous = new_element;
list->first = new_element;
}
else
{
list->first = new_element;
list->last = new_element;
}
list->size++;
}
void *list_get(t_err *err, const t_list *list, int index)
{
t_list_element *el;
el = list->first;
if (index < 0)
return ((*err)("index error"), NULL);
while (el && index)
{
el = el->next;
index--;
}
if (!el)
return ((*err)("index error"), NULL);
return (el->value);
}
void *list_revget(t_err *err, t_list list, int index)
{
t_list_element *el;
el = list.last;
while (el && index)
{
el = el->previous;
index--;
}
if (!el)
return ((*err)("index error"), NULL);
return (el->value);
}

86
libtf/src/list2.c Normal file
View file

@ -0,0 +1,86 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* list2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/15 15:58:05 by mcolonna #+# #+# */
/* Updated: 2024/02/13 17:02:42 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
void *list_pop(t_err *err, t_list *list)
{
t_list_element *r;
void *rr;
if (!list->first)
return ((*err)("empty list"), NULL);
r = list->first;
list->first = r->next;
if (!list->first)
list->last = NULL;
else
list->first->previous = NULL;
list->size--;
rr = r->value;
mem_free(r);
return (rr);
}
void *list_revpop(t_err *err, t_list *list)
{
t_list_element *r;
void *rr;
if (!list->last)
return ((*err)("empty list"), NULL);
r = list->last;
list->last = r->previous;
if (!list->last)
list->first = NULL;
else
list->first->next = NULL;
list->size--;
rr = r->value;
mem_free(r);
return (rr);
}
int list_getsize(const t_list *list)
{
return (list->size);
}
void list_rotate(t_list *list)
{
t_list_element *el;
if (list->size == 0)
return ;
el = list->first;
list->first = el->next;
list->last->next = el;
el->previous = list->last;
el->next->previous = NULL;
el->next = NULL;
list->last = el;
}
void list_revrotate(t_list *list)
{
t_list_element *el;
if (list->size == 0)
return ;
el = list->last;
list->last = el->previous;
list->first->previous = el;
el->next = list->first;
el->previous->next = NULL;
el->previous = NULL;
list->first = el;
}

110
libtf/src/mem.c Normal file
View file

@ -0,0 +1,110 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* mem.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/18 11:08:16 by mcolonna #+# #+# */
/* Updated: 2024/03/12 16:05:15 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
#include "mem_utils.h"
#include <stdlib.h>
t_memclass mem_newclass(t_err *err)
{
t_memclass_in *r;
r = malloc(sizeof(t_memclass_in));
if (!r)
return ((*err)("alloc error"), NULL);
r->first = NULL;
r->parent_element = NULL;
return (r);
}
void *mem_alloc(t_err *err, t_memclass mc, size_t size)
{
void *r;
t_element *new_element;
t_memclass_in *mc_in;
mc_in = (t_memclass_in *) mc;
new_element = malloc(sizeof(t_element));
if (!new_element)
return ((*err)("alloc error"), NULL);
r = create_address_with_element(new_element, size);
if (!r)
return (free(new_element), (*err)("alloc error"), NULL);
new_element->address = r;
new_element->subclass = NULL;
new_element->next = mc_in->first;
if (new_element->next)
new_element->next->previous = new_element;
new_element->previous = NULL;
new_element->mc = mc;
mc_in->first = new_element;
return (r);
}
void mem_freeall(t_memclass mc)
{
t_element *el;
t_element *next;
if (!mc)
return ;
el = ((t_memclass_in *) mc)->first;
while (el)
{
next = el->next;
free_address_with_element(el->address);
if (el->subclass)
mem_freeall(el->subclass);
else
free(el);
el = next;
}
if (((t_memclass_in *) mc)->parent_element)
freeelement(((t_memclass_in *) mc)->parent_element);
free(mc);
}
void mem_free(void *address)
{
t_element *el;
if (!address)
return ;
el = get_address_element(address);
free_address_with_element(address);
freeelement(el);
}
t_memclass mem_subclass(t_err *err, t_memclass parent)
{
t_memclass_in *r;
t_memclass_in *parent_in;
t_element *new_element;
parent_in = (t_memclass_in *) parent;
r = mem_newclass(err);
if (!r)
return (err("alloc error"), NULL);
new_element = malloc(sizeof(t_element));
if (!new_element)
return (err("alloc error"), mem_freeall(r), NULL);
new_element->address = NULL;
new_element->subclass = r;
new_element->next = parent_in->first;
if (new_element->next)
new_element->next->previous = new_element;
new_element->previous = NULL;
new_element->mc = parent;
parent_in->first = new_element;
r->parent_element = new_element;
return ((t_memclass) r);
}

46
libtf/src/mem_utils.c Normal file
View file

@ -0,0 +1,46 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* mem_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/18 16:36:49 by mcolonna #+# #+# */
/* Updated: 2024/03/11 14:03:20 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "mem_utils.h"
void freeelement(t_element *el)
{
if (el->previous)
el->previous->next = el->next;
else
el->mc->first = el->next;
if (el->next)
el->next->previous = el->previous;
free(el);
}
void *create_address_with_element(t_element *element, size_t size)
{
void *r;
r = malloc(sizeof(t_element *) + size);
if (!r)
return (free(r), NULL);
*((t_element **)r) = element;
return ((void *)((char *)r + sizeof(t_element *)));
}
t_element *get_address_element(void *address)
{
return (*(t_element **)((char *)address - sizeof(t_element *)));
}
void free_address_with_element(void *address)
{
if (address)
free((char *)address - sizeof(t_element *));
}

27
libtf/src/print.c Normal file
View file

@ -0,0 +1,27 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* print.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/08 14:38:27 by mcolonna #+# #+# */
/* Updated: 2024/02/20 17:07:33 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
#include <unistd.h>
void print_str(t_err *err, int fd, t_const_string str)
{
if (write(fd, str, str_len(str)) == -1)
(*err)("errno");
}
void print_line(t_err *err, int fd, t_const_string str)
{
print_str(err, fd, str);
if (write(fd, "\n", 1) == -1)
(*err)("errno");
}

104
libtf/src/read_line.c Normal file
View file

@ -0,0 +1,104 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* read_line.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/30 15:39:50 by mcolonna #+# #+# */
/* Updated: 2024/03/25 14:29:49 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include <unistd.h>
#include "libtf.h"
#include "read_line_utils.h"
// If *eol is set to:
// - 1, that means the line is ended with a '\n'.
// - 0, no '\n' found, buf is now empty.
// If error, returns -1 or else returns 1.
static int pop_until_line_break(int *eol, t_string2 *line, t_buf *buf)
{
int i1;
int i2;
*eol = 0;
i1 = 0;
while (!*eol && i1 < buf->size)
{
if (buf->str[i1] == '\n')
*eol = 1;
i1++;
}
if (append_to_string(line, buf->str, i1) == -1)
return (-1);
i2 = 0;
while (i2 < buf->size - i1)
{
buf->str[i2] = buf->str[i2 + i1];
i2++;
}
buf->size -= i1;
return (1);
}
// Returns -1 if error, or else 1.
static int fill_buf(int *eof, t_buf *buf, int fd)
{
int r;
const t_errmc errmc = setget_errmc(NULL, NULL);
*eof = 0;
r = read(fd, buf->str, BUFFER_SIZE);
if (r == -1)
return (errmc.err("errno"), -1);
buf->size += r;
if (!r)
*eof = 1;
return (1);
}
// Free things and returns to_return.
static void *free_and_return(
void *to_return, t_buf **buf, t_string2 **string, void *any)
{
if (buf)
{
mem_freeall((*buf)->mc);
*buf = NULL;
}
if (string)
free_string(string);
mem_free(any);
return (to_return);
}
t_const_string read_line(t_err err, t_memclass mc, int fd)
{
static t_buf *bufs[NB_FILE_DESCRIPTORS];
t_string2 *line;
int eofeol[2];
setget_errmc(err, mc);
if (fd >= NB_FILE_DESCRIPTORS || fd < 0)
return (err("bad value"), NULL);
if (!bufs[fd] && !create_empty_buf(&bufs[fd]))
return (NULL);
if (!create_empty_string(&line))
return (free_and_return(NULL, &bufs[fd], NULL, NULL));
eofeol[0] = 0;
eofeol[1] = 0;
while (!eofeol[0])
{
if (pop_until_line_break(&eofeol[1], line, bufs[fd]) == -1)
return (free_and_return(NULL, &bufs[fd], &line, NULL));
if (eofeol[1])
break ;
if (fill_buf(&eofeol[0], bufs[fd], fd) == -1)
return (free_and_return(NULL, &bufs[fd], &line, NULL));
}
if (append_to_string(line, "", 1) == 1 && line->size > 1)
return (free_and_return(line->str, NULL, NULL, line));
return (free_and_return(NULL, &bufs[fd], &line, NULL));
}

View file

@ -0,0 +1,89 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* read_line_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/06 14:28:19 by mcolonna #+# #+# */
/* Updated: 2024/03/25 14:45:18 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
#include "read_line_utils.h"
int create_empty_buf(t_buf **result)
{
const t_errmc errmc = setget_errmc(NULL, NULL);
const t_memclass mc = mem_newclass(errmc.err);
*result = mem_alloc(errmc.err, mc, sizeof(t_buf));
if (!*result)
return (0);
(*result)->size = 0;
(*result)->mc = mc;
return (1);
}
int create_empty_string(t_string2 **result)
{
const t_errmc errmc = setget_errmc(NULL, NULL);
*result = mem_alloc(errmc.err, errmc.mc, sizeof(t_string2));
if (!*result)
return (0);
(*result)->str = mem_alloc(errmc.err, errmc.mc, sizeof(char));
if (!(*result)->str)
{
mem_free(*result);
return (0);
}
(*result)->size = 0;
return (1);
}
int append_to_string(t_string2 *string, char *to_append, int to_append_size)
{
char *new_str;
int i;
const t_errmc errmc = setget_errmc(NULL, NULL);
new_str = mem_alloc(errmc.err, errmc.mc,
(string->size + to_append_size) * sizeof(char));
if (!new_str)
return (-1);
i = -1;
while (++i < string->size)
new_str[i] = string->str[i];
i = -1;
while (++i < to_append_size)
new_str[i + string->size] = to_append[i];
mem_free(string->str);
string->str = new_str;
string->size += to_append_size;
return (1);
}
void free_string(t_string2 **string)
{
mem_free((*string)->str);
mem_free(*string);
*string = NULL;
}
t_errmc setget_errmc(t_err err, t_memclass mc)
{
static t_err *err_v = NULL;
static t_memclass mc_v = NULL;
t_errmc r;
if (err && mc)
{
err_v = err;
mc_v = mc;
}
r.err = err_v;
r.mc = mc_v;
return (r);
}

42
libtf/src/str1.c Normal file
View file

@ -0,0 +1,42 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* str1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/22 13:39:04 by mcolonna #+# #+# */
/* Updated: 2024/04/09 14:05:13 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
#include "str_utils.h"
int str_len(t_const_string str)
{
int i;
i = 0;
while (str[i])
i++;
return (i);
}
t_string str_dup(t_err err, t_memclass mc, t_const_string str)
{
t_string r;
int i;
r = mem_alloc(err, mc, (str_len(str) + 1) * sizeof(char));
if (!r)
return (r);
i = 0;
while (str[i])
{
r[i] = str[i];
i++;
}
r[i] = '\0';
return (r);
}

89
libtf/src/str2.c Normal file
View file

@ -0,0 +1,89 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* str2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/30 15:19:37 by mcolonna #+# #+# */
/* Updated: 2024/02/15 11:12:22 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
unsigned int str_touint(t_err err, t_const_string str)
{
t_stream stream;
unsigned int r;
streamstr_init(&stream, str);
r = stream_readuint(&err_remember, &stream);
if (err_get() || stream_read(&stream))
return ((*err)("bad value"), 0);
return (r);
}
int str_toint(t_err err, t_const_string str)
{
t_stream stream;
int r;
streamstr_init(&stream, str);
r = stream_readint(&err_remember, &stream);
if (err_get() || stream_read(&stream))
return ((*err)("bad value"), -1);
return (r);
}
t_string str_join(t_err *err, t_memclass mc, t_const_string str1,
t_const_string str2)
{
const size_t len1 = str_len(str1);
const size_t len2 = str_len(str2);
t_string r;
r = mem_alloc(err, mc, sizeof(char) * (len1 + len2 + 1));
if (!r)
return (NULL);
data_cpy(r, str1, len1);
data_cpy(r + len1, str2, len2);
r[len1 + len2] = '\0';
return (r);
}
t_string str_uinttostr(t_err *err, t_memclass mc, unsigned int n)
{
const t_const_string digits[] = {
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
t_string r;
t_string tmp;
if (n == 0)
return (str_dup(err, mc, "0"));
r = str_dup(err, mc, digits[n % 10]);
n /= 10;
while (n > 0)
{
tmp = r;
r = str_join(err, mc, digits[n % 10], r);
mem_free(tmp);
n /= 10;
}
return (r);
}
t_string str_inttostr(t_err *err, t_memclass mc, int n)
{
t_string r;
if (n >= 0)
return (str_uinttostr(err, mc, n));
else
{
r = str_uinttostr(err, mc, -n);
if (!r)
return (NULL);
return (str_join(err, mc, "-", r));
}
}

105
libtf/src/str3.c Normal file
View file

@ -0,0 +1,105 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* str3.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/22 13:39:04 by mcolonna #+# #+# */
/* Updated: 2024/02/23 11:36:07 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
#include "str_utils.h"
static t_two_strings two_strings(t_const_string str, t_const_string charset)
{
t_two_strings r;
r.str = str;
r.charset = charset;
return (r);
}
static t_string get_word_at_index(
t_err *err, t_memclass mc, int index, t_two_strings args)
{
int i;
int j;
t_string r;
i = 0;
while (char_isin(args.str[i], args.charset))
i++;
while (--index >= 0)
{
while (args.str[i] && !char_isin(args.str[i], args.charset))
i++;
while (char_isin(args.str[i], args.charset))
i++;
}
j = 0;
while (args.str[i + j] && !char_isin(args.str[i + j], args.charset))
j++;
r = mem_alloc(err, mc, (j + 1) * sizeof(char));
if (!r)
return (NULL);
r[j] = '\0';
while (--j >= 0)
r[j] = args.str[i + j];
return (r);
}
static int count_words(t_const_string str, t_const_string charset)
{
t_stream stream;
int r;
streamstr_init(&stream, str);
r = 0;
while (stream_read(&stream))
{
stream_skip(&stream, charset);
if (stream_read(&stream))
{
r++;
while (stream_read(&stream)
&& !char_isin(stream_read(&stream), charset))
stream_pop(&stream);
}
}
return (r);
}
t_string *str_split(
t_err err, t_memclass mc, t_const_string str, t_const_string charset)
{
t_stream stream;
t_string *r;
int i;
i = count_words(str, charset);
r = mem_alloc(err, mc, (i + 1) * sizeof(t_string));
if (!r)
return (NULL);
streamstr_init(&stream, str);
r[i] = NULL;
while (--i >= 0)
{
r[i] = get_word_at_index(err, mc, i, two_strings(str, charset));
if (!r[i])
return (NULL);
}
return (r);
}
bool str_eq(t_const_string str1, t_const_string str2)
{
int i;
i = 0;
while (str1[i] && str1[i] == str2[i])
i++;
return (str1[i] == str2[i]);
}

47
libtf/src/str_char1.c Normal file
View file

@ -0,0 +1,47 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* str_char1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 13:09:35 by mcolonna #+# #+# */
/* Updated: 2024/02/13 13:29:59 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
bool char_isin(char c, t_const_string charset)
{
int i;
i = 0;
while (charset[i])
{
if (c == charset[i])
return (true);
i++;
}
return (false);
}
bool char_isdigit(char c)
{
return (c >= '0' && c <= '9');
}
bool char_isupper(char c)
{
return (c >= 'A' && c <= 'Z');
}
bool char_islower(char c)
{
return (c >= 'a' && c <= 'z');
}
bool char_isalpha(char c)
{
return (char_isupper(c) || char_islower(c));
}

18
libtf/src/str_char2.c Normal file
View file

@ -0,0 +1,18 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* str_char2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 13:15:23 by mcolonna #+# #+# */
/* Updated: 2024/02/13 13:28:57 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
bool char_isalphanum(char c)
{
return (char_isalpha(c) || char_isdigit(c));
}

23
libtf/src/str_stream.c Normal file
View file

@ -0,0 +1,23 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* str_stream.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/22 16:17:19 by mcolonna #+# #+# */
/* Updated: 2024/01/23 18:16:52 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
char stream_read(t_stream *stream)
{
return ((*stream->_read)(&stream->_data));
}
char stream_pop(t_stream *stream)
{
return ((*stream->_pop)(&stream->_data));
}

View file

@ -0,0 +1,60 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* str_stream_more.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/04 12:48:47 by mcolonna #+# #+# */
/* Updated: 2024/02/13 17:07:24 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
#include <limits.h>
void stream_skip(t_stream *stream, t_const_string charset)
{
while (stream_read(stream)
&& char_isin(stream_read(stream), charset))
stream_pop(stream);
}
unsigned int stream_readuint(t_err *err, t_stream *stream)
{
unsigned long r;
if (!char_isdigit(stream_read(stream)))
return ((*err)("bad value"), 0);
r = 0;
while (char_isdigit(stream_read(stream)))
{
r *= 10;
r += stream_pop(stream) - '0';
if (r > UINT_MAX)
return ((*err)("bad value"), 0);
}
return ((unsigned int)r);
}
int stream_readint(t_err *err, t_stream *stream)
{
unsigned int abs;
bool negative;
negative = false;
if (char_isin(stream_read(stream), "-+"))
{
if (stream_read(stream) == '-')
negative = true;
stream_pop(stream);
}
abs = stream_readuint(&err_remember, stream);
if (err_get())
return ((*err)("bad value"), -1);
if (negative && -(long)abs >= INT_MIN)
return ((int)-abs);
if (!negative && (long)abs <= INT_MAX)
return ((int)abs);
return ((*err)("bad value"), -1);
}

46
libtf/src/str_streamstr.c Normal file
View file

@ -0,0 +1,46 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* str_streamstr.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/08 12:09:37 by mcolonna #+# #+# */
/* Updated: 2024/02/12 17:07:35 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "libtf.h"
static char streamstr_pop(const void **data)
{
char r;
r = **(char **)data;
if (r)
(*(char **)data)++;
return (r);
}
static char streamstr_read(const void **data)
{
return (**(char **)data);
}
t_stream *streamstr_alloc(t_err err, t_memclass mc, t_const_string str)
{
t_stream *r;
r = mem_alloc(err, mc, sizeof(t_stream));
if (!r)
return (NULL);
streamstr_init(r, str);
return (r);
}
void streamstr_init(t_stream *stream, t_const_string str)
{
stream->_read = &streamstr_read;
stream->_pop = &streamstr_pop;
stream->_data = str;
}

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);
}

31
src/main.c Normal file
View file

@ -0,0 +1,31 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/23 14:33:45 by mcolonna #+# #+# */
/* Updated: 2024/04/23 14:55:04 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "include.h"
int main(int argc, char **argv)
{
t_command command;
int errorstatus;
(void)argc;
(void)argv;
errorstatus = 0;
while (true)
{
command = parse_command(ask_command());
if (command.error)
continue ;
errorstatus = execute_command(command);
}
return (errorstatus);
}