fix zstream inflate

This commit is contained in:
David Rose 2002-08-07 19:09:53 +00:00
parent 147af90897
commit cdb5139a10
3 changed files with 113 additions and 17 deletions

View File

@ -20,8 +20,10 @@
#include "zStream.h"
#include "filename.h"
#include "zlib.h"
void
decompress(istream &source) {
stream_decompress(istream &source) {
IDecompressStream zstream(&source, false);
int ch = zstream.get();
@ -32,7 +34,7 @@ decompress(istream &source) {
}
void
compress(istream &source) {
stream_compress(istream &source) {
OCompressStream zstream(&cout, false);
int ch = source.get();
@ -42,12 +44,89 @@ compress(istream &source) {
}
}
void
zlib_decompress(istream &source) {
// First, read the entire contents into a buffer.
string data;
int ch = source.get();
while (!source.eof() && !source.fail()) {
data += (char)ch;
ch = source.get();
}
// Now call zlib to decompress the buffer directly.
size_t source_len = data.length();
// Take a stab on the appropriate size of the output buffer.
size_t dest_len = source_len * 4;
char *dest = new char[dest_len];
uLongf actual_dest_len = dest_len;
int result = uncompress((Bytef *)dest, &actual_dest_len,
(const Bytef *)data.data(), source_len);
if (result != Z_OK) {
cerr << "compress result == " << result << "\n";
}
while (result == Z_BUF_ERROR) {
dest_len *= 2;
cerr << "Increasing buffer size to " << dest_len << "\n";
delete[] dest;
dest = new char[dest_len];
actual_dest_len = dest_len;
result = uncompress((Bytef *)dest, &actual_dest_len,
(const Bytef *)data.data(), source_len);
if (result != Z_OK) {
cerr << "compress result == " << result << "\n";
}
}
cout.write(dest, actual_dest_len);
}
void
zlib_compress(istream &source) {
// First, read the entire contents into a buffer.
string data;
int ch = source.get();
while (!source.eof() && !source.fail()) {
data += (char)ch;
ch = source.get();
}
// Now call zlib to compress the buffer directly.
size_t source_len = data.length();
size_t dest_len = (size_t)(source_len * 1.1) + 12;
char *dest = new char[dest_len];
uLongf actual_dest_len = dest_len;
int result = compress((Bytef *)dest, &actual_dest_len,
(const Bytef *)data.data(), source_len);
if (result != Z_OK) {
cerr << "compress result == " << result << "\n";
}
cout.write(dest, actual_dest_len);
}
int
main(int argc, char *argv[]) {
bool zlib_direct = false;
if (argc >= 2 && strcmp(argv[1], "-z") == 0) {
zlib_direct = true;
argc--;
argv++;
}
if (argc != 2) {
cerr << "test_zstream file\n"
cerr << "test_zstream [-z] file\n"
<< "compresses file to standard output, or decompresses it if the\n"
<< "filename ends in .pz.\n";
<< "filename ends in .pz.\n\n"
<< "With -z, calls zlib directly instead of using the zstream interface.\n";
return (1);
}
@ -60,10 +139,19 @@ main(int argc, char *argv[]) {
cerr << "Unable to open source " << source_filename << ".\n";
return (1);
}
if (source_filename.get_extension() == "pz") {
decompress(source);
if (zlib_direct) {
if (source_filename.get_extension() == "pz") {
zlib_decompress(source);
} else {
zlib_compress(source);
}
} else {
compress(source);
if (source_filename.get_extension() == "pz") {
stream_decompress(source);
} else {
stream_compress(source);
}
}
return (0);

View File

@ -243,27 +243,21 @@ underflow() {
////////////////////////////////////////////////////////////////////
size_t ZStreamBuf::
read_chars(char *start, size_t length) {
static const size_t decompress_buffer_size = 4096;
char decompress_buffer[decompress_buffer_size];
_z_source.next_out = (Bytef *)start;
_z_source.avail_out = length;
int flush = (_source->eof() || _source->fail()) ? Z_FINISH : 0;
bool eof = (_source->eof() || _source->fail());
while (_z_source.avail_out > 0) {
if (_z_source.avail_in == 0 && flush == 0) {
if (_z_source.avail_in == 0 && !eof) {
_source->read(decompress_buffer, decompress_buffer_size);
size_t read_count = _source->gcount();
if (read_count == 0 || _source->eof() || _source->fail()) {
// End of input; tell zlib to expect to stop.
flush = Z_FINISH;
}
eof = (read_count == 0 || _source->eof() || _source->fail());
_z_source.next_in = (Bytef *)decompress_buffer;
_z_source.avail_in = read_count;
}
int result = inflate(&_z_source, flush);
int result = inflate(&_z_source, 0);
size_t bytes_read = length - _z_source.avail_out;
if (result == Z_STREAM_END) {

View File

@ -61,6 +61,20 @@ private:
z_stream _z_source;
z_stream _z_dest;
// We need to store the decompression buffer on the class object,
// because zlib might not consume all of the input characters at
// each call to inflate(). This isn't a problem on output because
// in that case we can afford to wait until it does consume all of
// the characters we give it.
enum {
// It's not clear how large or small this buffer ought to be. It
// doesn't seem to matter much, especially since this is just a
// temporary holding area before getting copied into zlib's own
// internal buffers.
decompress_buffer_size = 128
};
char decompress_buffer[decompress_buffer_size];
};
#endif // HAVE_ZLIB