cmtkCompressedStream.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2010 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2493 $
00026 //
00027 //  $LastChangedDate: 2010-10-22 11:21:23 -0700 (Fri, 22 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include <System/cmtkCompressedStream.h>
00034 
00035 #include <System/cmtkConsole.h>
00036 #include <System/cmtkMemory.h>
00037 
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <stdio.h>
00041 #include <limits.h>
00042 #include <errno.h>
00043 
00044 #ifdef HAVE_SYS_TYPES_H
00045 #  include <sys/types.h>
00046 #endif
00047 
00048 #ifdef _MSC_VER
00049 #  include <process.h>
00050 #endif
00051 
00052 namespace
00053 cmtk
00054 {
00055 
00058 
00059 const CompressedStream::ArchiveLookupEntry 
00060 CompressedStream::ArchiveLookup[] = {
00061 #ifdef _MSC_VER
00062   {".Z",    "gunzip -cd %s > %s"},
00063   {".gz",   "gzip -cd %s > %s"},
00064   {".bz",   "bzip -Q -cd %s > %s"},
00065   {".bz2",  "bzip2 -cd %s > %s"},
00066   {".lzma", "lzma -cd %s > %s"},
00067   {".xz",   "xz -cd %s > %s"},
00068 #else
00069   {".Z",    "gunzip -c %s"},
00070   {".gz",   "gzip -cd %s"},
00071   {".bz",   "bzip -Q -cd %s"},
00072   {".bz2",  "bzip2 -cd %s"},
00073   {".lzma", "lzma -cd %s"},
00074   {".xz",   "xz -cd %s"},
00075 #endif
00076   { NULL,   NULL} 
00077 };
00078 
00079 CompressedStream::CompressedStream ( const char *filename ) 
00080   : m_Reader( NULL ),
00081     m_Compressed( false )
00082 {
00083   this->Open( filename );
00084 }
00085 
00086 CompressedStream::~CompressedStream () 
00087 {
00088   this->Close();
00089 }
00090 
00091 bool
00092 CompressedStream::Open ( const char *filename ) 
00093 {
00094   this->Close();
00095 
00096   if ( Self::Stat( filename ) == 2 )
00097     {
00098     StdErr << "WARNING: file '" << filename << "' exists both compressed and uncompressed!\n";
00099     }
00100   
00101   const char *suffix = strrchr( filename, '.' );
00102   
00103   this->m_Compressed = false;
00104   
00105   if ( suffix )
00106     for ( int i=0; ArchiveLookup[i].suffix && !this->m_Compressed; ++i )
00107       this->m_Compressed = this->m_Compressed || ! strcmp( ArchiveLookup[i].suffix, suffix );
00108 
00109   try
00110     {
00111     if ( !this->m_Compressed )
00112       {
00113       this->m_Reader = ReaderBase::SmartPtr( new Self::File( filename ) );
00114       }
00115     }
00116   catch (...)
00117     {
00118     }
00119 
00120   try 
00121     {
00122     if ( ! this->m_Reader )
00123       {
00124       bool result = false;
00125       for ( int i=0; ArchiveLookup[i].suffix && !result; ++i )
00126         result = this->OpenDecompressionPipe( filename, suffix, ArchiveLookup[i].command, ArchiveLookup[i].suffix );
00127       this->m_Compressed = true;
00128       }
00129     }
00130   catch ( ... )
00131     {
00132     this->m_Reader = ReaderBase::SmartPtr( NULL );
00133     }
00134   
00135   return this->IsValid();
00136 }
00137 
00138 void
00139 CompressedStream::Close()
00140 {
00141   if ( this->m_Reader )
00142     {
00143     this->m_Reader->Close();
00144     this->m_Reader = ReaderBase::SmartPtr( NULL );
00145     }
00146 }
00147 
00148 bool
00149 CompressedStream::OpenDecompressionPipe
00150 ( const char* filename, const char* suffix, const char* command, const char* compressedSuffix )
00151 {
00152   char fname[PATH_MAX];
00153 
00154   strcpy( fname, filename );
00155   if ( !suffix || strcmp( compressedSuffix, suffix ) )
00156     strcat( fname, compressedSuffix );
00157 
00158 #ifdef _MSC_VER 
00159   for ( char *p=fname; *p; ++p )
00160     if ( *p == '/' ) *p = '\\';
00161 #endif
00162 
00163   struct stat buf;
00164   if ( (! stat( fname, &buf )) && ( (buf.st_mode & S_IFREG) == S_IFREG ) ) 
00165     {
00166     if ( !strcmp( compressedSuffix, ".gz" ) ) 
00167       {
00168       this->m_Reader = ReaderBase::SmartPtr( new Self::Zlib( fname ) );
00169       }
00170 #ifdef CMTK_USE_BZIP2
00171     else if ( !strcmp( compressedSuffix, ".bz2" ) ) 
00172       {
00173       this->m_Reader = ReaderBase::SmartPtr( new Self::BZip2( fname ) );
00174       }
00175 #endif
00176 #ifdef CMTK_USE_LZMA
00177     else if ( !strcmp( compressedSuffix, ".lzma" ) ) 
00178       {
00179       this->m_Reader = ReaderBase::SmartPtr( new Self::LZMA( fname ) );
00180       }
00181 #endif
00182     else
00183       {
00184       this->m_Reader = ReaderBase::SmartPtr( new Self::Pipe( fname, command ) );
00185       }
00186     }
00187   return this->IsValid();
00188 }
00189 
00190 std::string
00191 CompressedStream::GetBaseName( const std::string& path )
00192 {
00193   const size_t suffixPos = path.rfind( '.' );
00194   
00195   if ( suffixPos != std::string::npos ) 
00196     {
00197     for ( int i = 0; ArchiveLookup[i].suffix; ++i )
00198       {
00199       const size_t suffixLen = strlen( ArchiveLookup[i].suffix );
00200       if ( !path.compare( suffixPos, suffixLen, ArchiveLookup[i].suffix, suffixLen ) )
00201         {
00202         return path.substr( 0, suffixPos );
00203         }
00204       }
00205     }
00206   return path;
00207 }
00208 
00209 int 
00210 CompressedStream::Stat( const char *path, struct stat* buf )
00211 {
00212   std::string baseName = CompressedStream::GetBaseName( path );
00213 
00214   struct stat statbuf;
00215   if ( ! buf )
00216     buf = &statbuf;
00217 
00218   const bool existsUncompressed = ! stat( baseName.c_str(), buf );
00219   
00220   for ( int i = 0; ArchiveLookup[i].suffix; ++i ) 
00221     {
00222     const std::string cpath = baseName + std::string( ArchiveLookup[i].suffix );
00223     if ( ! stat( cpath.c_str(), buf ) ) 
00224       return existsUncompressed ? 2 : 1;
00225     }
00226   
00227   return existsUncompressed ? 0 : -1;
00228 }
00229 
00230 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines