Line data Source code
1 : // Author(s): Maurice Laveaux 2 : // Copyright: see the accompanying file COPYING or copy at 3 : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING 4 : // 5 : // Distributed under the Boost Software License, Version 1.0. 6 : // (See accompanying file LICENSE_1_0.txt or copy at 7 : // http://www.boost.org/LICENSE_1_0.txt) 8 : // 9 : 10 : #ifndef MCRL2_UTILITIES_BITSTREAM_H 11 : #define MCRL2_UTILITIES_BITSTREAM_H 12 : 13 : #include <bitset> 14 : #include <cstdint> 15 : #include <vector> 16 : 17 : namespace mcrl2 18 : { 19 : namespace utilities 20 : { 21 : 22 : /// \returns The number of bits needed to represent a value of type T in most significant bit encoding. 23 : template<typename T> 24 6834 : constexpr std::size_t integer_encoding_size() 25 : { 26 6834 : return ((sizeof(T) + 1) * 8) / 7; 27 : } 28 : 29 : /// \brief A bitstream provides per bit writing of data to any stream (including stdout). 30 : /// \details Internally uses bitpacking and buffering for compact and efficient IO. 31 : class obitstream 32 : { 33 : public: 34 : /// \brief Provides the stream on which the write function operate. 35 : obitstream(std::ostream& stream); 36 80 : ~obitstream() { flush(); } 37 : 38 : /// \brief Write the num_of_bits least significant bits in descending order from value. 39 : /// @param value Variable that contains the bits. 40 : /// @param num_of_bits Number of bits to write to the output stream. 41 : void write_bits(std::size_t value, unsigned int num_of_bits); 42 : 43 : /// \brief Write the given string to the output stream. 44 : /// \details Encoded in bits using <length, string> 45 : void write_string(const std::string& string); 46 : 47 : /// \brief Write the given value to the output stream. 48 : /// \details Uses most significant bit encoding. 49 : void write_integer(std::size_t value); 50 : 51 : private: 52 : /// \brief Flush the remaining bits in the buffer to the output stream. 53 : /// \details Note that this aligns it to the next byte, e.g. when bits_in_buffer is 6 then two zero bits are added redundantly. 54 : void flush(); 55 : 56 : /// \brief Writes size bytes from the given buffer. 57 : void write(const std::uint8_t* buffer, std::size_t size); 58 : 59 : std::ostream& stream; 60 : 61 : /// \brief Buffer that is filled starting from bit 127 when writing 62 : std::bitset<128> write_buffer = 0; 63 : 64 : unsigned int bits_in_buffer = 0; ///< how many bits in are used in the buffer. 65 : 66 : std::uint8_t integer_buffer[integer_encoding_size<std::size_t>()]; ///< Reserved space to store an n byte integer. 67 : }; 68 : 69 : /// \brief The counterpart of obitstream, guarantees that the same data is read as has been written when calling the read operators 70 : /// in the same sequence as the corresponding write operators. 71 : class ibitstream 72 : { 73 : public: 74 : /// \brief Provides the stream on which the read function operate. 75 : ibitstream(std::istream& stream); 76 : 77 : /// \brief Reads an num_of_bits bits from the input stream and stores them in the least significant part (in descending order) of the return value. 78 : /// \param num_of_bits Number of bits to read from the input stream. 79 : std::size_t read_bits(unsigned int num_of_bits); 80 : 81 : /// \returns A pointer to the read string. 82 : /// \details Remains valid until the next call to read_string. 83 : const char* read_string(); 84 : 85 : /// \returns A natural number that was read from the binary stream encoded in most significant bit encoding. 86 : std::size_t read_integer(); 87 : 88 : private: 89 : /// \brief Read size bytes into the provided buffer. 90 : void read(std::size_t size, std::uint8_t* buffer); 91 : 92 : std::istream& stream; 93 : 94 : /// \brief Buffer that is filled starting from bit 127 when reading. 95 : std::bitset<128> read_buffer = 0; 96 : 97 : unsigned int bits_in_buffer = 0; ///< how many bits in the buffer are used. 98 : 99 : std::vector<char> m_text_buffer; ///< A temporary buffer to store char array strings. 100 : }; 101 : 102 : } // namespace utilities 103 : } // namespace mcrl2 104 : 105 : #endif // MCRL2_UTILITIES_BITSTREAM_H