/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/01 10:55:35 by agilliar #+# #+# */
-/* Updated: 2025/11/01 20:55:35 by agilliar ### ########.fr */
+/* Updated: 2025/11/06 18:00:50 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdbool.h>
#include <stdlib.h>
-#include "get_next_line.h"
-void *ft_memcpy(void *dest, const void *src, size_t n);
-bool buffer_shrink_near_fit(t_buf *buf);
-bool buffer_search(t_buf *buf);
-bool buffer_read(t_buf *buf, int fd);
+#include "get_next_line.h"
-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 = NULL;
- return (&(*buffers)->buf);
-}
+void buffer_pushchar(t_buf *buf, char c);
+void buffers_remove(t_readbufs *bufs, int fd);
+void *ft_memcpy(void *dest, const void *src, size_t n);
+bool readbuf_read(t_readbuf *buf);
+t_readbuf *buffers_get(t_readbufs *bufs, int fd);
-void *buffers_del(t_list **buffers, int fd)
+char *buffer_finish(t_buf buf, t_readbufs *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);
+ if (buf.buf)
+ buffer_pushchar(&buf, '\0');
+ if (!buf.buf)
+ buffers_remove(buffers, fd);
+ return (buf.buf);
}
-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)
+/*
+ returns whether it should keep going
+*/
+bool buffer_empty(t_readbuf *buf, t_buf *dst)
{
- char *res;
+ size_t i;
- 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);
+ if (buf->written == 0)
+ return (false);
+ i = 0;
+ while (i < buf->written)
+ {
+ buffer_pushchar(dst, buf->buf[i++]);
+ if (dst->buf == NULL)
+ return (false);
+ if (dst->buf[dst->len - 1] == '\n')
+ break ;
+ }
+ buf->written -= i;
+ ft_memcpy(buf->buf, &buf->buf[i], buf->written);
+ if (dst->buf[dst->len - 1] == '\n')
+ return (false);
+ return (true);
}
char *get_next_line(int fd)
{
- static t_list *buffers = NULL;
- t_buf *buf;
- char *res;
+ static t_readbufs buffers = {
+ .used = 0
+ };
+ t_readbuf *buf;
+ t_buf res;
+ res.len = 0;
+ res.capacity = 0;
+ res.buf = NULL;
buf = buffers_get(&buffers, fd);
if (!buf)
return (NULL);
- while (buf->len != buf->search_offset || buffer_read(buf, fd))
+ while (true)
{
- if (buf->search_offset == buf->len)
+ if (!readbuf_read(buf))
{
- res = ft_substr(buf->buf, buf->len);
- buffers_del(&buffers, fd);
- return (res);
+ buffers_remove(&buffers, fd);
+ free(res.buf);
+ return (NULL);
}
- if (buffer_search(buf))
- return (buffer_gnl(buf, &buffers, fd));
+ if (!buffer_empty(buf, &res))
+ return (buffer_finish(res, &buffers, fd));
}
- return (buffers_del(&buffers, fd));
}
/*
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/11/01 10:38:19 by agilliar #+# #+# */
-/* Updated: 2025/11/01 20:52:08 by agilliar ### ########.fr */
+/* Updated: 2025/11/06 17:20:44 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
# include <stddef.h>
+# ifndef BUFFER_SIZE
+# define BUFFER_SIZE 256
+# endif
+
+# ifndef GNL_MAX_FD
+# define GNL_MAX_FD 256
+# endif
+
typedef struct s_buf
{
size_t len;
size_t capacity;
- size_t search_offset;
char *buf;
} t_buf;
-typedef struct s_list
+typedef struct s_readbuf
{
- int fd;
- t_buf buf;
- struct s_list *next;
-} t_list;
+ size_t written;
+ int fd;
+ char buf[BUFFER_SIZE];
+} t_readbuf;
-# ifndef BUFFER_SIZE
-# define BUFFER_SIZE 256
-# endif
+typedef struct s_readbufs
+{
+ size_t used;
+ t_readbuf bufs[GNL_MAX_FD];
+} t_readbufs;
char *get_next_line(int fd);
+++ /dev/null
-/* ************************************************************************** */
-/* */
-/* ::: :::::::: */
-/* get_next_line_bonus.c :+: :+: :+: */
-/* +:+ +:+ +:+ */
-/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
-/* +#+#+#+#+#+ +#+ */
-/* Created: 2025/11/01 10:55:35 by agilliar #+# #+# */
-/* Updated: 2025/11/01 20:57:34 by agilliar ### ########.fr */
-/* */
-/* ************************************************************************** */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include "get_next_line_bonus.h"
-
-void *ft_memcpy(void *dest, const void *src, size_t n);
-bool buffer_shrink_near_fit(t_buf *buf);
-bool buffer_search(t_buf *buf);
-bool buffer_read(t_buf *buf, int fd);
-
-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 = NULL;
- 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);
- free(nl);
- }
- }
- for (char *nl; (nl = get_next_line(0));)
- {
- printf("stdin: %s", nl);
- free(nl);
- }
-}
-*/
+++ /dev/null
-/* ************************************************************************** */
-/* */
-/* ::: :::::::: */
-/* get_next_line_bonus.h :+: :+: :+: */
-/* +:+ +:+ +:+ */
-/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
-/* +#+#+#+#+#+ +#+ */
-/* Created: 2025/11/01 10:38:19 by agilliar #+# #+# */
-/* Updated: 2025/11/01 20:57:37 by agilliar ### ########.fr */
-/* */
-/* ************************************************************************** */
-
-#ifndef GET_NEXT_LINE_BONUS_H
-# define GET_NEXT_LINE_BONUS_H
-
-# include <stddef.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;
-
-# ifndef BUFFER_SIZE
-# define BUFFER_SIZE 256
-# endif
-
-char *get_next_line(int fd);
-
-#endif
/* ::: :::::::: */
/* get_next_line_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
-/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
-/* Created: 2025/11/01 20:47:32 by agilliar #+# #+# */
-/* Updated: 2025/11/01 20:52:30 by agilliar ### ########.fr */
+/* Created: 2025/11/06 17:56:20 by agilliar #+# #+# */
+/* Updated: 2025/11/06 17:58:50 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
+
#include "get_next_line.h"
-/*
- 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)
+t_readbuf *buffers_get(t_readbufs *bufs, int fd)
{
size_t i;
i = 0;
- while (i < n)
- {
- ((unsigned char *)dest)[i] = ((unsigned char *)src)[i];
+ while (i < bufs->used && bufs->bufs[i].fd != fd)
i++;
+ if (i == GNL_MAX_FD)
+ return (NULL);
+ if (i == bufs->used)
+ {
+ bufs->bufs[i].written = 0;
+ bufs->bufs[i].fd = fd;
+ bufs->used++;
}
- return (dest);
+ return (&bufs->bufs[i]);
}
-/*
- returns false when an allocation error occured
-*/
-bool buffer_reserve(t_buf *buf, size_t extra)
+void buffers_remove(t_readbufs *bufs, int fd)
{
- size_t new_capacity;
- char *new_buf;
+ size_t i;
+
+ i = 0;
+ while (i < bufs->used && bufs->bufs[i].fd != fd)
+ i++;
+ if (i == GNL_MAX_FD)
+ return ;
+ bufs->bufs[i] = bufs->bufs[--bufs->used];
+}
+
+bool readbuf_read(t_readbuf *buf)
+{
+ int n;
- if (buf->len + extra <= buf->capacity)
+ if (buf->written != 0)
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)
+ n = read(buf->fd, &buf->buf, BUFFER_SIZE);
+ if (n < 0)
return (false);
- ft_memcpy(new_buf, buf->buf, buf->len);
- free(buf->buf);
- buf->buf = new_buf;
- buf->capacity = new_capacity;
+ buf->written = n;
return (true);
}
-bool buffer_read(t_buf *buf, int fd)
+void *ft_memcpy(void *dest, const void *src, size_t n)
{
- char read_buf[BUFFER_SIZE];
- ssize_t res;
+ size_t i;
- 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);
+ i = 0;
+ while (i < n)
+ {
+ ((unsigned char *)dest)[i] = ((unsigned char *)src)[i];
+ i++;
+ }
+ return (dest);
}
/*
- returns false when an allocation error occured
+ frees its own resources on failure
*/
-bool buffer_shrink_near_fit(t_buf *buf)
+void buffer_pushchar(t_buf *buf, char c)
{
+ size_t new_capacity;
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);
+ if (buf->len + 1 > buf->capacity)
+ {
+ new_capacity = buf->len + 1;
+ if (new_capacity < BUFFER_SIZE + buf->capacity * 2)
+ new_capacity = BUFFER_SIZE + buf->capacity * 2;
+ new_buf = malloc(new_capacity);
+ if (!new_buf)
+ {
+ free(buf->buf);
+ buf->buf = NULL;
+ return ;
+ }
+ ft_memcpy(new_buf, buf->buf, buf->len);
+ free(buf->buf);
+ buf->buf = new_buf;
+ buf->capacity = new_capacity;
+ }
+ buf->buf[buf->len++] = c;
}
+++ /dev/null
-/* ************************************************************************** */
-/* */
-/* ::: :::::::: */
-/* get_next_line_utils_bonus.c :+: :+: :+: */
-/* +:+ +:+ +:+ */
-/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
-/* +#+#+#+#+#+ +#+ */
-/* Created: 2025/11/01 20:47:32 by agilliar #+# #+# */
-/* Updated: 2025/11/01 20:57:50 by agilliar ### ########.fr */
-/* */
-/* ************************************************************************** */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "get_next_line_bonus.h"
-
-/*
- 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);
-}