/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* get_next_line.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: maix +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/11/23 17:38:21 by maix #+# #+# */ /* Updated: 2024/05/14 18:39:59 by maiboyer ### ########.fr */ /* */ /* ************************************************************************** */ #include "me/buffered_str/buf_str.h" #include "me/gnl/gnl.h" #include "me/mem/mem.h" #include "me/mem/mem_move.h" #include "me/string/str_len.h" #include "me/types.h" #include #include #include static t_static_buffer *get_next_line_buffer(t_file fd) { t_usize index; static t_static_buffer bufs[BUFFER_LENGTH] = {0}; index = 0; while (index < BUFFER_LENGTH && (bufs[index].fd != fd && bufs[index].used)) index++; if (index == BUFFER_LENGTH) return (NULL); bufs[index].fd = fd; bufs[index].used = true; return (&bufs[index]); } static bool copy_next_line_into_buffer(t_file fd, t_buffer_str *out, char *temp_buffer, t_usize amount) { char *buf; char *newline; bool got_newline; t_usize other_part_len; buf = get_next_line_buffer(fd)->buf; newline = buf; while (*newline != '\n' && *newline && newline < buf + amount) newline++; got_newline = *newline == '\n'; other_part_len = amount - (t_usize)(newline - buf + !got_newline); if (amount < (t_usize)(newline - buf + !got_newline)) other_part_len = 0; mem_move(temp_buffer, buf, (t_usize)(newline - buf + got_newline)); buf[(t_usize)(newline - buf)] = 0; temp_buffer[(t_usize)(newline - buf + got_newline)] = 0; mem_move(buf, newline + 1, other_part_len); push_str_buffer(out, temp_buffer); buf[amount - (t_usize)(newline - buf + got_newline)] = 0; return (got_newline); } static bool read_and_copy(t_file fd, t_buffer_str *out, char *tmp, t_copy_flags *flags) { t_isize amount; t_static_buffer *buf; buf = get_next_line_buffer(fd); amount = read(fd, &buf->buf, BUFFER_SIZE); flags->error = amount < 0; if (flags->error) return (true); buf->init = true; if ((t_isize)amount < (t_isize)BUFFER_SIZE) { copy_next_line_into_buffer(fd, out, tmp, (t_usize)amount); flags->empty_read = (amount == 0 && out->len == 0); return (true); } buf->buf[(t_usize)amount] = 0; return (copy_next_line_into_buffer(fd, out, tmp, (t_usize)amount)); } static bool handle_leftovers(t_file fd, char *temp_buffer, t_buffer_str *buf) { t_static_buffer *static_buffer; static_buffer = get_next_line_buffer(fd); if (static_buffer->init) { if (copy_next_line_into_buffer(fd, buf, temp_buffer, str_len(static_buffer->buf))) { mem_free(temp_buffer); return (true); } } return (false); } t_buffer_str get_next_line(t_file fd, bool *error) { t_buffer_str buf; char *temp_buffer; t_copy_flags flags; *error = false; if (fd < 0 || BUFFER_SIZE <= 0) return (*error = true, (t_buffer_str){0}); flags = (t_copy_flags){ .error = false, .empty_read = false, }; temp_buffer = mem_alloc(sizeof(char) * (BUFFER_SIZE + 2)); buf = alloc_new_buffer(32); if (handle_leftovers(fd, temp_buffer, &buf)) return (buf); while (!read_and_copy(fd, &buf, temp_buffer, &flags) && !flags.empty_read) ; mem_free(temp_buffer); if (flags.error || flags.empty_read) { mem_free(buf.buf); return (*error = true, (t_buffer_str){0}); } return (buf); }