00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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 }