aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libqpdf/BitStream.cc17
-rw-r--r--libqpdf/BitWriter.cc15
-rw-r--r--libqpdf/qpdf/BitStream.hh2
-rw-r--r--libqpdf/qpdf/BitWriter.hh2
-rw-r--r--libtests/bits.cc14
-rw-r--r--libtests/qtest/bits/bits.out8
6 files changed, 58 insertions, 0 deletions
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<long long>(bits) > 1 << (nbits - 1))
+ {
+ result = static_cast<long long>(bits - (1 << nbits));
+ }
+ else
+ {
+ result = static_cast<long long>(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
@@ -18,6 +18,21 @@ BitWriter::writeBits(unsigned long long val, unsigned int bits)
}
void
+BitWriter::writeBitsSigned(long long val, unsigned int bits)
+{
+ unsigned long long uval = 0;
+ if (val < 0)
+ {
+ uval = static_cast<unsigned long long>((1 << bits) + val);
+ }
+ else
+ {
+ uval = static_cast<unsigned long long>(val);
+ }
+ writeBits(uval, bits);
+}
+
+void
BitWriter::flush()
{
if (bit_offset < 7)
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