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>
/**
* 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 é 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

View File

@ -3,36 +3,19 @@
#include <stdio.h>
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;
}