-
Notifications
You must be signed in to change notification settings - Fork 0
/
get_next_line_bonus.c
126 lines (118 loc) · 3.77 KB
/
get_next_line_bonus.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* get_next_line_bonus.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: rfelicio <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2021/08/15 21:51:45 by rfelicio #+# #+# */
/* Updated: 2021/08/30 15:40:33 by rfelicio ### ########.fr */
/* */
/* ************************************************************************** */
#include "get_next_line_bonus.h"
void ft_less(int fd, char **stream);
char *ft_get_line(char **stream);
/*
** The complicated and little perfect ultimate GeNiLson.
** Can takes more than one opened file descriptor (fd) and returns a line from
** eacg one of them.
** If sucessful, get_next_line returns a string with a line ended or not with
** the '\n' char.
** In the presence of errors or when reaching the end of the file, returns NULL
*/
char *get_next_line(int fd)
{
char *next_line;
static char *buffer[OPEN_MAX];
next_line = NULL;
if (fd < 0 || BUFFER_SIZE <= 0 || read(fd, next_line, 0) IS_INVALID)
return (NULL);
if (!buffer[fd])
buffer[fd] = ft_strdup(MOCK_DATA);
if (!ft_strchr(buffer[fd], NEW_LINE))
ft_less(fd, &buffer[fd]);
next_line = ft_get_line(&buffer[fd]);
if (buffer[fd] && buffer[fd][0] == '\0')
{
free(buffer[fd]);
buffer[fd] = NULL;
}
if (!next_line)
{
free(next_line);
next_line = NULL;
}
return (next_line);
}
/*
** Because less is more! RFTM: less ;)
** This procedure reads/unwrap the content of the file pointed by the file
** descriptor (fd), appending it to the pointer stored of the static char.
** This is made in this way:
** - Checks if buf and bytesread is valid
** - true:
** - Null terminate the read "string";
** - Reads until founds a '\n'char or the file ends. Either
** way, appends/joins the content read to the static variable.
** - false:
** - Memory deallocation.
*/
void ft_less(int fd, char **stream)
{
char *buf;
char *old_address;
ssize_t bytesread;
buf = (char *)malloc((BUFFER_SIZE + 1) * sizeof(char));
if (buf)
bytesread = read(fd, (void *)buf, BUFFER_SIZE);
if (buf && bytesread IS_VALID)
{
buf[bytesread] = '\0';
while (!ft_strchr(buf, NEW_LINE) && bytesread IS_VALID)
{
old_address = *stream;
*stream = ft_strjoin(*stream, buf);
if (old_address)
free(old_address);
bytesread = read(fd, (void *)buf, BUFFER_SIZE);
buf[bytesread] = '\0';
}
old_address = *stream;
*stream = ft_strjoin(*stream, buf);
if (old_address)
free(old_address);
}
free(buf);
}
/*
** Extracts a line to be returned by get_next_line(int fd).
** First of all:
** - Checks if there is an error *stream == NULL OR
** if the EOF was reached. In both scenarios, returns NULL.
** - Sets the line len (Remembering that the line can contain the
** '\n' char or not);
** - If the line ends with '\n', line len should be updated.
** - Write the current line;
** - Removes it from the static char;
** - Performs memory management.
*/
char *ft_get_line(char **stream)
{
int len;
char *line;
char *snippet;
if (*stream == NULL || (*(*stream)) == '\0')
return (GNL_EOF);
len = 0;
line = NULL;
snippet = *stream;
while (snippet[len] != NEW_LINE && snippet[len] != '\0')
++len;
if (snippet[len] == NEW_LINE)
++len;
line = ft_substr(snippet, 0, len);
*stream = ft_strdup(snippet + len);
free(snippet);
snippet = NULL;
return (line);
}