-
Notifications
You must be signed in to change notification settings - Fork 106
Expand file tree
/
Copy pathBitIoStream.cpp
More file actions
73 lines (60 loc) · 1.63 KB
/
BitIoStream.cpp
File metadata and controls
73 lines (60 loc) · 1.63 KB
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
/*
* Reference arithmetic coding
*
* Copyright (c) Project Nayuki
* MIT License. See readme file.
* https://www.nayuki.io/page/reference-arithmetic-coding
*/
#include <limits>
#include <stdexcept>
#include <string>
#include "BitIoStream.hpp"
BitInputStream::BitInputStream(std::istream &in) :
input(in),
currentByte(0),
numBitsRemaining(0) {}
int BitInputStream::read() {
if (currentByte == std::char_traits<char>::eof())
return -1;
if (numBitsRemaining == 0) {
currentByte = input.get(); // Note: istream.get() returns int, not char
if (currentByte == std::char_traits<char>::eof())
return -1;
if (!(0 <= currentByte && currentByte <= 255))
throw std::logic_error("Assertion error");
numBitsRemaining = 8;
}
if (numBitsRemaining <= 0)
throw std::logic_error("Assertion error");
numBitsRemaining--;
return (currentByte >> numBitsRemaining) & 1;
}
int BitInputStream::readNoEof() {
int result = read();
if (result != -1)
return result;
else
throw std::runtime_error("End of stream");
}
BitOutputStream::BitOutputStream(std::ostream &out) :
output(out),
currentByte(0),
numBitsFilled(0) {}
void BitOutputStream::write(int b) {
if (b != 0 && b != 1)
throw std::domain_error("Argument must be 0 or 1");
currentByte = (currentByte << 1) | b;
numBitsFilled++;
if (numBitsFilled == 8) {
// Note: ostream.put() takes char, which may be signed/unsigned
if (std::numeric_limits<char>::is_signed)
currentByte -= (currentByte >> 7) << 8;
output.put(static_cast<char>(currentByte));
currentByte = 0;
numBitsFilled = 0;
}
}
void BitOutputStream::finish() {
while (numBitsFilled != 0)
write(0);
}