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,6 +30,23 @@ BitStream::getBits(int nbits) | ||
| 30 | this->bits_available, nbits); | 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 | void | 50 | void |
| 34 | BitStream::skipToNextByte() | 51 | BitStream::skipToNextByte() |
| 35 | { | 52 | { |
libqpdf/BitWriter.cc
| @@ -18,6 +18,21 @@ BitWriter::writeBits(unsigned long long val, unsigned int bits) | @@ -18,6 +18,21 @@ BitWriter::writeBits(unsigned long long val, unsigned int bits) | ||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | void | 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 | BitWriter::flush() | 36 | BitWriter::flush() |
| 22 | { | 37 | { |
| 23 | if (bit_offset < 7) | 38 | if (bit_offset < 7) |
libqpdf/qpdf/BitStream.hh
| @@ -15,6 +15,8 @@ class BitStream | @@ -15,6 +15,8 @@ class BitStream | ||
| 15 | QPDF_DLL | 15 | QPDF_DLL |
| 16 | unsigned long long getBits(int nbits); | 16 | unsigned long long getBits(int nbits); |
| 17 | QPDF_DLL | 17 | QPDF_DLL |
| 18 | + long long getBitsSigned(int nbits); | ||
| 19 | + QPDF_DLL | ||
| 18 | void skipToNextByte(); | 20 | void skipToNextByte(); |
| 19 | 21 | ||
| 20 | private: | 22 | private: |
libqpdf/qpdf/BitWriter.hh
| @@ -16,6 +16,8 @@ class BitWriter | @@ -16,6 +16,8 @@ class BitWriter | ||
| 16 | BitWriter(Pipeline* pl); | 16 | BitWriter(Pipeline* pl); |
| 17 | QPDF_DLL | 17 | QPDF_DLL |
| 18 | void writeBits(unsigned long long val, unsigned int bits); | 18 | void writeBits(unsigned long long val, unsigned int bits); |
| 19 | + QPDF_DLL | ||
| 20 | + void writeBitsSigned(long long val, unsigned int bits); | ||
| 19 | // Force any partial byte to be written to the pipeline. | 21 | // Force any partial byte to be written to the pipeline. |
| 20 | QPDF_DLL | 22 | QPDF_DLL |
| 21 | void flush(); | 23 | void flush(); |
libtests/bits.cc
| @@ -124,6 +124,13 @@ test() | @@ -124,6 +124,13 @@ test() | ||
| 124 | b.skipToNextByte(); | 124 | b.skipToNextByte(); |
| 125 | std::cout << b.getBits(8) << std::endl; | 125 | std::cout << b.getBits(8) << std::endl; |
| 126 | std::cout << std::endl; | 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 | // Write tests | 135 | // Write tests |
| 129 | 136 | ||
| @@ -159,6 +166,13 @@ test() | @@ -159,6 +166,13 @@ test() | ||
| 159 | bw.writeBits(0xABUL, 8); | 166 | bw.writeBits(0xABUL, 8); |
| 160 | bw.flush(); | 167 | bw.flush(); |
| 161 | print_buffer(bp); | 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 | delete bp; | 177 | delete bp; |
| 164 | } | 178 | } |
libtests/qtest/bits/bits.out
| @@ -36,6 +36,12 @@ byte offset = 8, bit offset = 7, bits available = 0 | @@ -36,6 +36,12 @@ byte offset = 8, bit offset = 7, bits available = 0 | ||
| 36 | 21 | 36 | 21 |
| 37 | 101 | 37 | 101 |
| 38 | 38 | ||
| 39 | +-1 | ||
| 40 | +-22 | ||
| 41 | +5 | ||
| 42 | +0 | ||
| 43 | +-39559 | ||
| 44 | + | ||
| 39 | ch = f0, bit_offset = 2 | 45 | ch = f0, bit_offset = 2 |
| 40 | ch = 00, bit_offset = 6 | 46 | ch = 00, bit_offset = 6 |
| 41 | ch = 14, bit_offset = 0 | 47 | ch = 14, bit_offset = 0 |
| @@ -56,4 +62,6 @@ f5 15 65 79 12 89 75 4b | @@ -56,4 +62,6 @@ f5 15 65 79 12 89 75 4b | ||
| 56 | 62 | ||
| 57 | f0 ab | 63 | f0 ab |
| 58 | 64 | ||
| 65 | +fa 49 | ||
| 66 | + | ||
| 59 | done | 67 | done |