Ajout du pendant ReadBuffer pour lire bit par bit

This commit is contained in:
Mattéo Delabre 2016-11-19 15:53:43 +01:00
parent aa63afb9d8
commit 77ac3d3d4c
2 changed files with 95 additions and 46 deletions

View File

@ -4,46 +4,68 @@
#include <stdio.h> #include <stdio.h>
/** /**
* Informations sur un tampon de 8 caractères. * Tampon permettant d'abstraire l'écriture dans un fichier bit par
* Utiliser `createBuffer` pour initialiser un tampon * 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; typedef struct WriteBuffer WriteBuffer;
struct Buffer { struct WriteBuffer {
// Compte le nombre d'octets écrits dans le fichier // Contient les données du tampon d'écriture, c'est-à-dire
size_t flushed_bytes;
// Contient les données du tampon, c'est-à-dire
// les données en attente de vidage dans le fichier // les données en attente de vidage dans le fichier
char data; char data;
// Nombre de bits utilisés dans le tampon. Si ce // Nombre de bits utilisés dans `data`. Si ce nombre vaut 8,
// nombre vaut 8, le tampon est plein // le tampon d'écriture est plein
size_t used_bits; 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 // 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é. * Écrit le bit donné dans le tampon d'écriture
* Si le tampon déborde, le vide dans le fichier lié
*/ */
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 é 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 #endif

View File

@ -3,36 +3,19 @@
#include <stdio.h> #include <stdio.h>
Buffer createBuffer(FILE* file) { WriteBuffer createWriteBuffer(FILE* file) {
Buffer buffer = { WriteBuffer buffer = {
.flushed_bytes = 0,
.data = 0, .data = 0,
.used_bits = 0, .pending_bits = 0,
.linked_file = file .dest_file = file
}; };
return buffer; return buffer;
} }
size_t getFlushedBytes(Buffer* buffer) { void putBuffer(char bit, WriteBuffer* 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) {
// Si le tampon déborde, écriture dans le fichier // Si le tampon déborde, écriture dans le fichier
if (buffer->used_bits == 8) { if (buffer->pending_bits == 8) {
flushBuffer(buffer); flushBuffer(buffer);
} }
@ -40,5 +23,49 @@ void pushToBuffer(char bit, Buffer* buffer) {
// le tampon de sortie // le tampon de sortie
buffer->data <<= 1; buffer->data <<= 1;
buffer->data |= bit; 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;
} }