libStatGen Software
1
|
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