use zStreamBuf to handle compression/decompression interface

This commit is contained in:
David Rose 2002-10-19 02:28:59 +00:00
parent 5d56f13f1a
commit 74c8b349ff
10 changed files with 216 additions and 832 deletions

View File

@ -26,7 +26,7 @@
socketStream.h socketStream.I \
urlSpec.I urlSpec.h \
$[if $[HAVE_NET], downloadDb.I downloadDb.h downloader.I downloader.h] \
$[if $[HAVE_ZLIB], decompressor.h zcompressor.I zcompressor.h download_utils.h] \
$[if $[HAVE_ZLIB], decompressor.h download_utils.h] \
$[if $[HAVE_CRYPTO], patcher.cxx patcher.h patcher.I]
#define INCLUDED_SOURCES \
@ -43,7 +43,7 @@
multiplexStream.cxx multiplexStreamBuf.cxx \
urlSpec.cxx \
$[if $[HAVE_NET], downloadDb.cxx downloader.cxx] \
$[if $[HAVE_ZLIB], decompressor.cxx zcompressor.cxx download_utils.cxx]
$[if $[HAVE_ZLIB], decompressor.cxx download_utils.cxx]
#define INSTALL_HEADERS \
asyncUtility.h asyncUtility.I \
@ -63,8 +63,7 @@
multiplexStreamBuf.I multiplexStreamBuf.I \
patcher.h patcher.I \
socketStream.h socketStream.I \
urlSpec.h urlSpec.I \
zcompressor.I zcompressor.h
urlSpec.h urlSpec.I
#define IGATESCAN all

View File

@ -15,22 +15,3 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "config_downloader.h"
////////////////////////////////////////////////////////////////////
// Function: Decompressor::get_progress
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE float Decompressor::
get_progress(void) const {
if (_initiated == false) {
downloader_cat.warning()
<< "Decompressor::get_progress() - Decompression has not been "
<< "initiated" << endl;
return 0.0;
}
nassertr(_source_file_length > 0, 0.0);
return ((float)_total_bytes_read / (float)_source_file_length);
}

View File

