Commit d9c90497089ae5cf00891d6febfa7f486f021833
1 parent
bf2fb239
Add signed support to BitStream and BitWriter
Showing
6 changed files
with
58 additions
and
0 deletions
libqpdf/BitStream.cc
| ... | ... | @@ -30,6 +30,23 @@ BitStream::getBits(int nbits) |
| 30 | 30 | this->bits_available, nbits); |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | +long long | |
| 34 | +BitStream::getBitsSigned(int nbits) | |
| 35 | +{ | |
| 36 | + unsigned long long bits = read_bits(this->p, this->bit_offset, | |
| 37 | + this->bits_available, nbits); | |
| 38 | + long long result = 0; | |
| 39 | + if (static_cast<long long>(bits) > 1 << (nbits - 1)) | |
| 40 | + { | |
| 41 | + result = static_cast<long long>(bits - (1 << nbits)); | |
| 42 | + } | |
| 43 | + else | |
| 44 | + { | |
| 45 | + result = static_cast<long long>(bits); | |
| 46 | + } | |
| 47 | + return result; | |
| 48 | +} | |
| 49 | + | |
| 33 | 50 | void |
| 34 | 51 | BitStream::skipToNextByte() |
| 35 | 52 | { | ... | ... |
libqpdf/BitWriter.cc
| ... | ... | @@ -18,6 +18,21 @@ BitWriter::writeBits(unsigned long long val, unsigned int bits) |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | void |
| 21 | +BitWriter::writeBitsSigned(long long val, unsigned int bits) | |
| 22 | +{ | |
| 23 | + unsigned long long uval = 0; | |
| 24 | + if (val < 0) | |
| 25 | + { | |
| 26 | + uval = static_cast<unsigned long long>((1 << bits) + val); | |
| 27 | + } | |
| 28 | + else | |
| 29 | + { | |
| 30 | + uval = static_cast<unsigned long long>(val); | |
| 31 | + } | |
| 32 | + writeBits(uval, bits); | |
| 33 | +} | |
| 34 | + | |
| 35 | +void | |
| 21 | 36 | BitWriter::flush() |
| 22 | 37 | { |
| 23 | 38 | if (bit_offset < 7) | ... | ... |
libqpdf/qpdf/BitStream.hh
libqpdf/qpdf/BitWriter.hh
| ... | ... | @@ -16,6 +16,8 @@ class BitWriter |
| 16 | 16 | BitWriter(Pipeline* pl); |
| 17 | 17 | QPDF_DLL |
| 18 | 18 | void writeBits(unsigned long long val, unsigned int bits); |
| 19 | + QPDF_DLL | |
| 20 | + void writeBitsSigned(long long val, unsigned int bits); | |
| 19 | 21 | // Force any partial byte to be written to the pipeline. |
| 20 | 22 | QPDF_DLL |
| 21 | 23 | void flush(); | ... | ... |
libtests/bits.cc
| ... | ... | @@ -124,6 +124,13 @@ test() |
| 124 | 124 | b.skipToNextByte(); |
| 125 | 125 | std::cout << b.getBits(8) << std::endl; |
| 126 | 126 | std::cout << std::endl; |
| 127 | + b.reset(); | |
| 128 | + std::cout << b.getBitsSigned(3) << std::endl; | |
| 129 | + std::cout << b.getBitsSigned(6) << std::endl; | |
| 130 | + std::cout << b.getBitsSigned(5) << std::endl; | |
| 131 | + std::cout << b.getBitsSigned(1) << std::endl; | |
| 132 | + std::cout << b.getBitsSigned(17) << std::endl; | |
| 133 | + std::cout << std::endl; | |
| 127 | 134 | |
| 128 | 135 | // Write tests |
| 129 | 136 | |
| ... | ... | @@ -159,6 +166,13 @@ test() |
| 159 | 166 | bw.writeBits(0xABUL, 8); |
| 160 | 167 | bw.flush(); |
| 161 | 168 | print_buffer(bp); |
| 169 | + bw.writeBitsSigned(-1, 3); // 111 | |
| 170 | + bw.writeBitsSigned(-12, 6); // 110100 | |
| 171 | + bw.writeBitsSigned(4, 3); // 100 | |
| 172 | + bw.writeBitsSigned(-4, 3); // 100 | |
| 173 | + bw.writeBitsSigned(-1, 1); // 1 | |
| 174 | + bw.flush(); | |
| 175 | + print_buffer(bp); | |
| 162 | 176 | |
| 163 | 177 | delete bp; |
| 164 | 178 | } | ... | ... |
libtests/qtest/bits/bits.out
| ... | ... | @@ -36,6 +36,12 @@ byte offset = 8, bit offset = 7, bits available = 0 |
| 36 | 36 | 21 |
| 37 | 37 | 101 |
| 38 | 38 | |
| 39 | +-1 | |
| 40 | +-22 | |
| 41 | +5 | |
| 42 | +0 | |
| 43 | +-39559 | |
| 44 | + | |
| 39 | 45 | ch = f0, bit_offset = 2 |
| 40 | 46 | ch = 00, bit_offset = 6 |
| 41 | 47 | ch = 14, bit_offset = 0 |
| ... | ... | @@ -56,4 +62,6 @@ f5 15 65 79 12 89 75 4b |
| 56 | 62 | |
| 57 | 63 | f0 ab |
| 58 | 64 | |
| 65 | +fa 49 | |
| 66 | + | |
| 59 | 67 | done | ... | ... |