Array.hh

Go to the documentation of this file.
00001 #ifndef BIT_ARRAY_HH
00002 #define BIT_ARRAY_HH
00003 
00004 #include <errno.h>
00005 #include "bit/Buffer.hh"
00006 
00007 namespace bit {
00008 
00015   class Array {
00016 
00017   public:
00020     static const u64 index_limit = (u64)-1;
00021 
00022   public:
00023     
00025     Array()
00026       : m_bits_per_elem(0), m_num_elems(0), m_capacity(0)
00027     {
00028     }
00029 
00037     Array(u64 num_elems, unsigned int bits_per_elem)
00038       : m_num_elems(0), m_capacity(0)
00039     {
00040       if (bits_per_elem > max_bits_per_value)
00041         throw bit::invalid_argument("bit::Array(): too many bits per elem");
00042       m_bits_per_elem = bits_per_elem;
00043       resize(num_elems);
00044     }
00045 
00047     u64 num_elems() const { 
00048       return m_num_elems;
00049     }
00050 
00053     unsigned int bits_per_elem() const {
00054       return m_bits_per_elem;
00055     }
00056 
00058     u64 capacity() const {
00059       return m_capacity;
00060     }
00061 
00067     void resize(u64 num_elems)
00068     {
00069       m_num_elems = num_elems;
00070       if (m_capacity < m_num_elems) {
00071         m_capacity = m_num_elems;
00072         m_buffer.resize(bytes_required(m_capacity, m_bits_per_elem));
00073       }
00074     }
00075 
00080     void reserve(u64 capacity)
00081     {
00082       if (capacity <= m_capacity)
00083         return;
00084       m_capacity = capacity;
00085       m_buffer.resize(bytes_required(m_capacity, m_bits_per_elem));
00086     }
00087 
00094     void set_width(unsigned int bits_per_elem)
00095     {
00096       if (bits_per_elem == m_bits_per_elem)
00097         return;
00098 
00099       Buffer new_buffer(bytes_required(m_capacity, bits_per_elem));
00100       for (u64 i = 0; i < m_num_elems; i++) {
00101         u32 value = get(i);
00102         new_buffer.write_elem(i, bits_per_elem, value);
00103       }
00104       m_buffer.swap(new_buffer);
00105       m_bits_per_elem = bits_per_elem;
00106     }
00107 
00116     void set(u64 elem, u32 value)
00117     {
00118       if (elem >= m_num_elems)
00119         throw bit::out_of_range("bit::Array::set(): out of range");
00120       m_buffer.write_elem(elem, m_bits_per_elem, value);
00121     }
00122 
00137     void set_grow(u64 elem, u32 value)
00138     {
00139       if (elem >= m_num_elems) {
00140         if (elem >= m_capacity) {
00141           u64 new_capacity = m_capacity * 2;
00142           if (elem >= new_capacity)
00143             new_capacity = elem + 1;
00144           reserve(new_capacity);
00145         }
00146         resize(elem + 1);
00147       }
00148       m_buffer.write_elem(elem, m_bits_per_elem, value);
00149     }
00150 
00158     void set_grow_widen(u64 elem, u32 value)
00159     {
00160       unsigned int bits = highest_bit(value);
00161       if (bits > m_bits_per_elem)
00162         set_width(bits);
00163       set_grow(elem, value);
00164     }
00165 
00171     u32 get(u64 elem) const
00172     {
00173       if (elem >= m_num_elems)
00174         throw bit::out_of_range("bit::Array::get(): out of range");
00175       return m_buffer.read_elem(elem, m_bits_per_elem);
00176     }
00177 
00182     const unsigned char *data() const
00183     {
00184       return m_buffer.data();
00185     }
00186 
00191     unsigned char *data() 
00192     {
00193       return m_buffer.data();
00194     }
00195 
00199     u64 data_len() const 
00200     {
00201       return bytes_required(m_num_elems, m_bits_per_elem);
00202     }
00203 
00211     void write(FILE *file) const
00212     {
00213       fputs("ARRAY1:", file);
00214       fprintf(file, "%d:", m_bits_per_elem);
00215       fprintf(file, "%lld:", m_num_elems);
00216       assert(data_len() == bytes_required(m_num_elems, m_bits_per_elem));
00217       if (data_len() > 0) {
00218         size_t ret = fwrite(data(), data_len(), 1, file);
00219         if (ret != 1)
00220           throw bit::io_error(
00221             std::string("bit::Array::write() fwrite failed: ") + 
00222             strerror(errno));
00223       }
00224     }
00225 
00233     void read(FILE *file)
00234     {
00235       int version;
00236       int ret = fscanf(file, "ARRAY%d:%d:%lld:", 
00237                        &version, &m_bits_per_elem, &m_num_elems);
00238       if (ret != 3 || version != 1)
00239         throw bit::io_error("bit::Array::read() error while reading header");
00240       m_buffer.resize(bytes_required(m_num_elems, m_bits_per_elem));
00241       m_capacity = m_num_elems;
00242       if (data_len() > 0) {
00243         size_t ret = fread(data(), data_len(), 1, file);
00244         if (ret != 1) {
00245           if (ferror(file))
00246             throw bit::io_error("bit::Array::read() error while reading buffer");
00247           assert(feof(file));
00248           throw bit::io_error("bit::Array::read() eof while reading buffer");
00249         }
00250       }
00251     }
00252 
00253   private:
00254 
00256     unsigned int m_bits_per_elem;
00257 
00259     u64 m_num_elems;
00260 
00264     u64 m_capacity;
00265 
00267     Buffer m_buffer;
00268 
00269   };
00270 
00271 };
00272 
00273 #endif /* BIT_ARRAY_HH */

Generated on Mon Jan 8 15:51:03 2007 for bit by  doxygen 1.4.6