/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/08/28 00:01:15 by ljiriste #+# #+# */
-/* Updated: 2023/10/13 16:01:58 by ljiriste ### ########.fr */
+/* Updated: 2023/10/25 13:06:18 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
cur = cur->next;
}
if (prev == NULL)
- *list = NULL;
+ *list = cur->next;
else
prev->next = cur->next;
free(((t_ft *)(cur->content))->buffer);
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* get_next_line.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2023/08/28 00:01:15 by ljiriste #+# #+# */
+/* Updated: 2023/10/25 13:06:18 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include "get_next_line.h"
+
+// 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);
+ buffer[i] = '\0';
+ if (i <= 0)
+ delete_file_node(fd, &list);
+ if (i < 0)
+ {
+ free(res);
+ return (NULL);
+ }
+ if (i == 0)
+ return (res);
+ }
+ }
+ return (res);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* get_next_line.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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 <stddef.h>
+
+typedef struct s_file_thread
+{
+ int fd;
+ char *buffer;
+} t_ft;
+
+typedef struct s_list
+{
+ void *content;
+ struct s_list *next;
+} t_list;
+
+char *get_next_line(int fd);
+
+t_list *new_ft_node(int fd);
+t_list *ft_lstnew(void *content);
+void *ft_memmove(void *dest, const void *src, size_t n);
+void ft_strncat_alloc(char **dest, const char *src, int n);
+
+char *get_next_line(int fd);
+
+#endif
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* get_next_line_utils.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2023/09/11 13:36:53 by ljiriste #+# #+# */
+/* Updated: 2023/10/11 15:42:18 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+/* Functions in this file may (and should) be substituted by Libft functions
+ after this project is integrated into Libft
+*/
+
+#include <stdlib.h> // malloc etc.
+#include "get_next_line.h"
+
+//This function may be useful enough to add to Libft
+/* Functions like ft_strncat but reallocates dest to
+ make sure it is large enough */
+void ft_strncat_alloc(char **dest, const char *src, int n)
+{
+ int size;
+ char *temp;
+
+ if (n <= 0)
+ return ;
+ temp = *dest;
+ size = 0;
+ if (temp)
+ while (temp[size])
+ ++size;
+ size += n + 1;
+ *dest = malloc(size);
+ if (*dest == NULL)
+ {
+ free(temp);
+ return ;
+ }
+ ft_memmove(*dest, temp, size - n - 1);
+ ft_memmove(*dest + size - n - 1, src, n);
+ (*dest)[size - 1] = '\0';
+ free(temp);
+ return ;
+}
+
+void *ft_memmove(void *dest, const void *src, size_t n)
+{
+ size_t i;
+
+ if (dest > src)
+ {
+ i = n;
+ while (i > 0)
+ {
+ --i;
+ *((unsigned char *)dest + i) = *((unsigned char *)src + i);
+ }
+ }
+ else if (dest < src)
+ {
+ i = 0;
+ while (i < n)
+ {
+ *((unsigned char *)dest + i) = *((unsigned char *)src + i);
+ ++i;
+ }
+ }
+ return (dest);
+}
+
+t_list *ft_lstnew(void *content)
+{
+ t_list *res;
+
+ res = malloc(sizeof(t_list));
+ if (res == NULL)
+ return (res);
+ res->content = content;
+ res->next = NULL;
+ return (res);
+}
+
+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);
+}