mirror of
https://github.com/qpdf/qpdf.git
synced 2024-11-16 09:37:08 +00:00
5d4cad9c02
Significantly improve the code's use of off_t for file offsets, size_t for memory sizes, and integer types in cases where there has to be compatibility with external interfaces. Rework sections of the code that would have prevented qpdf from working on files larger than 2 (or maybe 4) GB in size.
150 lines
3.3 KiB
Plaintext
150 lines
3.3 KiB
Plaintext
|
|
#ifndef __BITS_CC__
|
|
#define __BITS_CC__
|
|
|
|
#include <algorithm>
|
|
#include <stdexcept>
|
|
#include <qpdf/QTC.hh>
|
|
#include <qpdf/Pipeline.hh>
|
|
|
|
// These functions may be run at places where the function call
|
|
// overhead from test coverage testing would be too high. Therefore,
|
|
// we make the test coverage cases conditional upon a preprocessor
|
|
// symbol. BitStream.cc includes this file without defining the
|
|
// symbol, and the specially designed test code that fully exercises
|
|
// this code includes with the symbol defined.
|
|
|
|
#ifdef BITS_READ
|
|
static unsigned long
|
|
read_bits(unsigned char const*& p, unsigned int& bit_offset,
|
|
unsigned int& bits_available, unsigned int bits_wanted)
|
|
{
|
|
// View p as a stream of bits:
|
|
|
|
// 76543210 76543210 ....
|
|
|
|
// bit_offset is the bit number within the first byte that marks
|
|
// the first bit that we would read.
|
|
|
|
if (bits_wanted > bits_available)
|
|
{
|
|
throw std::length_error("overflow reading bit stream");
|
|
}
|
|
if (bits_wanted > 32)
|
|
{
|
|
throw std::out_of_range("read_bits: too many bits requested");
|
|
}
|
|
|
|
unsigned long result = 0;
|
|
#ifdef BITS_TESTING
|
|
if (bits_wanted == 0)
|
|
{
|
|
QTC::TC("libtests", "bits zero bits wanted");
|
|
}
|
|
#endif
|
|
while (bits_wanted > 0)
|
|
{
|
|
// Grab bits from the first byte clearing anything before
|
|
// bit_offset.
|
|
unsigned char byte = *p & ((1 << (bit_offset + 1)) - 1);
|
|
|
|
// There are bit_offset + 1 bits available in the first byte.
|
|
unsigned int to_copy = std::min(bits_wanted, bit_offset + 1);
|
|
unsigned int leftover = (bit_offset + 1) - to_copy;
|
|
|
|
#ifdef BITS_TESTING
|
|
QTC::TC("libtests", "bits bit_offset",
|
|
((bit_offset == 0) ? 0 :
|
|
(bit_offset == 7) ? 1 :
|
|
2));
|
|
QTC::TC("libtests", "bits leftover", (leftover > 0) ? 1 : 0);
|
|
#endif
|
|
|
|
// Right shift so that all the bits we want are right justified.
|
|
byte >>= leftover;
|
|
|
|
// Copy the bits into result
|
|
result <<= to_copy;
|
|
result |= byte;
|
|
|
|
// Update pointers
|
|
if (leftover)
|
|
{
|
|
bit_offset = leftover - 1;
|
|
}
|
|
else
|
|
{
|
|
bit_offset = 7;
|
|
++p;
|
|
}
|
|
bits_wanted -= to_copy;
|
|
bits_available -= to_copy;
|
|
|
|
#ifdef BITS_TESTING
|
|
QTC::TC("libtests", "bits iterations",
|
|
((bits_wanted > 8) ? 0 :
|
|
(bits_wanted > 0) ? 1 :
|
|
2));
|
|
#endif
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
#ifdef BITS_WRITE
|
|
static void
|
|
write_bits(unsigned char& ch, unsigned int& bit_offset,
|
|
unsigned long val, unsigned int bits, Pipeline* pipeline)
|
|
{
|
|
if (bits > 32)
|
|
{
|
|
throw std::out_of_range("write_bits: too many bits requested");
|
|
}
|
|
|
|
// bit_offset + 1 is the number of bits left in ch
|
|
#ifdef BITS_TESTING
|
|
if (bits == 0)
|
|
{
|
|
QTC::TC("libtests", "bits write zero bits");
|
|
}
|
|
#endif
|
|
while (bits > 0)
|
|
{
|
|
int bits_to_write = std::min(bits, bit_offset + 1);
|
|
unsigned char newval =
|
|
(val >> (bits - bits_to_write)) & ((1 << bits_to_write) - 1);
|
|
int bits_left_in_ch = bit_offset + 1 - bits_to_write;
|
|
newval <<= bits_left_in_ch;
|
|
ch |= newval;
|
|
if (bits_left_in_ch == 0)
|
|
{
|
|
#ifdef BITS_TESTING
|
|
QTC::TC("libtests", "bits write pipeline");
|
|
#endif
|
|
pipeline->write(&ch, 1);
|
|
bit_offset = 7;
|
|
ch = 0;
|
|
}
|
|
else
|
|
{
|
|
#ifdef BITS_TESTING
|
|
QTC::TC("libtests", "bits write leftover");
|
|
#endif
|
|
bit_offset -= bits_to_write;
|
|
}
|
|
bits -= bits_to_write;
|
|
#ifdef BITS_TESTING
|
|
QTC::TC("libtests", "bits write iterations",
|
|
((bits > 8) ? 0 :
|
|
(bits > 0) ? 1 :
|
|
2));
|
|
#endif
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
#endif // __BITS_CC__
|