m2.enlarge-your-data/src/lib/eyd_bitwriter.cpp
2005-10-29 22:51:22 +00:00

135 lines
3.6 KiB
C++

#include "eyd_bitwriter.hh"
#define DEBUG 0
namespace EydLib {
/*
* int _group_pos;
int _fd;
*/
BitWriter::BitWriter(int size, int buffer_size = 1024){
// tous les groupes de bits seront de la taille donnée
this->_bitgroup_size = size;
this->_wanted_buffer_size = buffer_size;
this->_write_buffer = new char[this->_wanted_buffer_size];
this->_file_desc = -1;
this->_ready = false;
}
BitWriter::~BitWriter(){
delete(this->_write_buffer);
}
void BitWriter::open(std::string filename){
this->_file_desc = ::open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (this->_file_desc < 0){
throw eBitWriterBadFileDescriptor();
}
this->_real_buffer_size_in_bits = 0;
this->_current_bit_position = 0;
this->_ready = true;
}
ssize_t BitWriter::writeDirect(void *buf, size_t count){
return ::write(this->_file_desc, buf, count);
}
void BitWriter::setBitAt(int position, bool value){
// on attrappe la bonne case du tableau
// on shift dans le bon sens
// on retourne la valeur du bit.
int size_of_char = 8 * sizeof(char);
int i;
int index_of_char = position / size_of_char;
int shift_of_char = position % size_of_char;
char writer;
pDEBUG("BitWriter::setBitAt","pos %d - size %d\n", position, this->_real_buffer_size_in_bits );
if (position >= this->_real_buffer_size_in_bits){
throw eBitWriterOutOfBound();
} else {
unsigned char mask_fill;
unsigned char mask_hole;
for (i=0; i < size_of_char; i++){
mask_fill = (mask_fill << 1) | 1;
if (shift_of_char == i){
mask_hole = (mask_hole << 1) | 0;
} else {
mask_hole = (mask_hole << 1) | 1;
}
}
writer = this->_write_buffer[index_of_char];
if (value){
writer = ((writer ^ mask_fill) & mask_hole) ^ mask_fill;
} else {
writer = writer & mask_hole;
}
this->_write_buffer[index_of_char] = writer;
}
}
void BitWriter::flush(){
int nb_chars;
int size_of_char = 8 * sizeof(char);
int right_bit_len;
//nb_chars = ((this->_real_buffer_size_in_bits) / size_of_char);
// au pire on fait un write de trop
// donc la derniere "bonne valeur" se situe à
right_bit_len = this->_real_buffer_size_in_bits;
nb_chars = (right_bit_len / size_of_char);
// sauf qu'il reste de quoi finir un octet
if (nb_chars > this->_wanted_buffer_size) {
nb_chars = this->_wanted_buffer_size;
}
if ((this->_real_buffer_size_in_bits - 1) > this->_bitgroup_size) {
// on flush seulement si on a écrit + de 1 bitgroup dans le nouveau
// buffer
pDEBUG("BitWriter::flush","buffer() -> write()\n");
pDEBUG("BitWriter::flush","WRITE_BUFFER(%d chars) = %s\n",nb_chars, this->_write_buffer);
::write(this->_file_desc, this->_write_buffer, nb_chars);
}
this->_current_bit_position = 0;
this->_real_buffer_size_in_bits=1;
}
void BitWriter::write(BitGroup data){
int i;
bool bitValue;
int size_of_char = 8 * sizeof(char);
if (this->_file_desc < 0){
throw eBitWriterBadFileDescriptor();
}
for (i=0; i < this->_bitgroup_size; i++){
if (i < data.size()){
bitValue = data.getBitAt(i);
this->_real_buffer_size_in_bits += 1;
if (this->_real_buffer_size_in_bits > (this->_wanted_buffer_size * size_of_char)){
this->flush();
}
this->setBitAt(this->_current_bit_position, bitValue);
this->_current_bit_position += 1;
}
}
return;
}
void BitWriter::close(){
// on vide le dernier buffer jusqu'a la position réelle...
pDEBUG("BitWriter::close","Remaining %d\n",this->_real_buffer_size_in_bits);
this->flush();
::close(this->_file_desc);
}
}
#undef DEBUG