tgrekov-get_next_line
HIVE gnl Nov 2023
Loading...
Searching...
No Matches
get_next_line_bonus.c
Go to the documentation of this file.
1/* ************************************************************************** */
2/* */
3/* ::: :::::::: */
4/* get_next_line_bonus.c :+: :+: :+: */
5/* +:+ +:+ +:+ */
6/* By: tgrekov <tgrekov@student.hive.fi> +#+ +:+ +#+ */
7/* +#+#+#+#+#+ +#+ */
8/* Created: 2023/10/28 02:23:33 by tgrekov #+# #+# */
9/* Updated: 2023/12/12 07:48:20 by tgrekov ### ########.fr */
10/* */
11/* ************************************************************************** */
12
20#include "get_next_line_bonus.h"
21
32static char *consume_and_resize(char **s1, size_t len)
33{
34 size_t new_s1_len;
35 char *new_s1;
36 char *s2;
37
38 s2 = malloc(len + 1);
39 if (!s2)
40 return (0);
41 ft_memcpy(s2, *s1, len);
42 s2[len] = '\0';
43 new_s1_len = ft_strlen(*s1 + len);
44 new_s1 = 0;
45 if (new_s1_len)
46 {
47 new_s1 = malloc(new_s1_len + 1);
48 if (!new_s1)
49 {
50 free(s2);
51 return (0);
52 }
53 ft_memcpy(new_s1, *s1 + len, new_s1_len + 1);
54 }
55 free(*s1);
56 *s1 = new_s1;
57 return (s2);
58}
59
69static size_t find_line_end(char *s, size_t *len)
70{
71 *len = 0;
72 if (!s)
73 return (0);
74 while (s[*len])
75 {
76 if (s[(*len)++] == '\n')
77 return (*len);
78 }
79 return (*len = 0);
80}
81
94static size_t fill_line_buf(int fd, char **line_buf, size_t *first_line_len)
95{
96 char read_buf[BUFFER_SIZE + 1];
97 ssize_t read_len;
98 char *old;
99
100 read_len = BUFFER_SIZE;
101 while (!find_line_end(*line_buf, first_line_len) && read_len == BUFFER_SIZE)
102 {
103 read_len = read(fd, read_buf, BUFFER_SIZE);
104 if (read_len < 0)
105 return (*first_line_len = 0);
106 read_buf[read_len] = '\0';
107 if (!*line_buf)
108 *line_buf = ft_strdup(read_buf);
109 else
110 {
111 old = *line_buf;
112 *line_buf = ft_strjoin(*line_buf, read_buf);
113 free(old);
114 }
115 if (!*line_buf)
116 return (*first_line_len = 0);
117 }
118 if (read_len != BUFFER_SIZE && !*first_line_len)
119 *first_line_len = ft_strlen(*line_buf);
120 return (*first_line_len);
121}
122
131char *get_next_line(int fd)
132{
133 static char *line_buf[MAX_FD + 1] = {0};
134 size_t first_line_len;
135 char *out;
136
137 if (fd < 0 || fd > MAX_FD || BUFFER_SIZE < 1)
138 return (0);
139 fill_line_buf(fd, line_buf + fd, &first_line_len);
140 if (!first_line_len)
141 {
142 if (line_buf[fd])
143 free(line_buf[fd]);
144 return (line_buf[fd] = 0);
145 }
146 out = consume_and_resize(line_buf + fd, first_line_len);
147 if (!out)
148 {
149 free(line_buf[fd]);
150 line_buf[fd] = 0;
151 }
152 return (out);
153}
#define BUFFER_SIZE
Set default BUFFER_SIZE if it is not defined at compile time.
#define MAX_FD
Max open file descriptors per process.
static char * consume_and_resize(char **s1, size_t len)
Allocate and return a new string of size len + 1 containing len characters from string pointed to by ...
static size_t find_line_end(char *s, size_t *len)
Find the first newline in string s and write its index + 1 into len.
char * get_next_line(int fd)
Return the next segment of text ending in a newline or EOF from file descriptor fd.
static size_t fill_line_buf(int fd, char **line_buf, size_t *first_line_len)
Reading from fd, fill and / or allocate line buffer at line_buf, set first_line_len to the length of ...