# Visualization Library

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

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

- Main Page
- 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.com                                               */
    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("ZippedFile() 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   while(root.endsWith('/'))
    00062     root = root.left(-1);
    00063   root.trim();
    00064   if (root.empty())
    00065   {
    00066     vl::Log::error("Directory path must be a non null string and must not be '/'.\n");
    00067     return false;
    00068   }
    00069   std::map< String, ref<ZippedFile> > file_map;
    00070   for( std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin(); it != mFiles.end(); ++it )
    00071   {
    00072     String p = it->first;
    00073     if (path().length())
    00074       p = p.right(-path().length());
    00075     while(p.startsWith('/'))
    00076       p = p.right(-1);
    00077     it->second->setPath(root + '/' + p);
    00078     file_map[it->second->path()] = it->second;
    00079   }
    00080   mFiles = file_map;
    00081   mPath = root;
    00082   return true;
    00083 }
    00084 //-----------------------------------------------------------------------------
    00085 VirtualFile* ZippedDirectory::sourceZipFile() const
    00086 {
    00087   return mSourceZipFile.get();
    00088 }
    00089 //-----------------------------------------------------------------------------
    00090 void ZippedDirectory::setSourceZipFile(VirtualFile* file)
    00091 {
    00092   reset();
    00093   mSourceZipFile = file;
    00094   if(file)
    00095     init();
    00096 }
    00097 //-----------------------------------------------------------------------------
    00098 void ZippedDirectory::reset()
    00099 {
    00100   mSourceZipFile = NULL;
    00101   mFiles.clear();
    00102 }
    00103 //-----------------------------------------------------------------------------
    00104 bool ZippedDirectory::init()
    00105 {
    00106   mFiles.clear();
    00107   if (path().empty())
    00108   {
    00109     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00110     return false;
    00111   }
    00112   ref<VirtualFile> zip = sourceZipFile();
    00113   if (!zip)
    00114   {
    00115     Log::error("ZippedFile::init() called but not zip file mounted.\n");
    00116     return false;
    00117   }
    00118   zip->close();
    00119   if ( !zip->open(OM_ReadOnly) )
    00120   {
    00121     Log::error("ZippedDirectory::init(): cannot open source zip file.\n");
    00122     return false;
    00123   }
    00124
    00125   for( unsigned int local_file_header_signature = 0;
    00126        zip->read(&local_file_header_signature, 4) && local_file_header_signature == 0x04034b50;
    00127        local_file_header_signature = 0 )
    00128   {
    00129     // creates and fills a new ZippedFileInfo and a new ZippedFile
    00130     ref<ZippedFileInfo> zfile_info = new ZippedFileInfo;
    00131     zfile_info->setSourceZipFile( sourceZipFile()->clone().get() );
    00132
    00133     unsigned short last_mod_file_time;
    00134     unsigned short last_mod_file_date;
    00135
    00136     zfile_info->mVersionNeeded = zip->readUInt16();
    00137     zfile_info->mGeneralPurposeFlag = zip->readUInt16();
    00138     zfile_info->mCompressionMethod = zip->readUInt16();
    00139     last_mod_file_time = zip->readUInt16();
    00140     last_mod_file_date = zip->readUInt16();
    00141     zfile_info->mCRC32 = zip->readUInt32();
    00142     zfile_info->mCompressedSize = zip->readUInt32();
    00143     zfile_info->mUncompressedSize = zip->readUInt32();
    00144     zfile_info->mFileNameLength = zip->readUInt16();
    00145     zfile_info->mExtraFieldLength = zip->readUInt16();
    00146
    00147     String name;
    00148
    00149     // file name
    00150     std::string file_name;
    00151     file_name.resize(zfile_info->mFileNameLength);
    00152     zip->read(&file_name[0], file_name.size());
    00153     file_name.push_back(0);
    00154     name = String::fromUTF8( file_name.c_str() );
    00155     name.normalizeSlashes();
    00156
    00157     // don't add directories
    00158     if (name.endsWith('/'))
    00159       continue;
    00160
    00161     ref<ZippedFile> zipped_file = new ZippedFile;
    00162     zipped_file->setZippedFileInfo( zfile_info.get() );
    00163
    00164     zfile_info->mFileName = name;
    00165     zipped_file->setPath( path() + '/' + name );
    00166     mFiles[zipped_file->path()] = zipped_file;
    00167
    00168     // extra field
    00169     if ( zfile_info->mExtraFieldLength )
    00170     {
    00171       std::vector<char> extra_field;
    00172       extra_field.resize(zfile_info->mExtraFieldLength);
    00173       zip->read(&extra_field[0], extra_field.size());
    00174     }
    00175
    00176     // MS DOS Time              MS DOS Date
    00177     // 0 - 4   5 - 10  11 - 15  16 - 20       21 - 24         25 - 31
    00178     // second  minute  hour     day (1 - 31)  month (1 - 12)  years from 1980
    00179
    00180     zfile_info->mSecond = int(( last_mod_file_time & 31 ) / 31.0f * 59.5f);
    00181     zfile_info->mMinute = (last_mod_file_time>>5)  & 63;
    00182     zfile_info->mHour   = (last_mod_file_time>>11) & 31;
    00183     zfile_info->mDay    = last_mod_file_date       & 31;
    00184     zfile_info->mMonth  = (last_mod_file_date>>5)  & 15;
    00185     zfile_info->mYear   = ((last_mod_file_date>>9) & 127 ) + 1980;
    00186
    00187     #if 0
    00188       #if !defined(NDEBUG)
    00189         printf("-------------------------\n");
    00190         printf("%s\n", name.toStdString().c_str());
    00191         printf("mVersionNeeded       = %d\n", zfile_info->mVersionNeeded);
    00192         printf("mGeneralPurposeFlag  = %d\n", zfile_info->mGeneralPurposeFlag);
    00193         printf("mCompressionMethod   = %d\n", zfile_info->mCompressionMethod);
    00194         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);
    00195         printf("mUncompressedSize    = %d\n", zfile_info->mUncompressedSize);
    00196         printf("mCompressedSize      = %d -> %.1f\n", zfile_info->mCompressedSize, 100.0f * zfile_info->mCompressedSize / zfile_info->mUncompressedSize);
    00197         printf("mCRC32               = %08X\n", zfile_info->mCRC32);
    00198       #endif
    00199     #endif
    00200
    00201     long long cur_pos = zip->position();
    00202
    00203     // 2*4 + 4*4 is the length of a v2.0 zip header
    00204     if (cur_pos < 2*4 + 4*4)
    00205     {
    00206       Log::error("ZippedDirectory::init(): mounted a non seek-able zip file.\n");
    00207       zip->close();
    00208       mFiles.clear();
    00209       return false;
    00210     }
    00211
    00212     zfile_info->mZippedFileOffset = (unsigned int)cur_pos;
    00213
    00214     // skip compressed data
    00215     zip->seekCur( zfile_info->mCompressedSize );
    00216
    00217     if ( zfile_info->mGeneralPurposeFlag & (1<<3) )
    00218     {
    00219       zfile_info->mCRC32 = zip->readUInt32();
    00220       // sometimes the first 4 bytes are the header according to the specs... !!!
    00221       if (zfile_info->mCRC32 == 0x08074b50)
    00222         zfile_info->mCRC32 = zip->readUInt32();
    00223       zfile_info->mCompressedSize = zip->readUInt32();
    00224       zfile_info->mUncompressedSize = zip->readUInt32();
    00225     }
    00226   }
    00227
    00228   if (zip->position() == 4)
    00229   {
    00230     Log::error( Say("ZippedDirectory::init(): '%s' does not look like a zip file.\n") << sourceZipFile()->path() );
    00231     return false;
    00232   }
    00233
    00234   zip->close();
    00235   return true;
    00236 }
    00237 //-----------------------------------------------------------------------------
    00238 ref<VirtualFile> ZippedDirectory::file(const String& name) const
    00239 {
    00240   return zippedFile(name);
    00241 }
    00242 //-----------------------------------------------------------------------------
    00243 int ZippedDirectory::zippedFileCount() const
    00244 {
    00245   return (int)mFiles.size();
    00246 }
    00247 //-----------------------------------------------------------------------------
    00248 ZippedFile* ZippedDirectory::zippedFile(int index) const
    00249 {
    00250   std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin();
    00251   for(int i=0; i<index; ++i)
    00252     ++it;
    00253   return it->second.get();
    00254 }
    00255 //-----------------------------------------------------------------------------
    00256 ref<ZippedFile> ZippedDirectory::zippedFile(const String& name) const
    00257 {
    00258   String p = translatePath(name);
    00259   std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.find(p);
    00260   if (it == mFiles.end())
    00261     return NULL;
    00262   else
    00263   {
    00264     ref<ZippedFile> zip_file = new ZippedFile;
    00265     zip_file->operator=(*it->second);
    00266     return zip_file.get();
    00267   }
    00268 }
    00269 //-----------------------------------------------------------------------------
    00270 void ZippedDirectory::listFilesRecursive( std::vector<String>& file_list ) const
    00271 {
    00272   file_list.clear();
    00273   if (path().empty())
    00274   {
    00275     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00276     return;
    00277   }
    00278   for( std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin(); it != mFiles.end();  ++it)
    00279   {
    00280     if (!it->first.startsWith(path()+'/'))
    00281       vl::Log::warning( Say("ZippedFile '%s' does not belong to ZippedDirectory '%s'.\n") << it->first << path() );
    00282     file_list.push_back( it->first );
    00283   }
    00284 }
    00285 //-----------------------------------------------------------------------------
    00286 void ZippedDirectory::listSubDirs(std::vector<String>& dirs, bool append) const
    00287 {
    00288   if (!append)
    00289     dirs.clear();
    00290   if (path().empty())
    00291   {
    00292     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00293     return;
    00294   }
    00295   std::set<String> sub_dirs;
    00296   for( std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin(); it != mFiles.end(); ++it )
    00297   {
    00298     VL_CHECK(it->first.startsWith(path()+'/'))
    00299     String p = it->first.extractPath();
    00300     if (path().length())
    00301       p = p.right(-path().length());
    00302     while(p.startsWith('/'))
    00303       p = p.right(-1);
    00304     String drive_letter;
    00305     if (p.length()>3 && p[1] == ':' && p[2] == '/')
    00306     {
    00307       drive_letter = p.left(3);
    00308       p = p.right(-3);
    00309     }
    00310     if (p.empty()) // is a file
    00311       continue;
    00312     std::vector<String> tokens;
    00313     p.split('/',tokens,true);
    00314     if (tokens.size())
    00315       sub_dirs.insert(path() + '/' + tokens[0]);
    00316   }
    00317   for(std::set<String>::const_iterator it = sub_dirs.begin(); it != sub_dirs.end(); ++it)
    00318     dirs.push_back(*it);
    00319 }
    00320 //-----------------------------------------------------------------------------
    00321 ref<ZippedDirectory> ZippedDirectory::zippedSubDir(const String& subdir_name) const
    00322 {
    00323   if (path().empty())
    00324   {
    00325     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00326     return NULL;
    00327   }
    00328   String p = translatePath(subdir_name);
    00329   ref<ZippedDirectory> dir = new ZippedDirectory(p);
    00330   for( std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin(); it != mFiles.end(); ++it )
    00331   {
    00332     if (it->first.startsWith(p+'/'))
    00333     {
    00334       ref<ZippedFile> mfile = dynamic_cast<ZippedFile*>(it->second->clone().get());
    00335       VL_CHECK(mfile)
    00336       dir->mFiles[mfile->path()] = mfile;
    00337     }
    00338   }
    00339
    00340   if (dir->mFiles.empty())
    00341     return NULL;
    00342   else
    00343     return dir;
    00344 }
    00345 //-----------------------------------------------------------------------------
    00346 void ZippedDirectory::listFiles(std::vector<String>& file_list, bool append) const
    00347 {
    00348   if (!append)
    00349     file_list.clear();
    00350   if (path().empty())
    00351   {
    00352     Log::error( "VirtualDirectory::path() must not be empty!\n" );
    00353     return;
    00354   }
    00355   for( std::map< String, ref<ZippedFile> >::const_iterator it = mFiles.begin(); it != mFiles.end(); ++it )
    00356   {
    00357     if (it->first.extractPath().left(-1) == path())
    00358       file_list.push_back( it->first );
    00359   }
    00360 }
    00361 //-----------------------------------------------------------------------------
    00362 bool ZippedDirectory::isCorrupted()
    00363 {
    00364   if ( !init() )
    00365     return true;
    00366   for (int i=0; i<zippedFileCount(); ++i)
    00367     if ( zippedFile(i)->crc32() != zippedFile(i)->zippedFileInfo()->crc32() )
    00368       return true;
    00369   return false;
    00370 }
    00371 //-----------------------------------------------------------------------------

Visualization Library v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:22.
Permission is granted to use this page to write and publish articles regarding Visualization Library.