6
\$\begingroup\$

In a previous question I posted a method for easy std::bitset IO on a bit-for-bit basis. This question was later followed up in another solution. Both of these solutions had limitations; the interface of my original solution was not pretty, and the second method was limited to 64 bit std::bitsets.

Here is the solution I settled on. I have benchmarked this against my original solution (with the suggested improvements), and the runtime performance characteristics are very comparable. In fact, it seems this method is even faster than the buffering approach, while obviously also having the advantage of memory savings.

bitio.h

template <std::size_t N>
class BitIO
{
public:
 std::bitset<N> data;
 BitIO() {};
 BitIO(const std::bitset<N>& data) : data(data)
 {
 bitset_to_bytes();
 }
private:
 template <std::size_t T>
 friend std::ostream& operator<<(std::ostream& os, const BitIO<T>& bio);
 template <std::size_t T>
 friend std::istream& operator>>(std::istream& is, BitIO<T>& bio);
 void bitset_to_bytes()
 {
 for (std::size_t j = 0; j < N; ++j) {
 bytes[j >> 3] |= (data[j] << (j & 7));
 }
 }
 void bytes_to_bitset()
 {
 data.reset();
 for (std::size_t j = 0; j < N; ++j) {
 data[j] = ((bytes[(j >> 3)] >> (j & 7)) & 1);
 }
 }
 std::istream& read_file(std::istream& is)
 {
 is.read(reinterpret_cast<char*>(&bytes[0]), (N + 7) >> 3);
 bytes_to_bitset();
 return is;
 }
 std::array<unsigned char, ((N + 7) >> 3)> bytes{};
};
template <std::size_t N>
std::ostream& operator<<(std::ostream& os, const BitIO<N>& bio)
{
 for (const auto& byte : bio.bytes) {
 os << byte;
 }
 return os;
}
template <std::size_t N>
std::istream& operator>>(std::istream& is, BitIO<N>& bio)
{
 bio.read_file(is);
 is.peek(); // To set eof flag.
 return is;
}

main.cpp

#include "bitio.h"
#include <iostream>
int main()
{
 std::ofstream bin_out("~/bf.bin", std::ios::out | std::ios::binary);
 std::vector<std::bitset<16>> values { std::bitset<16>(100), std::bitset<16>(200), std::bitset<16>(255) };
 std::copy(std::begin(values), std::end(values), std::ostream_iterator<BitIO<16>>(bin_out));
 bin_out.close();
 std::ifstream bin_in("~/bf.bin", std::ios::binary);
 values.clear();
 while (!bin_in.eof()) {
 BitIO<16> bio;
 bin_in >> bio;
 values.push_back(bio.data);
 }
}

Any further suggestions for improvement are welcome!

asked Oct 30, 2014 at 20:35
\$\endgroup\$

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.