get_next_lineest une fonction utilitaire en C qui lit une ligne à la fois depuis un descripteur de fichier (fd) et la retourne sous forme de chaîne allouée dynamiquement.

L’objectif du projet est double :

  • Comprendre comment construire une lecture streaming (sans charger tout le fichier en mémoire).
  • Maîtriser un concept clé en C : les variables statiques, indispensables pour conserver l’état entre deux appels.

Principe

À chaque appel, get_next_line(fd):

1. Lit depuis fd par blocs de taille BUFFER_SIZE.

2. Accumule les données jusqu’à trouver un \n ou atteindre la fin du flux.

3. Retourne la prochaine ligne :

  • la ligne inclut le \n si la ligne en contient un,
  • sauf en fin de fichier si le dernier morceau n’est pas terminé par \n.

Si aucune ligne n’est disponible (EOF) ou en cas d’erreur, la fonction retourne NULL.

Points importants

  • Des appels successifs permettent de lire l’intégralité d’un fichier/flux ligne par ligne.

  • La fonction doit fonctionner aussi bien sur un fichier que sur l’entrée standard.

  • La lecture doit être minimale : dès qu’un \n est rencontré, on retourne la ligne correspondante (on ne lit pas le fichier entier).

Contraintes respectées

  • Fonctions autorisées : read, malloc, free

  • Compilation avec la macro : -D BUFFER_SIZE=n (valeur testée avec plusieurs tailles)

  • Interdits : libft, lseek(), variables globales

Ce que ça m’a apporté

Ce projet m’a appris à écrire une fonction fiable sur un flux de données : gestion d’un buffer résiduel entre appels (via static), découpage propre "ligne retournée" / "reste à conserver", et attention aux cas limites (buffer très petit, très grand, fichiers sans \n, stdin, etc.).

Bonus

Version avec une seule variable statique.

Gestion de plusieurs fd en parallèle : lire fd=3, puis 4, puis 5, puis revenir à 3 sans perdre l’état de chacun.

Objectif

Implémenter get_next_line(int fd) : une fonction qui retourne la prochaine ligne lue depuis un file descriptor, à chaque appel.

Règles de retour

  • La ligne retournée est une chaîne allouéefree() côté appelant).
  • La ligne inclut le \n si la ligne en contient un.
  • Si la fin de fichier est atteinte et qu’il reste des caractères sans \n, on retourne cette dernière ligne.
  • Si EOF sans reste ou en cas d’erreur : NULL.

Contraintes techniques

  • Lecture par blocs via read() avec une taille BUFFER_SIZE.
  • Compilation avec : -D BUFFER_SIZE=n (testée avec plusieurs valeurs).
  • Interdits selon sujet : pas de libft, pas de variables globales, pas de lseek().
  • Fonctions autorisées (classique) : read, malloc, free.

Bonus

  • Gestion de plusieurs fd sans perdre l’état de chacun.
  • Variante imposant une seule variable statique (selon consignes).

Build

Exemple de compilation :

cc -Wall -Wextra -Werror -D BUFFER_SIZE=42 \
  get_next_line.c get_next_line_utils.c \
  main.c -o gnl

Exemple minimal

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.hn>

char *get_next_line(int fd);

int main(void)
{
    int fd = open("file.txt", O_RDONLY);
    char *line;

    if (fd < 0)
        return (1);

    while ((line = get_next_line(fd)) != NULL)
    {
        printf("%s", line);
        free(line);
    }
    close(fd);
    return (0);
}

Notes importantes

  • Toujours free() chaque ligne.
  • Tester avec :

  • fichier vide

  • fichier sans \n
  • BUFFER_SIZE=1
  • très gros fichiers
  • stdin (fd = 0)

Idée centrale

Conserver un reste (stash) entre deux appels pour ne pas perdre les caractères après un \n.

Flux logique (mandatory)

  1. stash (statique) contient les données non consommées.
  2. Lire avec read(fd, buffer, BUFFER_SIZE) tant que :
  • aucun \n dans stash et
  • read() renvoie > 0
    3. Dès qu’un \n est présent (ou EOF), construire :

  • line = partie de stash jusqu’au \n inclus (ou fin)

  • stash = reste après la ligne (ou NULL)
    4. Retourner line.

Découpage conseillé

  • read_to_stash(fd, stash) : boucle de lecture jusqu’à trouver \n ou EOF.
  • extract_line(stash) : crée la ligne à retourner.
  • trim_stash(stash) : garde uniquement ce qui reste après la ligne.
  • utils (interdiction libft) : ft_strlen, ft_strchr, ft_strjoin, ft_substr (ou équivalents maison).

Gestion des erreurs

  • Si read() retourne -1 : cleanup + NULL.
  • Si malloc échoue : cleanup + NULL.

Bonus multi-fd (si fait)

  • Utiliser un static char *stash[OPEN_MAX] (ou structure équivalente) pour stocker un stash par fd.
  • Même algorithme, mais indexé sur fd.

Pourquoi c’est intéressant

Ce projet combine I/O bas niveau, gestion mémoire, et état persistant (via static) — le tout avec des cas limites très concrets (fichiers sans \n, petites tailles de buffer, stdin, multi-fd).