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