#ifndef BITSTREAM_H #define BITSTREAM_H // Oldham, Jeffrey D. // 2000Apr26 // CS1321 // Read and Write Bits From Streams // To ease reading and writing individual bits from istreams and // ostreams, I wrote these classes. // // 1) bitistream returns the next bit from the istream. // 2) bitostream writes the next bit to the ostream. // // Mixing bit reading/writing with other types of reading/writing is // dangerous. // Reading and writing individual bits is inherently non-portable and // error-prone. Be cautious. #include #include // has CHAR_BIT #include // permits looking at individual bits // should have // declared before it since it relies // on CHAR_BIT but does not include #include // Returns the next bit (as a bool) from the given istream. class bitistream { public: bitistream(istream & inStream) : i(inStream) { position = -1; return; } // Return the next bit from the stream in the given parameter. // Return false if there is no more input. bool nextBit(bool& bit) { if (position < 0) { char c; if (!(cin.get(c))) return false; b = bitset(static_cast(c)); position = CHAR_BIT-1; } bit = b.test(position--); return true; } private: istream & i; bitset b; int position; // CHAR_BIT indicates no data in b // next position to read }; // Sends bits to the given ostream. class bitostream { public: bitostream(ostream & outStream) : o(outStream) { position = CHAR_BIT-1; return; } ~bitostream(void) { // Push false bits into the ostream to finish the character. while (position >= 0) nextBit(false); o << static_cast(b.to_ulong()); return; } // Return the next bit from the stream. void nextBit(const bool bt) { if (position < 0) { o << static_cast(b.to_ulong()); b.reset(); position = CHAR_BIT-1; } b.set(position--, bt); return; } // Return the given bits to the stream. void nextBits(const vector & v) { for (vector::const_iterator pos = v.begin(); pos != v.end(); ++pos) nextBit(*pos); return; } private: ostream & o; bitset b; int position; // CHAR_BIT indicates no data in b // next position to write }; #endif // BITSTREAM_H