diff --git a/incs/get_next_line.h b/incs/get_next_line.h index 95de7f9..6238329 100644 --- a/incs/get_next_line.h +++ b/incs/get_next_line.h @@ -1,10 +1,29 @@ #ifndef GET_NEXT_LINE_H # define GET_NEXT_LINE_H +# define BUFF_SIZE 1024 + # include "libft.h" -# define BUFF_SIZE 32 +# include + +typedef struct s_gnl +{ + int fd; + char *str; + char *tmp; + char *line; + size_t len; + size_t len_old; + size_t i; + char eof; + char start; + char stop; + char lf; + struct s_gnl *next; + struct s_gnl *prev; +} t_gnl; -int get_next_line(const int fd, char **line); +int get_next_line(int const fd, char **line); #endif diff --git a/srcs/ft_get_/get_next_line.c b/srcs/ft_get_/get_next_line.c index 5be3f2e..3e85c44 100644 --- a/srcs/ft_get_/get_next_line.c +++ b/srcs/ft_get_/get_next_line.c @@ -1,95 +1,127 @@ +#include +#include +#include +#include "libft.h" #include "get_next_line.h" -static int copy_line(char **line, char *buf) +static t_gnl *gnl_init(int const fd, t_gnl **gnl) { - char *c; - char *tmp; - int len; + t_gnl *el; - len = ft_strlen(buf); - tmp = ft_strnew(len); - if (!tmp) - return (-1); - ft_memccpy(tmp, buf, '\n', len); - c = ft_strchr(tmp, '\n'); - if (c) - *c = '\0'; - c = *line; - *line = ft_strjoin(*line, tmp); - ft_strdel(&c); - ft_strdel(&tmp); - if (!*line) - return (-1); - return (1); + if ((el = *gnl)) + { + while (el->prev) + el = el->prev; + while (el) + { + if (el->fd == fd) + return (el); + el = el->next; + } + } + if (!(el = (t_gnl *)ft_memalloc(sizeof(t_gnl)))) + return (NULL); + el->fd = fd; + if (!(el->str = ft_strnew(BUFF_SIZE))) + return (NULL); + el->prev = NULL; + el->next = *gnl; + el->eof = 0; + el->len = 0; + if (*gnl != NULL) + (*gnl)->prev = el; + return ((*gnl = el)); } -static int line_endl(char *buf) +static int gnl_return(t_gnl **gnl, char **line, char stop) { - char *str; + t_gnl *old; - if ((str = ft_strchr(buf, '\n'))) - { - ft_strcpy(buf, (str + 1)); + if ((*line = (*gnl)->line)) return (1); + free((*gnl)->str); + if ((*gnl)->prev) + (*gnl)->prev->next = (*gnl)->next; + if ((*gnl)->next) + (*gnl)->next->prev = (*gnl)->prev; + if ((*gnl)->next == NULL && (*gnl)->prev == NULL) + { + ft_memdel((void **)gnl); } - ft_strclr(buf); - return (0); + else + { + old = *gnl; + *gnl = ((*gnl)->prev ? (*gnl)->prev : (*gnl)->next); + ft_memdel((void **)&old); + } + *line = NULL; + return (stop); } -static int read_lines(int fd, char **line, char *buf) +static void gnl_getstr(t_gnl *gnl, char *stop) { - int res; - int ret; - - while ((res = read(fd, buf, BUFF_SIZE)) > 0) + if (gnl->len > 0 && ((!(gnl->str[0] == '\n') && *stop == 0) || gnl->line)) { - buf[res] = '\0'; - ret = copy_line(line, buf); - if (ret == -1) - return (-1); - if (line_endl(buf)) - return (1); + gnl->len_old = (gnl->tmp == NULL ? 0 : ft_strlen(gnl->tmp)); + while (gnl->i < gnl->len && gnl->str[gnl->i] != '\n') + gnl->i++; + if (gnl->i > 0) + { + if (!(gnl->line = ft_strnew(gnl->i + gnl->len_old)) + && (*stop = -1) == -1) + return ; + ft_memmove(gnl->line, gnl->tmp, gnl->len_old); + ft_memmove(gnl->line + gnl->len_old, gnl->str, gnl->i); + ft_memdel((void **)&gnl->tmp); + } } - if (res == 0) + else if (gnl->len > 0) + gnl->line = ft_strdup("\0"); + if (gnl->str[gnl->i] == '\n' && (*stop = 1) == *stop) { - if (ft_strlen(*line)) - return (1); - return (0); + gnl->lf = 1; + ft_memmove(gnl->str, gnl->str + gnl->i + 1, gnl->len - gnl->i); } - return (-1); + else if (gnl->eof == 1) + ft_memmove(gnl->str, gnl->str + gnl->i, gnl->len - gnl->i); + ft_memset(gnl->str + gnl->len - gnl->i, '\0', gnl->i); } -static int init_read(char **line) +static void gnl_read(t_gnl *gnl, char *stop) { - *line = ft_strnew(0); - if (!*line) - return (-1); - return (0); + gnl->len = read(gnl->fd, gnl->str, BUFF_SIZE); + if (gnl->len == (size_t)(-1) && (*stop = -1) == -1) + return ; + gnl->str[gnl->len] = '\0'; + if ((gnl->len != BUFF_SIZE && gnl->fd != 0) + || (gnl->fd == 0 && gnl->len == 0)) + gnl->eof = 1; } -int get_next_line(const int fd, char **line) +int get_next_line(int const fd, char **line) { - int ret; - static char buf[BUFF_SIZE + 1]; + static t_gnl *gnl = NULL; - if (!line) - return (-1); - ret = init_read(line); - if (ret == -1) + if (!line || fd < 0 || !(gnl = gnl_init(fd, &gnl))) return (-1); - if (ft_strlen(buf)) + gnl->line = NULL; + if (gnl->len == 0 && gnl->eof == 1) + return (gnl_return(&gnl, line, 0)); + gnl->stop = 0; + gnl->start = 0; + while (gnl->stop == 0) { - ret = copy_line(line, buf); - if (ret == -1) - return (-1); - if (line_endl(buf)) - return (1); + gnl->i = 0; + gnl->lf = 0; + gnl->tmp = gnl->line; + if (gnl->len > 0 || gnl->start == 1) + gnl_getstr(gnl, &gnl->stop); + gnl->len -= (gnl->i + gnl->lf); + if (gnl->eof == 1) + break ; + if (gnl->stop == 0 && gnl->eof == 0) + gnl_read(gnl, &gnl->stop); + gnl->start = 1; } - ret = read_lines(fd, line, buf); - if (ret == -1) - return (-1); - else if (ret == 0) - return (0); - else - return (1); + return (gnl_return(&gnl, line, gnl->stop)); }