basic functions to make
This commit is contained in:
parent
1a34e2f64b
commit
a0ad80a375
52 changed files with 2964 additions and 3 deletions
7
Makefile
7
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 #####
|
||||
|
||||
|
|
46
include/include.h
Normal file
46
include/include.h
Normal 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
58
libtf/Makefile
Normal 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
28
libtf/dev/Makefile
Normal 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
24
libtf/dev/data.c
Normal 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
14
libtf/dev/error.c
Normal 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
55
libtf/dev/list.c
Normal 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
50
libtf/dev/mem.c
Normal 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
44
libtf/dev/mem2.c
Normal 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
7
libtf/dev/print.c
Normal 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
105
libtf/dev/printf.c
Normal 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
33
libtf/dev/read.c
Normal 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
86
libtf/dev/str.c
Normal 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
28
libtf/dev/str2.c
Normal 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
35
libtf/dev/str3.c
Normal 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
45
libtf/include/mem_utils.h
Normal 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
|
62
libtf/include/read_line_utils.h
Normal file
62
libtf/include/read_line_utils.h
Normal 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
22
libtf/include/str_utils.h
Normal 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
392
libtf/libtf.h
Normal 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
37
libtf/src/data.c
Normal 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
33
libtf/src/error.c
Normal 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
102
libtf/src/list1.c
Normal 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
86
libtf/src/list2.c
Normal 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
110
libtf/src/mem.c
Normal 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
46
libtf/src/mem_utils.c
Normal 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
27
libtf/src/print.c
Normal 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
104
libtf/src/read_line.c
Normal 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));
|
||||
}
|
89
libtf/src/read_line_utils.c
Normal file
89
libtf/src/read_line_utils.c
Normal 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
42
libtf/src/str1.c
Normal 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
89
libtf/src/str2.c
Normal 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
105
libtf/src/str3.c
Normal 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
47
libtf/src/str_char1.c
Normal 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
18
libtf/src/str_char2.c
Normal 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
23
libtf/src/str_stream.c
Normal 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));
|
||||
}
|
60
libtf/src/str_stream_more.c
Normal file
60
libtf/src/str_stream_more.c
Normal 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
46
libtf/src/str_streamstr.c
Normal 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;
|
||||
}
|
57
libtf/tf_printf/include/conversions.h
Normal file
57
libtf/tf_printf/include/conversions.h
Normal 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
|
25
libtf/tf_printf/include/do_conversion.h
Normal file
25
libtf/tf_printf/include/do_conversion.h
Normal 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
|
38
libtf/tf_printf/include/stream.h
Normal file
38
libtf/tf_printf/include/stream.h
Normal 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
|
18
libtf/tf_printf/include/tf_printf.h
Normal file
18
libtf/tf_printf/include/tf_printf.h
Normal 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
|
36
libtf/tf_printf/include/utils.h
Normal file
36
libtf/tf_printf/include/utils.h
Normal 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
|
72
libtf/tf_printf/src/conversions1.c
Normal file
72
libtf/tf_printf/src/conversions1.c
Normal 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);
|
||||
}
|
68
libtf/tf_printf/src/conversions2.c
Normal file
68
libtf/tf_printf/src/conversions2.c
Normal 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);
|
||||
}
|
40
libtf/tf_printf/src/do_conversion.c
Normal file
40
libtf/tf_printf/src/do_conversion.c
Normal 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);
|
||||
}
|
66
libtf/tf_printf/src/ft_itoa.c
Normal file
66
libtf/tf_printf/src/ft_itoa.c
Normal 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);
|
||||
}
|
42
libtf/tf_printf/src/ft_strjoin.c
Normal file
42
libtf/tf_printf/src/ft_strjoin.c
Normal 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);
|
||||
}
|
51
libtf/tf_printf/src/stream1.c
Normal file
51
libtf/tf_printf/src/stream1.c
Normal 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);
|
||||
}
|
19
libtf/tf_printf/src/stream2.c
Normal file
19
libtf/tf_printf/src/stream2.c
Normal 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);
|
||||
}
|
71
libtf/tf_printf/src/tf_printf.c
Normal file
71
libtf/tf_printf/src/tf_printf.c
Normal 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);
|
||||
}
|
85
libtf/tf_printf/src/utils1.c
Normal file
85
libtf/tf_printf/src/utils1.c
Normal 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);
|
||||
}
|
43
libtf/tf_printf/src/utils2.c
Normal file
43
libtf/tf_printf/src/utils2.c
Normal 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
31
src/main.c
Normal 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);
|
||||
}
|
Loading…
Add table
Reference in a new issue