1 // ========================================================================== 2 // SeqAn - The Library for Sequence Analysis 3 // ========================================================================== 4 // Copyright (c) 2006-2018, Knut Reinert, FU Berlin 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above copyright 13 // notice, this list of conditions and the following disclaimer in the 14 // documentation and/or other materials provided with the distribution. 15 // * Neither the name of Knut Reinert or the FU Berlin nor the names of 16 // its contributors may be used to endorse or promote products derived 17 // from this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE 23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 // DAMAGE. 30 // 31 // ========================================================================== 32 // Author: David Weese <david.weese@fu-berlin.de> 33 // ========================================================================== 34 // Defines basic file access functions. 35 // ========================================================================== 36 37 #ifndef SEQAN_INCLUDE_SEQAN_FILE_BASE_H_ 38 #define SEQAN_INCLUDE_SEQAN_FILE_BASE_H_ 39 40 /* IOREV 41 * _doc_ 42 * 43 * base class with SPecs and Tags 44 * also contains standard calls for IO as wrappers around members 45 * in system/file_sync.h and system/file_ssync.h 46 * (these files are built around c++ fstream IO) 47 * well documented (in comparison to other files) 48 * 49 * SEQAN_DIRECTIO Macro mentioned here but not documented or tested 50 */ 51 52 namespace seqan { 53 54 // Manual Forward. 55 template < typename TSpec, typename TPos > 56 inline typename Position< File<TSpec> >::Type seek(File<TSpec> &me, TPos const fileOfs, int origin); 57 template < typename TSpec, typename TPos > 58 inline typename Position< File<TSpec> >::Type seek(File<TSpec> &me, TPos const fileOfs); 59 60 ////////////////////////////////////////////////////////////////////////////// 61 // generic open/close interface 62 63 /*! 64 * @fn File#open 65 * @brief Opens a file, stream, or persistent string. 66 * 67 * @signature bool open(file, fileName, openMode); 68 * 69 * @param[in,out] file The File to open. 70 * @param[in] fileName A <tt>char const *</tt> string containing the file name. 71 * @param[in] openMode Combination of flags defining how the file should be opened. See @link FileOpenMode 72 * @endlink for more details. Type: <tt>int</tt>. If you omit the <tt>OPEN_APPEND</tt> flag in 73 * write mode, the file will be cleared when opened. Default: <tt>OPEN_RDWR | OPEN_CREATE | 74 * OPEN_APPEND</tt>. 75 * 76 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 77 */ 78 79 template < typename TSpec > open(File<TSpec> & me,const char * fileName,int openMode)80 inline bool open(File<TSpec> &me, const char *fileName, int openMode) 81 { 82 //IOREV resolves to member in file_(a)sync.h which resolves to fstream 83 return me.open(fileName, openMode); 84 } 85 86 template < typename TSpec > open(File<TSpec> & me,const char * fileName)87 inline bool open(File<TSpec> &me, const char *fileName) 88 { 89 //IOREV 90 return open(me, fileName, DefaultOpenMode<File<TSpec> >::VALUE); 91 } 92 93 /*! 94 * @fn File#openTemp 95 * @brief Opens a temporary file. 96 * 97 * @signature bool openTemp(file); 98 * 99 * @param[in,out] file The File object to open the temporary file. 100 * 101 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 102 * 103 * @section Remarks 104 * 105 * After closing this file will be deleted automatically. The openmode (see @link File#open @endlink) is <tt>OPEN_RDWR 106 * | OPEN_CREATE</tt>. 107 * 108 * @return bool <tt>true</tt> on success <tt>false</tt> on failure. 109 */ 110 111 template < typename TSpec > openTemp(File<TSpec> & me)112 inline bool openTemp(File<TSpec> &me) 113 { 114 //IOREV 115 return me.openTemp(); 116 } 117 118 template < typename TSpec > openTemp(File<TSpec> & me,int openMode)119 inline bool openTemp(File<TSpec> &me, int openMode) 120 { 121 //IOREV 122 return me.openTemp(openMode); 123 } 124 125 template < typename File > reopen(File &,int)126 inline void reopen(File &, int) 127 { 128 //IOREV _stub_ _nodoc_ This is currently a no-op. Is that intended? 129 } 130 131 /*! 132 * @fn File#close 133 * @brief Close a file. 134 * 135 * @signature bool close(file); 136 * 137 * @param[in,out] file The File object to close. 138 * 139 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 140 */ 141 142 template < typename TSpec > close(File<TSpec> & me)143 inline bool close(File<TSpec> & me) 144 { 145 //IOREV 146 return me.close(); 147 } 148 149 template < typename TSpec > sectorSize(File<TSpec> const &)150 inline unsigned sectorSize(File<TSpec> const & /*me*/) 151 { 152 //IOREV _duplicate_ _nodoc_ duplicate or identical spec. in file_cstyle.h should'nt this be variable 153 return 4096; 154 } 155 156 157 ////////////////////////////////////////////////////////////////////////////// 158 // generic read(At)/write(At) interface 159 160 /*! 161 * @fn File#read 162 * @brief Loads record from a file. 163 * 164 * @signature bool read(file, memPtr, count); 165 * 166 * @param[in,out] file The File object. 167 * @param[out] memPtr A pointer to the first destination record in memory. 168 * @param[in] count The amount of records to be read. 169 * 170 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 171 * 172 * @section Remarks 173 * 174 * The records are read from the position pointed to by the current file pointer (see @link File#seek @endlink). 175 */ 176 177 template < typename TSpec, typename TValue, typename TSize > read(File<TSpec> & me,TValue * memPtr,TSize const count)178 inline bool read(File<TSpec> & me, TValue *memPtr, TSize const count) 179 { 180 //IOREV 181 typedef typename Size<File<TSpec> >::Type TFileSize; 182 TFileSize nbytes = (TFileSize)count * (TFileSize)sizeof(TValue); 183 return me.read(memPtr, nbytes) == nbytes; 184 } 185 186 /*! 187 * @fn File#write 188 * @brief Saves records to a file. 189 * 190 * @signature bool write(file, memPtr, count); 191 * 192 * @param[in,out] file The File object. 193 * @param[in] memPtr Pointer to the source for the data to write. 194 * @param[in] count The number of records to write. 195 * 196 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 197 * 198 * @section Remarks 199 * 200 * The records are written at the position pointed to by the current file pointer (see @link File#seek @endlink). 201 */ 202 203 template < typename TSpec, typename TValue, typename TSize > write(File<TSpec> & me,TValue const * memPtr,TSize const count)204 inline bool write(File<TSpec> & me, TValue const *memPtr, TSize const count) 205 { 206 //IOREV 207 typedef typename Size<File<TSpec> >::Type TFileSize; 208 TFileSize nbytes = (TFileSize)count * (TFileSize)sizeof(TValue); 209 return me.write(memPtr, nbytes) == nbytes; 210 } 211 212 /*! 213 * @fn File#readAt 214 * @brief Loads records from a specific position in a file. 215 * 216 * @signature bool readAt(file, memPtr, count, fileOfs); 217 * 218 * @param[in,out] file The File object to read from. 219 * @param[out] memPtr A pointer to the first destination record in memory. 220 * @param[in] count The amount of records to be read. 221 * @param[in] fileOfs The absolute file position in bytes measured from the beginning. 222 * 223 * @return bool <tt>true</tt> on success and <tt>false</tt> on failure. 224 */ 225 226 template < typename TFile, typename TValue, typename TSize, typename TPos > readAt(TFile & me,TValue * memPtr,TSize const count,TPos const fileOfs)227 inline bool readAt(TFile & me, TValue *memPtr, TSize const count, TPos const fileOfs) 228 { 229 //IOREV 230 typedef typename Position<TFile>::Type pos_t; 231 seek(me, (pos_t)fileOfs * (pos_t)sizeof(TValue)); 232 return read(me, memPtr, count); 233 } 234 235 /*! 236 * @fn File#writeAt 237 * @brief Saves records to a specific position in a file. 238 * 239 * @signature bool writeAt(file, memPtr, count, fileOfs); 240 * 241 * @param[in,out] file The File object to write to. 242 * @param[in] memPtr Pointer to the memory to write. 243 * @param[in] count The amount of records to be written. 244 * @param[in] fileOfs The absolute file position in bytes measured from the beginning. 245 * 246 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 247 */ 248 249 template < typename TFile, typename TValue, typename TSize, typename TPos > writeAt(TFile & me,TValue const * memPtr,TSize const count,TPos const fileOfs)250 inline bool writeAt(TFile & me, TValue const *memPtr, TSize const count, TPos const fileOfs) 251 { 252 //IOREV 253 typedef typename Position<TFile>::Type pos_t; 254 seek(me, (pos_t)fileOfs * (pos_t)sizeof(TValue)); 255 return write(me, memPtr, count); 256 } 257 258 259 260 ////////////////////////////////////////////////////////////////////////////// 261 // generic seek/tell/size/resize interface 262 263 /*! 264 * @fn File#seek 265 * @brief Changes the current file pointer. 266 * 267 * @signature TPosition seek(file, fileOfs[, origin]); 268 * 269 * @param[in,out] file The File object to seek in. 270 * @param[in] fileOfs A file offset measured in bytes relative to <tt>origin</tt>. 271 * @param[in] origin Selects the origin from where to calculate the new position. One of <tt>SEEK_BEGIN</tt>, 272 * <tt>SEEK_CURRENT</tt>, and <tt>SEEK_END<tt> (origin is beginning, current pointer, end of 273 * the file). Default: <tt>SEEK_BEGIN</tt>. 274 * 275 * @return TPosition The new file position measured in bytes from the beginning. 276 */ 277 278 template < typename TSpec, typename TPos > seek(File<TSpec> & me,TPos const fileOfs,int origin)279 inline typename Position< File<TSpec> >::Type seek(File<TSpec> &me, TPos const fileOfs, int origin) 280 { 281 //IOREV 282 typedef typename Position< File<TSpec> >::Type TFilePos; 283 TFilePos newOfs = me.seek(fileOfs, origin); 284 #if SEQAN_ENABLE_DEBUG || SEQAN_ENABLE_TESTING 285 if (origin == SEEK_BEGIN && newOfs != (TFilePos)fileOfs) { 286 std::cerr << "seek returned " << std::hex << newOfs << " instead of " << fileOfs << std::dec << std::endl; 287 } 288 #endif 289 return newOfs; 290 } 291 292 template < typename TSpec, typename TPos > seek(File<TSpec> & me,TPos const fileOfs)293 inline typename Position< File<TSpec> >::Type seek(File<TSpec> &me, TPos const fileOfs) 294 { 295 //IOREV 296 return seek(me, fileOfs, SEEK_BEGIN); 297 } 298 299 /*! 300 * @fn File#tell 301 * @brief Gets the current file pointer. 302 * 303 * @signature TPosition tell(file); 304 * 305 * @param[in] file The File object to query for the current position. 306 * 307 * @return TPosition The current position in the file. 308 */ 309 310 template < typename TSpec > tell(File<TSpec> & me)311 inline typename Position< File<TSpec> >::Type tell(File<TSpec> &me) 312 { 313 //IOREV 314 return me.tell(); 315 } 316 317 /*! 318 * @fn File#rewind 319 * @brief Sets the current file pointer to the beginning of a file. 320 * 321 * @signature void rewind(file); 322 * 323 * @param[in,out] file The file to reset the file pointer of. 324 */ 325 326 template < typename File > rewind(File & me)327 inline void rewind(File &me) 328 { 329 //IOREV 330 seek(me, 0); 331 } 332 333 /*! 334 * @fn File#length 335 * @brief Return the file size. 336 * 337 * @signature TSize length(file); 338 * 339 * @param[in] file The File object to query for its size. 340 * 341 * @return TSize The file size measured in bytes. 342 */ 343 344 template < typename TSpec > length(File<TSpec> & me)345 inline typename Size<File<TSpec> >::Type length(File<TSpec> &me) 346 { 347 //IOREV 348 typename Size<File<TSpec> >::Type old_pos = tell(me); 349 typename Size<File<TSpec> >::Type result = seek(me, 0, SEEK_END); 350 seek(me, old_pos, SEEK_BEGIN); 351 return result; 352 } 353 354 /*! 355 * @fn File#resize 356 * @brief A file object. 357 * 358 * @signature void resize(file, newLength); 359 * 360 * @param[in,out] file The File object to resize. 361 * @param[in] newLength The file size in bytes to resize to in bytes. 362 */ 363 364 template < typename TSpec, typename TSize > resize(File<TSpec> & me,TSize new_length)365 inline void resize(File<TSpec> &me, TSize new_length) 366 { 367 //IOREV possibly not standard-conformant, see resize() in file_cstyle.h 368 typename Size<File<TSpec> >::Type old_pos = tell(me); 369 seek(me, new_length, SEEK_BEGIN); 370 setEof(me); 371 seek(me, old_pos, SEEK_BEGIN); 372 } 373 374 /*! 375 * @fn File#setEof 376 * @brief Sets the file end to the current pointer. 377 * 378 * @signature bool setEof(file); 379 * 380 * @param[in,out] file The File object to set the end of. 381 * 382 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 383 */ 384 385 template < typename TSpec > setEof(File<TSpec> &)386 inline bool setEof(File<TSpec> &/*me*/) 387 { 388 //IOREV _noop_ specialized for async file access but not for sync 389 return true; 390 } 391 392 393 ////////////////////////////////////////////////////////////////////// 394 // Pseudo asynchronous Methods 395 ////////////////////////////////////////////////////////////////////// 396 397 ////////////////////////////////////////////////////////////////////// 398 // callback based read/write 399 /* 400 template < typename File, typename TValue, typename TSize, 401 typename aCallback, typename aHint > 402 inline typename AsyncRequest<File>::Type 403 asyncRead(File & me, TValue *memPtr, TSize const count, 404 aCallback* cb, aHint* hint) 405 { 406 result = read(me, memPtr, count); 407 cb(hint); 408 return NULL; 409 } 410 411 template < typename File, typename TValue, typename TSize, 412 typename aCallback, typename aHint > 413 inline typename AsyncRequest<File>::Type 414 asyncWrite(File & me, TValue const *memPtr, TSize const count, 415 aCallback* cb, aHint* hint) 416 { 417 write(me, memPtr, count); 418 cb(hint); 419 return NULL; 420 } 421 422 template < typename File, typename TValue, typename TSize, typename TPos, 423 typename aCallback, typename aHint > 424 inline typename AsyncRequest<File>::Type 425 asyncReadAt(File & me, TValue *memPtr, TSize const count, TPos const fileOfs, 426 aCallback* cb, aHint* hint) 427 { 428 readAt(me, memPtr, count, fileOfs); 429 cb(hint); 430 return NULL; 431 } 432 433 template < typename File, typename TValue, typename TSize, typename TPos, 434 typename aCallback, typename aHint > 435 inline typename AsyncRequest<File>::Type 436 asyncWriteAt(File & me, TValue const *memPtr, TSize const count, TPos const fileOfs, 437 aCallback* cb, aHint* hint) 438 { 439 result = writeAt(me, memPtr, count, fileOfs); 440 cb(hint); 441 return NULL; 442 } 443 444 445 ////////////////////////////////////////////////////////////////////// 446 // event based read/write 447 448 template < typename File, typename TValue, typename TSize, 449 typename aEvent > 450 inline typename AsyncRequest<File>::Type 451 asyncRead(File & me, TValue *memPtr, TSize const count, 452 aEvent &event) 453 { 454 read(me, memPtr, count); 455 event.signal(); 456 return NULL; 457 } 458 459 template < typename File, typename TValue, typename TSize, 460 typename aEvent > 461 inline typename AsyncRequest<File>::Type 462 asyncWrite(File & me, TValue const *memPtr, TSize const count, 463 aEvent &event) 464 { 465 write(me, memPtr, count); 466 event.signal(); 467 return NULL; 468 } 469 470 template < typename File, typename TValue, typename TSize, typename TPos, 471 typename aEvent > 472 inline typename AsyncRequest<File>::Type 473 asyncReadAt(File & me, TValue *memPtr, TSize const count, TPos const fileOfs, 474 aEvent &event) 475 { 476 readAt(me, memPtr, count, fileOfs); 477 event.signal(); 478 return NULL; 479 } 480 481 template < typename File, typename TValue, typename TSize, typename TPos, 482 typename aEvent > 483 inline typename AsyncRequest<File>::Type 484 asyncWriteAt(File & me, TValue const *memPtr, TSize const count, TPos const fileOfs, 485 aEvent &event) 486 { 487 writeAt(me, memPtr, count, fileOfs); 488 event.signal(); 489 return NULL; 490 } 491 */ 492 493 ////////////////////////////////////////////////////////////////////// 494 // queue-less request based pseudo asynchronous read/write 495 496 /*! 497 * @fn File#asyncReadAt 498 * @brief Asynchronously loads records from a specific position in a file. 499 * 500 * @signature bool asyncReadAt(file, memPtr, count, fileOfs, request); 501 * 502 * @param[in,out] file The File object to read from. 503 * @param[out] memPtr A pointer to the first destination record in memory. 504 * @param[in] count The amount of records to be read. 505 * @param[in] fileOfs The absolute file position in bytes measured from the beginning. 506 * @param[in] request Reference to a structure that will be associated with this asynchronous request. Type: 507 * @link AsyncRequest @endlink. 508 * 509 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 510 */ 511 512 template < typename File, typename TValue, typename TSize, typename TPos, 513 typename AsyncRequest > 514 inline bool asyncReadAt(File & me,TValue * memPtr,TSize const count,TPos const fileOfs,AsyncRequest &)515 asyncReadAt(File & me, TValue *memPtr, TSize const count, TPos const fileOfs, 516 AsyncRequest &) 517 { 518 //IOREV _stub_ see general discussion about AsynRequest 519 return readAt(me, memPtr, count, fileOfs); 520 } 521 522 /*! 523 * @fn File#asyncWriteAt 524 * @brief Asynchronously writes records to a specific position in a file. 525 * 526 * @signature bool asyncWriteAt(file, memPtr, count, fileOfs, request); 527 * 528 * @param[in,out] file The File object. 529 * @param[in] memPtr A pointer to the first source record in memory. 530 * @param[in] count The amount of records to be written. 531 * @param[in] fileOfs The absolute file position in bytes measured form the beginning. 532 * @param[in] request Reference to a structure that will be associated with this asynchronous request. 533 * 534 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 535 */ 536 537 template < typename File, typename TValue, typename TSize, typename TPos, 538 typename TAsyncRequest > 539 inline bool asyncWriteAt(File & me,TValue const * memPtr,TSize const count,TPos const fileOfs,TAsyncRequest &)540 asyncWriteAt(File & me, TValue const *memPtr, TSize const count, TPos const fileOfs, 541 TAsyncRequest &) 542 { 543 //IOREV _stub_ see general discussion about AsynRequest 544 return writeAt(me, memPtr, count, fileOfs); 545 } 546 547 548 ////////////////////////////////////////////////////////////////////// 549 // pseudo queue specific functions 550 551 /*! 552 * @fn File#flush 553 * @brief Waits for all open requests to complete. 554 * 555 * @signature void flush(file); 556 * 557 * @param[in,out] file The File object to flush. 558 */ 559 560 template < typename TSpec > flush(File<TSpec> &)561 inline void flush(File<TSpec> &) 562 { 563 //IOREV _noop_ specialized for async file access but not for sync 564 } 565 566 /*! 567 * @fn File#waitFor 568 * @brief Waits for an asynchronous request to complete. 569 * 570 * @signature bool waitFor(request[, timeout]); 571 * 572 * @param[in,out] request Reference to an AsyncRequest. 573 * @param[in] timeout A timeout value in milliseconds. A value of 0 can be used to test for completion without 574 * waiting. Default: 0. 575 * 576 * @return bool <tt>true</tt> on completion, <tt>false</tt> on timeout. 577 * 578 * @section Remarks 579 * 580 * <tt>waitfor</tt> block sand suspends the calling thread process until <tt>request</tt> is completed or after 581 * <tt>timeout</tt> milliseconds. 582 */ 583 waitFor(AsyncDummyRequest &)584 inline bool waitFor(AsyncDummyRequest &) 585 { 586 //IOREV _noop_ see general discussion about AsynRequest 587 return true; 588 } 589 590 template < typename TTime > waitFor(AsyncDummyRequest &,TTime,bool & inProgress)591 inline bool waitFor(AsyncDummyRequest &, TTime, bool &inProgress) 592 { 593 //IOREV _noop_ see general discussion about AsynRequest 594 inProgress = false; 595 return true; 596 } 597 598 // deprecated 599 template < typename TSpec, typename AsyncRequest > 600 [[deprecated]] release(File<TSpec> &,AsyncRequest &)601 inline void release(File<TSpec> &, AsyncRequest &) 602 { 603 //IOREV _noop_ see general discussion about AsynRequest 604 } 605 606 /*! 607 * @fn File#cancel 608 * @brief Cancels an asynchronous request. 609 * 610 * @signature bool cancel(file, request); 611 * 612 * @param[in,out] file The File to cancel the request for. 613 * @param[in] request Reference to an AsyncRequest object. Type: @link AsyncRequest @endlink. 614 * 615 * @return bool <tt>true</tt> on success, <tt>false</tt> on failure. 616 */ 617 618 template < typename TSpec, typename AsyncRequest > cancel(File<TSpec> &,AsyncRequest &)619 inline bool cancel(File<TSpec> &, AsyncRequest &) 620 { 621 //IOREV _noop_ see general discussion about AsynRequest 622 return true; 623 } 624 625 626 // little helpers 627 628 template <typename T1, typename T2> inline enclosingBlocks(T1 _size,T2 _blockSize)629 T1 enclosingBlocks(T1 _size, T2 _blockSize) 630 { 631 //IOREV not sure what this does, but is used in several places 632 return (_size + (T1)_blockSize - (T1)1) / (T1)_blockSize; 633 } 634 635 template <typename T1, typename T2> inline alignSize(T1 _size,T2 _aligning)636 T1 alignSize(T1 _size, T2 _aligning) 637 { 638 //IOREV not sure what this does, but is used in several places 639 if (_size < (T1)_aligning) 640 return _aligning; 641 else 642 return (_size / (T1)_aligning) * (T1)_aligning; 643 } 644 } // namespace seqan 645 646 #endif // #ifndef SEQAN_INCLUDE_SEQAN_FILE_BASE_H_ 647