Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

πŸ“œ Get Next Line (42 Paris) β€” Line-by-line reader for file descriptors in C. Arbitrary BUFFER_SIZE, optimized memory management, multiple file descriptors handling, linked-list based stash system.

Notifications You must be signed in to change notification settings

guillaumeast/42_GNL

Repository files navigation

This project has been created as part of the 42 curriculum by gastesan.

Get Next Line β€” 42 Paris Project

42 C Bonus Grade: 125/100

After evaluation, I refactored this project and integrated it into my libft as a separator-agnostic get_next_chunk() function.
You can find the detailed Doxygen documentation here

πŸ“‹ Table of Contents

πŸ“‡ Description

TL;DR

get_next_line is an implementation of a line-by-line reader for file descriptors (fd).

Precisions

Its goal is to provide a reliable, stateful, and norm-compliant function capable of returning one line per call while handling arbitrary buffer sizes and multiple file descriptors (bonus).
This project explores static storage, controlled memory management, and iterative parsing of streamed input.

Repository structure

.
β”œβ”€β”€ README.md
β”œβ”€β”€ main.c			# Only for tests
β”œβ”€β”€ file.txt		# Only for tests
β”œβ”€β”€ get_next_line.h
β”œβ”€β”€ get_next_line.c
β”œβ”€β”€ get_next_line_bonus.h
β”œβ”€β”€ get_next_line_bonus.c
β”œβ”€β”€ get_next_line_utils.c
└── get_next_line_utils_bonus.c

πŸ“– Instructions

Compilation

This project doesn't include main() function, so you need to provide your own one to compile:

cc get_next_line.c get_next_line_utils.c <your_main.c>

You can compile get_next_line with a custom BUFFER_SIZE by adding the -D BUFFER_SIZE=<N> flags

Usage

Call get_next_line(fd) to get the next line of a given fd (You can use as many fd you want, in any order).
When end of file (EOF) is reached or if an error occurs, get_next_line(fd) will return NULL.

Example

#include "get_next_line_bonus.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int	main(void)
{
	int		fd;
	char	*line;

	fd = open("file.txt", O_RDONLY);
	if (fd == -1)
		return (1);
	while ((line = get_next_line(fd)))
	{
		printf("%s", line);
		free(line);
	}
    close(fd);
	return (0);
}

πŸ’‘ Returned strings include the trailing newline (\n) when present.

⚠️ Don't forget to free() the line returned by get_next_line(fd)

🧠 Technical choices

Dynamic exponential growth

The output line buffer grows exponentially to minimize reallocations.
This ensures O(1) amortized concatenation when appending data read from the internal buffer.

Final shrink-to-fit

Once the line is complete, the allocated memory is reduced to the minimum required capacity before returning it.
This reduces memory footprint and avoids over-provisioning resulting from exponential growth.

Linked-list based fd management

To support multiple file descriptors simultaneously (required for the bonus), each fd is associated with its own stash node stored inside a linked list.

This prevents static global arrays, avoids overflow of the .bss segment, and keeps memory usage proportional to the number of active FDs.

Every node stores:

  • its fd
  • its read buffer and length
  • a pointer to the next node

Nodes are created on demand and removed as soon as the fd reaches EOF or an error occurs.

Norm constraints

No libc helpers such as memset/bzero were allowed, which would otherwise optimize buffer resets.
All operations are done manually.

Memory handling

Buffers are free'd as soon as possible (errors, EOF per fd, etc.).
However, since only the caller knows when an fd is no longer needed, some memory remains malloc'd until the program ends.
These are not true leaks; they remain β€œreachable” and intentionally persist due to project constraints.

🧩 Algorithm explanation

The algorithm centers around a per-fd stash storing:

  • a fixed-size read buffer
  • its current length
  • its continuation pointer for the linked list of stashes

Process summary

  1. Retrieve or create a stash for the requested fd.
  2. If leftover data exists in the buffer, process it first.
  3. Otherwise, read from the fd into the buffer.
  4. Search for \n.
    • If found β†’ append the slice, adjust buffer, shrink the allocated (line) buffer and return it.
    • If not β†’ append the full buffer, reset it, read again.
  5. If EOF is reached, return whatever has been accumulated (or NULL).
  6. When an fd finishes, remove its stash.

This ensures:

  • Minimal reads
  • Perfect multi-fd support
  • Norm‑compliant modularity
  • O(n) total complexity per returned line (where n is the length of the returned line)
    (Each character is copied at most once thanks to exponential buffer growth.)

πŸ“š Resources

  • man 2 read (RTFM πŸ™ˆ)
  • Project subject
  • Norm.v4

πŸ€– AI usage notice

No code was generated by AI.

AI was used only to:

  • reason about architectural approaches,
  • clarify tester/compiler logs,
  • refine explanations during debugging,

All technical decisions and implementations are original.

About

πŸ“œ Get Next Line (42 Paris) β€” Line-by-line reader for file descriptors in C. Arbitrary BUFFER_SIZE, optimized memory management, multiple file descriptors handling, linked-list based stash system.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages