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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
ft_getline
==========
Description
----------
This is a custom implementation of a function that reads a stream of text and
returns the stream read when it finds the end of the file (EOL) or the end of
the file (EOF).
Instructions
------------
To clone the repository of this library run:
$ git clone https://git.yctct.com/ft_getline
$ cd ft_getline
This repository contains a main.c file for testing purposes.
To compile:
$ cc -Werror -Wall -Wextra main.c ft_getline.c getline_utils.c
ft_getline.h
You can define buffer size when compiling:
$ cc -Werror -Wall -Wextra -D BUFFER_SIZE=10 main.c ft_getline.c
ft_getline_utils.c ft_getline.h
Implementation choices
--------------------
### ft_getline
This function coordinates all the other functions, and, first it:
- copies the static variable stash from previous call of ft_getline to the
variable line
- checks if there is an EOL character in the current line
- if there is an EOL, the case is handled by eol_is_in_line
- if not, ft_getline calls keep_reading to keep reading the line
### keep_reading
This function runs a while loop until read_file returns 0.
Through each iteration this function:
- joins what was read in the buffer with what was previously stored in line
- checks if there is a EOL char
- if true, this case is handled by the function eol_is_in_line
- else, the function returns the line, if buffer is empty only (i.e. if nothing
was read), otherwise the function moves forward with the next iteration and
keeps reading the file
### read_file
This function reads a stream from a file
- reads file for a number of bytes
- null terminates the buffer used by read() to avoid garbage
- if zero bytes were read, there is two cases to deal with
- there are bytes left in the line from the previous iteration: in that
case the function print the line
- the variable line is empty, so the function returns NULL
- in the first case, this function assigns 0 to the stash, otherwise line would
be malloc'ed with 0 at the beginning of ft_getline and so the condition `if
(line[0] != 0)` in the function read_file would always be true
### eol_is_in_line
When EOF is found, this function:
- stashes bytes found after the EOL in the static variable stash
- assigns a 0 to the position pointed to by the pointer pivot, i.e. right after
the EOL in the line, so it can return the line up to EOL
- string duplicates the line before returning it so it is malloc'ed to the
right size
### Misc.
- EOL is set as macro in ft_getline.h
- the static variable stash is not malloc'ed to prevent leaks if there is an
error in between ft_getline calls
### Limitations
- this implementation does not malloc buffer through read store bytes; so
BUFFER_SIZE is limited to stack; to see stack size run ulimit -s
- this implementation does not handle BUFFER_SIZE 0
You can handle these two limitations in main.
### Possible improvements
- malloc the variable buf to handle BUFFER_SIZE with heap
- use OPEN_MAX instead of 1024 to limit of fd
- refactor code so ft_getline looks for EOL only once
- create condition to limit BUFFER_SIZE to the size of the stack (i.e. $ ulimit
-s)
Resources
---------
On static variables:
> "Internal static variables are local to a particular function [...], they
> remain in existence rather than coming and going each time the function is
> activated. This means that internal static variables provide private,
> *permanent storage within a single function*." *Highlight is mine*, C
> Programming Language, 2nd Edition, Brian W. Kernighan, Dennis M. Ritchie, 4.6
> Static Variables, p. 91.
On read() function:
> "Input uses the read and write system calls, which are accessed from C
> programs through two functions called read and write. For both, the first
> argument is a file descriptor. The second argument is a character array in
> your program where the data is to go to or to come from. The third argument
> is the number is the number of bytes to be transferred.
int n_read = read(int fd, char *buf, int n); [...]
> Each call returns a count of the number of bytes transferred. On reading, the
> number of bytes returned may be less than the number requested. A return
> value of zero bytes implies end of file, and -1 indicates an error of some
> sort. For writing, the return value is the number of bytes written; an error
> has occurred if this isn't equal to the number requested." C Programming
> Language, 2nd Edition, Brian W. Kernighan, Dennis M. Ritchie, 8.2 Low Level
> I/O - Read and Write, p. 184.
On unbuffered I/0, file descriptor and the read() function:
- Practical C programming, Steve Oualline, p.220-224
Also used:
- man page of read(), limits.h
License
-------
Copyright (C) 2026 yctct
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>.
See the file COPYING.
|