InputFile.h

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2010-2012  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 /*! \file */ 
00018 #ifndef __INPUTFILE_H__
00019 #define __INPUTFILE_H__
00020 
00021 #include <stdio.h>
00022 #include <iostream>
00023 #include <cstring>
00024 #include <stdint.h>
00025 
00026 #include "FileType.h"
00027 
00028 /// Class for easily reading/writing files without having to worry about
00029 /// file type (uncompressed, gzip, bgzf) when reading.
00030 /// It hides the low level file operations/structure from the user, allowing
00031 /// them to generically open and operate on a file using the same
00032 /// interface without knowing the file format (standard uncompressed,
00033 /// gzip, or bgzf).  For writing, the user must specify the file type.
00034 /// There is a typedef IFILE which is InputFile* and setup to mimic FILE
00035 /// including global methods that take IFILE as a parameter.
00036 class InputFile
00037 {
00038     bool    myAttemptRecovery;  // use recovery techniques if possible
00039 public:
00040 
00041     /// Compression to use when writing a file & decompression used when
00042     /// reading a file from stdin.  Any other read checks the file to determine
00043     ///  how to uncompress it.
00044     enum ifileCompression {
00045         DEFAULT,  ///< Check the extension, if it is ".gz", treat as gzip, otherwise treat it as UNCOMPRESSED.
00046         UNCOMPRESSED,  ///< uncompressed file.
00047         GZIP,  ///< gzip file.
00048         BGZF ///< bgzf file.
00049     };
00050 
00051     /// Default constructor
00052     InputFile()
00053     {
00054         myAttemptRecovery = false;
00055         myFileTypePtr = NULL;
00056         myBufferIndex = 0;
00057         myCurrentBufferSize = 0;
00058         // Default to buffer.
00059         myAllocatedBufferSize = DEFAULT_BUFFER_SIZE;
00060         myFileBuffer = new char[myAllocatedBufferSize];
00061         myFileName.clear();
00062     }
00063 
00064     /// Destructor
00065     ~InputFile();
00066 
00067     /// Constructor for opening a file.
00068     /// \param filename file to open
00069     /// \param mode same format as fopen: "r" for read & "w" for write.
00070     /// \param compressionMode set the type of file to open for writing or
00071     /// for reading from stdin (when reading files, the compression type is 
00072     /// determined by reading the file).
00073     InputFile(const char * filename, const char * mode,
00074               InputFile::ifileCompression compressionMode = InputFile::DEFAULT);
00075 
00076     /// Set the buffer size for reading from files so that bufferSize bytes
00077     /// are read at a time and stored until accessed by another read call.
00078     /// This improves performance over reading the file small bits at a time.
00079     /// Buffering reads disables the tell call for bgzf files.
00080     /// Any previous values in the buffer will be deleted.
00081     /// \param bufferSize number of bytes to read/buffer at a time,
00082     /// default buffer size is 1048576, and turn off read buffering by setting
00083     /// bufferSize = 1;
00084     inline void bufferReads(unsigned int bufferSize = DEFAULT_BUFFER_SIZE)
00085     {
00086         // If the buffer size is the same, do nothing.
00087         if(bufferSize == myAllocatedBufferSize)
00088         {
00089             return;
00090         }
00091         // Delete the previous buffer.
00092         if(myFileBuffer != NULL)
00093         {
00094             delete[] myFileBuffer;
00095         }
00096         myBufferIndex = 0;
00097         myCurrentBufferSize = 0;
00098         // The buffer size must be at least 1 so one character can be
00099         // read and ifgetc can just assume reading into the buffer.
00100         if(bufferSize < 1)
00101         {
00102             bufferSize = 1;
00103         }
00104         myFileBuffer = new char[bufferSize];
00105         myAllocatedBufferSize = bufferSize;
00106 
00107         if(myFileTypePtr != NULL)
00108         {
00109             if(bufferSize == 1)
00110             {
00111                 myFileTypePtr->setBuffered(false);
00112             }
00113             else
00114             {
00115                 myFileTypePtr->setBuffered(true);
00116             }
00117         }
00118     }
00119 
00120 
00121     /// Disable read buffering.
00122     inline void disableBuffering()
00123     {
00124         bufferReads(1);
00125         if(myFileTypePtr != NULL)
00126         {
00127             myFileTypePtr->setBuffered(false);
00128         }
00129     }
00130 
00131     
00132     /// Close the file.
00133     /// \return status of the close (0 is success).
00134     inline int ifclose()
00135     {
00136         if (myFileTypePtr == NULL)
00137         {
00138             return EOF;
00139         }
00140         int result = myFileTypePtr->close();
00141         delete myFileTypePtr;
00142         myFileTypePtr = NULL;
00143         myFileName.clear();
00144         return result;
00145     }
00146 
00147     /// Read size bytes from the file into the buffer.
00148     /// \param buffer pointer to memory at least size bytes big to write the
00149     /// data into.
00150     /// \param size number of bytes to be read
00151     /// \return number of bytes read, if it is not equal to size,
00152     /// there was either an error or the end of the file was reached, use
00153     /// ifeof to determine which case it was.
00154     inline int ifread(void * buffer, unsigned int size)
00155     {
00156         // There are 2 cases:
00157         //  1) There are already size available bytes in buffer.
00158         //  2) There are not size bytes in buffer.
00159 
00160         // Determine the number of available bytes in the buffer.
00161         unsigned int availableBytes = myCurrentBufferSize - myBufferIndex;
00162         int returnSize = 0;
00163 
00164         // Case 1: There are already size available bytes in buffer.
00165         if (size <= availableBytes)
00166         {
00167             //   Just copy from the buffer, increment the index and return.
00168             memcpy(buffer, myFileBuffer+myBufferIndex, size);
00169             // Increment the buffer index.
00170             myBufferIndex += size;
00171             returnSize = size;
00172         }
00173         // Case 2: There are not size bytes in buffer.
00174         else
00175         {
00176             // Check to see if there are some bytes in the buffer.
00177             if (availableBytes > 0)
00178             {
00179                 // Size > availableBytes > 0
00180                 // Copy the available bytes into the buffer.
00181                 memcpy(buffer, myFileBuffer+myBufferIndex, availableBytes);
00182             }
00183             // So far availableBytes have been copied into the read buffer.
00184             returnSize = availableBytes;
00185             // Increment myBufferIndex  by what was read.
00186             myBufferIndex += availableBytes;
00187 
00188             unsigned int remainingSize = size - availableBytes;
00189 
00190             // Check if the remaining size is more or less than the
00191             // max buffer size.
00192             if(remainingSize < myAllocatedBufferSize)
00193             {
00194                 // the remaining size is not the full buffer, but read
00195                 //  a full buffer worth of data anyway.
00196                 myCurrentBufferSize =
00197                     readFromFile(myFileBuffer, myAllocatedBufferSize);
00198 
00199                 // Check for an error.
00200                 if(myCurrentBufferSize <= 0)
00201                 {
00202                     // No more data was successfully read, so check to see
00203                     // if any data was copied to the return buffer at all.
00204                     if( returnSize == 0)
00205                     {
00206                         // No data has been copied at all into the
00207                         // return read buffer, so just return the value
00208                         // returned from readFromFile.
00209                         returnSize = myCurrentBufferSize;
00210                         // Otherwise, returnSize is already set to the
00211                         // available bytes that was already copied (so no
00212                         // else statement is needed).
00213                     }
00214                     // Set myBufferIndex & myCurrentBufferSize to 0.
00215                     myCurrentBufferSize = 0;
00216                     myBufferIndex = 0;
00217                 }
00218                 else
00219                 {
00220                     // Successfully read more data.
00221                     // Check to see how much was copied.
00222                     int copySize = remainingSize;
00223                     if(copySize > myCurrentBufferSize)
00224                     {
00225                         // Not the entire requested amount was read
00226                         // (either from EOF or there was a partial read due to
00227                         // an error), so set the copySize to what was read.
00228                         copySize = myCurrentBufferSize;
00229                     }
00230 
00231                     // Now copy the rest of the bytes into the buffer.
00232                     memcpy((char*)buffer+availableBytes, 
00233                            myFileBuffer, copySize);
00234 
00235                     // set the buffer index to the location after what we are
00236                     // returning as read.
00237                     myBufferIndex = copySize;
00238                 
00239                     returnSize += copySize;
00240                 }
00241             }
00242             else
00243             {
00244                 // More remaining to be read than the max buffer size, so just
00245                 // read directly into the output buffer.
00246                 int readSize = readFromFile((char*)buffer + availableBytes,
00247                                             remainingSize);
00248 
00249                 // Already used the buffer, so "clear" it.
00250                 myCurrentBufferSize = 0;
00251                 myBufferIndex = 0;
00252                 if(readSize <= 0)
00253                 {
00254                     // No more data was successfully read, so check to see
00255                     // if any data was copied to the return buffer at all.
00256                     if(returnSize == 0)
00257                     {
00258                         // No data has been copied at all into the
00259                         // return read buffer, so just return the value
00260                         // returned from readFromFile.
00261                         returnSize = readSize;
00262                         // Otherwise, returnSize is already set to the
00263                         // available bytes that was already copied (so no
00264                         // else statement is needed).
00265                     }
00266                 }
00267                 else
00268                 {
00269                     // More data was read, so increment the return count.
00270                     returnSize += readSize;
00271                 }
00272             }
00273         }
00274         return(returnSize);
00275     }
00276 
00277     /// Read until the specified characters, returning which character was
00278     /// found causing the stop, -1 returned for EOF, storing the other read
00279     /// characters into the specified string.
00280     /// Note: If stopChars is just '\n', readLine is faster and if
00281     /// stopChars is just '\n' and '\t', readTilTab is faster.
00282     /// \param stopChars characters to stop reading when they are hit.
00283     /// \param stringRef reference to a string that the read characters should
00284     /// be apppended to (does not include the stopchar).
00285     /// \return index of the character in stopChars that caused it to stop
00286     /// reading or -1 for EOF.
00287     int readTilChar(const std::string& stopChars, std::string& stringRef);
00288 
00289     /// Read until the specified characters, returning which character was
00290     /// found causing the stop, -1 returned for EOF, dropping all read chars.
00291     /// Note: If stopChars is just '\n', discardLine is faster.
00292     /// \param stopChars characters to stop reading when they are hit.
00293     /// \return index of the character in stopChars that caused it to stop
00294     /// reading or -1 for EOF.
00295     int readTilChar(const std::string& stopChars);
00296 
00297     /// Read until the end of the line, discarding the characters,
00298     /// returning -1 returned for EOF and returning 0 if the end of the line
00299     /// was found.
00300     /// \return 0 if the end of the line was found before EOF or -1 for EOF.
00301     int discardLine();
00302 
00303     /// Read, appending the characters into the specified string until new
00304     /// line or EOF is found, returning -1 if EOF is found first and 0 if new
00305     /// line is found first.  The new line and EOF are not written into the 
00306     /// specified string.
00307     /// \param line reference to a string that the read characters should
00308     /// be apppended to (does not include the new line or eof).
00309     /// \return 0 if new line and -1 for EOF.
00310     int readLine(std::string& line);
00311 
00312     /// Read, appending the characters into the specified string until tab, new
00313     /// line, or EOF is found, returning -1 if EOF is found first, 0 if new
00314     /// line is found first, or 1 if a tab is found first.  The tab, new line,
00315     /// and EOF are not written into the specified string.
00316     /// \param field reference to a string that the read characters should
00317     /// be apppended to (does not include the tab, new line, or eof).
00318     /// \return 1 if tab is found, 0 if new line, and -1 for EOF.
00319     int readTilTab(std::string& field);
00320 
00321     /// Get a character from the file.  Read a character from the internal
00322     /// buffer, or if the end of the buffer has been reached, read from the
00323     /// file into the buffer and return index 0.
00324     /// \return character that was read or EOF.
00325     inline int ifgetc()
00326     {
00327         if (myBufferIndex >= myCurrentBufferSize)
00328         {
00329             // at the last index, read a new buffer.
00330             myCurrentBufferSize = readFromFile(myFileBuffer, myAllocatedBufferSize);
00331             myBufferIndex = 0;
00332             // If the buffer index is still greater than or equal to the
00333             // myCurrentBufferSize, then we failed to read the file - return EOF.
00334             // NB: This only needs to be checked when myCurrentBufferSize
00335             // is changed.  Simplify check - readFromFile returns zero on EOF
00336             if (myCurrentBufferSize == 0)
00337             {
00338                 return(EOF);
00339             }
00340         }
00341         return(myFileBuffer[myBufferIndex++]);
00342     }
00343 
00344     /// Get a line from the file.
00345     /// \param buffer the buffer into which data is to be placed
00346     /// \param max the maximum size of the buffer, in bytes
00347     /// \return true if the last character read was an EOF
00348     inline bool ifgetline(void *voidBuffer, size_t max)
00349     {
00350         int ch;
00351         char *buffer = (char *) voidBuffer;
00352 
00353         while( (ch=ifgetc()) != '\n' && ch != EOF) {
00354             *buffer++ = ch;
00355             if((--max)<2)
00356             {
00357                 // truncate the line, so drop remainder
00358                 while( (ch=ifgetc()) && ch != '\n' && ch != EOF)
00359                 {
00360                 }
00361                 break;
00362             }
00363         }
00364         *buffer++ = '\0';
00365         return ch==EOF;
00366     }
00367 
00368     /// Reset to the beginning of the file.
00369     inline void ifrewind()
00370     {
00371         // Just set the myBufferIndex and the myCurrentBufferSize to 0 to simulate
00372         // clearing the buffer and call rewind to move to the beginning of the
00373         // file.
00374         if (myFileTypePtr == NULL)
00375         {
00376             // No pointer, so nothing to rewind.
00377             return;
00378         }
00379         myCurrentBufferSize = 0;
00380         myBufferIndex = 0;
00381         myFileTypePtr->rewind();
00382     }
00383 
00384 
00385     /// Check to see if we have reached the EOF.
00386     /// \return 0 if not EOF, any other value means EOF.
00387     inline int ifeof()
00388     {
00389         // Not EOF if we are not at the end of the buffer.
00390         if (myBufferIndex < myCurrentBufferSize)
00391         {
00392             // There are still available bytes in the buffer, so NOT EOF.
00393             return false;
00394         }
00395         else
00396         {
00397             if (myFileTypePtr == NULL)
00398             {
00399                 // No myFileTypePtr, so not eof (return 0).
00400                 return 0;
00401             }
00402             // exhausted our buffer, so check the file for eof.
00403             return myFileTypePtr->eof();
00404         }
00405     }
00406 
00407     /// Write the specified buffer into the file.
00408     /// \param buffer buffer containing size bytes to write to the file.
00409     /// \param size number of bytes to write
00410     /// \return number of bytes written
00411     /// We do not buffer the write call, so just leave this as normal.
00412     inline unsigned int ifwrite(const void * buffer, unsigned int size)
00413     {
00414         if (myFileTypePtr == NULL)
00415         {
00416             // No myFileTypePtr, so return 0 - nothing written.
00417             return 0;
00418         }
00419         return myFileTypePtr->write(buffer, size);
00420     }
00421 
00422     /// Returns whether or not the file was successfully opened.
00423     /// \return true if the file is open, false if not.
00424     inline bool isOpen()
00425     {
00426         // It is open if the myFileTypePtr is set and says it is open.
00427         if ((myFileTypePtr != NULL) && myFileTypePtr->isOpen())
00428         {
00429             return true;
00430         }
00431         // File was not successfully opened.
00432         return false;
00433     }
00434 
00435     /// Get current position in the file.
00436     /// \return current position in the file, -1 indicates an error.
00437     inline int64_t iftell()
00438     {
00439         if (myFileTypePtr == NULL)
00440         {
00441             // No myFileTypePtr, so return false - could not seek.
00442             return -1;
00443         }
00444         int64_t pos = myFileTypePtr->tell();
00445         pos -= (myCurrentBufferSize - myBufferIndex);
00446         return(pos);
00447     }
00448 
00449 
00450     /// Seek to the specified offset from the origin.
00451     /// \param offset offset into the file to move to (must be from a tell call)
00452     /// \param origin can be any of the following:
00453     /// Note: not all are valid for all filetypes.
00454     ///   SEEK_SET - Beginning of file
00455     ///   SEEK_CUR - Current position of the file pointer
00456     ///   SEEK_END - End of file
00457     /// \return true on successful seek and false on a failed seek.
00458     inline bool ifseek(int64_t offset, int origin)
00459     {
00460         if (myFileTypePtr == NULL)
00461         {
00462             // No myFileTypePtr, so return false - could not seek.
00463             return false;
00464         }
00465         // TODO - may be able to seek within the buffer if applicable.
00466         // Reset buffering since a seek is being done.
00467         myBufferIndex = 0;
00468         myCurrentBufferSize = 0;
00469         return myFileTypePtr->seek(offset, origin);
00470     }
00471 
00472     /// Get the filename that is currently opened.
00473     /// \return filename associated with this class
00474     const char* getFileName() const
00475     {
00476         return(myFileName.c_str());
00477     }
00478 
00479     /// Enable (default) or disable recovery.
00480     /// 
00481     /// When true, we can attach a myFileTypePtr
00482     /// that implements a recovery capable decompressor.
00483     /// This requires that the caller be able to catch
00484     /// the exception XXX "blah blah blah".
00485     ///
00486     void setAttemptRecovery(bool flag = false)
00487     {
00488         myAttemptRecovery = flag;
00489     }
00490 
00491     bool attemptRecoverySync(bool (*checkSignature)(void *data) , int length)
00492     {
00493         if(myFileTypePtr==NULL) return false; 
00494         return myFileTypePtr->attemptRecoverySync(checkSignature, length);
00495     }
00496 
00497     // Open a file. Called by the constructor.
00498     // Returns true if the file was successfully opened, false otherwise.
00499     bool openFile(const char * filename, const char * mode,
00500                   InputFile::ifileCompression compressionMode);
00501 
00502 protected:
00503     // Read into a buffer from the file.  Since the buffer is passed in and
00504     // this would bypass the myFileBuffer used by this class, this method must
00505     // be protected.
00506     inline int readFromFile(void * buffer, unsigned int size)
00507     {
00508         // If no myFileTypePtr, return 0 - nothing read.
00509         if (myFileTypePtr == NULL)
00510         {
00511             return 0;
00512         }
00513         return myFileTypePtr->read(buffer, size);
00514     }
00515 
00516 #ifdef __ZLIB_AVAILABLE__
00517     // Only necessary with zlib to determine what file type on a new
00518     // file.  Without zlib, there are only uncompressed files, so a special
00519     // method is not needed to determine the type of file to open.
00520     // Open a file.  This method will open a file with the specified name and
00521     // mode with the fileTypePtr associated with the specified compressionMode.
00522     void openFileUsingMode(const char* filename, const char* mode,
00523                            InputFile::ifileCompression compressionMode);
00524 #endif
00525 
00526     // The size of the buffer used by this class.
00527     static const unsigned int DEFAULT_BUFFER_SIZE = 1048576;
00528 
00529     // Pointer to a class that interfaces with different file types.
00530     FileType* myFileTypePtr;
00531 
00532     unsigned int myAllocatedBufferSize;
00533 
00534     // Buffer used to do large reads rather than 1 by 1 character reads
00535     // from the file.  The class is then managed to iterate through the buffer.
00536     char* myFileBuffer;
00537 
00538     // Current index into the buffer.  Used to track where we are in reading the
00539     // file from the buffer.
00540     int myBufferIndex;
00541 
00542     // Current number of entries in the buffer.  Used to ensure that
00543     // if a read did not fill the buffer, we stop before hitting the
00544     // end of what was read.
00545     int myCurrentBufferSize;
00546 
00547     std::string myFileName;
00548 };
00549 
00550 
00551 /// Define IFILE as a pointer to an InputFile object.
00552 typedef InputFile* IFILE;
00553 
00554 
00555 /// Open a file with the specified name and mode, using a filename of "-" to 
00556 /// indicate stdin/stdout.
00557 /// \param filename file to open ("-" meands stdin/stdout)
00558 /// \param mode same format as fopen: "r" for read & "w" for write.
00559 /// \param compressionMode set the type of file to open for writing or
00560 /// for reading from stdin (when reading files not from stdin, the compression
00561 /// type is determined by reading the file).
00562 /// \return IFILE - pointer to the InputFile object that has been opened.
00563 inline IFILE ifopen(const char * filename, const char * mode,
00564                     InputFile::ifileCompression compressionMode = InputFile::DEFAULT)
00565 {
00566     IFILE file = new InputFile(filename, mode, compressionMode);
00567     if (!file->isOpen())
00568     {
00569 
00570         // Not open, so delete the file, and return null.
00571         delete file;
00572         file = NULL;
00573     }
00574     return file;
00575 }
00576 
00577 
00578 /// Close the file.
00579 /// \param file file to be closed - IFILE is a pointer to an InputFile object
00580 /// \return status of the close (0 is success or if NULL is passed in).
00581 inline int ifclose(IFILE file)
00582 {
00583     if(file == NULL)
00584     {
00585         // NULL Pointer passed in, so return 0, since no file is open, so
00586         // does not need to be closed.
00587         return(0);
00588     }
00589     int result = file->ifclose();
00590     delete file;
00591     file = NULL;
00592     return(result);
00593 }
00594 
00595 /// Read up to size bytes from the file into the buffer.
00596 /// \param file file to be read - IFILE is a pointer to an InputFile object
00597 /// \param buffer pointer to memory at least size bytes big to write the
00598 /// data into.
00599 /// \param size number of bytes to be read
00600 /// \return number of bytes read
00601 inline unsigned int ifread(IFILE file, void * buffer, unsigned int size)
00602 {
00603     if(file == NULL)
00604     {
00605         // No file was passed in, so 0 bytes were read.
00606         return(0);
00607     }
00608     return(file->ifread(buffer, size));
00609 }
00610 
00611 /// Get a character from the file.  Read a character from the internal
00612 /// buffer, or if the end of the buffer has been reached, read from the
00613 /// file into the buffer and return index 0.
00614 /// \param file file to be read - IFILE is a pointer to an InputFile object
00615 /// \return character that was read or EOF.
00616 inline int ifgetc(IFILE file)
00617 {
00618     if(file == NULL)
00619     {
00620         // return eof since there is no file.
00621         return(EOF);
00622     }
00623     return(file->ifgetc());
00624 }
00625 
00626 /// Get a line from the file.
00627 /// \param file file to be read - IFILE is a pointer to an InputFile object
00628 /// \param buffer the buffer into which data is to be placed
00629 /// \param max the maximum size of the buffer, in bytes
00630 /// \return true if the last character read was an EOF
00631 inline bool ifgetline(IFILE file, void *buffer, size_t max)
00632 {
00633     if(file == NULL)
00634     {
00635         // return eof since there is no file.
00636         return(EOF);
00637     }
00638     return(file->ifgetline(buffer, max));
00639 }
00640 
00641 /// Reset to the beginning of the file (cannot be done for stdin/stdout).
00642 /// \param file file to be rewound - IFILE is a pointer to an InputFile object
00643 inline void ifrewind(IFILE file)
00644 {
00645     if(file == NULL)
00646     {
00647         return;
00648     }
00649     file->ifrewind();
00650 }
00651 
00652 /// Check to see if we have reached the EOF (returns 0 if not EOF).
00653 /// \param file file to be checked - IFILE is a pointer to an InputFile object
00654 /// \return 0 if not EOF, any other value means EOF.
00655 inline int ifeof(IFILE file)
00656 {
00657     if(file == NULL)
00658     {
00659         // No file, so that is considered to be EOF, so return 1.
00660         return(1);
00661     }
00662     return(file->ifeof());
00663 }
00664 
00665 /// Write the specified number of bytes from the specified buffer into the file.
00666 /// \param file file to write to - IFILE is a pointer to an InputFile object
00667 /// \param buffer buffer containing size bytes to write to the file.
00668 /// \param size number of bytes to write
00669 /// \return number of bytes written
00670 inline unsigned int ifwrite(IFILE file, const void * buffer, unsigned int size)
00671 {
00672     if(file == NULL)
00673     {
00674         // No file specified, so retun 0 bytes written.
00675         return(0);
00676     }
00677     return(file->ifwrite(buffer, size));
00678 }
00679 
00680 /// Get current position in the file.  Can be fed back into ifseek.
00681 /// \param file file to perform tell on - IFILE is a pointer to an InputFile object
00682 /// \return current position in the file, -1 indicates an error.
00683 inline int64_t iftell(IFILE file)
00684 {
00685     if(file == NULL)
00686     {
00687         return(-1);
00688     }
00689     return (file->iftell());
00690 }
00691 
00692 /// Seek to the specified position (result from an iftell), but cannot
00693 /// be done for stdin/stdout.
00694 /// \param file file to perform seek on - IFILE is a pointer to an InputFile object
00695 /// \param offset offset into the file to move to (must be from a tell call)
00696 /// \param origin can be any of the following:
00697 /// Note: not all are valid for all filetypes.
00698 ///   SEEK_SET - Beginning of file
00699 ///   SEEK_CUR - Current position of the file pointer
00700 ///   SEEK_END - End of file
00701 /// \return true on successful seek and false on a failed seek.
00702 inline bool ifseek(IFILE file, int64_t offset, int origin)
00703 {
00704     if(file == NULL)
00705     {
00706         // Could not see since no file was specified.
00707         return(false);
00708     }
00709     return (file->ifseek(offset, origin));
00710 }
00711 
00712 /// Write to a file using fprintf format.
00713 /// \param file file to write to - IFILE is a pointer to an InputFile object
00714 /// \param format printf format for writing, followed by parameters.
00715 /// \return number of bytes written
00716 int ifprintf(IFILE output, const char * format, ...);
00717 
00718 /// Read a line from a file using streaming.
00719 /// \param stream file to read from - IFILE is a pointer to an InputFile object
00720 /// \param str output string containing the line read from the file.
00721 inline IFILE operator >> (IFILE stream, std::string &str)
00722 {
00723     str.clear();
00724     int ch;
00725     // not safe... newline handling?
00726     while ((ch = stream->ifgetc())!=EOF && (ch != '\n')) str.push_back(ch);
00727     return stream;
00728 }
00729 
00730 /// Write to a file using streaming.
00731 /// \param stream file to write to - IFILE is a pointer to an InputFile object
00732 /// \param str string containing what should be written to the file.
00733 inline InputFile& operator << (InputFile& stream, const std::string& str)
00734 {
00735     unsigned int numExpected = str.length();
00736     unsigned int numWritten = 
00737         stream.ifwrite(str.c_str(), numExpected);
00738     if(numExpected != numWritten)
00739     {
00740         std::cerr << "Failed to stream to IFILE, expected " 
00741                   << numExpected << " but only wrote "
00742                   << numWritten << std::endl;
00743     }
00744     return(stream);
00745 }
00746 
00747 /// Write to a file using streaming.
00748 /// \param stream file to write to - IFILE is a pointer to an InputFile object
00749 /// \param str string containing what should be written to the file.
00750 inline InputFile& operator << (InputFile& stream, const char* str)
00751 {
00752     unsigned int numExpected = strlen(str);
00753     unsigned int numWritten = 
00754         stream.ifwrite(str, numExpected);
00755     if(numExpected != numWritten)
00756     {
00757         std::cerr << "Failed to stream to IFILE, expected " 
00758                   << numExpected << " but only wrote "
00759                   << numWritten << std::endl;
00760     }
00761     return(stream);
00762 }
00763 
00764 
00765 /// Write to a file using streaming.
00766 /// \param stream file to write to - IFILE is a pointer to an InputFile object
00767 /// \param num number that should be written to the file.
00768 InputFile& operator << (InputFile& stream, double num);
00769 
00770 /// Write to a file using streaming.
00771 /// \param stream file to write to - IFILE is a pointer to an InputFile object
00772 /// \param num number that should be written to the file.
00773 InputFile& operator << (InputFile& stream, int num);
00774 
00775 /// Write to a file using streaming.
00776 /// \param stream file to write to - IFILE is a pointer to an InputFile object
00777 /// \param num number that should be written to the file.
00778 InputFile& operator << (InputFile& stream, unsigned int num);
00779 
00780 /// Write to a file using streaming.
00781 /// \param stream file to write to - IFILE is a pointer to an InputFile object
00782 /// \param ch character that should be written to the file.
00783 inline InputFile& operator << (InputFile& stream, char ch)
00784 {
00785     unsigned int numWritten = 
00786         stream.ifwrite(&ch, 1);
00787     if(1 != numWritten)
00788     {
00789         std::cerr << "Failed to stream to IFILE, expected 1, but only wrote " 
00790                   << numWritten << std::endl;
00791     }
00792     return(stream);
00793 }
00794 
00795 #endif
00796 
Generated on Mon Feb 11 13:45:18 2013 for libStatGen Software by  doxygen 1.6.3