InputFile.cpp

00001 /*
00002  *  Copyright (C) 2010  Regents of the University of Michigan
00003  *
00004  *   This program is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #include "InputFile.h"
00019 #include "StringBasics.h"
00020 #include "GzipHeader.h"
00021 #include "BgzfFileType.h"
00022 #include "GzipFileType.h"
00023 #include "UncompressedFileType.h"
00024 
00025 #include <stdarg.h>
00026 
00027 InputFile::InputFile(const char * filename, const char * mode,
00028                      InputFile::ifileCompression compressionMode)
00029 {
00030     myFileTypePtr = NULL;
00031     myBufferIndex = 0;
00032     myCurrentBufferSize = 0;
00033     myAllocatedBufferSize = DEFAULT_BUFFER_SIZE;
00034     myFileBuffer = new char[myAllocatedBufferSize];
00035     myFileName.clear();
00036 
00037     openFile(filename, mode, compressionMode);
00038 }
00039 
00040 
00041 #ifdef __ZLIB_AVAILABLE__
00042 
00043 // Open a file. Called by the constructor.
00044 // Returns true if the file was successfully opened, false otherwise.
00045 bool InputFile::openFile(const char * filename, const char * mode,
00046                          InputFile::ifileCompression compressionMode)
00047 {
00048     // If a file is for write, just open a new file.
00049     if (mode[0] == 'w' || mode[0] == 'W')
00050     {
00051         openFileUsingMode(filename, mode, compressionMode);
00052     }
00053     else
00054     {
00055         // Check if reading from stdin.
00056         if(strcmp(filename, "-") == 0)
00057         {
00058             // Reading from stdin, open it based on the 
00059             // compression mode.
00060             openFileUsingMode(filename, mode, compressionMode);
00061         }
00062         else
00063         {
00064             // Not from stdin, so determine the file type.
00065 
00066             // Open the file read only to determine file type.
00067             FILE* filePtr = fopen(filename, "r");
00068             
00069             // If the file could not be opened, either create a new one or
00070             // return failure.
00071             if (filePtr == NULL)
00072             {
00073                 // If the mode is for read, then the file must exist, otherwise,
00074                 // create a new file.
00075                 if (mode[0] == 'r' || mode[0] == 'R')
00076                 {
00077                     // File must exist.
00078                     if (myFileTypePtr != NULL)
00079                     {
00080                         delete myFileTypePtr;
00081                         myFileTypePtr = NULL;
00082                     }
00083                     // Return false, was not opened.
00084                     return false;
00085                 }
00086                 else
00087                 {
00088                     openFileUsingMode(filename, mode, compressionMode);
00089                 }
00090             }
00091             else
00092             {
00093                 // File was successfully opened, so try to determine the
00094                 // filetype from the file.
00095                 // Read the file to see if it a gzip file.
00096                 GzipHeader gzipHeader;
00097                 bool isGzip = gzipHeader.readHeader(filePtr);
00098                 
00099                 // The file header has been read, so close the file, so it can
00100                 // be re-opened as the correct type.
00101                 fclose(filePtr);
00102 
00103                 if (isGzip)
00104                 {
00105                     // This file is a gzip file.
00106                     // Check to see if it is BGZF Compression.
00107                     if (gzipHeader.isBgzfFile())
00108                     {
00109                         // This file has BGZF Compression, so set the file
00110                         // pointer.
00111                         myFileTypePtr = new BgzfFileType(filename, mode);
00112                     }
00113                     else
00114                     {
00115                         // Not BGZF, just a normal gzip.
00116                         myFileTypePtr = new GzipFileType(filename, mode);
00117                    }
00118                 }
00119                 else
00120                 {
00121                     // The file is a uncompressed, uncompressed file,
00122                     // so set the myFileTypePtr accordingly.
00123                     myFileTypePtr = new UncompressedFileType(filename, mode);
00124                 }
00125             }
00126         }
00127     }
00128     if(myFileTypePtr == NULL)
00129     {
00130         return(false);
00131     }
00132     if (!myFileTypePtr->isOpen())
00133     {
00134         // The file was not opened, so delete the pointer and set to null.
00135         delete myFileTypePtr;
00136         myFileTypePtr = NULL;
00137         return false;
00138     }
00139 
00140     if(myAllocatedBufferSize == 1)
00141     {
00142         myFileTypePtr->setBuffered(false);
00143     }
00144     else
00145     {
00146         myFileTypePtr->setBuffered(true);
00147     }
00148     myFileName = filename;
00149     return true;
00150 }
00151 
00152 
00153 // Open a file.  This method will open a file with the specified name and
00154 // mode with the fileTypePtr associated with the specified compressionMode.
00155 void InputFile::openFileUsingMode(const char * filename, const char * mode,
00156                                   ifileCompression compressionMode)
00157 {
00158     switch (compressionMode)
00159     {
00160         case GZIP:
00161             // Gzipped.
00162             myFileTypePtr = new GzipFileType(filename, mode);
00163             break;
00164         case BGZF:
00165             // BGZF compression.
00166             myFileTypePtr = new BgzfFileType(filename, mode);
00167             break;
00168         case UNCOMPRESSED:
00169             myFileTypePtr = new UncompressedFileType(filename, mode);
00170             break;
00171         case InputFile::DEFAULT:
00172         default:
00173             // Check the extension. If it is ".gz", treat as gzip.
00174             // otherwise treat it as UNCOMPRESSED.
00175             int lastchar = 0;
00176             while (filename[lastchar] != 0) lastchar++;
00177             if ((lastchar >= 3 &&
00178                     filename[lastchar - 3] == '.' &&
00179                     filename[lastchar - 2] == 'g' &&
00180                     filename[lastchar - 1] == 'z'))
00181             {
00182                 // .gz files files should be gzipped.
00183                 myFileTypePtr = new GzipFileType(filename, mode);
00184             }
00185             else
00186             {
00187                 // Create an uncompressed file.
00188                 myFileTypePtr = new UncompressedFileType(filename, mode);
00189             }
00190             break;
00191     }
00192 
00193     if(myFileTypePtr == NULL)
00194     {
00195         return;
00196     }
00197     if(myAllocatedBufferSize == 1)
00198     {
00199         myFileTypePtr->setBuffered(false);
00200     }
00201     else
00202     {
00203         myFileTypePtr->setBuffered(true);
00204     }
00205 }
00206 
00207 #else
00208 
00209 // No zlib, so just treat all files as std files.
00210 // Open a file. Called by the constructor.
00211 // Returns true if the file was successfully opened, false otherwise.
00212 bool InputFile::openFile(const char * filename, const char * mode)
00213 {
00214     //  No zlib, so it is a uncompressed, uncompressed file.
00215     myFileTypePtr = new UncompressedFileType(filename, mode);
00216 
00217     if(myFileTypePtr == NULL)
00218     {
00219         return(false);
00220     }
00221     if (!myFileTypePtr->isOpen())
00222     {
00223         // The file was not opened, so delete the pointer and set to null.
00224         delete myFileTypePtr;
00225         myFileTypePtr = NULL;
00226         return false;
00227     }
00228     if(myAllocatedBufferSize == 1)
00229     {
00230         myFileTypePtr->setBuffered(false);
00231     }
00232     else
00233     {
00234         myFileTypePtr->setBuffered(true);
00235     }
00236     myFileName = filename;
00237     return true;
00238 }
00239 
00240 #endif
00241 
00242 
00243 InputFile::~InputFile()
00244 {
00245     delete myFileTypePtr;
00246     myFileTypePtr = NULL;
00247 
00248     if(myFileBuffer != NULL)
00249     {
00250         delete[] myFileBuffer;
00251         myFileBuffer = NULL;
00252     }
00253 }
00254 
00255 
00256 int ifprintf(IFILE output, char * format, ...)
00257 {
00258     String buffer;
00259 
00260     va_list  ap;
00261     va_start(ap, format);
00262 
00263     buffer.vprintf(format, ap);
00264 
00265     va_end(ap);
00266 
00267     return ::ifwrite(output, (const char *) buffer, buffer.Length());
00268 }
00269 
00270 
Generated on Tue Mar 22 22:50:18 2011 for StatGen Software by  doxygen 1.6.3