diff --git a/Makefile b/Makefile index 63ad09b..0f8f456 100644 --- a/Makefile +++ b/Makefile @@ -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 ##### diff --git a/include/include.h b/include/include.h new file mode 100644 index 0000000..8af1a83 --- /dev/null +++ b/include/include.h @@ -0,0 +1,46 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* include.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 + +// 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 diff --git a/libtf/Makefile b/libtf/Makefile new file mode 100644 index 0000000..977f51b --- /dev/null +++ b/libtf/Makefile @@ -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 diff --git a/libtf/dev/Makefile b/libtf/dev/Makefile new file mode 100644 index 0000000..819587d --- /dev/null +++ b/libtf/dev/Makefile @@ -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) diff --git a/libtf/dev/data.c b/libtf/dev/data.c new file mode 100644 index 0000000..eb10c6e --- /dev/null +++ b/libtf/dev/data.c @@ -0,0 +1,24 @@ +#include "libtf.h" +#include + +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); + +} diff --git a/libtf/dev/error.c b/libtf/dev/error.c new file mode 100644 index 0000000..41f518a --- /dev/null +++ b/libtf/dev/error.c @@ -0,0 +1,14 @@ +#include "libtf.h" +#include + +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()); +} diff --git a/libtf/dev/list.c b/libtf/dev/list.c new file mode 100644 index 0000000..76329c9 --- /dev/null +++ b/libtf/dev/list.c @@ -0,0 +1,55 @@ +#include "libtf.h" +#include + +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"); +} diff --git a/libtf/dev/mem.c b/libtf/dev/mem.c new file mode 100644 index 0000000..bed0aac --- /dev/null +++ b/libtf/dev/mem.c @@ -0,0 +1,50 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* mem.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/18 11:23:58 by mcolonna #+# #+# */ +/* Updated: 2024/01/15 14:38:30 by marvin ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libtf.h" +#include + +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); +} diff --git a/libtf/dev/mem2.c b/libtf/dev/mem2.c new file mode 100644 index 0000000..f9e7e3b --- /dev/null +++ b/libtf/dev/mem2.c @@ -0,0 +1,44 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* mem2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/12/18 11:23:58 by mcolonna #+# #+# */ +/* Updated: 2024/03/11 13:44:48 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libtf.h" +#include + +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); +} diff --git a/libtf/dev/print.c b/libtf/dev/print.c new file mode 100644 index 0000000..9e7655b --- /dev/null +++ b/libtf/dev/print.c @@ -0,0 +1,7 @@ +#include "libtf.h" + +int main() +{ + print_str(NULL, 1, "Hello "); + print_line(NULL, 1, "World!"); +} diff --git a/libtf/dev/printf.c b/libtf/dev/printf.c new file mode 100644 index 0000000..20120e4 --- /dev/null +++ b/libtf/dev/printf.c @@ -0,0 +1,105 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* printf.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/10/16 17:55:23 by mcolonna #+# #+# */ +/* Updated: 2024/02/12 13:03:35 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +#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); +} diff --git a/libtf/dev/read.c b/libtf/dev/read.c new file mode 100644 index 0000000..7a0d3c6 --- /dev/null +++ b/libtf/dev/read.c @@ -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); +} diff --git a/libtf/dev/str.c b/libtf/dev/str.c new file mode 100644 index 0000000..e83e043 --- /dev/null +++ b/libtf/dev/str.c @@ -0,0 +1,86 @@ +#include "libtf.h" +#include + +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); +} diff --git a/libtf/dev/str2.c b/libtf/dev/str2.c new file mode 100644 index 0000000..7770a7d --- /dev/null +++ b/libtf/dev/str2.c @@ -0,0 +1,28 @@ +#include "libtf.h" +#include + +void err(t_const_string msg) +{ + printf("\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); +} diff --git a/libtf/dev/str3.c b/libtf/dev/str3.c new file mode 100644 index 0000000..d93a25d --- /dev/null +++ b/libtf/dev/str3.c @@ -0,0 +1,35 @@ +#include "libtf.h" +#include +#include + +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); +} diff --git a/libtf/include/mem_utils.h b/libtf/include/mem_utils.h new file mode 100644 index 0000000..c0835ca --- /dev/null +++ b/libtf/include/mem_utils.h @@ -0,0 +1,45 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* mem_utils.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 + +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 diff --git a/libtf/include/read_line_utils.h b/libtf/include/read_line_utils.h new file mode 100644 index 0000000..5f4b140 --- /dev/null +++ b/libtf/include/read_line_utils.h @@ -0,0 +1,62 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* read_line_utils.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 diff --git a/libtf/include/str_utils.h b/libtf/include/str_utils.h new file mode 100644 index 0000000..b330e53 --- /dev/null +++ b/libtf/include/str_utils.h @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_utils.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 diff --git a/libtf/libtf.h b/libtf/libtf.h new file mode 100644 index 0000000..953cae3 --- /dev/null +++ b/libtf/libtf.h @@ -0,0 +1,392 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* libtf.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 +# include + +///// 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 diff --git a/libtf/src/data.c b/libtf/src/data.c new file mode 100644 index 0000000..5f76e18 --- /dev/null +++ b/libtf/src/data.c @@ -0,0 +1,37 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* data.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/09 17:36:23 by mcolonna #+# #+# */ +/* Updated: 2024/02/13 17:03:23 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +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]; + } + } +} diff --git a/libtf/src/error.c b/libtf/src/error.c new file mode 100644 index 0000000..9ccb97b --- /dev/null +++ b/libtf/src/error.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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)); +} diff --git a/libtf/src/list1.c b/libtf/src/list1.c new file mode 100644 index 0000000..c8f1b04 --- /dev/null +++ b/libtf/src/list1.c @@ -0,0 +1,102 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* list1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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); +} diff --git a/libtf/src/list2.c b/libtf/src/list2.c new file mode 100644 index 0000000..5802919 --- /dev/null +++ b/libtf/src/list2.c @@ -0,0 +1,86 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* list2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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; +} diff --git a/libtf/src/mem.c b/libtf/src/mem.c new file mode 100644 index 0000000..bde9c62 --- /dev/null +++ b/libtf/src/mem.c @@ -0,0 +1,110 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* mem.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 + +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); +} diff --git a/libtf/src/mem_utils.c b/libtf/src/mem_utils.c new file mode 100644 index 0000000..70ddf35 --- /dev/null +++ b/libtf/src/mem_utils.c @@ -0,0 +1,46 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* mem_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 *)); +} diff --git a/libtf/src/print.c b/libtf/src/print.c new file mode 100644 index 0000000..bf5338f --- /dev/null +++ b/libtf/src/print.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* print.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/08 14:38:27 by mcolonna #+# #+# */ +/* Updated: 2024/02/20 17:07:33 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libtf.h" +#include + +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"); +} diff --git a/libtf/src/read_line.c b/libtf/src/read_line.c new file mode 100644 index 0000000..7be62c0 --- /dev/null +++ b/libtf/src/read_line.c @@ -0,0 +1,104 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* read_line.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/10/30 15:39:50 by mcolonna #+# #+# */ +/* Updated: 2024/03/25 14:29:49 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#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)); +} diff --git a/libtf/src/read_line_utils.c b/libtf/src/read_line_utils.c new file mode 100644 index 0000000..5679813 --- /dev/null +++ b/libtf/src/read_line_utils.c @@ -0,0 +1,89 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* read_line_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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); +} diff --git a/libtf/src/str1.c b/libtf/src/str1.c new file mode 100644 index 0000000..f36cece --- /dev/null +++ b/libtf/src/str1.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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); +} diff --git a/libtf/src/str2.c b/libtf/src/str2.c new file mode 100644 index 0000000..7bcbe9b --- /dev/null +++ b/libtf/src/str2.c @@ -0,0 +1,89 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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)); + } +} diff --git a/libtf/src/str3.c b/libtf/src/str3.c new file mode 100644 index 0000000..db52b97 --- /dev/null +++ b/libtf/src/str3.c @@ -0,0 +1,105 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str3.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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]); +} diff --git a/libtf/src/str_char1.c b/libtf/src/str_char1.c new file mode 100644 index 0000000..47ca9d4 --- /dev/null +++ b/libtf/src/str_char1.c @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_char1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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)); +} diff --git a/libtf/src/str_char2.c b/libtf/src/str_char2.c new file mode 100644 index 0000000..7e6ad47 --- /dev/null +++ b/libtf/src/str_char2.c @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_char2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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)); +} diff --git a/libtf/src/str_stream.c b/libtf/src/str_stream.c new file mode 100644 index 0000000..764bfc7 --- /dev/null +++ b/libtf/src/str_stream.c @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_stream.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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)); +} diff --git a/libtf/src/str_stream_more.c b/libtf/src/str_stream_more.c new file mode 100644 index 0000000..7d18e01 --- /dev/null +++ b/libtf/src/str_stream_more.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_stream_more.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/01/04 12:48:47 by mcolonna #+# #+# */ +/* Updated: 2024/02/13 17:07:24 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libtf.h" +#include + +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); +} diff --git a/libtf/src/str_streamstr.c b/libtf/src/str_streamstr.c new file mode 100644 index 0000000..4568787 --- /dev/null +++ b/libtf/src/str_streamstr.c @@ -0,0 +1,46 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_streamstr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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; +} diff --git a/libtf/tf_printf/include/conversions.h b/libtf/tf_printf/include/conversions.h new file mode 100644 index 0000000..e26a44c --- /dev/null +++ b/libtf/tf_printf/include/conversions.h @@ -0,0 +1,57 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* conversions.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 +# include + +// 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 diff --git a/libtf/tf_printf/include/do_conversion.h b/libtf/tf_printf/include/do_conversion.h new file mode 100644 index 0000000..73df76d --- /dev/null +++ b/libtf/tf_printf/include/do_conversion.h @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* do_conversion.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 + +// 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 diff --git a/libtf/tf_printf/include/stream.h b/libtf/tf_printf/include/stream.h new file mode 100644 index 0000000..83c83db --- /dev/null +++ b/libtf/tf_printf/include/stream.h @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stream.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 diff --git a/libtf/tf_printf/include/tf_printf.h b/libtf/tf_printf/include/tf_printf.h new file mode 100644 index 0000000..47080cd --- /dev/null +++ b/libtf/tf_printf/include/tf_printf.h @@ -0,0 +1,18 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tf_printf.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 diff --git a/libtf/tf_printf/include/utils.h b/libtf/tf_printf/include/utils.h new file mode 100644 index 0000000..0825d29 --- /dev/null +++ b/libtf/tf_printf/include/utils.h @@ -0,0 +1,36 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 diff --git a/libtf/tf_printf/src/conversions1.c b/libtf/tf_printf/src/conversions1.c new file mode 100644 index 0000000..94f7dec --- /dev/null +++ b/libtf/tf_printf/src/conversions1.c @@ -0,0 +1,72 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* conversions1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 + +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); +} diff --git a/libtf/tf_printf/src/conversions2.c b/libtf/tf_printf/src/conversions2.c new file mode 100644 index 0000000..ac8cd80 --- /dev/null +++ b/libtf/tf_printf/src/conversions2.c @@ -0,0 +1,68 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* conversions2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 + +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); +} diff --git a/libtf/tf_printf/src/do_conversion.c b/libtf/tf_printf/src/do_conversion.c new file mode 100644 index 0000000..dc082ff --- /dev/null +++ b/libtf/tf_printf/src/do_conversion.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* do_conversion.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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); +} diff --git a/libtf/tf_printf/src/ft_itoa.c b/libtf/tf_printf/src/ft_itoa.c new file mode 100644 index 0000000..c6c277d --- /dev/null +++ b/libtf/tf_printf/src/ft_itoa.c @@ -0,0 +1,66 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_itoa.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/10/03 13:51:10 by mcolonna #+# #+# */ +/* Updated: 2024/02/12 12:13:37 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +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); +} diff --git a/libtf/tf_printf/src/ft_strjoin.c b/libtf/tf_printf/src/ft_strjoin.c new file mode 100644 index 0000000..c552fb5 --- /dev/null +++ b/libtf/tf_printf/src/ft_strjoin.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strjoin.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/10/03 11:31:45 by mcolonna #+# #+# */ +/* Updated: 2024/02/12 12:13:04 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#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); +} diff --git a/libtf/tf_printf/src/stream1.c b/libtf/tf_printf/src/stream1.c new file mode 100644 index 0000000..41dbcb2 --- /dev/null +++ b/libtf/tf_printf/src/stream1.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stream1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/10/26 18:15:47 by mcolonna #+# #+# */ +/* Updated: 2024/02/12 12:05:01 by mcolonna ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "stream.h" +#include + +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); +} diff --git a/libtf/tf_printf/src/stream2.c b/libtf/tf_printf/src/stream2.c new file mode 100644 index 0000000..59d0951 --- /dev/null +++ b/libtf/tf_printf/src/stream2.c @@ -0,0 +1,19 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stream2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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); +} diff --git a/libtf/tf_printf/src/tf_printf.c b/libtf/tf_printf/src/tf_printf.c new file mode 100644 index 0000000..bfbfaeb --- /dev/null +++ b/libtf/tf_printf/src/tf_printf.c @@ -0,0 +1,71 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* tf_printf.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 +#include +#include + +// 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); +} diff --git a/libtf/tf_printf/src/utils1.c b/libtf/tf_printf/src/utils1.c new file mode 100644 index 0000000..ce2da0c --- /dev/null +++ b/libtf/tf_printf/src/utils1.c @@ -0,0 +1,85 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils1.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 + +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); +} diff --git a/libtf/tf_printf/src/utils2.c b/libtf/tf_printf/src/utils2.c new file mode 100644 index 0000000..0881bdb --- /dev/null +++ b/libtf/tf_printf/src/utils2.c @@ -0,0 +1,43 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utils2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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 + +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); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..154b06f --- /dev/null +++ b/src/main.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mcolonna +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* 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); +}