Commit d9c90497089ae5cf00891d6febfa7f486f021833

Authored by Jay Berkenbilt
1 parent bf2fb239

Add signed support to BitStream and BitWriter

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