131 lines
3.4 KiB
C++
131 lines
3.4 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<6E>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;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
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;
|
|||
|
printf("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 <20>
|
|||
|
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 <20>crit + de 1 bitgroup dans le nouveau
|
|||
|
// buffer
|
|||
|
printf("BitWriter::write / buffer() -> write()\n");
|
|||
|
printf("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...
|
|||
|
printf("Remaining %d\n",this->_real_buffer_size_in_bits);
|
|||
|
this->flush();
|
|||
|
::close(this->_file_desc);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
#undef DEBUG
|