From 6da979416f6ac74ac539e0ccbf2ed3c01ddd04cd Mon Sep 17 00:00:00 2001 From: kurrrru Date: Wed, 11 Dec 2024 20:34:54 +0900 Subject: [PATCH] add gnl --- libft/Makefile | 3 +- libft/get_next_line.c | 47 +++++++++++++ libft/get_next_line.h | 33 ++++++++++ libft/get_next_line_utils.c | 127 ++++++++++++++++++++++++++++++++++++ libft/libft.h | 1 + 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 libft/get_next_line.c create mode 100644 libft/get_next_line.h create mode 100644 libft/get_next_line_utils.c diff --git a/libft/Makefile b/libft/Makefile index 9b8ae94..b39db28 100644 --- a/libft/Makefile +++ b/libft/Makefile @@ -6,7 +6,8 @@ SRCS = ft_atoi.c ft_memchr.c ft_split.c ft_strncmp.c \ ft_isascii.c ft_putchar_fd.c ft_strlcat.c ft_tolower.c \ ft_isdigit.c ft_putendl_fd.c ft_strlcpy.c ft_toupper.c \ ft_isprint.c ft_putnbr_fd.c ft_strlen.c \ - ft_itoa.c ft_putstr_fd.c ft_strmapi.c + ft_itoa.c ft_putstr_fd.c ft_strmapi.c \ + get_next_line.c get_next_line_utils.c BONUS_SRCS = ft_lstadd_back_bonus.c ft_lstlast_bonus.c \ ft_lstadd_front_bonus.c ft_lstmap_bonus.c \ ft_lstclear_bonus.c ft_lstnew_bonus.c \ diff --git a/libft/get_next_line.c b/libft/get_next_line.c new file mode 100644 index 0000000..19ea277 --- /dev/null +++ b/libft/get_next_line.c @@ -0,0 +1,47 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_next_line.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: nkawaguc +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/03 20:02:39 by nkawaguc #+# #+# */ +/* Updated: 2024/06/28 00:35:41 by nkawaguc ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "get_next_line.h" + +// get_next_line: read a line from a file descriptor +// If fd is invalid or BUFFER_SIZE is invalid, return NULL. +// If buf is not initialized, initialize it with buf_init. +// Allocate a line buffer and initialize it with '\0'. +// Read until a newline character is found or EOF is reached with gnl_read. +// return: a line read from the file descriptor +char *get_next_line(int fd) +{ + static char *buf = NULL; + char *line; + int line_size; + int flag; + + if (fd < 0 || BUFFER_SIZE <= 0 || buf_init(&buf) == -1) + return (NULL); + line_size = BUFFER_SIZE + 1; + line = (char *)malloc(line_size * sizeof(char)); + if (!line) + return (free(buf), gnl_bzero(&buf, sizeof(char *)), NULL); + gnl_bzero(line, line_size); + flag = gnl_read(fd, &line, &line_size, buf); + if (flag == -1 || flag == 0) + { + free(buf); + gnl_bzero(&buf, sizeof(char *)); + if (flag == -1 || line[0] == '\0') + return (free(line), NULL); + } + line = gnl_realloc(line, 0, line_size); + if (line == NULL) + return (free(buf), gnl_bzero(&buf, sizeof(char *)), NULL); + return (line); +} diff --git a/libft/get_next_line.h b/libft/get_next_line.h new file mode 100644 index 0000000..94ecc8b --- /dev/null +++ b/libft/get_next_line.h @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_next_line.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: nkawaguc +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/03 20:02:43 by nkawaguc #+# #+# */ +/* Updated: 2024/06/28 00:35:31 by nkawaguc ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef GET_NEXT_LINE_H +# define GET_NEXT_LINE_H + +# include +# include +# include + +# ifndef BUFFER_SIZE +# define BUFFER_SIZE 1024 +# endif + +// # define DEBUG + +char *get_next_line(int fd); +int buf_init(char **buf); +void *gnl_realloc(void *ptr, size_t new_size, size_t old_size); +int gnl_strncat(char **dst, const char *src, int *line_size, int *cat_size); +int gnl_read(int fd, char **line, int *line_size, char *buf); +void gnl_bzero(void *buf, size_t size); + +#endif diff --git a/libft/get_next_line_utils.c b/libft/get_next_line_utils.c new file mode 100644 index 0000000..a0263ea --- /dev/null +++ b/libft/get_next_line_utils.c @@ -0,0 +1,127 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* get_next_line_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: nkawaguc +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/03 20:02:34 by nkawaguc #+# #+# */ +/* Updated: 2024/06/28 00:25:18 by nkawaguc ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "get_next_line.h" + +// buf_init: Initialize buf if it is not initialized. +// After memory allocation, initialize the memory with '\0'. +// Return: whether the initialization is successful. (1: success, -1: error) +int buf_init(char **buf) +{ + if (*buf) + return (1); + *buf = (char *)malloc((BUFFER_SIZE + 1) * sizeof(char)); + if (*buf == NULL) + return (-1); + gnl_bzero(*buf, BUFFER_SIZE + 1); + return (1); +} + +// gnl_realloc: Reallocate memory with new_size. +// If the reallocation fails, free the original pointer and return NULL. +// If the reallocation succeeds, copy the original data to the new pointer. +// Return: the new pointer. +void *gnl_realloc(void *ptr, size_t new_size, size_t old_size) +{ + void *new_ptr; + size_t i; + + if (new_size == 0) + while (new_size == 0 || ((char *)ptr)[new_size - 1]) + new_size++; + new_ptr = malloc(new_size); + if (new_ptr == NULL) + return (free(ptr), NULL); + i = 0; + while (i < old_size && i < new_size) + { + ((char *)new_ptr)[i] = ((char *)ptr)[i]; + i++; + } + free(ptr); + return (new_ptr); +} + +// gnl_strncat: Concatenate src to dst. +// If the new_size of dst is not enough, it is reallocated in gnl_realloc. +// The size of the concatenated string of src is stored in cat_size. +// Return: the size of the concatenated string of src. +int gnl_strncat(char **dst, const char *src, int *line_size, int *cat_size) +{ + int i; + int j; + + i = -1; + while ((*dst)[++i]) + ; + j = 0; + while (src[j] && (j == 0 || src[j - 1] != '\n')) + { + if (i + j + 1 >= *line_size) + { + *dst = gnl_realloc(*dst, *line_size * 2, *line_size); + if (*dst == NULL) + { + *cat_size = -1; + return (-1); + } + *line_size *= 2; + } + (*dst)[i + j] = src[j]; + j++; + } + (*dst)[i + j] = '\0'; + *cat_size = j; + return (j); +} + +// gnl_bzero: Initialize buf with '\0'. +// Return: None +void gnl_bzero(void *buf, size_t size) +{ + while (size) + ((char *)buf)[--size] = '\0'; +} + +// gnl_read: Read from fd to buf and concatenate buf to line. +// If line is not empty, concatenate buf to line. +// If '\n' is not found in buf, read until '\n' is found or EOF is reached. +// Move the characters after first '\n' to the beginning of buf. +// Return: whether the reading is successful. (1: success, 0: EOF, -1: error) +int gnl_read(int fd, char **line, int *line_size, char *buf) +{ + int read_size; + int cat_size; + int i; + + cat_size = 0; + if (line[0] && gnl_strncat(line, buf, line_size, &cat_size) == -1) + return (-1); + if (!buf[cat_size] && (cat_size == 0 || buf[cat_size - 1] != '\n')) + { + while (1) + { + read_size = read(fd, buf, BUFFER_SIZE); + if (read_size == -1 || read_size == 0) + return (read_size); + buf[read_size] = '\0'; + if (gnl_strncat(line, buf, line_size, &cat_size) <= 0) + return (cat_size); + if (buf[cat_size - 1] == '\n') + break ; + } + } + i = -1; + while (++i <= BUFFER_SIZE - cat_size) + buf[i] = buf[cat_size + i]; + return (1); +} diff --git a/libft/libft.h b/libft/libft.h index 3ebf8a5..5e86442 100644 --- a/libft/libft.h +++ b/libft/libft.h @@ -17,6 +17,7 @@ # include # include # include +# include "get_next_line.h" // libc functions int ft_atoi(const char *str);