trafi

Transducteurs finis
git clone git://git.asteride.xyz/trafi.git
Journaux | Fichiers | Références

commit b6468cc7ff6c2a45edb02c0db8d6b8106ba797c2
Auteur: Loïc Daignault-Pichette <loic@asteride.xyz>
Date:   Thu, 12 Feb 2026 15:44:36 -0500

Créer des tampons infinis

Diffstat:
AMakefile | 16++++++++++++++++
Aattvtfd.c | 7+++++++
Atampinf.c | 210+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atampinf.h | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 fichiers modifiés, 305 insertions(+), 0 suppressions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,16 @@ +.SUFFIXES: +.SUFFIXES: .c .o + +CC = cc +COPTS = -Wall -Wextra -Wpedantic -std=c99 -O0 #-DNDEBUG -O3 -flto + +.c.o: + ${CC} ${COPTS} ${CPPOPTS} -c "$<" + +tout: attvtfd + +attvtfd: attvtfd.o tampinf.o + ${CC} ${COPTS} -o "$@" attvtfd.o tampinf.o + +net: + rm -rf attvtfd *.o *.core diff --git a/attvtfd.c b/attvtfd.c @@ -0,0 +1,7 @@ +#include "tampinf.h" + +int +main(void) +{ + return 0; +} diff --git a/tampinf.c b/tampinf.c @@ -0,0 +1,210 @@ +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include "tampinf.h" + +#define TAMPINF_COHERENT(ti) \ + /* Le pointeur n’est pas NULL. */ \ + assert(ti); \ + /* Le pointeur vers le contenu n’est pas NULL. */ \ + assert((ti)->ctn); \ + /* Un élément a une taille supérieure à zéro. */ \ + assert((ti)->tll > 0); \ + /* Le tampon peut contenir au moins un élément. */ \ + assert((ti)->lngr > 0); \ + /* Le nombre d’éléments est inférieur ou égal à la longueur. */ \ + assert((ti)->nelem <= (ti)->lngr); + +/* Faire qu’un tampon soit au moins aussi grand que lngr. + * Prend pour acquis que la longueur du tampon est inférieure à lngr. + * Renvoie la longueur du tatmpon, ou -1 en cas d’erreur. */ +static ssize_t tampinf_agr(struct tampinf *ti, size_t lngr); + +struct tampinf * +tampinf_init(size_t lngr, size_t tll) +{ + struct tampinf *ti; + + assert(lngr > 0); + assert(tll > 0); + + if ((ti = malloc(sizeof(struct tampinf))) == NULL) + return NULL; + + if ((ti->ctn = calloc(lngr, tll)) == NULL) { + free(ti); + return NULL; + } + + ti->lngr = lngr; + ti->tll = tll; + ti->nelem = 0; + + TAMPINF_COHERENT(ti); + + return ti; +} + +void +tampinf_reinit(struct tampinf *ti) +{ + TAMPINF_COHERENT(ti); + + memset(ti->ctn, 0, ti->nelem); + ti->nelem = 0; +} + +void +tampinf_libr(struct tampinf *ti) +{ + TAMPINF_COHERENT(ti); + + free(ti->ctn); + free(ti); +} + +ssize_t +tampinf_plc(struct tampinf *ti, size_t i, size_t n, void *elem) +{ + TAMPINF_COHERENT(ti); + assert(n > 0); + assert(elem); + + /* Agrandir le tampon s’il est trop petit. + * La taille minimale du tampon est i + n. */ + if (ti->lngr < i + n && tampinf_agr(ti, i + n) < 0) + return -1; + + memcpy((char *)ti->ctn + (i * ti->tll), elem, n * ti->tll); + + /* Mettre à jour nelem s’il le faut. */ + if (i + n > ti->nelem) + ti->nelem = i + n; + + TAMPINF_COHERENT(ti); + + return i; +} + +ssize_t +tampinf_obt(struct tampinf *ti, size_t i, size_t n, void *elem) +{ + TAMPINF_COHERENT(ti); + assert(n > 0); + assert(elem); + + /* Agrandir le tampon s’il est trop petit. + * La taille minimale du tampon est i + n. */ + if (ti->lngr < i + n && tampinf_agr(ti, i + n) < 0) + return -1; + + /* Copier dans elem. */ + memcpy(elem, (char *)ti->ctn + (i * ti->tll), n * ti->tll); + + /* Mettre à jour nelem s’il le faut. */ + if (i + n > ti->nelem) + ti->nelem = i + n; + + TAMPINF_COHERENT(ti); + + return i; +} + +ssize_t +tampinf_ajt(struct tampinf *ti, size_t n, void *elem) +{ + int i; /* Indice où elem aura été placé. */ + + TAMPINF_COHERENT(ti); + assert(n > 0); + assert(elem); + + /* Placer elem à ti->nelem. */ + if ((i = tampinf_plc(ti, ti->nelem, n, elem)) < 0) + return -1; + + TAMPINF_COHERENT(ti); + + return i; +} + +ssize_t +tampinf_dpl(struct tampinf *ti, size_t n, void *elem) +{ + TAMPINF_COHERENT(ti); + assert(n > 0); + assert(elem); + + /* Il doit y avoir assez d’éléments dans le tampon. */ + assert(ti->nelem >= n); + + /* Obtenir n éléments à ti->nelem - n. */ + if (tampinf_obt(ti, ti->nelem - n, n, elem) < 0) + return -1; + + /* Mettre à jour ti->nelem. */ + ti->nelem -= n; + + return ti->nelem; +} + +void * +tampinf_ctn(struct tampinf *ti) +{ + TAMPINF_COHERENT(ti); + + return ti->ctn; +} + +size_t +tampinf_nelem(struct tampinf *ti) +{ + TAMPINF_COHERENT(ti); + + return ti->nelem; +} + +size_t +tampinf_esp(struct tampinf *ti) +{ + TAMPINF_COHERENT(ti); + + return ti->nelem * ti->tll; +} + +bool +tampinf_dedans(struct tampinf *ti, size_t i) +{ + TAMPINF_COHERENT(ti); + + if (i < ti->nelem) + return 1; + return 0; +} + +static ssize_t +tampinf_agr(struct tampinf *ti, size_t lngr) +{ + size_t nlngr; /* Nouvelle longueur. */ + void *nctn; /* Nouveau contenu. */ + + TAMPINF_COHERENT(ti); + assert(ti->lngr < lngr); + + /* Doubler la longueur jusqu’à ce quelle soit supérieure ou égale à la longueur + * recherchée. */ + for (nlngr = ti->lngr; nlngr < lngr; nlngr *= 2) + ; + + /* Agrandir le tampon et en initialiser à zéro la nouvelle partie. */ + if ((nctn = realloc(ti->ctn, nlngr * ti->tll)) == NULL) + return -1; + memset((char *)nctn + ti->lngr * ti->tll, 0, (nlngr - ti->lngr) * ti->tll); + ti->ctn = nctn; + ti->lngr = nlngr; + + TAMPINF_COHERENT(ti); + + return ti->lngr; +} diff --git a/tampinf.h b/tampinf.h @@ -0,0 +1,72 @@ +#ifndef TAMPINF_H +#define TAMPINF_H + +#include <stdbool.h> +#include <stddef.h> +#include <sys/types.h> + +/* Un tampinf est un tampon qui donne l’illusion d’être infini. Sa structure + * comporte quatre champs. Le premier contient est un pointeur vers le contenu + * du tampon, placé dans un espace alloué par malloc(). Le deuxième champ + * contient la taille d’un élément du tampon, exprimée en octets. Le troisième + * champ donne la longueur actuelle du tampon, en multiples de la taille. Le + * caracètre extensible de la structure fait qu’elle est susceptible + * d’augmenter. Enfin, le quatrième champ indique le nombre d’éléments placés + * dans le tampon. + * + * L’emplacement du contenu du tampon n’étant pas statique, utiliser le résultat + * de tampinf_ctn() après une fonction susceptible d’agrandir le tampon est + * dangereux. */ + +struct tampinf { + void *ctn; /* Contenu. */ + size_t tll; /* Taille d’un élément. */ + size_t lngr; /* Longueur du tampon. */ + size_t nelem; /* Nombre d’éléments dans le tampon. */ +}; + +/* Initialiser un tampon. + * La longueur est interprétée en multiples de tll. Le tampon est initialisé à + * zéro. Renvoie NULL en cas d’erreur. */ +struct tampinf *tampinf_init(size_t lngr, size_t tll); + +/* Réinitialiser le tampon ti. + * Son contenu est aussi réinitialisé à zéro. */ +void tampinf_reinit(struct tampinf *ti); + +/* Libérer l’espace utilisé par le tampon ti. */ +void tampinf_libr(struct tampinf *ti); + +/* Placer n éléments contenus dans elem à l’emplacement i dans le tampon ti. + * Renvoie i, ou -1 en cas d’erreur. */ +ssize_t tampinf_plc(struct tampinf *ti, size_t i, size_t n, void *elem); + +/* Placer dans elem n éléments à l’emplacement i du tampon ti. + * Renvoie i, ou -1 en cas d’erreur. */ +ssize_t tampinf_obt(struct tampinf *ti, size_t i, size_t n, void *elem); + +/* Ajouter au tampon ti n éléments contenus dans elem. + * Renvoie l’indice du nouvel élément, ou -1 en cas d’erreur. */ +ssize_t tampinf_ajt(struct tampinf *ti, size_t n, void *elem); + +/* Retirer et copier dans elem les n derniers éléments du tampon ti. + * L’espace libéré n’est pas réinitialisé à zéro. Renvoie l’indice le plus + * faible des éléments retirés, ou -1 en cas d’erreur. */ +ssize_t tampinf_dpl(struct tampinf *ti, size_t n, void *elem); + +/* Renvoyer un pointeur vers le contenu du tampon ti. + * Le pointeur n’est plus utilisable après qu’une routine susceptible + * d’agrandir le tampon ait été exécutée. */ +void *tampinf_ctn(struct tampinf *ti); + +/* Obtenir le nombre d’éléments contenus dans le tampon ti. */ +size_t tampinf_nelem(struct tampinf *tp); + +/* Obtenir l’espace utilisé par les éléments du tampon ti. */ +size_t tampinf_esp(struct tampinf *ti); + +/* Renvoie 1 si l’indice i est dans la partie utilisée du tampon, 0 + * autrement. */ +bool tampinf_dedans(struct tampinf *ti, size_t i); + +#endif