#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; } 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