diff --git a/inc/buffer.h b/inc/buffer.h index 929c54c..f85546e 100644 --- a/inc/buffer.h +++ b/inc/buffer.h @@ -4,46 +4,68 @@ #include /** - * Informations sur un tampon de 8 caractères. - * Utiliser `createBuffer` pour initialiser un tampon + * Tampon permettant d'abstraire l'écriture dans un fichier bit par + * bit au lieu d'octet par octet. Les bits sont vidés dans le fichier + * dès qu'un octet est complet */ -typedef struct Buffer Buffer; -struct Buffer { - // Compte le nombre d'octets écrits dans le fichier - size_t flushed_bytes; - - // Contient les données du tampon, c'est-à-dire +typedef struct WriteBuffer WriteBuffer; +struct WriteBuffer { + // Contient les données du tampon d'écriture, c'est-à-dire // les données en attente de vidage dans le fichier char data; - // Nombre de bits utilisés dans le tampon. Si ce - // nombre vaut 8, le tampon est plein - size_t used_bits; + // Nombre de bits utilisés dans `data`. Si ce nombre vaut 8, + // le tampon d'écriture est plein + size_t pending_bits; - // Fichier dans lequel le tampon est vidé à l'appel + // Fichier dans lequel le tampon d'éciture est vidé à l'appel // de `flushBuffer` ou au débordement - FILE* linked_file; + FILE* dest_file; }; /** - * Initialise un tampon vide lié au fichier donné + * Initialise un tampon d'écriture vide, avec le fichier donné comme + * destination */ -Buffer createBuffer(FILE*); +WriteBuffer createWriteBuffer(FILE*); /** - * Pousse le bit donné dans le tampon passé. - * Si le tampon déborde, le vide dans le fichier lié + * Écrit le bit donné dans le tampon d'écriture */ -void pushToBuffer(char bit, Buffer*); +void putBuffer(char bit, WriteBuffer*); /** - * Récupère le nombre de fois qu'on a écrit un octet dans le fichier lié + * Force le vidage du tampon dans son fichier et sa réinitialisation + * (les bits non-remplis seront remplacés par des 0) */ -size_t getFlushedBytes(Buffer*); +void flushBuffer(WriteBuffer*); /** - * Vide le tampon dans son fichier et le réinitialise + * Tampon permettant d'abstraire le lecture depuis un fichier bit par + * bit au lieu d'octet par octet. Un octet est lu depuis le fichier + * dès que tous les bits du précédent ont été lus */ -void flushBuffer(Buffer*); +typedef struct ReadBuffer ReadBuffer; +struct ReadBuffer { + // Contient les données du tampon de lecture, c'est-à-dire + // le dernier octet lu depuis le fichier + char data; + + // Numéro du prochain bit de `data` qui sera lu par `getBuffer` + size_t next_bit; + + // Fichier depuis lequel le tampon de lecture est rempli + FILE* source_file; +}; + +/** + * Initialise un tampon de lecture avec le fichier donné comme source + */ +ReadBuffer createReadBuffer(FILE*); + +/** + * Lit le prochain bit depuis le tampon de lecture + */ +char getBuffer(ReadBuffer*); #endif diff --git a/src/buffer.c b/src/buffer.c index ea7e0a8..46b55a6 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -3,36 +3,19 @@ #include -Buffer createBuffer(FILE* file) { - Buffer buffer = { - .flushed_bytes = 0, +WriteBuffer createWriteBuffer(FILE* file) { + WriteBuffer buffer = { .data = 0, - .used_bits = 0, - .linked_file = file + .pending_bits = 0, + .dest_file = file }; return buffer; } -size_t getFlushedBytes(Buffer* buffer) { - return buffer->flushed_bytes; -} - -void flushBuffer(Buffer* buffer) { - // FIXME: gérer les erreurs d'écriture - - // Alignement des données à gauche de l'octet - buffer->data <<= 8 - buffer->used_bits; - fputc(buffer->data, buffer->linked_file); - - buffer->data = 0; - buffer->used_bits = 0; - buffer->flushed_bytes += 1; -} - -void pushToBuffer(char bit, Buffer* buffer) { +void putBuffer(char bit, WriteBuffer* buffer) { // Si le tampon déborde, écriture dans le fichier - if (buffer->used_bits == 8) { + if (buffer->pending_bits == 8) { flushBuffer(buffer); } @@ -40,5 +23,49 @@ void pushToBuffer(char bit, Buffer* buffer) { // le tampon de sortie buffer->data <<= 1; buffer->data |= bit; - buffer->used_bits += 1; + buffer->pending_bits += 1; +} + +void flushBuffer(WriteBuffer* buffer) { + // FIXME: gérer les erreurs d'écriture + + // Alignement des données à gauche de l'octet + buffer->data <<= 8 - buffer->pending_bits; + fputc(buffer->data, buffer->dest_file); + + buffer->data = 0; + buffer->pending_bits = 0; +} + +ReadBuffer createReadBuffer(FILE* file) { + ReadBuffer buffer = { + .data = fgetc(file), + .next_bit = 7, + .source_file = file + }; + + return buffer; +} + +char getBuffer(ReadBuffer* buffer) { + if (buffer->data == EOF) { + return EOF; + } + + // Lecture du n-ième bit dans le dernier octet lu + char result = ( + buffer->data & + (1 << buffer->next_bit) + ) != 0; + + if (buffer->next_bit > 0) { + // Il reste des bits à lire, décalage du compteur + buffer->next_bit--; + } else { + // Besoin de lire le prochain octet depuis le fichier + buffer->data = fgetc(buffer->source_file); + buffer->next_bit = 7; + } + + return result; }