00001 #ifndef BIT_BUFFER_HH
00002 #define BIT_BUFFER_HH
00003
00004 #include "bit/base.hh"
00005
00006 namespace bit {
00007
00012 class Buffer {
00013
00014 public:
00016 typedef std::vector<unsigned char> DataVector;
00017
00018 public:
00019
00023 Buffer(u64 size = 0)
00024 {
00025 m_data.resize(size);
00026 }
00027
00031 void swap(Buffer &buffer)
00032 {
00033 m_data.swap(buffer.m_data);
00034 }
00035
00036
00039 u64 size() const
00040 {
00041 return m_data.size();
00042 }
00043
00049 void resize(u64 size)
00050 {
00051 m_data.resize(size);
00052 }
00053
00062 u32 read_pos(u64 byte_pos, unsigned int bit_offset,
00063 unsigned int bits) const
00064 {
00065 if (bit_offset >= max_bits_per_value)
00066 throw bit::invalid_argument(
00067 "bit::Buffer::read_pos(): invalid bit_offset");
00068 if (bits > max_bits_per_value)
00069 throw bit::invalid_argument(
00070 "bit::Buffer::read_pos(): tried to read too many bits");
00071 if (bits == 0)
00072 return 0;
00073
00074
00075
00076 u64 last_byte_required = byte_pos + (bit_offset + bits - 1) / 8;
00077 if (last_byte_required >= m_data.size())
00078 throw bit::out_of_range("bit::Buffer::read_pos(): out_of_range");
00079
00080 u64 value = 0;
00081 int num_bytes = (bits + bit_offset + 7) / 8;
00082 for (int i = 0; i < num_bytes; i++)
00083 value += (u64)m_data[byte_pos + i] << shift[i];
00084 value >>= bit_offset;
00085 value &= one_masks[bits];
00086 return (u32)value;
00087 }
00088
00095 u32 read_elem(u64 elem, unsigned int bits_per_elem) const
00096 {
00097 u64 bit_pos = elem * bits_per_elem;
00098 return read_pos(bit_pos / 8, bit_pos % 8, bits_per_elem);
00099 }
00100
00101
00110 void write_pos(u64 byte_pos, unsigned int bit_offset, u32 value,
00111 unsigned int bits)
00112 {
00113 if (bit_offset >= max_bits_per_value)
00114 throw bit::invalid_argument(
00115 "bit::Buffer::write_pos(): invalid bit_offset");
00116 if (bits > max_bits_per_value)
00117 throw bit::invalid_argument(
00118 "bit::Buffer::write_pos(): tried to write too many bits");
00119 if (bit::highest_bit(value) > bits)
00120 throw bit::invalid_argument(
00121 "bit::Buffer::write_pos(): value greater than given bits");
00122 if (bits == 0)
00123 return;
00124
00125
00126
00127 u64 last_byte_required = byte_pos + (bit_offset + bits - 1) / 8;
00128 if (last_byte_required >= m_data.size())
00129 throw bit::out_of_range("bit::Buffer::write_pos(): out_of_range");
00130
00131 u64 zero_mask = one_masks[bits];
00132 zero_mask <<= bit_offset;
00133 zero_mask = ~zero_mask;
00134 u64 value_mask = value;
00135 value_mask <<= bit_offset;
00136
00137 int num_bytes = (bits + bit_offset + 7) / 8;
00138 for (int i = 0; i < num_bytes; i++) {
00139 m_data[byte_pos + i] &= (unsigned char)(zero_mask & 0xff);
00140 m_data[byte_pos + i] |= (unsigned char)(value_mask & 0xff);
00141 zero_mask >>= 8;
00142 value_mask >>= 8;
00143 }
00144 }
00145
00153 void write_elem(u64 elem, unsigned int bits_per_elem, u32 value)
00154 {
00155 u64 bit_pos = elem * bits_per_elem;
00156 write_pos(bit_pos / 8, bit_pos % 8, value, bits_per_elem);
00157 }
00158
00162 const unsigned char *data() const
00163 {
00164 return &m_data[0];
00165 }
00166
00170 unsigned char *data()
00171 {
00172 return &m_data[0];
00173 }
00174
00175 private:
00176
00178 DataVector m_data;
00179
00180 };
00181
00182
00183 };
00184
00185 #endif