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:
| A | Makefile | | | 16 | ++++++++++++++++ |
| A | attvtfd.c | | | 7 | +++++++ |
| A | tampinf.c | | | 210 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | tampinf.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