bitArray.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef BITARRAY_H
00045 # define BITARRAY_H
00046 
00047 # include <aleph.H>
00048 
00049 namespace Aleph {
00050 
00069 class BitArray
00070 {
00071 
00072 private:
00073 
00074   struct Byte
00075   {
00076     unsigned int b0 : 1;
00077     unsigned int b1 : 1;
00078     unsigned int b2 : 1;
00079     unsigned int b3 : 1;
00080     unsigned int b4 : 1;
00081     unsigned int b5 : 1;
00082     unsigned int b6 : 1;
00083     unsigned int b7 : 1;
00084 
00085     unsigned int read_bit(const unsigned int & i) const
00086     {
00087 
00088       I(i < 8);
00089 
00090       switch (i)
00091         {
00092         case 0 : return b0;
00093         case 1 : return b1;
00094           // ...
00095 
00096         case 2 : return b2;
00097         case 3 : return b3;
00098         case 4 : return b4;
00099         case 5 : return b5;
00100         case 6 : return b6;
00101 
00102         case 7 : return b7;
00103 
00104         default: throw std::out_of_range ("bit index greater than 7"); 
00105 
00106         }
00107     } 
00108     void write_bit(const unsigned int & i, const unsigned int & value)
00109     {
00110 
00111       I(i < 8);
00112       I(value <= 1);
00113 
00114       switch (i)
00115         {
00116         case 0 : b0 = value; break;
00117         case 1 : b1 = value; break;
00118           // ...
00119 
00120         case 2 : b2 = value; break;
00121         case 3 : b3 = value; break;
00122         case 4 : b4 = value; break;
00123         case 5 : b5 = value; break;
00124         case 6 : b6 = value; break;
00125 
00126         case 7 : b7 = value; break;
00127 
00128         default: throw std::out_of_range ("bit index greater than 7"); 
00129 
00130         }
00131     } 
00132     Byte() : b0(0), b1(0), b2(0), b3(0), b4(0), b5(0), b6(0), b7(0) { /* empty */ }
00133   };
00134   mutable size_t     num_bits;
00135   mutable size_t     num_bytes; 
00136   Byte * array_of_bytes; 
00137   class BitProxy
00138   {
00139     const size_t bit_index;
00140     Byte * byte_ptr;
00141 
00142   public:
00143 
00144     BitProxy(BitArray & array, const size_t & i) : bit_index(i % 8)
00145     {
00146 
00147       if (i >= array.num_bits)
00148         throw std::out_of_range ("Bit array size too big");
00149 
00150       const size_t byte_index = i/8;
00151 
00152       byte_ptr = &array.array_of_bytes[byte_index];
00153     }
00154     operator int () const { return byte_ptr->read_bit(bit_index); }
00155     BitProxy& operator = (const size_t & value)
00156     {
00157 
00158       I(value <= 1);
00159 
00160       byte_ptr->write_bit(bit_index, value);
00161 
00162       return *this;
00163     }
00164     BitProxy& operator = (const BitProxy & proxy)
00165     {
00166       byte_ptr->write_bit(bit_index, proxy.byte_ptr->read_bit(proxy.bit_index));
00167 
00168       return *this;
00169     }
00170   };
00171 
00172 public:
00173 
00180   BitArray(const size_t & dim = 256) 
00181 
00182     throw(std::exception, std::bad_alloc) 
00183 
00184     : num_bits(dim), num_bytes(num_bits/8 + (((num_bits % 8) != 0) ? 1 : 0)), 
00185       array_of_bytes (new Byte [num_bytes]) 
00186   {
00187     // empty
00188   }
00189 
00191   ~BitArray() { delete [] array_of_bytes; }
00192 
00194   const size_t & get_len() const { return num_bits; }
00195 
00197   const size_t & size() const { return  get_len(); }
00198   BitProxy operator [] (const size_t & i) const
00199   { 
00200     return BitProxy(const_cast<BitArray&>(*this), i);
00201   }
00202 
00203   BitProxy operator [] (const size_t & i)
00204   { 
00205     return BitProxy(*this, i);
00206   }
00213   int read_bit(const size_t & i) const
00214   {
00215     const int bit_index = i % 8;
00216 
00217     return array_of_bytes[i/8].read_bit(bit_index);
00218   }
00219 
00227   void write_bit(const size_t & i, const unsigned int & value) const
00228   {
00229     array_of_bytes[i/8].write_bit(i, value);
00230   }
00239   BitArray(const BitArray & array) 
00240     throw(std::exception, std::bad_alloc)
00241     :  num_bits(array.num_bits), num_bytes(array.num_bytes),
00242        array_of_bytes (new Byte [num_bytes])
00243   { 
00244     for (int i = 0; i < num_bytes; ++i)
00245       array_of_bytes[i] = array.array_of_bytes[i];
00246   }
00247 
00258   BitArray(const BitArray & array, const size_t & dim) 
00259     throw(std::exception, std::bad_alloc)
00260     : num_bits       (dim),         
00261       num_bytes      (num_bits/8 + (((num_bits % 8) != 0) ? 1 : 0)),
00262       array_of_bytes (new Byte [num_bytes])
00263   { 
00264         // copiar contenido de array
00265     const size_t n = Aleph::min(num_bytes, array.num_bytes);
00266 
00267     for (int i = 0; i < n; ++i)
00268       array_of_bytes[i] = array.array_of_bytes[i];
00269   }
00270 
00282   BitArray & operator = (const BitArray & array) 
00283     throw(std::exception, std::bad_alloc)
00284   {
00285     if (this == &array)
00286       return *this;
00287     
00288         // respaldar atributos por si ocurre excepción
00289     Byte * old_array = array_of_bytes; 
00290     const size_t old_num_bits  = num_bits;
00291     const size_t old_num_bytes = num_bytes;
00292 
00293     num_bits  = array.num_bits;
00294     num_bytes = array.num_bytes; 
00295 
00296     try
00297       {
00298         array_of_bytes = new Byte [num_bytes];
00299 
00300         delete [] old_array;
00301 
00302         for (int i = 0; i < num_bytes; ++i)
00303           array_of_bytes[i] = array.array_of_bytes[i];
00304 
00305         return *this;
00306       }
00307     catch (std::bad_alloc) 
00308       {
00309         num_bits  = old_num_bits;
00310         num_bytes = old_num_bytes;
00311         array_of_bytes = old_array;
00312 
00313         throw;
00314       }
00315   }
00323   void resize(const size_t & new_dim) 
00324 
00325     throw(std::exception, std::bad_alloc)
00326 
00327   {
00328     const size_t new_num_bytes = new_dim/8 + (((new_dim % 8) != 0) ? 1 : 0);
00329     
00330     Byte * new_array_of_bytes = new Byte [new_num_bytes];
00331 
00332     for (int i = 0; i < new_num_bytes; ++i)
00333       new_array_of_bytes[i] = array_of_bytes[i];
00334 
00335     num_bits  = new_dim;
00336     num_bytes = new_num_bytes;
00337 
00338     delete [] array_of_bytes;
00339 
00340     array_of_bytes = new_array_of_bytes;
00341   }
00342 };
00343 
00344 } // end namespace Aleph
00345 # endif /* BITARRAY_H */
00346 

Leandro R. León