patterncppMinor
Easy bitset I/O
Viewed 0 times
easybitsetstackoverflow
Problem
I'm writing a program that makes heavy use of
I've seen a few questions on Stack Overflow relating to this, such as this question, but it seems there is no standard or easy way to do
Here is an example usage:
```
std::ofstream bin_out("
std::bitset's and occasionally needs to read/write these to file. std::bitset does overload the > operators, but using these will result in an ASCII encoded file (i.e. {0,1} = 1 byte), which is ~8x bigger than it would be if using a bit-for-bit encoding.I've seen a few questions on Stack Overflow relating to this, such as this question, but it seems there is no standard or easy way to do
bitset I/O. I therefore set about writing a general bitset I/O class that is able to easily read and write multiple bitset's.#include
#include
#include
template
class BitIo
{
public:
void push_back(const std::bitset& bs)
{
std::vector result((N + 7) >> 3);
for (int j = 0; j > 3] |= (bs[j] pop_front()
{
std::bitset result;
for (int j = 0; j > 3) + offset] >> (j & 7)) & 1);
}
offset += NUM_BYTES_PER_BITSET;
num_bytes -= NUM_BYTES_PER_BITSET;
return result;
}
bool empty()
{
return num_bytes
friend std::ostream& operator& bio);
template
friend std::istream& operator>>(std::istream& is, BitIo& bio);
std::istream& read_file(std::istream& is)
{
bytes.clear();
std::streampos current_pos, file_size;
current_pos = is.tellg();
is.seekg(0, std::ios::end);
file_size = is.tellg() - current_pos;
is.seekg(current_pos, std::ios::beg);
bytes.resize(file_size);
is.read((char*) &bytes[0], file_size);
num_bytes += file_size;
return is;
}
std::vector bytes;
std::size_t offset = 0;
std::size_t num_bytes = 0;
};
template
std::ostream& operator& bio)
{
for (const auto& byte : bio.bytes) {
os
std::istream& operator>>(std::istream& is, BitIo& bio)
{
if(!is) {
is.setstate(std::ios::failbit);
}
bio.read_file(is);
return is;
}Here is an example usage:
```
std::ofstream bin_out("
Solution
You are using an
Appending the vectors inside
You can use
This is also more efficient, since
This
Also, why are you keeping a separate byte count in
Avoid C-style casts:
Change to:
Methods that don't mutate member state are
std::vector for temporary storage inside push_back(). This is a possible point of optimization, since the size of it is constant ((N + 7) >> 3). You could use an std::array in this case to make sure no dynamic memory is allocated. If you are concerned however that your N is going to be, in some cases, big enough to cause a stack overflow, then the vector would be indeed the best choice.Appending the vectors inside
push_back() can be simplified:for (const Byte& byte : result) {
bytes.push_back(byte);
}You can use
std::vector::insert():bytes.insert(std::end(bytes), std::begin(result), std::end(result));This is also more efficient, since
insert() can take the difference between begin / end and reserve() the exact amount of memory that will be needed.for (int j = 0; j < int(N); ++j)This
int(N) cast is silly. Declare j with std::size_t type.Also, why are you keeping a separate byte count in
num_bytes if the bytes vector has that same info in its size() method?Avoid C-style casts:
is.read((char*) &bytes[0], file_size);Change to:
is.read(reinterpret_cast(&bytes[0]), file_size);Methods that don't mutate member state are
const:bool empty() const;
std::size_t size() const;Code Snippets
for (const Byte& byte : result) {
bytes.push_back(byte);
}bytes.insert(std::end(bytes), std::begin(result), std::end(result));for (int j = 0; j < int(N); ++j)is.read((char*) &bytes[0], file_size);is.read(reinterpret_cast<char *>(&bytes[0]), file_size);Context
StackExchange Code Review Q#67012, answer score: 7
Revisions (0)
No revisions yet.