@ -18,69 +18,27 @@
// This file is compiled only if we have zlib installed.
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include "config_downloader.h"
#include "error_utils.h"
#include "filename.h"
#include "zStream.h"
#include "decompressor.h"
#include <stdio.h>
#include <errno.h>
#include <error_utils.h>
#include <filename.h>
#include "decompressor.h"
////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: Decompressor::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
Decompressor::
Decompressor(void) {
if (downloader_cat.is_debug())
downloader_cat.debug()
<< "Decompressor::constructor() - Creating buffer of size: "
<< decompressor_buffer_size << endl;
PT(Buffer) buffer = new Buffer(decompressor_buffer_size);
init(buffer);
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
Decompressor::
Decompressor(PT(Buffer) buffer) {
init(buffer);
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::Constructor
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void Decompressor::
init(PT(Buffer) buffer) {
if (downloader_cat.is_debug())
downloader_cat.debug()
<< "Decompressor constructor called" << endl;
_initiated = false;
nassertv(!buffer.is_null());
_half_buffer_length = buffer->get_length()/2;
_buffer = buffer;
char *temp_name = tempnam(NULL, "dc");
_temp_file_name = temp_name;
_temp_file_name.set_binary();
delete temp_name;
_decompressor = new ZDecompressor();
Decompressor() {
_source = NULL;
_decompress = NULL;
_dest = NULL;
}
////////////////////////////////////////////////////////////////////
@ -89,267 +47,208 @@ init(PT(Buffer) buffer) {
// Description:
////////////////////////////////////////////////////////////////////
Decompressor::
~Decompressor(void) {
if (downloader_cat.is_debug())
downloader_cat.debug()
<< "Decompressor destructor called" << endl;
_temp_file_name.unlink();
if (_initiated == true)
cleanup();
~Decompressor() {
cleanup();
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::initiate
// Access: Public
// Description:
// Description: Begins a background decompression of the named file
// (whose filename must end in ".pz") to a new file
// without the .pz extension. The source file is
// removed after successful completion.
////////////////////////////////////////////////////////////////////
int Decompressor::
initiate(Filename &source_file) {
Filename dest_file = source_file;
initiate(const Filename &source_file) {
string extension = source_file.get_extension();
if (extension == "pz")
if (extension == "pz") {
Filename dest_file = source_file;
dest_file = source_file.get_fullpath_wo_extension();
else {
if (downloader_cat.is_debug())
downloader_cat.debug()
<< "Decompressor::request_decompress() - Unknown file extension: ."
<< extension << endl;
return EU_error_abort;
}
return initiate(source_file, dest_file);
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::initiate
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
int Decompressor::
initiate(Filename &source_file, Filename &dest_file) {
if (_initiated == true) {
downloader_cat.error()
<< "Decompressor::initiate() - Decompression has already been initiated"
<< endl;
return EU_error_abort;
return initiate(source_file, dest_file);
}
// Open source file
_source_file = source_file;
_source_file.set_binary();
if (!_source_file.open_read(_read_stream)) {
downloader_cat.error()
<< "Decompressor::initiate() - Error opening source file: "
<< _source_file << " : " << strerror(errno) << endl;
return get_write_error();
}
// Determine source file length
_read_stream.seekg(0, ios::end);
_source_file_length = _read_stream.tellg();
if (_source_file_length == 0) {
downloader_cat.warning()
<< "Decompressor::initiate() - Zero length file: "
<< source_file << " : " << strerror(errno) << endl;
return get_write_error();
}
_read_stream.seekg(0, ios::beg);
// Open destination file
dest_file.set_binary();
if (!dest_file.open_write(_write_stream)) {
downloader_cat.error()
<< "Decompressor::initiate() - Error opening dest file: "
<< source_file << " : " << strerror(errno) << endl;
return get_write_error();
}
// Read from the source file into the first half of the buffer,
// decompress into the second half of the buffer, write the second
// half of the buffer to disk, and repeat.
_total_bytes_read = 0;
_read_all_input = false;
_source_buffer_length = 0;
_initiated = true;
_decompressor = new ZDecompressor();
_decompress_to_ram = false;
return EU_success;
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::initiate
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
int Decompressor::
initiate(Ramfile &source_file) {
if (_initiated == true) {
downloader_cat.error()
<< "Decompressor::initiate() - Decompression has already been initiated"
<< endl;
return EU_error_abort;
}
// Open source file
_read_string_stream = new istringstream(source_file._data);
// Determine source file length
_source_file_length = source_file._data.length();
if (_source_file_length == 0) {
downloader_cat.warning()
<< "Decompressor::initiate() - Zero length file: "
<< strerror(errno) << endl;
return get_write_error();
}
// Open destination file
_write_string_stream = new ostringstream();
// Read from the source file into the first half of the buffer,
// decompress into the second half of the buffer, write the second
// half of the buffer to disk, and repeat.
_total_bytes_read = 0;
_read_all_input = false;
_source_buffer_length = 0;
_initiated = true;
_decompressor = new ZDecompressor();
_decompress_to_ram = true;
return EU_success;
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::cleanup
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void Decompressor::
cleanup(void) {
if (downloader_cat.is_debug())
if (downloader_cat.is_debug()) {
downloader_cat.debug()
<< "Decompressor cleanup called" << endl;
if (_initiated == false) {
<< "Unknown file extension for decompressor: ."
<< extension << endl;
}
return EU_error_abort;
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::initiate
// Access: Public
// Description: Begins a background decompression from the named
// source file to the named destination file. The
// source file is removed after successful completion.
////////////////////////////////////////////////////////////////////
int Decompressor::
initiate(const Filename &source_file, const Filename &dest_file) {
cleanup();
// Open source file
_source_filename = Filename(source_file);
_source_filename.set_binary();
ifstream *source_fstream = new ifstream;
_source = source_fstream;
if (!_source_filename.open_read(*source_fstream)) {
downloader_cat.error()
<< "Decompressor::cleanup() - Decompression has not been "
<< "initiated" << endl;
return;
<< "Unable to read " << _source_filename << "\n";
return get_write_error();
}
_initiated = false;
delete _decompressor;
_decompressor = NULL;
_read_stream.close();
_write_stream.close();
if (_decompress_to_ram == false)
_source_file.unlink();
// Determine source file length
source_fstream->seekg(0, ios::end);
_source_length = source_fstream->tellg();
if (_source_length == 0) {
downloader_cat.warning()
<< "Zero length file: " << source_file << "\n";
return EU_error_file_empty;
}
source_fstream->seekg(0, ios::beg);
// Open destination file
Filename dest_filename(dest_file);
dest_filename.set_binary();
ofstream *dest_fstream = new ofstream;
_dest = dest_fstream;
if (!dest_filename.open_write(*dest_fstream)) {
downloader_cat.error()
<< "Unable to write to " << dest_filename << "\n";
return get_write_error();
}
// Now create the decompressor stream.
_decompress = new IDecompressStream(_source, false);
return EU_success;
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::run
// Access: Public
// Description:
// Description: Called each frame to do the next bit of work in the
// background task. Returns EU_ok if a chunk is
// completed but there is more to go, or EU_success when
// we're all done. Any other return value indicates an
// error.
////////////////////////////////////////////////////////////////////
int Decompressor::
run(void) {
if (_initiated == false) {
downloader_cat.error()
<< "Decompressor::run() - Decompression has not been initiated"
<< endl;
return EU_error_abort;
run() {
if (_decompress == (istream *)NULL) {
// Hmm, we were already done.
return EU_success;
}
// See if there is anything left in the source file
if (_read_all_input == false) {
if (_decompress_to_ram == false) {
_read_stream.read(_buffer->_buffer, _half_buffer_length);
_source_buffer_length = _read_stream.gcount();
_total_bytes_read += _source_buffer_length;
if (_read_stream.eof()) {
nassertr(_total_bytes_read == _source_file_length, false);
_read_all_input = true;
}
} else {
_read_string_stream->read(_buffer->_buffer, _half_buffer_length);
_source_buffer_length = _read_string_stream->gcount();
_total_bytes_read += _source_buffer_length;
if (_read_string_stream->eof()) {
nassertr(_total_bytes_read == _source_file_length, false);
_read_all_input = true;
}
// Read a bunch of characters from the decompress stream, but no
// more than decompressor_buffer_size.
int count = 0;
int ch = _decompress->get();
while (!_decompress->eof() && !_decompress->fail()) {
_dest->put(ch);
if (++count >= decompressor_buffer_size) {
// That's enough for now.
return EU_ok;
}
ch = _decompress->get();
}
char *next_in = _buffer->_buffer;
int avail_in = _source_buffer_length;
char *dest_buffer = _buffer->_buffer + _source_buffer_length;
char *next_out = dest_buffer;
int dest_buffer_length = _buffer->get_length() - _source_buffer_length;
int avail_out = dest_buffer_length;
nassertr(avail_out > 0 && avail_in > 0, false);
while (avail_in > 0) {
int ret;
if (_decompress_to_ram == false)
ret = _decompressor->decompress_to_stream(next_in, avail_in,
next_out, avail_out, dest_buffer,
dest_buffer_length, _write_stream);
else
ret = _decompressor->decompress_to_stream(next_in, avail_in,
next_out, avail_out, dest_buffer,
dest_buffer_length, *_write_string_stream);
if (ret == ZCompressorBase::S_error)
return EU_error_zlib;
if ((int)_decompressor->get_total_in() == _source_file_length &&
avail_out == dest_buffer_length) {
cleanup();
return EU_success;
}
}
return EU_ok;
// All done!
cleanup();
_source_filename.unlink();
return EU_success;
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::decompress
// Access: Public
// Description:
// Description: Performs a foreground decompression of the named
// file; does not return until the decompression is
// complete.
////////////////////////////////////////////////////////////////////
bool Decompressor::
decompress(Filename &source_file) {
decompress(const Filename &source_file) {
int ret = initiate(source_file);
if (ret < 0)
return false;
for (;;) {
ret = run();
if (ret == EU_success)
return true;
else if (ret < 0)
return false;
int ch = _decompress->get();
while (!_decompress->eof() && !_decompress->fail()) {
_dest->put(ch);
ch = _decompress->get();
}
return false;
cleanup();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::decompress
// Access: Public
// Description:
// Description: Does an in-memory decompression of the indicated
// Ramfile. The decompressed contents are written back
// into the same Ramfile on completion.
////////////////////////////////////////////////////////////////////
bool Decompressor::
decompress(Ramfile &source_file) {
int ret = initiate(source_file);
if (ret < 0)
return false;
for (;;) {
ret = run();
if (ret == EU_success) {
source_file._data = _write_string_stream->str();
delete _read_string_stream;
_read_string_stream = NULL;
delete _write_string_stream;
_write_string_stream = NULL;
return true;
} else if (ret < 0)
return false;
decompress(Ramfile &source_and_dest_file) {
istringstream source(source_and_dest_file._data);
ostringstream dest;
IDecompressStream decompress(&source, false);
int ch = decompress.get();
while (!decompress.eof() && !decompress.fail()) {
dest.put(ch);
ch = decompress.get();
}
source_and_dest_file._pos = 0;
source_and_dest_file._data = dest.str();
return true;
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::get_progress
// Access: Public
// Description: Returns the ratio through the decompression step
// in the background.
////////////////////////////////////////////////////////////////////
float Decompressor::
get_progress() const {
if (_decompress == (istream *)NULL) {
// Hmm, we were already done.
return 1.0f;
}
nassertr(_source_length > 0, 0.0);
size_t source_pos = _source->tellg();
// We stop the scale at 0.99 because there may be a little bit more
// to do even after the decompressor has read all of the source.
return (0.99f * (float)source_pos / (float)_source_length);
}
////////////////////////////////////////////////////////////////////
// Function: Decompressor::cleanup
// Access: Private
// Description: Called to reset a previous decompressor state and
// clean up properly.
////////////////////////////////////////////////////////////////////
void Decompressor::
cleanup() {
if (_source != (istream *)NULL) {
delete _source;
_source = NULL;
}
if (_dest != (ostream *)NULL) {
delete _dest;
_dest = NULL;
}
if (_decompress != (istream *)NULL) {
delete _decompress;
_decompress = NULL;
}
return false;
}

View File

@ -15,59 +15,45 @@
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef DECOMPRESSOR_H
#define DECOMPRESSOR_H
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <filename.h>
#include <buffer.h>
#include <pointerTo.h>
#include "zcompressor.h"
#include "pandabase.h"
#include "filename.h"
class Ramfile;
////////////////////////////////////////////////////////////////////
// Class : Decompressor
// Description :
// Description : This manages run-time decompression of a
// zlib-compressed stream, as a background or foreground
// task.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAEXPRESS Decompressor {
PUBLISHED:
Decompressor(void);
Decompressor(PT(Buffer) buffer);
virtual ~Decompressor(void);
Decompressor();
~Decompressor();
int initiate(Filename &source_file);
int initiate(Filename &source_file, Filename &dest_file);
int initiate(Ramfile &source_file);
int run(void);
int initiate(const Filename &source_file);
int initiate(const Filename &source_file, const Filename &dest_file);
int run();
bool decompress(Filename &source_file);
bool decompress(Ramfile &source_file);
bool decompress(const Filename &source_file);
bool decompress(Ramfile &source_and_dest_file);
INLINE float get_progress(void) const;
float get_progress() const;
private:
void init(PT(Buffer) buffer);
void cleanup(void);
bool _initiated;
PT(Buffer) _buffer;
int _half_buffer_length;
Filename _temp_file_name;
Filename _source_filename;
istream *_source;
istream *_decompress;
ostream *_dest;
Filename _source_file;
ifstream _read_stream;
ofstream _write_stream;
istringstream *_read_string_stream;
ostringstream *_write_string_stream;
int _source_file_length;
int _total_bytes_read;
bool _read_all_input;
bool _handled_all_input;
int _source_buffer_length;
ZDecompressor *_decompressor;
bool _decompress_to_ram;
size_t _source_length;
};
#include "decompressor.I"

View File

@ -1,4 +1,3 @@
#include "download_utils.cxx"
#include "decompressor.cxx"
#include "zcompressor.cxx"

View File

@ -1,95 +0,0 @@
// Filename: zcompressor.I
// Created by: mike (09Jan97)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ZCompressorBase::get_total_in
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ulong ZCompressorBase::
get_total_in(void) const {
return (_stream->total_in);
}
////////////////////////////////////////////////////////////////////
// Function: ZCompressorBase::get_total_out
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE ulong ZCompressorBase::
get_total_out(void) const {
return (_stream->total_out);
}
////////////////////////////////////////////////////////////////////
// Function: ZCompressorBase::reset
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void ZCompressorBase::
reset(void) {
reset_stream(_stream);
}
////////////////////////////////////////////////////////////////////
// Function: ZCompressorBase::reset_stream
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
INLINE void ZCompressorBase::
reset_stream(z_stream *strm) const {
strm->next_in = Z_NULL;
strm->avail_in = 0;
strm->total_in = 0;
strm->next_out = Z_NULL;
strm->avail_out = 0;
strm->total_out = 0;
strm->zalloc = Z_NULL;
strm->zfree = Z_NULL;
strm->opaque = Z_NULL;
}
#ifndef CPPPARSER
////////////////////////////////////////////////////////////////////
// Function: ZCompressorBase::put_stream
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
INLINE void ZCompressorBase::
put_stream(z_stream *strm, char *next_in, int avail_in, char *next_out,
int avail_out) const {
strm->next_in = (uchar *)next_in;
strm->avail_in = (ulong)avail_in;
strm->next_out = (uchar *)next_out;
strm->avail_out = (ulong)avail_out;
}
////////////////////////////////////////////////////////////////////
// Function: ZCompressorBase::get_stream
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
INLINE void ZCompressorBase::
get_stream(z_stream *strm, char *&next_in, int &avail_in, char *&next_out,
int &avail_out) const {
next_in = (char *)strm->next_in;
avail_in = (int)strm->avail_in;
next_out = (char *)strm->next_out;
avail_out = (int)strm->avail_out;
}
#endif

View File

@ -1,242 +0,0 @@
// Filename: zcompressor.cxx
// Created by: mike (09Jan97)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
// This file is compiled only if we have zlib installed.
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include "config_downloader.h"
#include <zlib.h>
#include "zcompressor.h"
////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ZCompressor::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
ZCompressor::
ZCompressor(void) {
if (downloader_cat.is_debug())
downloader_cat.debug()
<< "ZCompressor constructor called" << endl;
_stream = new z_stream;
reset_stream(_stream);
int ret = deflateInit(_stream, 9);
if (ret == Z_OK)
downloader_cat.debug()
<< "ZCompressor::ZCompressor() - Zlib deflate initialized" << endl;
else
handle_zerror(ret, _stream);
}
////////////////////////////////////////////////////////////////////
// Function: ZCompressor::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
ZCompressor::
~ZCompressor(void) {
if (downloader_cat.is_debug())
downloader_cat.debug()
<< "ZCompressor destructor called" << endl;
handle_zerror(deflateEnd(_stream), _stream);
delete _stream;
}
////////////////////////////////////////////////////////////////////
// Function: ZCompressor::compress
// Access: Public
// Description: Compress from next_in into next_out until avail_in
// is 0 or avail_out is 0 or an error occurs.
////////////////////////////////////////////////////////////////////
int ZCompressor::
compress(char *&next_in, int &avail_in, char *&next_out, int &avail_out,
bool finish) {
int fin_flag = (finish == true) ? Z_FINISH : Z_NO_FLUSH;
put_stream(_stream, next_in, avail_in, next_out, avail_out);
int ret = handle_zerror(deflate(_stream, fin_flag), _stream);
get_stream(_stream, next_in, avail_in, next_out, avail_out);
return ret;
}
////////////////////////////////////////////////////////////////////
// Function: ZCompressor::compress_to_stream
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
int ZCompressor::
compress_to_stream(char *&next_in, int &avail_in, char *&next_out,
int &avail_out, char *out_buffer,
int out_buffer_length, ofstream &write_stream,
bool finish) {
int ret = compress(next_in, avail_in, next_out, avail_out, finish);
if (ret == S_error)
return ret;
// See if there is any output to write
int out_bytes = out_buffer_length - avail_out;
if (out_bytes > 0) {
write_stream.write(out_buffer, out_bytes);
next_out = out_buffer;
avail_out = out_buffer_length;
}
return ret;
}
////////////////////////////////////////////////////////////////////
// Function: ZDecompressor::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
ZDecompressor::
ZDecompressor(void) {
if (downloader_cat.is_debug())
downloader_cat.debug()
<< "ZDecompressor constructor called" << endl;
_stream = new z_stream;
reset_stream(_stream);
int ret = inflateInit(_stream);
if (ret == Z_OK)
downloader_cat.debug()
<< "ZDecompressor::ZDecompressor() - Zlib inflate initialized" << endl;
else
handle_zerror(ret, _stream);
}
////////////////////////////////////////////////////////////////////
// Function: ZDecompressor::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
ZDecompressor::
~ZDecompressor(void) {
if (downloader_cat.is_debug())
downloader_cat.debug()
<< "ZDecompressor destructor called" << endl;
handle_zerror(inflateEnd(_stream), _stream);
}
////////////////////////////////////////////////////////////////////
// Function: ZDecompressor::decompress
// Access: Public
// Description: Decompress from next_in into next_out until avail_in
// is 0 or avail_out is 0 or an error occurs.
////////////////////////////////////////////////////////////////////
int ZDecompressor::
decompress(char *&next_in, int &avail_in, char *&next_out, int &avail_out,
bool finish) {
int fin_flag = (finish == true) ? Z_FINISH : Z_NO_FLUSH;
put_stream(_stream, next_in, avail_in, next_out, avail_out);
int ret = handle_zerror(inflate(_stream, fin_flag), _stream);
get_stream(_stream, next_in, avail_in, next_out, avail_out);
return ret;
}
////////////////////////////////////////////////////////////////////
// Function: ZDecompressor::decompress_to_stream
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
int ZDecompressor::
decompress_to_stream(char *&next_in, int &avail_in, char *&next_out,
int &avail_out, char *out_buffer,
int out_buffer_length, ostream &write_stream,
bool finish) {
int ret = decompress(next_in, avail_in, next_out, avail_out, finish);
if (ret == S_error)
return ret;
// See if there is any output to write
int out_bytes = out_buffer_length - avail_out;
if (out_bytes > 0) {
write_stream.write(out_buffer, out_bytes);
next_out = out_buffer;
avail_out = out_buffer_length;
}
return ret;
}
////////////////////////////////////////////////////////////////////
// Function: ZCompressorBase::handle_zerror
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
int ZCompressorBase::
handle_zerror(int code, const z_stream *strm) const {
if (code == Z_OK)
return S_ok;
else if (code == Z_STREAM_END)
return S_finished;
else {
downloader_cat.error()
<< "ZCompressorBase::handle_zerror() - ";
switch (code) {
case Z_DATA_ERROR:
downloader_cat.error()
<< "corrupt data";
break;
case Z_NEED_DICT:
downloader_cat.error()
<< "need a dictionary";
break;
case Z_STREAM_ERROR:
downloader_cat.error()
<< "next_in or next_out = NULL";
break;
case Z_MEM_ERROR:
downloader_cat.error()
<< "not enough memory";
break;
case Z_BUF_ERROR:
downloader_cat.error()
<< "no progress is possible";
break;
case Z_VERSION_ERROR:
downloader_cat.error()
<< "zlib version conflict";
break;
default:
downloader_cat.error()
<< "unknown error: " << code;
break;
}
if (strm != NULL) {
if (strm->msg != NULL) {
downloader_cat.error()
<< " - zlib message: " << strm->msg;
}
}
downloader_cat.error()
<< endl;
}
return S_error;
}

View File

@ -1,90 +0,0 @@
// Filename: zcompressor.h
// Created by: mike (09Jan97)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#ifndef ZCOMPRESSOR_H
#define ZCOMPRESSOR_H
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <zlib.h>
#include "typedef.h"
////////////////////////////////////////////////////////////////////
// Class : ZCompressorBase
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAEXPRESS ZCompressorBase {
public:
enum status {
S_ok,
S_finished,
S_error,
};
INLINE ulong get_total_in(void) const;
INLINE ulong get_total_out(void) const;
INLINE void reset(void);
INLINE void reset_stream(z_stream *strm) const;
#ifndef CPPPARSER
INLINE void put_stream(z_stream *strm, char *next_in, int avail_in,
char *next_out, int avail_out) const;
INLINE void get_stream(z_stream *strm, char *&next_in, int &avail_in,
char *&next_out, int &avail_out) const;
#endif
int handle_zerror(int code, const z_stream *strm = NULL) const;
protected:
z_stream *_stream;
};
////////////////////////////////////////////////////////////////////
// Class : ZCompressor
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAEXPRESS ZCompressor : public ZCompressorBase {
public:
ZCompressor(void);
~ZCompressor(void);
int compress(char *&next_in, int &avail_in, char *&next_out,
int &avail_out, bool finish = false);
int compress_to_stream(char *&next_in, int &avail_in, char *&next_out,
int &avail_out, char *out_buffer, int out_buffer_length,
ofstream &write_stream, bool finish = false);
};
////////////////////////////////////////////////////////////////////
// Class : ZDecompressor
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDAEXPRESS ZDecompressor : public ZCompressorBase {
public:
ZDecompressor(void);
~ZDecompressor(void);
int decompress(char *&next_in, int &avail_in, char *&next_out,
int &avail_out, bool finish = false);
int decompress_to_stream(char *&next_in, int &avail_in, char *&next_out,
int &avail_out, char *out_buffer, int out_buffer_length,
ostream &write_stream, bool finish = false);
};
#include "zcompressor.I"
#endif

View File

@ -16,15 +16,15 @@
//
////////////////////////////////////////////////////////////////////
#include <filename.h>
#include <zcompressor.h>
#include <notify.h>
#include "filename.h"
#include "zStream.h"
#include "notify.h"
int
main(int argc, char *argv[]) {
if (argc < 2) {
cerr << "Usage: pcompress <file>" << endl;
return 0;
return 1;
}
Filename source_file = argv[1];
@ -37,7 +37,7 @@ main(int argc, char *argv[]) {
source_file.set_binary();
if (!source_file.open_read(read_stream)) {
cerr << "failed to open: " << source_file << endl;
return 0;
return 1;
}
// Determine source file length
@ -55,64 +55,16 @@ main(int argc, char *argv[]) {
dest_file.set_binary();
if (!dest_file.open_write(write_stream)) {
cerr << "failed to open: " << dest_file << endl;
return 0;
return 1;
}
ZCompressor compressor;
int buffer_length = 1000000;
int half_buffer_length = buffer_length/2;
char *buffer = new char[buffer_length];
// Read from the source file into the first half of the buffer,
// decompress into the second half of the buffer, write the second
// half of the buffer to disk, and repeat.
int total_bytes_read = 0;
bool read_all_input = false;
bool handled_all_input = false;
int source_buffer_length;
int ret;
while (handled_all_input == false) {
// See if there is anything left in the source file
if (read_all_input == false) {
read_stream.read(buffer, half_buffer_length);
source_buffer_length = read_stream.gcount();
total_bytes_read += source_buffer_length;
if (read_stream.eof()) {
nassertr(total_bytes_read == source_file_length, false);
read_all_input = true;
}
}
char *next_in = buffer;
int avail_in = source_buffer_length;
char *dest_buffer = buffer + source_buffer_length;
char *next_out = dest_buffer;
int dest_buffer_length = buffer_length - source_buffer_length;
int avail_out = dest_buffer_length;
nassertr(avail_out > 0 && avail_in > 0, false);
// Consume all the input from the input buffer, writing to disk
// as we go to free output buffer space
while (avail_in > 0) {
ret = compressor.compress_to_stream(next_in, avail_in,
next_out, avail_out, dest_buffer,
dest_buffer_length, write_stream);
if (ret == ZCompressorBase::S_error)
return 0;
}
// If all the input has been consumed, we need to keep processing
// output until it says it's finished
if (compressor.get_total_in() == source_file_length) {
while (ret != ZCompressorBase::S_finished) {
ret = compressor.compress_to_stream(next_in, avail_in,
next_out, avail_out, dest_buffer,
dest_buffer_length, write_stream, true);
if (ret == ZCompressorBase::S_error)
return 0;
}
handled_all_input = true;
{
OCompressStream compress(&write_stream, false);
int ch = read_stream.get();
while (!read_stream.eof() && !read_stream.fail()) {
compress.put(ch);
ch = read_stream.get();
}
}
@ -120,5 +72,5 @@ main(int argc, char *argv[]) {
write_stream.close();
source_file.unlink();
return 1;
return 0;
}

View File

@ -16,27 +16,22 @@
//
////////////////////////////////////////////////////////////////////
#include <filename.h>
#include <decompressor.h>
#include <buffer.h>
#include "filename.h"
#include "decompressor.h"
int
main(int argc, char *argv[]) {
if (argc < 2) {
cerr << "Usage: pdecompress <file>" << endl;
return 0;
return 1;
}
Filename source_file = argv[1];
#ifdef TESTING_CODE
Decompressor decompressor;
#else
PT(Buffer) buffer = new Buffer(1000000);
Decompressor decompressor(buffer);
#endif
if (decompressor.decompress(source_file) == false)
if (decompressor.decompress(source_file) == false) {
cerr << "Decompress failed" << endl;
return 1;
}
return 1;
return 0;
}