]> Untitled Git - axy/ft/get_next_line.git/commitdiff
Full impl
authorAxy <gilliardmarthey.axel@gmail.com>
Sat, 1 Nov 2025 15:36:51 +0000 (16:36 +0100)
committerAxy <gilliardmarthey.axel@gmail.com>
Sat, 1 Nov 2025 15:36:51 +0000 (16:36 +0100)
.editorconfig [new file with mode: 0644]
.gitignore [new file with mode: 0644]
get_next_line.c [new file with mode: 0644]
get_next_line.h [new file with mode: 0644]

diff --git a/.editorconfig b/.editorconfig
new file mode 100644 (file)
index 0000000..0b225af
--- /dev/null
@@ -0,0 +1,2 @@
+[*]
+indent_style = tab
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..a22a1c5
--- /dev/null
@@ -0,0 +1,3 @@
+*.o
+*.a
+*.out
diff --git a/get_next_line.c b/get_next_line.c
new file mode 100644 (file)
index 0000000..90f6879
--- /dev/null
@@ -0,0 +1,222 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   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);
+               }
+       }
+}
+*/
diff --git a/get_next_line.h b/get_next_line.h
new file mode 100644 (file)
index 0000000..5b88a19
--- /dev/null
@@ -0,0 +1,20 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   get_next_line.h                                    :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   By: agilliar <agilliar@student.42mulhouse.fr>  +#+  +:+       +#+        */
+/*                                                +#+#+#+#+#+   +#+           */
+/*   Created: 2025/11/01 10:38:19 by agilliar          #+#    #+#             */
+/*   Updated: 2025/11/01 13:17:10 by agilliar         ###   ########.fr       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#ifndef GET_NEXT_LINE_H
+# define GET_NEXT_LINE_H
+
+# include <stddef.h>
+
+char   *get_next_line(int fd);
+
+#endif