Moved compress/uncompress code across to using gzip compatible methods

This commit is contained in:
Robert Osfield 2008-10-10 12:01:54 +00:00
parent 46172c931e
commit d8525815fd

View File

@ -103,6 +103,11 @@ class ReaderWriterGZ : public osgDB::ReaderWriter
WriteResult writeFile(ObjectType objectType, const osg::Object* object, const std::string& fullFileName, const osgDB::ReaderWriter::Options* options) const;
bool read(std::istream& fin, std::string& destination) const;
bool write(std::ostream& fout, const std::string& source) const;
};
ReaderWriterGZ::ReaderWriterGZ()
@ -169,30 +174,9 @@ osgDB::ReaderWriter::ReadResult ReaderWriterGZ::readFile(ObjectType objectType,
std::ifstream fin(fileName.c_str());
if (!fin) return ReadResult::ERROR_IN_READING_FILE;
std::streampos start = fin.tellg();
fin.seekg(0, std::ios::end);
std::streampos end = fin.tellg();
fin.seekg(start, std::ios::beg);
std::streampos sourceLen = end - start;
/* empty stream into memory, open that, and keep the pointer in a FreeTypeFont for cleanup */
char* buffer = new char[sourceLen];
fin.read(reinterpret_cast<char*>(buffer), sourceLen);
if (!fin || (static_cast<std::streampos>(fin.gcount()) != sourceLen))
{
osg::notify(osg::WARN)<<" .... the compressed file could not be read from its stream"<<std::endl;
return 0;
}
uLongf destLen = 1000000;
std::string dest;
dest.resize(destLen);
int result = uncompress ((Bytef *)(&(*dest.begin())), &destLen,
(const Bytef *)buffer, sourceLen);
delete [] buffer;
read(fin, dest);
std::stringstream strstream(dest);
@ -241,35 +225,137 @@ osgDB::ReaderWriter::WriteResult ReaderWriterGZ::writeFile(ObjectType objectType
std::stringstream strstream;
osgDB::ReaderWriter::WriteResult writeResult = writeFile(objectType, object, rw, strstream, options);
std::ofstream fout(fullFileName.c_str());
std::string str(strstream.str());
write(fout,strstream.str());
uLong destLen = compressBound(str.size());
osg::notify(osg::NOTICE)<<"compressBound("<<str.size()<<") = "<<destLen<<std::endl;
std::string output;
output.resize(destLen);
int level = 6;
char* source = new char[str.size()];
char* dest = new char[destLen];
int result = compress2( (Bytef *)(&(*output.begin())), &destLen,
(const Bytef *)(&(*str.begin())), str.size(),
level);
osg::notify(osg::NOTICE)<<"compress2()"<<result<<", destLen="<<destLen<<std::endl;
output.resize(destLen);
std::ofstream fout(fullFileName.c_str());
fout<<output;
return writeResult;
}
#define CHUNK 16384
bool ReaderWriterGZ::read(std::istream& fin, std::string& destination) const
{
int ret;
unsigned have;
z_stream strm;
unsigned char in[CHUNK];
unsigned char out[CHUNK];
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm,
15 + 32 // autodected zlib or gzip header
);
if (ret != Z_OK)
return ret;
/* decompress until deflate stream ends or end of file */
do {
osg::notify(osg::NOTICE)<<"Doing readsome"<<std::endl;
strm.avail_in = fin.readsome((char*)in, CHUNK);
if (fin.fail())
{
(void)inflateEnd(&strm);
return false;
}
if (strm.avail_in == 0)
break;
strm.next_in = in;
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
switch (ret) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return false;
}
have = CHUNK - strm.avail_out;
destination.append((char*)out, have);
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? true : false;
}
bool ReaderWriterGZ::write(std::ostream& fout, const std::string& source) const
{
int ret, flush = Z_FINISH;
unsigned have;
z_stream strm;
unsigned char out[CHUNK];
int level = 6;
int stategy = Z_DEFAULT_STRATEGY; // looks to be the best for .osg/.ive files
//int stategy = Z_FILTERED;
//int stategy = Z_HUFFMAN_ONLY;
//int stategy = Z_RLE;
/* allocate deflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit2(&strm,
level,
Z_DEFLATED,
15+16, // +16 to use gzip encoding
8, // default
stategy);
if (ret != Z_OK)
return false;
strm.avail_in = source.size();
strm.next_in = (Bytef*)(&(*source.begin()));
/* run deflate() on input until output buffer not full, finish
compression if all of source has been read in */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = deflate(&strm, flush); /* no bad return value */
if (ret == Z_STREAM_ERROR)
{
osg::notify(osg::NOTICE)<<"Z_STREAM_ERROR"<<std::endl;
return false;
}
have = CHUNK - strm.avail_out;
if (have>0) fout.write((const char*)out, have);
if (fout.fail())
{
(void)deflateEnd(&strm);
return false;
}
} while (strm.avail_out == 0);
/* clean up and return */
(void)deflateEnd(&strm);
return true;
}
// now register with Registry to instantiate the above
// reader/writer.
REGISTER_OSGPLUGIN(GZ, ReaderWriterGZ)