diff --git a/libqpdf/BitStream.cc b/libqpdf/BitStream.cc index 14eae55d..bb52af31 100644 --- a/libqpdf/BitStream.cc +++ b/libqpdf/BitStream.cc @@ -30,6 +30,23 @@ BitStream::getBits(int nbits) this->bits_available, nbits); } +long long +BitStream::getBitsSigned(int nbits) +{ + unsigned long long bits = read_bits(this->p, this->bit_offset, + this->bits_available, nbits); + long long result = 0; + if (static_cast(bits) > 1 << (nbits - 1)) + { + result = static_cast(bits - (1 << nbits)); + } + else + { + result = static_cast(bits); + } + return result; +} + void BitStream::skipToNextByte() { diff --git a/libqpdf/BitWriter.cc b/libqpdf/BitWriter.cc index 4fb375cb..7513ac76 100644 --- a/libqpdf/BitWriter.cc +++ b/libqpdf/BitWriter.cc @@ -17,6 +17,21 @@ BitWriter::writeBits(unsigned long long val, unsigned int bits) write_bits(this->ch, this->bit_offset, val, bits, this->pl); } +void +BitWriter::writeBitsSigned(long long val, unsigned int bits) +{ + unsigned long long uval = 0; + if (val < 0) + { + uval = static_cast((1 << bits) + val); + } + else + { + uval = static_cast(val); + } + writeBits(uval, bits); +} + void BitWriter::flush() { diff --git a/libqpdf/qpdf/BitStream.hh b/libqpdf/qpdf/BitStream.hh index e45a90ee..8ea8bec4 100644 --- a/libqpdf/qpdf/BitStream.hh +++ b/libqpdf/qpdf/BitStream.hh @@ -15,6 +15,8 @@ class BitStream QPDF_DLL unsigned long long getBits(int nbits); QPDF_DLL + long long getBitsSigned(int nbits); + QPDF_DLL void skipToNextByte(); private: diff --git a/libqpdf/qpdf/BitWriter.hh b/libqpdf/qpdf/BitWriter.hh index 7e3b07a9..3d93c0b7 100644 --- a/libqpdf/qpdf/BitWriter.hh +++ b/libqpdf/qpdf/BitWriter.hh @@ -16,6 +16,8 @@ class BitWriter BitWriter(Pipeline* pl); QPDF_DLL void writeBits(unsigned long long val, unsigned int bits); + QPDF_DLL + void writeBitsSigned(long long val, unsigned int bits); // Force any partial byte to be written to the pipeline. QPDF_DLL void flush(); diff --git a/libtests/bits.cc b/libtests/bits.cc index ba1d5483..3b274f93 100644 --- a/libtests/bits.cc +++ b/libtests/bits.cc @@ -124,6 +124,13 @@ test() b.skipToNextByte(); std::cout << b.getBits(8) << std::endl; std::cout << std::endl; + b.reset(); + std::cout << b.getBitsSigned(3) << std::endl; + std::cout << b.getBitsSigned(6) << std::endl; + std::cout << b.getBitsSigned(5) << std::endl; + std::cout << b.getBitsSigned(1) << std::endl; + std::cout << b.getBitsSigned(17) << std::endl; + std::cout << std::endl; // Write tests @@ -159,6 +166,13 @@ test() bw.writeBits(0xABUL, 8); bw.flush(); print_buffer(bp); + bw.writeBitsSigned(-1, 3); // 111 + bw.writeBitsSigned(-12, 6); // 110100 + bw.writeBitsSigned(4, 3); // 100 + bw.writeBitsSigned(-4, 3); // 100 + bw.writeBitsSigned(-1, 1); // 1 + bw.flush(); + print_buffer(bp); delete bp; } diff --git a/libtests/qtest/bits/bits.out b/libtests/qtest/bits/bits.out index 73111536..8483c110 100644 --- a/libtests/qtest/bits/bits.out +++ b/libtests/qtest/bits/bits.out @@ -36,6 +36,12 @@ byte offset = 8, bit offset = 7, bits available = 0 21 101 +-1 +-22 +5 +0 +-39559 + ch = f0, bit_offset = 2 ch = 00, bit_offset = 6 ch = 14, bit_offset = 0 @@ -56,4 +62,6 @@ f5 15 65 79 12 89 75 4b f0 ab +fa 49 + done