From: Lukas Jiriste Date: Sun, 3 Dec 2023 19:41:16 +0000 (+0100) Subject: Add get_next_line to libft X-Git-Url: https://git.ljiriste.work/?a=commitdiff_plain;h=830b7f66376b924179255f12ab4f46c11674a68a;p=Libft.git Add get_next_line to libft Splice get_next_line project neatly fit it inside libft while conforming the Norm. Change libft.h and Makefile accordingly. --- diff --git a/Makefile b/Makefile index 92ef2da..3f7e3e8 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ SOURCES := ft_strndup.c \ ft_split.c \ ft_toupper.c \ ft_strlcat.c \ + ft_strncat_alloc.c \ ft_bzero.c \ ft_abs.c \ ft_isalpha.c \ @@ -50,6 +51,8 @@ SOURCES := ft_strndup.c \ ft_strncmp.c \ ft_swap.c \ \ + get_next_line.c \ + \ ft_lst/ft_lstnew.c \ ft_lst/ft_lstiter.c \ ft_lst/ft_lstmap.c \ diff --git a/ft_strncat_alloc.c b/ft_strncat_alloc.c new file mode 100755 index 0000000..d9f246d --- /dev/null +++ b/ft_strncat_alloc.c @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strncat_alloc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/09/11 13:36:53 by ljiriste #+# #+# */ +/* Updated: 2023/12/03 19:45:18 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include // malloc etc. +#include "libft.h" + +/* Functions like ft_strncat but reallocates dest to + make sure it is large enough */ +char *ft_strncat_alloc(char **dest, const char *src, size_t n) +{ + int size; + char *temp; + + if (n == 0) + return (*dest); + temp = *dest; + size = 0; + if (temp) + while (temp[size]) + ++size; + size += n + 1; + *dest = malloc(size); + if (*dest == NULL) + { + free(temp); + return (NULL); + } + ft_memmove(*dest, temp, size - n - 1); + ft_memmove(*dest + size - n - 1, src, n); + (*dest)[size - 1] = '\0'; + free(temp); + return (*dest); +} diff --git a/get_next_line.c b/get_next_line.c new file mode 100755 index 0000000..07ed37b --- /dev/null +++ b/get_next_line.c @@ -0,0 +1,139 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_next_line.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/08/28 00:01:15 by ljiriste #+# #+# */ +/* Updated: 2023/12/03 19:52:16 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include +#include "get_next_line.h" +#include "libft.h" + +t_list *new_ft_node(int fd) +{ + t_list *node; + t_ft *thread; + + thread = malloc(sizeof(t_ft)); + if (thread == NULL) + return (NULL); + node = ft_lstnew(thread); + if (node == NULL) + { + free(thread); + return (NULL); + } + thread->buffer = malloc((BUFFER_SIZE + 1) * sizeof(char)); + if (thread->buffer == NULL) + { + free(thread); + free(node); + return (NULL); + } + (thread->buffer)[0] = '\0'; + thread->fd = fd; + return (node); +} + +// How to free? +// static in get_next_line? So it could be passed to select AND delete +static char *select_file_buffer(int fd, t_list **list) +{ + t_list *local_head; + + if (*list == NULL) + { + *list = new_ft_node(fd); + if (list == NULL) + return (NULL); + return (((t_ft *)((*list)->content))->buffer); + } + local_head = *list; + while (local_head->next && ((t_ft *)(local_head->content))->fd != fd) + local_head = local_head->next; + if (((t_ft *)(local_head->content))->fd == fd) + return (((t_ft *)(local_head->content))->buffer); + local_head->next = new_ft_node(fd); + if (local_head->next == NULL) + return (NULL); + return (((t_ft *)(local_head->next->content))->buffer); +} + +static void delete_file_node(int fd, t_list **list) +{ + t_list *cur; + t_list *prev; + + prev = NULL; + cur = *list; + while (((t_ft *)(cur->content))->fd != fd) + { + prev = cur; + cur = cur->next; + } + if (prev == NULL) + *list = cur->next; + else + prev->next = cur->next; + free(((t_ft *)(cur->content))->buffer); + free(cur->content); + free(cur); + return ; +} + +/* Concatenates res and buffer up to newline. + Shifts buffer by the transfered characters. + Returns 0 when buffer is empty (and needs filling with read). + Also returns 1 when newline is transfered + unless buffer empty (to delete node). + Otherwise returns true. +*/ +static int transfer_string(char **res, char *buffer) +{ + int i; + int nl; + + i = 0; + while (buffer[i] && buffer[i] != '\n') + ++i; + nl = (buffer[i] == '\n'); + i += nl; + ft_strncat_alloc(res, buffer, i); + ft_memmove(buffer, buffer + i, BUFFER_SIZE + 1 - i); + return (buffer[0] || nl); +} + +char *get_next_line(int fd) +{ + static t_list *list; + char *buffer; + char *res; + int i; + + res = NULL; + buffer = select_file_buffer(fd, &list); + while (!transfer_string(&res, buffer)) + { + if (buffer[0] == '\0') + { + i = read(fd, buffer, BUFFER_SIZE); + if (i <= 0) + delete_file_node(fd, &list); + if (i < 0) + { + free(res); + return (NULL); + } + if (i == 0) + return (res); + buffer[i] = '\0'; + } + } + return (res); +} diff --git a/get_next_line.h b/get_next_line.h new file mode 100644 index 0000000..0b0f615 --- /dev/null +++ b/get_next_line.h @@ -0,0 +1,30 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_next_line.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/08/28 11:24:52 by ljiriste #+# #+# */ +/* Updated: 2023/10/11 18:16:37 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef GET_NEXT_LINE_H +# define GET_NEXT_LINE_H + +# ifndef BUFFER_SIZE +# define BUFFER_SIZE 80 +# endif + +# include + +typedef struct s_file_thread +{ + int fd; + char *buffer; +} t_ft; + +char *get_next_line(int fd); + +#endif diff --git a/libft.h b/libft.h index e40e688..ac0e5b2 100644 --- a/libft.h +++ b/libft.h @@ -38,6 +38,7 @@ int ft_memcmp(const void *s1, const void *s2, size_t n); size_t ft_strlen(const char *s); size_t ft_strlcpy(char *dst, const char *src, size_t size); size_t ft_strlcat(char *dst, const char *src, size_t size); +char *ft_strncat_alloc(char **dest, const char *src, size_t n); int ft_strncmp(const char *s1, const char *s2, size_t n); char *ft_strchr(const char *s, int c); char *ft_strrchr(const char *s, int c); @@ -71,6 +72,8 @@ int ft_printf(const char *format, ...); void ft_swap(void **a, void **b); +char *get_next_line(int fd); + typedef struct s_list { struct s_list *next;