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