trafi

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

commit 638ca1dfb964cbec03899453ef452acb190eebc9
parent 03ca6b6c5a2318d1d03e1fc62b50b993f652a632
Auteur: Loïc Daignault-Pichette <loic@asteride.xyz>
Date:   Fri,  3 Apr 2026 17:28:29 -0400

Apporter des changements substanciels à tampinf

Ils peuvent maintenant être manipulés comme des tableaux normaux dans un
grand nombre de cas.

Diffstat:
Mtampinf.c | 220++++++++++++++++++++++++++++++++-----------------------------------------------
Mtampinf.h | 42++++++++++++++----------------------------
2 fichiers modifiés, 102 insertions(+), 160 suppressions(-)

diff --git a/tampinf.c b/tampinf.c @@ -5,222 +5,178 @@ #include "tampinf.h" +/* Calculer l’adresse de l’entête d’un taminf. */ +#define ENTETE(ti) ((Entete *)ti - 1) + +/* Calculer l’adresse du tampon d’un tampinf. */ +#define TAMPON(ent) (ent + 1) + +/* Tester la cohérence du tampon. */ #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); - -/* La structure d’un tampinf 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. */ - -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. */ -}; + assert(ENTETE(ti)); \ + /* Un élémENTETE(ti) a une taille supérieure à zéro. */ \ + assert((ENTETE(ti))->s.tll > 0); \ + /* Le tampon peut contenir au moins un élémENTETE(ti). */ \ + assert((ENTETE(ti))->s.lngr > 0); \ + /* Le nombre d’élémENTETE(ti)s est inférieur ou égal à la longueur. */ \ + assert((ENTETE(ti))->s.nelem <= (ENTETE(ti))->s.lngr); + +/* La structure du tampon infini a été conçue pour que son utilisation + * ressemble le plus possible à celle des tableaux statiques. C’est donc sous + * cette forme qu’ils se présentent à l’utilisateur. Or, une partie de la + * réalité lui est cachée, car sous le tampon qui lui est renvoyé sous trouve + * une entête contenant l’information nécessaires au bon fonctionnement des + * fonctions de cette bilbiothèque: la taille des éléments du tampon, exprimée + * en octets, la longueur du tampon, excluant l’entête et exprimée en multiples + * de la taille, et enfin le nombre d’éléments que contient le tampon. */ + +/* Entête d’un tampinf. + * L’union assure que l’entête occupe un multiple de sizeof(long) octets. */ +typedef union entete { + struct { + size_t tll; /* Taille des éléments. */ + size_t lngr; /* Longueur du tampon. */ + size_t nelem; /* Nombre d’éléments dans le tampon. */ + } s; + long alignement; +} Entete; /* 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); + * Renvoie l’adresse du tampon, ou NULL en cas d’erreur. */ +static void *tampinf_agr(void *ti, size_t lngr); -struct tampinf * +void * tampinf_init(size_t lngr, size_t tll) { - struct tampinf *ti; + Entete *ent; assert(lngr > 0); assert(tll > 0); - if ((ti = malloc(sizeof(struct tampinf))) == NULL) + if ((ent = malloc(sizeof(Entete) + lngr * tll)) == NULL) return NULL; - if ((ti->ctn = calloc(lngr, tll)) == NULL) { - free(ti); - return NULL; - } + ent->s.tll = tll; + ent->s.lngr = lngr; + ent->s.nelem = 0; - ti->lngr = lngr; - ti->tll = tll; - ti->nelem = 0; + tampinf_reinit(TAMPON(ent)); - TAMPINF_COHERENT(ti); + TAMPINF_COHERENT(TAMPON(ent)); - return ti; + return TAMPON(ent); } void -tampinf_reinit(struct tampinf *ti) +tampinf_reinit(void *ti) { TAMPINF_COHERENT(ti); - memset(ti->ctn, 0, ti->nelem); - ti->nelem = 0; + memset(ti, 0, ENTETE(ti)->s.tll * ENTETE(ti)->s.nelem); + + ENTETE(ti)->s.nelem = 0; } void -tampinf_libr(struct tampinf *ti) +tampinf_libr(void *ti) { TAMPINF_COHERENT(ti); - free(ti->ctn); - free(ti); + free(ENTETE(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) +void * +tampinf_plc(void *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; + * La taille minimale que le tampon devrait avoir est i + n. */ + if (ENTETE(ti)->s.lngr < i + n + && (ti = tampinf_agr(ti, i + n)) == NULL) + return NULL; - /* Copier dans elem. */ - memcpy(elem, (char *)ti->ctn + (i * ti->tll), n * ti->tll); + memcpy((char *)ti + (i * ENTETE(ti)->s.tll), elem, + n * ENTETE(ti)->s.tll); /* Mettre à jour nelem s’il le faut. */ - if (i + n > ti->nelem) - ti->nelem = i + n; + if (i + n > ENTETE(ti)->s.nelem) + ENTETE(ti)->s.nelem = i + n; TAMPINF_COHERENT(ti); - return i; + return ti; } -ssize_t -tampinf_ajt(struct tampinf *ti, size_t n, void *elem) +void * +tampinf_ajt(void *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; -} + if ((ti = tampinf_plc(ti, ENTETE(ti)->s.nelem, n, elem)) == NULL) + return NULL; -void * -tampinf_ctn(struct tampinf *ti) -{ TAMPINF_COHERENT(ti); - return ti->ctn; + return ti; } size_t -tampinf_nelem(struct tampinf *ti) +tampinf_nelem(void *ti) { TAMPINF_COHERENT(ti); - return ti->nelem; + return ENTETE(ti)->s.nelem; } size_t -tampinf_esp(struct tampinf *ti) +tampinf_esp(void *ti) { TAMPINF_COHERENT(ti); - return ti->nelem * ti->tll; + return ENTETE(ti)->s.nelem * ENTETE(ti)->s.tll; } bool -tampinf_dedans(struct tampinf *ti, size_t i) +tampinf_dedans(void *ti, size_t i) { TAMPINF_COHERENT(ti); - if (i < ti->nelem) + if (i < ENTETE(ti)->s.nelem) return 1; return 0; } -static ssize_t -tampinf_agr(struct tampinf *ti, size_t lngr) +static void * +tampinf_agr(void *ti, size_t lngr) { size_t nlngr; /* Nouvelle longueur. */ - void *nctn; /* Nouveau contenu. */ + Entete *nent; /* Nouvelle entête. */ TAMPINF_COHERENT(ti); - assert(ti->lngr < lngr); + assert(ENTETE(ti)->s.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) + /* Doubler la longueur jusqu’à ce quelle soit supérieure ou égale à la + * longueur recherchée. */ + for (nlngr = ENTETE(ti)->s.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; + if ((nent = realloc(ENTETE(ti), + sizeof(Entete) + nlngr * ENTETE(ti)->s.tll)) == NULL) + return NULL; + memset((char *)TAMPON(nent) + nent->s.lngr * nent->s.tll, 0, + (nlngr - nent->s.lngr) * nent->s.tll); + nent->s.lngr = nlngr; - TAMPINF_COHERENT(ti); + TAMPINF_COHERENT(TAMPON(nent)); - return ti->lngr; + return TAMPON(nent); } diff --git a/tampinf.h b/tampinf.h @@ -7,54 +7,40 @@ /* Un tampinf est un tampon qui donne l’illusion d’être infini. * - * 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; + * L’adresse d’un tampon n’est pas statique, et plusieurs fonctions sont + * susceptibles de la changer. Ces fonctions renvoient toutes l’adresse + * courante du tampon. Toute variable qui contiendrait l’adresse du tampon doit + * être mise à jour à l’occasion de l’appel de ce genre de fonctions. */ /* 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); + * zéro. + * Renvoie le tampon, ou NULL en cas d’erreur. */ +void *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); +void tampinf_reinit(void *ti); /* Libérer l’espace utilisé par le tampon ti. */ -void tampinf_libr(struct tampinf *ti); +void tampinf_libr(void *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); +void *tampinf_plc(void *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); +void *tampinf_ajt(void *ti, size_t n, void *elem); /* Obtenir le nombre d’éléments contenus dans le tampon ti. */ -size_t tampinf_nelem(struct tampinf *tp); +size_t tampinf_nelem(void *ti); /* Obtenir l’espace utilisé par les éléments du tampon ti. */ -size_t tampinf_esp(struct tampinf *ti); +size_t tampinf_esp(void *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); +bool tampinf_dedans(void *ti, size_t i); #endif