-
Notifications
You must be signed in to change notification settings - Fork 0
/
input_stream.hpp
executable file
·102 lines (82 loc) · 2.65 KB
/
input_stream.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/* input_stream.hpp
CSC 485B/CSC 578B/SENG 480B - Summer 2020
Definition of a bitstream class which complies with the bit ordering
required by the gzip format.
(The member function definitions are all inline in this header file
for convenience, even though the use of such long inlined functions
might be frowned upon under some style manuals)
B. Bird - 06/19/2020
*/
#ifndef INPUT_STREAM_HPP
#define INPUT_STREAM_HPP
#include <iostream>
#include <cstdint>
/* These definitions are more reliable for fixed width types than using "int" and assuming its width */
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
class InputBitStream{
public:
/* Constructor */
InputBitStream( std::istream& input_stream ): bitvec{0}, numbits{8}, infile{input_stream}, done{false}, last_real_bit{0} {
}
/* Destructor */
virtual ~InputBitStream(){
}
/* Read an entire byte from the stream, with the least significant bit read first */
unsigned char read_byte(){
return read_bits(8);
}
/* Read a 32 bit unsigned integer value (LSB first) */
u32 read_u32(){
return read_bits(8) | (read_bits(8)<<8) | (read_bits(8)<<16) | (read_bits(8)<<24);
}
/* Read a 16 bit unsigned short value (LSB first) */
u16 read_u16(){
return read_bits(8) | (read_bits(8)<<8);
}
/* Read the lowest order num_bits bits from the stream into a u32,
with the least significant bit read first.
*/
u32 read_bits(int num_bits){
u32 result{};
for (int i = 0; i < num_bits; i++)
result |= read_bit()<<i;
return result;
}
/* Read a single bit b (stored as the LSB of an unsigned int)
from the stream */
unsigned int read_bit(){
//This has been set up to emit an infinite number of copies
//of the last bit once EOF is reached (so if the last bit
//in the file is a 1, any subsequent call to read_bit will
//return 1).
if (numbits == 8)
input_byte();
if (!done)
last_real_bit = (bitvec>>(numbits++))&0x1;
return last_real_bit;
}
/* Flush the currently stored bits*/
void flush_to_byte(){
numbits = 8; //Force the next read to read a byte from the input file
}
private:
void input_byte(){
char c;
if (!infile.get(c)){
done = true;
numbits = 0;
return;
}
bitvec = (unsigned char)c;
numbits = 0;
}
u32 bitvec;
u32 numbits;
std::istream& infile;
bool done;
unsigned int last_real_bit;
};
#endif