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