# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlCore/ZippedDirectory.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.org                                               */
    00005 /*                                                                                    */
    00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
    00007 /*  All rights reserved.                                                              */
    00008 /*                                                                                    */
    00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
    00010 /*  are permitted provided that the following conditions are met:                     */
    00011 /*                                                                                    */
    00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
    00013 /*  list of conditions and the following disclaimer.                                  */
    00014 /*                                                                                    */
    00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
    00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
    00017 /*  other materials provided with the distribution.                                   */
    00018 /*                                                                                    */
    00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
    00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
    00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
    00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
    00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
    00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
    00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
    00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
    00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
    00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
    00029 /*                                                                                    */
    00030 /**************************************************************************************/
    00031
    00032 #include <vlCore/ZippedDirectory.hpp>
    00033 #include <vlCore/VisualizationLibrary.hpp>
    00034 #include <vlCore/FileSystem.hpp>
    00035 #include <set>
    00036
    00037 using namespace vl;
    00038 //-----------------------------------------------------------------------------
    00039 ZippedDirectory::ZippedDirectory() {}
    00040 //-----------------------------------------------------------------------------
    00041 ZippedDirectory::ZippedDirectory(const String& zip_file)
    00042 {
    00043   ref<VirtualFile> v_file = defFileSystem()->locateFile(zip_file);
    00044   if (v_file)
    00045     setSourceZipFile(v_file.get());
    00046   else
    00047     Log::error( Say("ZippedDirectory() could not locate zip file '%s'.\n") << zip_file );
    00048 }
    00049 //-----------------------------------------------------------------------------
    00050 ZippedDirectory::ZippedDirectory(VirtualFile* zip_file)
    00051 {
    00052   if (zip_file)
    00053     setSourceZipFile(zip_file);
    00054 }
    00055 //-----------------------------------------------------------------------------
    00056 bool ZippedDirectory::setPath(const String& name)
    00057 {
    00058   String root = name;
    00059   root.trim();
    00060   root.normalizeSlashes();
    00061   if (root.empty())
    00062   {
    00063     Log::error("ZippedDirectory::setPath() given an empty path.\n");
    00064     return false;
    00065   }
    00066   if (!root.endsWith('/'))
    00067   {
    00068     // Log::warning( Say("ZippedDirectory::setPath() : path (%s) must end with a '/'.\n") << root );
    00069     root += '/';
    00070   }
    00071
    00072   std::map< String, ref<ZippedFile> > file_map;
    00073   for( std::map< String, ref<ZippedFile> >::iterator it = mFiles.begin(); it != mFiles.end(); ++it )
    00074   {
    00075     String p = it->first;
    00076     if ( !p.startsWith(path()) )
    00077     {
    00078       Log::warning( Say("ZippedDirectory::setPath() : invalid path file '%s'.\n") << p );
    00079       continue;
    00080     }
    00081     p = p.right(-path().length());
    00082     it->second->setPath(root + p);
    00083     file_map[it->second->path()] = it->second;
    00084   }
    00085   mFiles = file_map;
    00086   mPath = root;
    00087   return true;
    00088 }
    00089 //-----------------------------------------------------------------------------
    00090 const VirtualFile* ZippedDirectory::sourceZipFile() const
    00091 {
    00092   return mSourceZipFile.get();
    00093 }
    00094 //-----------------------------------------------------------------------------
    00095 VirtualFile* ZippedDirectory::sourceZipFile()
    00096 {
    00097   return mSourceZipFile.get();
    00098 }
    00099 //-----------------------------------------------------------------------------
    00100 void ZippedDirectory::setSourceZipFile(VirtualFile* file)
    00101 {
    00102   reset();
    00103   mSourceZipFile = file;
    00104   if(file)
    00105     init();
    00106 }
    00107 //-----------------------------------------------------------------------------
    00108 void ZippedDirectory::reset()
    00109 {
    00110   mSourceZipFile = NULL;
    00111   mFiles.clear();
    00112 }
    00113 //-----------------------------------------------------------------------------
    00114 bool ZippedDirectory::init()
    00115 {
    00116   mFiles.clear();
    00117   if (path().empty())
    00118   {
    00119     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00120     return false;
    00121   }
    00122   ref<VirtualFile> zip = sourceZipFile();
    00123   if (!zip)
    00124   {
    00125     Log::error("ZippedFile::init() called but not zip file mounted.\n");
    00126     return false;
    00127   }
    00128   zip->close();
    00129   if ( !zip->open(OM_ReadOnly) )
    00130   {
    00131     Log::error("ZippedDirectory::init(): cannot open source zip file.\n");
    00132     return false;
    00133   }
    00134
    00135   for( unsigned int local_file_header_signature = 0;
    00136        zip->read(&local_file_header_signature, 4) && local_file_header_signature == 0x04034b50;
    00137        local_file_header_signature = 0 )
    00138   {
    00139     // creates and fills a new ZippedFileInfo and a new ZippedFile
    00140     ref<ZippedFileInfo> zfile_info = new ZippedFileInfo;
    00141     zfile_info->setSourceZipFile( sourceZipFile()->clone().get() );
    00142
    00143     unsigned short last_mod_file_time;
    00144     unsigned short last_mod_file_date;
    00145
    00146     zfile_info->mVersionNeeded = zip->readUInt16();
    00147     zfile_info->mGeneralPurposeFlag = zip->readUInt16();
    00148     zfile_info->mCompressionMethod = zip->readUInt16();
    00149     last_mod_file_time = zip->readUInt16();
    00150     last_mod_file_date = zip->readUInt16();
    00151     zfile_info->mCRC32 = zip->readUInt32();
    00152     zfile_info->mCompressedSize = zip->readUInt32();
    00153     zfile_info->mUncompressedSize = zip->readUInt32();
    00154     zfile_info->mFileNameLength = zip->readUInt16();
    00155     zfile_info->mExtraFieldLength = zip->readUInt16();
    00156
    00157     String name;
    00158
    00159     // file name
    00160     std::string file_name;
    00161     file_name.resize(zfile_info->mFileNameLength);
    00162     zip->read(&file_name[0], file_name.size());
    00163     file_name.push_back(0);
    00164     name = String::fromUTF8( file_name.c_str() );
    00165     name.normalizeSlashes();
    00166
    00167     // don't add directories
    00168     if (name.endsWith('/'))
    00169       continue;
    00170
    00171     ref<ZippedFile> zipped_file = new ZippedFile;
    00172     zipped_file->setZippedFileInfo( zfile_info.get() );
    00173
    00174     zfile_info->mFileName = name;
    00175     zipped_file->setPath( path() + name );
    00176     mFiles[zipped_file->path()] = zipped_file;
    00177
    00178     // extra field
    00179     if ( zfile_info->mExtraFieldLength )
    00180     {
    00181       std::vector<char> extra_field;
    00182       extra_field.resize(zfile_info->mExtraFieldLength);
    00183       zip->read(&extra_field[0], extra_field.size());
    00184     }
    00185
    00186     // MS DOS Time              MS DOS Date
    00187     // 0 - 4   5 - 10  11 - 15  16 - 20       21 - 24         25 - 31
    00188     // second  minute  hour     day (1 - 31)  month (1 - 12)  years from 1980
    00189
    00190     zfile_info->mSecond = int(( last_mod_file_time & 31 ) / 31.0f * 59.5f);
    00191     zfile_info->mMinute = (last_mod_file_time>>5)  & 63;
    00192     zfile_info->mHour   = (last_mod_file_time>>11) & 31;
    00193     zfile_info->mDay    = last_mod_file_date       & 31;
    00194     zfile_info->mMonth  = (last_mod_file_date>>5)  & 15;
    00195     zfile_info->mYear   = ((last_mod_file_date>>9) & 127 ) + 1980;
    00196
    00197     #if 0
    00198       #if !defined(NDEBUG)
    00199         printf("-------------------------\n");
    00200         printf("%s\n", name.toStdString().c_str());
    00201         printf("mVersionNeeded       = %d\n", zfile_info->mVersionNeeded);
    00202         printf("mGeneralPurposeFlag  = %d\n", zfile_info->mGeneralPurposeFlag);
    00203         printf("mCompressionMethod   = %d\n", zfile_info->mCompressionMethod);
    00204         printf("Time and date        = %d/%d/%d %d:%d:%d\n", zfile_info->mYear, zfile_info->mMonth, zfile_info->mDay, zfile_info->mHour, zfile_info->mMinute, zfile_info->mSecond);
    00205         printf("mUncompressedSize    = %d\n", zfile_info->mUncompressedSize);
    00206         printf("mCompressedSize      = %d -> %.1f\n", zfile_info->mCompressedSize, 100.0f * zfile_info->mCompressedSize / zfile_info->mUncompressedSize);
    00207         printf("mCRC32               = %08X\n", zfile_info->mCRC32);
    00208       #endif
    00209     #endif
    00210
    00211     long long cur_pos = zip->position();
    00212
    00213     // 2*4 + 4*4 is the length of a v2.0 zip header
    00214     if (cur_pos < 2*4 + 4*4)
    00215     {
    00216       Log::error("ZippedDirectory::init(): mounted a non seek-able zip file.\n");
    00217       zip->close();
    00218       mFiles.clear();
    00219       return false;
    00220     }
    00221
    00222     zfile_info->mZippedFileOffset = (unsigned int)cur_pos;
    00223
    00224     // skip compressed data
    00225     zip->seekCur( zfile_info->mCompressedSize );
    00226
    00227     if ( zfile_info->mGeneralPurposeFlag & (1<<3) )
    00228     {
    00229       zfile_info->mCRC32 = zip->readUInt32();
    00230       // sometimes the first 4 bytes are the header according to the specs... !!!
    00231       if (zfile_info->mCRC32 == 0x08074b50)
    00232         zfile_info->mCRC32 = zip->readUInt32();
    00233       zfile_info->mCompressedSize = zip->readUInt32();
    00234       zfile_info->mUncompressedSize = zip->readUInt32();
    00235     }
    00236   }
    00237
    00238   if (zip->position() == 4)
    00239   {
    00240     Log::error( Say("ZippedDirectory::init(): '%s' does not look like a zip file.\n") << sourceZipFile()->path() );
    00241     return false;
    00242   }
    00243
    00244   zip->close();
    00245   return true;
    00246 }
    00247 //-----------------------------------------------------------------------------
    00248 ref<VirtualFile> ZippedDirectory::file(const String& name) const
    00249 {
    00250   return zippedFile(name);
    00251 }
    00252 //-----------------------------------------------------------------------------
    00253 int ZippedDirectory::zippedFileCount() const
    00254 {
    00255   return (int)mFiles.size();
    00256 }
    00257 //-----------------------------------------------------------------------------
    00258 const ZippedFile* ZippedDirectory::zippedFile(int index) const
    00259 {
    00260   std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin();
    00261   for(int i=0; i<index && it != mFiles.end(); ++i)
    00262     ++it;
    00263   if ( it == mFiles.end() )
    00264     return NULL;
    00265   else
    00266     return it->second.get();
    00267 }
    00268 //-----------------------------------------------------------------------------
    00269 ZippedFile* ZippedDirectory::zippedFile(int index)
    00270 {
    00271   std::map< String, ref<ZippedFile> >::iterator it = mFiles.begin();
    00272   for(int i=0; i<index && it != mFiles.end(); ++i)
    00273     ++it;
    00274   if ( it == mFiles.end() )
    00275     return NULL;
    00276   else
    00277     return it->second.get();
    00278 }
    00279 //-----------------------------------------------------------------------------
    00280 ref<ZippedFile> ZippedDirectory::zippedFile(const String& name) const
    00281 {
    00282   String p = translatePath(name);
    00283   std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.find(p);
    00284   if (it == mFiles.end())
    00285     return NULL;
    00286   else
    00287   {
    00288     ref<ZippedFile> zip_file = new ZippedFile;
    00289     zip_file->operator=(*it->second);
    00290     return zip_file.get();
    00291   }
    00292 }
    00293 //-----------------------------------------------------------------------------
    00294 void ZippedDirectory::listFilesRecursive( std::vector<String>& file_list ) const
    00295 {
    00296   file_list.clear();
    00297   if (path().empty())
    00298   {
    00299     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00300     return;
    00301   }
    00302   for( std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin(); it != mFiles.end();  ++it)
    00303   {
    00304     if (!it->first.startsWith(path()))
    00305       vl::Log::warning( Say("ZippedFile '%s' does not belong to ZippedDirectory '%s'.\n") << it->first << path() );
    00306     file_list.push_back( it->first );
    00307   }
    00308 }
    00309 //-----------------------------------------------------------------------------
    00310 void ZippedDirectory::listSubDirs(std::vector<String>& dirs, bool append) const
    00311 {
    00312   if (!append)
    00313     dirs.clear();
    00314   if (path().empty())
    00315   {
    00316     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00317     return;
    00318   }
    00319   std::set<String> sub_dirs;
    00320   for( std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin(); it != mFiles.end(); ++it )
    00321   {
    00322     VL_CHECK(it->first.startsWith(path()))
    00323     String p = it->first.extractPath();
    00324     if (path().length())
    00325       p = p.right(-path().length());
    00326     while(p.startsWith('/'))
    00327       p = p.right(-1);
    00328     String drive_letter;
    00329     if (p.length()>3 && p[1] == ':' && p[2] == '/')
    00330     {
    00331       drive_letter = p.left(3);
    00332       p = p.right(-3);
    00333     }
    00334     if (p.empty()) // is a file
    00335       continue;
    00336     std::vector<String> tokens;
    00337     p.split('/',tokens,true);
    00338     if (tokens.size())
    00339       sub_dirs.insert(path() + tokens[0]);
    00340   }
    00341   for(std::set<String>::const_iterator it = sub_dirs.begin(); it != sub_dirs.end(); ++it)
    00342     dirs.push_back(*it);
    00343 }
    00344 //-----------------------------------------------------------------------------
    00345 ref<ZippedDirectory> ZippedDirectory::zippedSubDir(const String& subdir_name) const
    00346 {
    00347   if (path().empty())
    00348   {
    00349     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00350     return NULL;
    00351   }
    00352   String p = translatePath(subdir_name);
    00353   ref<ZippedDirectory> dir = new ZippedDirectory(p);
    00354   for( std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin(); it != mFiles.end(); ++it )
    00355   {
    00356     if (it->first.startsWith(p+'/'))
    00357     {
    00358       ref<ZippedFile> mfile = static_cast<ZippedFile*>(it->second->clone().get());
    00359       VL_CHECK(mfile)
    00360       dir->mFiles[mfile->path()] = mfile;
    00361     }
    00362   }
    00363
    00364   if (dir->mFiles.empty())
    00365     return NULL;
    00366   else
    00367     return dir;
    00368 }
    00369 //-----------------------------------------------------------------------------
    00370 void ZippedDirectory::listFiles(std::vector<String>& file_list, bool append) const
    00371 {
    00372   if (!append)
    00373     file_list.clear();
    00374   if (path().empty())
    00375   {
    00376     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00377     return;
    00378   }
    00379   for( std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin(); it != mFiles.end(); ++it )
    00380   {
    00381     if (it->first.extractPath().left(-1) == path())
    00382       file_list.push_back( it->first );
    00383   }
    00384 }
    00385 //-----------------------------------------------------------------------------
    00386 bool ZippedDirectory::isCorrupted()
    00387 {
    00388   if ( !init() )
    00389     return true;
    00390   for (int i=0; i<zippedFileCount(); ++i)
    00391     if ( zippedFile(i)->crc32() != zippedFile(i)->zippedFileInfo()->crc32() )
    00392       return true;
    00393   return false;
    00394 }
    00395 //-----------------------------------------------------------------------------

Visualization Library v2011.09.1162 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu Jan 26 2012 00:43:34.
Permission is granted to use this page to write and publish articles regarding Visualization Library.