From 8e2b2031e2b366fb7720c0a2a4b568428b111d3d Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 28 May 2009 12:25:35 +0000 Subject: [PATCH] From Neil Hughes, "Two changes here... 1. I've implemented an option controlled route by which users can still access the old method of extracting the zip content to the local filesystem. This is in response to Ulrich's comments about zip files encorporating files other than those that OSG knows about, but which an application may require. To access this the user makes the following call on their options object that they pass to the reader. Without it, the plugin will extract by default to memory. local_opt->setPluginStrData("zipextract","filesystem"); 2. The second change is that I've moved the declaration of one of the variables to within the numitems loop so that if loading of a specific file within the zip fails, subsequent files still load correctly. This was the issue that Ulrich raised." --- src/osgPlugins/zip/ReaderWriterZIP.cpp | 80 ++++++++++++++++---------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/src/osgPlugins/zip/ReaderWriterZIP.cpp b/src/osgPlugins/zip/ReaderWriterZIP.cpp index 5804120ee..34058ff2c 100644 --- a/src/osgPlugins/zip/ReaderWriterZIP.cpp +++ b/src/osgPlugins/zip/ReaderWriterZIP.cpp @@ -21,40 +21,61 @@ class ReaderWriterZIP : public osgDB::ReaderWriter virtual ReadResult readNode(const std::string& file, const osgDB::Options* options) const { - std::string ext = osgDB::getLowerCaseFileExtension(file); - if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; - - std::string fileName = osgDB::findDataFile( file, options ); - if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; - - osg::notify(osg::INFO)<<"ReaderWriterZIP::readNode( "<getPluginStringData("zipextract"); + if (!(optExtractTo.empty())) + { + if (osgDB::convertToLowerCase(optExtractTo)=="filesystem") + { + bExtractToFileSystem = true; + } + } + } - // Setup appropriate options - osg::ref_ptr local_opt = options ? - static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : - new Options; + if (bExtractToFileSystem) + { + rresult = original_readNode(file,options); + } + else + { + std::string ext = osgDB::getLowerCaseFileExtension(file); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; - // minor issue associated with database path list, as in context of zip file it - // doesn't make sense. Need to set to empty path for other plugins to access - local_opt->getDatabasePathList().push_front(osgDB::getFilePath(file)); + std::string fileName = osgDB::findDataFile( file, options ); + if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; - // Now pass through to memory zip handler - rresult = readNode(tmpStrmBuffer,local_opt); + osg::notify(osg::INFO)<<"ReaderWriterZIP::readNode( "<getDatabasePathList().pop_front(); + // First open file as stream + std::ifstream srcFileStrm(fileName.c_str(),std::ios::in|std::ios::binary); + if (!srcFileStrm.fail()) + { + // Now read entire zip file into stream buffer + std::stringstream tmpStrmBuffer; + srcFileStrm.seekg(0,std::ios_base::beg); + tmpStrmBuffer.operator <<(srcFileStrm.rdbuf()); + srcFileStrm.close(); + + // Setup appropriate options + osg::ref_ptr local_opt = options ? + static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : + new Options; + + // minor issue associated with database path list, as in context of zip file it + // doesn't make sense. Need to set to empty path for other plugins to access + local_opt->getDatabasePathList().push_front(osgDB::getFilePath(file)); + + // Now pass through to memory zip handler + rresult = readNode(tmpStrmBuffer,local_opt); + + // Clean up options + local_opt->getDatabasePathList().pop_front(); + } } return rresult; @@ -63,7 +84,7 @@ class ReaderWriterZIP : public osgDB::ReaderWriter virtual ReadResult readNode(std::istream& fin,const osgDB::Options* options =NULL) const { ReadResult result = ReadResult(ReadResult::FILE_NOT_HANDLED); - std::stringstream buffer; + if (!fin.fail()) { @@ -102,7 +123,8 @@ class ReaderWriterZIP : public osgDB::ReaderWriter { GetZipItem(hz,i,&ze); std::string StreamName = ze.name; - + std::stringstream buffer; + char *ibuf = new char[ze.unc_size]; if (ibuf) {