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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
#ifndef __BITS_CC__
#define __BITS_CC__
#include <algorithm>
#include <stdexcept>
#include <qpdf/QTC.hh>
#include <qpdf/Pipeline.hh>
// These functions may be run at places where the function call
// overhead from test coverage testing would be too high. Therefore,
// we make the test coverage cases conditional upon a preprocessor
// symbol. BitStream.cc includes this file without defining the
// symbol, and the specially designed test code that fully exercises
// this code includes with the symbol defined.
#ifdef BITS_READ
static unsigned long long
read_bits(unsigned char const*& p, unsigned int& bit_offset,
unsigned int& bits_available, unsigned int bits_wanted)
{
// View p as a stream of bits:
// 76543210 76543210 ....
// bit_offset is the bit number within the first byte that marks
// the first bit that we would read.
if (bits_wanted > bits_available)
{
throw std::length_error("overflow reading bit stream");
}
if (bits_wanted > 32)
{
throw std::out_of_range("read_bits: too many bits requested");
}
unsigned long result = 0;
#ifdef BITS_TESTING
if (bits_wanted == 0)
{
QTC::TC("libtests", "bits zero bits wanted");
}
#endif
while (bits_wanted > 0)
{
// Grab bits from the first byte clearing anything before
// bit_offset.
unsigned char byte = *p & ((1 << (bit_offset + 1)) - 1);
// There are bit_offset + 1 bits available in the first byte.
unsigned int to_copy = std::min(bits_wanted, bit_offset + 1);
unsigned int leftover = (bit_offset + 1) - to_copy;
#ifdef BITS_TESTING
QTC::TC("libtests", "bits bit_offset",
((bit_offset == 0) ? 0 :
(bit_offset == 7) ? 1 :
2));
QTC::TC("libtests", "bits leftover", (leftover > 0) ? 1 : 0);
#endif
// Right shift so that all the bits we want are right justified.
byte >>= leftover;
// Copy the bits into result
result <<= to_copy;
result |= byte;
// Update pointers
if (leftover)
{
bit_offset = leftover - 1;
}
else
{
bit_offset = 7;
++p;
}
bits_wanted -= to_copy;
bits_available -= to_copy;
#ifdef BITS_TESTING
QTC::TC("libtests", "bits iterations",
((bits_wanted > 8) ? 0 :
(bits_wanted > 0) ? 1 :
2));
#endif
}
return result;
}
#endif
#ifdef BITS_WRITE
static void
write_bits(unsigned char& ch, unsigned int& bit_offset,
unsigned long long val, unsigned int bits, Pipeline* pipeline)
{
if (bits > 32)
{
throw std::out_of_range("write_bits: too many bits requested");
}
// bit_offset + 1 is the number of bits left in ch
#ifdef BITS_TESTING
if (bits == 0)
{
QTC::TC("libtests", "bits write zero bits");
}
#endif
while (bits > 0)
{
int bits_to_write = std::min(bits, bit_offset + 1);
unsigned char newval =
(val >> (bits - bits_to_write)) & ((1 << bits_to_write) - 1);
int bits_left_in_ch = bit_offset + 1 - bits_to_write;
newval <<= bits_left_in_ch;
ch |= newval;
if (bits_left_in_ch == 0)
{
#ifdef BITS_TESTING
QTC::TC("libtests", "bits write pipeline");
#endif
pipeline->write(&ch, 1);
bit_offset = 7;
ch = 0;
}
else
{
#ifdef BITS_TESTING
QTC::TC("libtests", "bits write leftover");
#endif
bit_offset -= bits_to_write;
}
bits -= bits_to_write;
#ifdef BITS_TESTING
QTC::TC("libtests", "bits write iterations",
((bits > 8) ? 0 :
(bits > 0) ? 1 :
2));
#endif
}
}
#endif
#endif // __BITS_CC__
|