--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* get_next_line.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/11/01 10:55:35 by agilliar #+# #+# */
+/* Updated: 2025/11/01 16:36:45 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+typedef struct s_buf
+{
+ size_t len;
+ size_t capacity;
+ size_t search_offset;
+ char *buf;
+} t_buf;
+
+typedef struct s_list
+{
+ int fd;
+ t_buf buf;
+ struct s_list *next;
+} t_list;
+
+#define BUFFER_SIZE 256
+
+/*
+ not restrict, therefor it is safe to use it on overlapping memory regions so
+ long as the destination is before the source
+*/
+void *ft_memcpy(void *dest, const void *src, size_t n)
+{
+ size_t i;
+
+ i = 0;
+ while (i < n)
+ {
+ ((unsigned char *)dest)[i] = ((unsigned char *)src)[i];
+ i++;
+ }
+ return (dest);
+}
+
+/*
+ returns false when an allocation error occured
+*/
+bool buffer_reserve(t_buf *buf, size_t extra)
+{
+ size_t new_capacity;
+ char *new_buf;
+
+ if (buf->len + extra <= buf->capacity)
+ return (true);
+ new_capacity = buf->len + extra;
+ if (new_capacity < buf->capacity * 2)
+ new_capacity = buf->capacity * 2;
+ new_buf = malloc(new_capacity);
+ if (!new_buf)
+ return (false);
+ ft_memcpy(new_buf, buf->buf, buf->len);
+ free(buf->buf);
+ buf->buf = new_buf;
+ buf->capacity = new_capacity;
+ return (true);
+}
+
+bool buffer_read(t_buf *buf, int fd)
+{
+ char read_buf[BUFFER_SIZE];
+ ssize_t res;
+
+ res = read(fd, read_buf, BUFFER_SIZE);
+ if (res < 1 || !buffer_reserve(buf, res))
+ return (false);
+ ft_memcpy(&buf->buf[buf->len], read_buf, res);
+ buf->len += res;
+ return (true);
+}
+
+/*
+ returns false when an allocation error occured
+*/
+bool buffer_shrink_near_fit(t_buf *buf)
+{
+ char *new_buf;
+
+ if (buf->capacity <= buf->len * 2 + BUFFER_SIZE)
+ return (true);
+ new_buf = malloc(buf->len * 2);
+ if (!new_buf)
+ return (false);
+ ft_memcpy(new_buf, buf->buf, buf->len);
+ free(buf->buf);
+ buf->buf = new_buf;
+ buf->capacity = buf->len * 2;
+ return (true);
+}
+
+bool buffer_search(t_buf *buf)
+{
+ while (buf->search_offset < buf->len)
+ if (buf->buf[buf->search_offset++] == '\n')
+ return (true);
+ return (false);
+}
+
+t_buf *buffers_get(t_list **buffers, int fd)
+{
+ while (*buffers && (*buffers)->fd != fd)
+ buffers = &(*buffers)->next;
+ if (*buffers)
+ return (&(*buffers)->buf);
+ (*buffers) = malloc(sizeof(t_list));
+ if (!*buffers)
+ return (NULL);
+ (*buffers)->next = NULL;
+ (*buffers)->fd = fd;
+ (*buffers)->buf.len = 0;
+ (*buffers)->buf.capacity = 0;
+ (*buffers)->buf.search_offset = 0;
+ (*buffers)->buf.buf = malloc(0);
+ return (&(*buffers)->buf);
+}
+
+void *buffers_del(t_list **buffers, int fd)
+{
+ t_list *next;
+
+ while (*buffers && (*buffers)->fd != fd)
+ buffers = &(*buffers)->next;
+ if (!*buffers)
+ return (NULL);
+ free((*buffers)->buf.buf);
+ next = (*buffers)->next;
+ free(*buffers);
+ *buffers = next;
+ return (NULL);
+}
+
+char *ft_substr(const char *src, size_t len)
+{
+ char *res;
+
+ res = malloc(len + 1);
+ if (!res)
+ return (res);
+ ft_memcpy(res, src, len);
+ res[len] = '\0';
+ return (res);
+}
+
+char *buffer_gnl(t_buf *buf, t_list **buffers, int fd)
+{
+ char *res;
+
+ res = ft_substr(buf->buf, buf->search_offset);
+ if (!res)
+ return (buffers_del(buffers, fd));
+ buf->len -= buf->search_offset;
+ ft_memcpy(buf->buf, &buf->buf[buf->search_offset], buf->len);
+ buf->search_offset = 0;
+ buffer_shrink_near_fit(buf);
+ return (res);
+}
+
+char *get_next_line(int fd)
+{
+ static t_list *buffers = NULL;
+ t_buf *buf;
+ char *res;
+
+ buf = buffers_get(&buffers, fd);
+ if (!buf)
+ return (NULL);
+ while (buf->len != buf->search_offset || buffer_read(buf, fd))
+ {
+ if (buf->search_offset == buf->len)
+ {
+ res = ft_substr(buf->buf, buf->len);
+ buffers_del(&buffers, fd);
+ return (res);
+ }
+ if (buffer_search(buf))
+ return (buffer_gnl(buf, &buffers, fd));
+ }
+ return (buffers_del(&buffers, fd));
+}
+
+/*
+#include <fcntl.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ char *nl;
+ bool any_line;
+
+ for (int i = 1; i < argc; i++)
+ ((int *)argv)[i] = open(argv[i], O_RDONLY);
+ any_line = true;
+ for (int i = 0; any_line; i++)
+ {
+ any_line = false;
+ for (int j = 1; j < argc; j++)
+ {
+ nl = get_next_line(((int *)argv)[j]);
+ if (!nl)
+ continue;
+ any_line = true;
+ printf("line %i file %i: %s", i, j, nl);
+ }
+ }
+}
+*/