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 // Basic definitions for the stream module. 35 // ========================================================================== 36 37 #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_STREAM_H_ 38 #define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_STREAM_H_ 39 40 namespace seqan { 41 42 // ============================================================================ 43 // Forwards 44 // ============================================================================ 45 46 template <typename TDirection> 47 struct StreamIterator; 48 49 template <typename TValue, typename TTraits, typename TValue2> 50 inline void writeValue(std::basic_ostream<TValue, TTraits> &ostream, TValue2 val); 51 52 template <typename TValue, typename TTraits, typename TValue2> 53 inline void writeValue(std::ostreambuf_iterator<TValue, TTraits> &iter, TValue2 val); 54 55 template <typename TContainer, typename TValue> 56 inline void writeValue(Iter<TContainer, StreamIterator<Output> > &iter, TValue val); 57 58 template <typename TValue, typename TTraits> 59 inline bool atEnd(std::istreambuf_iterator<TValue, TTraits> const &it); 60 61 template <typename TContainer> 62 inline SEQAN_FUNC_ENABLE_IF(Is<StlContainerConcept<TContainer> >, typename Size<TContainer>::Type) 63 length(TContainer const & me); 64 65 template <typename TContainer, typename TSource> 66 inline void 67 appendValue(TContainer && me, TSource && source); 68 69 /*! 70 * @macro SEQAN_HAS_ZLIB 71 * @headerfile <seqan/stream.h> 72 * @brief Defined as 0 or 1, depending on zlib being available. 73 * 74 * @signature #define SEQAN_HAS_ZLIB 0 // or 1 75 */ 76 77 /*! 78 * @macro SEQAN_HAS_BZIP2 79 * @headerfile <seqan/stream.h> 80 * @brief Defined as 0 or 1, depending on bzlib being available. 81 * 82 * @signature #define SEQAN_HAS_BZIP 0 // or 1 83 */ 84 85 // ============================================================================ 86 // Tags 87 // ============================================================================ 88 89 // ============================================================================ 90 // Concepts 91 // ============================================================================ 92 93 // -------------------------------------------------------------------------- 94 // Concept StreamConcept 95 // -------------------------------------------------------------------------- 96 97 /*! 98 * @concept StreamConcept 99 * @headerfile <seqan/basic.h> 100 * 101 * @brief Base concept for streams. 102 * 103 * @signature concept StreamConcept; 104 */ 105 106 /*! 107 * @mfn StreamConcept#Value 108 * @brief Metafunction for retrieving the value type of a stream. 109 * 110 * @signature Value<TStream>::Type; 111 * 112 * @tparam TStream The stream type to query for its value type. 113 * @return Type The resulting value type. 114 */ 115 116 /*! 117 * @mfn StreamConcept#Size 118 * @brief Metafunction for retrieving the type of a stream. 119 * 120 * @signature Size<TStream>::Type; 121 * 122 * @tparam TStream The stream type to query for its size type. 123 * @return Type The resulting size type. 124 */ 125 126 /*! 127 * @mfn StreamConcept#Position 128 * @brief Metafunction for retrieving the position type of a stream. 129 * 130 * @signature Position<TStream>::Type; 131 * 132 * @tparam TStream The stream type to query for its position type. 133 * @return Type The resulting position type. 134 */ 135 136 /*! 137 * @fn StreamConcept#position 138 * @brief Return current stream position. 139 * 140 * @signature TPosition position(stream); 141 * 142 * @param[in] stream The stream to query. 143 * @return TPosition Current position in stream, see @link StreamConcept#Position Position @endlink. 144 */ 145 146 /*! 147 * @fn StreamConcept#setPosition 148 * @brief Set stream position. 149 * 150 * @signature void setPosition(stream, pos); 151 * 152 * @param[in,out] stream The stream to update 153 * @param[in] pos The positoin to set. 154 */ 155 156 /*! 157 * @fn StreamConcept#atEnd 158 * @brief Return whether stream is at the end. 159 * 160 * @signature bool atEnd(stream); 161 * 162 * @param[in] stream The stream to check. 163 * @return bool <tt>true</tt> if the file at EOF, <tt>false</tt> otherwise. 164 */ 165 166 SEQAN_CONCEPT(StreamConcept, (TStream)) 167 {}; 168 169 // -------------------------------------------------------------------------- 170 // Concept InputStreamConcept 171 // -------------------------------------------------------------------------- 172 173 /*! 174 * @concept InputStreamConcept Input StreamConcept 175 * @extends StreamConcept 176 * @headerfile <seqan/basic.h> 177 * 178 * @signature concept InputStreamConcept : StreamConcept; 179 * 180 * @brief Concept for input streams (for reading). 181 */ 182 183 SEQAN_CONCEPT_REFINE(InputStreamConcept, (TStream), (StreamConcept)) 184 { 185 typedef typename Value<TStream>::Type TValue; 186 typedef typename Size<TStream>::Type TSize; 187 typedef typename Position<TStream>::Type TPosition; 188 189 SEQAN_CONCEPT_ASSERT((SignedIntegerConcept<TPosition>)); 190 SEQAN_CONCEPT_USAGE(InputStreamConcept)191 SEQAN_CONCEPT_USAGE(InputStreamConcept) 192 {} 193 }; 194 195 // -------------------------------------------------------------------------- 196 // Concept OutputStreamConcept 197 // -------------------------------------------------------------------------- 198 199 /*! 200 * @concept OutputStreamConcept Output StreamConcept 201 * @extends StreamConcept 202 * @headerfile <seqan/basic.h> 203 * 204 * @signature concept OutputStreamConcept : StreamConcept; 205 * 206 * @brief Concept for output streams (for writing). 207 */ 208 209 SEQAN_CONCEPT_REFINE(OutputStreamConcept, (TStream), (StreamConcept)) 210 { 211 typedef typename Value<TStream>::Type TValue; 212 typedef typename Size<TStream>::Type TSize; 213 typedef typename Position<TStream>::Type TPosition; 214 215 SEQAN_CONCEPT_ASSERT((SignedIntegerConcept<TPosition>)); 216 SEQAN_CONCEPT_USAGE(OutputStreamConcept)217 SEQAN_CONCEPT_USAGE(OutputStreamConcept) 218 {} 219 }; 220 221 // -------------------------------------------------------------------------- 222 // Concept BidirectionalStreamConcept 223 // -------------------------------------------------------------------------- 224 225 /*! 226 * @concept BidirectionalStreamConcept Bidirectional StreamConcept 227 * @extends StreamConcept 228 * @headerfile <seqan/basic.h> 229 * 230 * @signature concept BidirectionalStreamConcept : StreamConcept; 231 * 232 * @brief Concept for bidirectional streams (both for reading and writing). 233 */ 234 235 SEQAN_CONCEPT_REFINE(BidirectionalStreamConcept, (TStream), (InputStreamConcept)(OutputStreamConcept)) 236 {}; 237 238 // ============================================================================ 239 // Classes 240 // ============================================================================ 241 242 // ---------------------------------------------------------------------------- 243 // Struct FormattedNumber 244 // ---------------------------------------------------------------------------- 245 246 /*! 247 * @class FormattedNumber 248 * @implements NumberConcept 249 * @headerfile <seqan/basic.h> 250 * 251 * @brief Helper class for storing a numeric value together with a 252 * <a href="http://www.cplusplus.com/reference/cstdio/printf/">printf format string</a>. 253 * 254 * @signature template <typename TValue> 255 * struct FormattedNumber; 256 * 257 * @tparam The numeric value type. 258 */ 259 260 template <typename TValue> 261 struct FormattedNumber 262 { 263 char const * format; 264 TValue value; 265 266 /*! 267 * @fn FormattedNumber::FormattedNumber 268 * @brief Constructor. 269 * 270 * @signature FormattedNumber::FormattedNumber(format, value); 271 * 272 * @param[in] format A <tt>char const *</tt> for the format string. 273 * @param[in] value The <tt>TValue</tt> to store. 274 * 275 * The constructed FormattedNumber object store the <tt>format</tt> pointer "as is". This means that you are 276 * responsible for keeping this pointer valid until the object is deconstructed. Passing in a C string literal 277 * (as in <tt>FormattedNumber<double>("%.2f", 1.234)</tt> is fine. 278 */ 279 FormattedNumberFormattedNumber280 FormattedNumber(char const * format, TValue const & value) : 281 format(format), value(value) 282 {} 283 TValueFormattedNumber284 operator TValue() const 285 { 286 return value; 287 } 288 }; 289 290 template <typename TValue> 291 struct Is< NumberConcept< FormattedNumber<TValue> > > : 292 Is< NumberConcept<TValue> > {}; 293 294 // ============================================================================ 295 // Exceptions 296 // ============================================================================ 297 298 // ---------------------------------------------------------------------------- 299 // Exception ParseError 300 // ---------------------------------------------------------------------------- 301 302 /*! 303 * @class ParseError 304 * @extends RuntimeError 305 * @headerfile <seqan/basic.h> 306 * 307 * @brief Exception class for parser errors. 308 * 309 * @signature struct ParseError : RuntimeError; 310 */ 311 312 struct ParseError : RuntimeError 313 { 314 /*! 315 * @fn ParseError::ParseError 316 * @headerfile <seqan/basic.h> 317 * 318 * @brief Constructor. 319 * 320 * @signature ParseError::ParseError(message); 321 * 322 * @param[in] message The error message to use, <tt>std::string</tt> or <tt>char const * </tt>. 323 */ 324 325 template <typename TString> 326 ParseError(TString const & message) : 327 RuntimeError(message) 328 {} 329 }; 330 331 // ---------------------------------------------------------------------------- 332 // Exception UnexpectedEnd 333 // ---------------------------------------------------------------------------- 334 335 /*! 336 * @class UnexpectedEnd 337 * @extends ParseError 338 * @headerfile <seqan/basic.h> 339 * 340 * @brief Exception class for "unexpected end of input" errors. 341 * 342 * @signature struct UnexpectedEnd : RuntimeError; 343 */ 344 345 struct UnexpectedEnd : ParseError 346 { 347 /*! 348 * @fn UnexpectedEnd::UnexpectedEnd 349 * @headerfile <seqan/basic.h> 350 * 351 * @brief Default constructor, makes the object use a default message. 352 * 353 * @signature UnexpectedEnd::UnexpectedEnd(); 354 */ 355 356 UnexpectedEnd() : 357 ParseError("Unexpected end of input.") 358 {} 359 }; 360 361 // ---------------------------------------------------------------------------- 362 // Exception EmptyFieldError 363 // ---------------------------------------------------------------------------- 364 365 /*! 366 * @class EmptyFieldError 367 * @extends ParseError 368 * @headerfile <seqan/basic.h> 369 * 370 * @brief Exception class for "empty field" errors. 371 * 372 * @signature struct EmptyFieldError : RuntimeError; 373 */ 374 375 struct EmptyFieldError : ParseError 376 { 377 /*! 378 * @fn EmptyFieldError::EmptyFieldError 379 * @headerfile <seqan/basic.h> 380 * 381 * @brief Construct the exception with <tt>fieldName + " field was empty."</tt>. 382 * 383 * @signature EmptyFieldEror::EmptyFieldError(fieldName); 384 * 385 * @param[in] fieldName The field name to use for the message, <tt>std::string</tt>. 386 */ 387 388 EmptyFieldError(std::string fieldName): 389 ParseError(fieldName + " field was empty.") 390 {} 391 }; 392 393 // ============================================================================ 394 // Metafunctions 395 // ============================================================================ 396 397 // ---------------------------------------------------------------------------- 398 // Metafunction Iterator 399 // ---------------------------------------------------------------------------- 400 401 /*! 402 * @mfn StreamConcept#DirectionIterator 403 * @brief Return the direction iterator for the given direction. 404 * 405 * @signature DirectionIterator<TStream>::Type; 406 * 407 * @tparam TStream The stream to query for its direction iterator. 408 * @return Type The resulting direction iterator. 409 */ 410 411 /*! 412 * @mfn ContainerConcept#DirectionIterator 413 * @brief Return the direction iterator for the given direction. 414 * 415 * @signature DirectionIterator<TContainer>::Type; 416 * 417 * @tparam TContainer The container to query for its direction iterator. 418 * @return Type The resulting direction iterator. 419 */ 420 421 template <typename TObject, typename TDirection> 422 struct DirectionIterator : 423 If<Is<StreamConcept<TObject> >, 424 Iter<TObject, StreamIterator<TDirection> >, 425 typename Iterator<TObject, Rooted>::Type> 426 {}; 427 428 // -------------------------------------------------------------------------- 429 // Metafunction BasicStream 430 // -------------------------------------------------------------------------- 431 432 /*! 433 * @mfn BasicStream 434 * @headerfile <seqan/basic.h> 435 * @brief Return the stream type to read or write values. 436 * 437 * @signature BasicStream<TValue, TDirection[, TTraits]>::Type; 438 * 439 * @tparam TValue The value type of the stream. 440 * @tparam TDirection The direction of the stream, one of the @link DirectionTags @endlink. 441 * @tparam TTraits The traits to use for the values, defaults to <tt>std::char_traits<TValue></tt>. 442 * 443 */ 444 445 template <typename TValue, typename TDirection, typename TTraits = std::char_traits<TValue> > 446 struct BasicStream : 447 If< 448 IsSameType<TDirection, Input>, 449 std::basic_istream<TValue, TTraits>, 450 typename If< 451 IsSameType<TDirection, Output>, 452 std::basic_ostream<TValue, TTraits>, 453 std::basic_iostream<TValue, TTraits> 454 >::Type 455 > 456 {}; 457 458 // -------------------------------------------------------------------------- 459 // Metafunction IosOpenMode 460 // -------------------------------------------------------------------------- 461 462 /*! 463 * @mfn IosOpenMode 464 * @headerfile <seqan/basic.h> 465 * @brief Return the <tt>std::ios</tt> open mode for a direction. 466 * 467 * @signature IosOpenMode<TDirection[, TDummy]>::Type; 468 * 469 * @tparam TDirection The direction to query for the open mode, one of the @link DirectionTags @endlink. 470 * @tparam TDummy Implementation detail, defaults to <tt>void</tt> and is ignored. 471 * @return Type The resulting open mode of type <tt>const int</tt>. 472 */ 473 474 template <typename TDirection, typename TDummy = void> 475 struct IosOpenMode; 476 477 478 template <typename TDummy> 479 struct IosOpenMode<Input, TDummy> 480 { 481 static const int VALUE; 482 }; 483 484 template <typename TDummy> 485 struct IosOpenMode<Output, TDummy> 486 { 487 static const int VALUE; 488 }; 489 490 template <typename TDummy> 491 struct IosOpenMode<Bidirectional, TDummy> 492 { 493 static const int VALUE; 494 }; 495 496 template <typename TDummy> 497 const int IosOpenMode<Input, TDummy>::VALUE = std::ios::in | std::ios::binary; 498 499 template <typename TDummy> 500 const int IosOpenMode<Output, TDummy>::VALUE = std::ios::out | std::ios::binary; 501 502 template <typename TDummy> 503 const int IosOpenMode<Bidirectional, TDummy>::VALUE = std::ios::in | std::ios::out | std::ios::binary; 504 505 506 // -------------------------------------------------------------------------- 507 // Metafunction MagicHeader 508 // -------------------------------------------------------------------------- 509 510 /*! 511 * @mfn MagicHeader 512 * @headerfile <seqan/basic.h> 513 * @brief Returns the magic header for a file format tag. 514 * 515 * The magic header is used for recognizing files from the first few bytes. 516 * 517 * @signature MagicHeader<TTag[, TDummy]>::VALUE; 518 * 519 * @tparam TTag The file format tag to use for the query. 520 * @tparam TDummy Implementation detail, defaults to <tt>void</tt> and is ignored. 521 * @return VALUE The magic header string, of type <tt>char const *</tt>. 522 * 523 * This metafunction must be implemented in the modules implementing the file I/O. The metafunction is predefined when 524 * <tt>TTag</tt> is @link Nothing @endlink. In this case, <tt>VALUE</tt> is <tt>NULL</tt>. 525 */ 526 527 template <typename TTag, typename T = void> 528 struct MagicHeader; 529 530 template <typename T> 531 struct MagicHeader<Nothing, T> 532 { 533 static char const * VALUE; 534 }; 535 536 template <typename T> 537 char const * MagicHeader<Nothing, T>::VALUE = NULL; 538 539 // -------------------------------------------------------------------------- 540 // Metafunction FileExtensions 541 // -------------------------------------------------------------------------- 542 543 /*! 544 * @mfn FileExtensions 545 * @headerfile <seqan/basic.h> 546 * @brief Returns an array of file format extension strings for file foramt tag. 547 * 548 * @signature FileExtensions<TFormat[, TDummy]>::VALUE; 549 * 550 * @tparam TTag The file format tag to use for the query. 551 * @tparam TDummy Implementation detail, defaults to <tt>void</tt> and is ignored. 552 * @return VALUE The array of file format extension, of type <tt>char const *[]</tt>. 553 * 554 * This metafunction must be implemented in the modules implementing the file I/O. The metafunction is predefined when 555 * <tt>TTag</tt> is @link Nothing @endlink. In this case, <tt>VALUE</tt> is <tt>{""}</tt>. 556 */ 557 558 template <typename TFormat, typename T = void> 559 struct FileExtensions; 560 561 template <typename T> 562 struct FileExtensions<Nothing, T> 563 { 564 static char const * VALUE[1]; 565 }; 566 567 template <typename T> 568 char const * FileExtensions<Nothing, T>::VALUE[1] = 569 { 570 "" // default output extension 571 }; 572 573 // ---------------------------------------------------------------------------- 574 // Metafunction IntegerFormatString_ 575 // ---------------------------------------------------------------------------- 576 // Return the format string for numbers. 577 578 template <typename TUnsigned, unsigned SIZE, typename T = void> 579 struct IntegerFormatString_; 580 581 582 template <typename TUnsigned, typename T> 583 struct IntegerFormatString_<TUnsigned, 1, T> : 584 IntegerFormatString_<TUnsigned, 2, T> {}; 585 586 587 template <typename T> 588 struct IntegerFormatString_<False, 2, T> 589 { 590 static const char VALUE[]; 591 typedef short Type; 592 }; 593 template <typename T> 594 const char IntegerFormatString_<False, 2, T>::VALUE[] = "%hi"; 595 596 597 template <typename T> 598 struct IntegerFormatString_<True, 2, T> 599 { 600 static const char VALUE[]; 601 typedef unsigned short Type; 602 }; 603 template <typename T> 604 const char IntegerFormatString_<True, 2, T>::VALUE[] = "%hu"; 605 606 607 template <typename T> 608 struct IntegerFormatString_<False, 4, T> 609 { 610 static const char VALUE[]; 611 typedef int Type; 612 }; 613 template <typename T> 614 const char IntegerFormatString_<False, 4, T>::VALUE[] = "%i"; 615 616 617 template <typename T> 618 struct IntegerFormatString_<True, 4, T> 619 { 620 static const char VALUE[]; 621 typedef unsigned Type; 622 }; 623 template <typename T> 624 const char IntegerFormatString_<True, 4, T>::VALUE[] = "%u"; 625 626 627 // helper for the case: typedef long int64_t; 628 template <typename TIsUnsigned, typename T> 629 struct LongFormatString_; 630 631 template <typename T> 632 struct LongFormatString_<False, T> 633 { 634 static const char VALUE[]; 635 typedef long Type; 636 }; 637 template <typename T> 638 const char LongFormatString_<False, T>::VALUE[] = "%li"; 639 640 template <typename T> 641 struct LongFormatString_<True, T> 642 { 643 static const char VALUE[]; 644 typedef unsigned long Type; 645 }; 646 template <typename T> 647 const char LongFormatString_<True, T>::VALUE[] = "%lu"; 648 649 // helper for the case: typedef long long int64_t; 650 template <typename TIsUnsigned, typename T> 651 struct Int64FormatString_; 652 653 template <typename T> 654 struct Int64FormatString_<False, T> 655 { 656 static const char VALUE[]; 657 typedef int64_t Type; 658 }; 659 template <typename T> 660 const char Int64FormatString_<False, T>::VALUE[] = "%lli"; 661 662 template <typename T> 663 struct Int64FormatString_<True, T> 664 { 665 static const char VALUE[]; 666 typedef uint64_t Type; 667 }; 668 template <typename T> 669 const char Int64FormatString_<True, T>::VALUE[] = "%llu"; 670 671 672 template <typename TIsUnsigned, typename T> 673 struct IntegerFormatString_<TIsUnsigned, 8, T> : 674 If<IsSameType<uint64_t, unsigned long>, 675 LongFormatString_<TIsUnsigned, T>, 676 Int64FormatString_<TIsUnsigned, T> >::Type {}; 677 678 679 // ============================================================================ 680 // Functions 681 // ============================================================================ 682 683 // ---------------------------------------------------------------------------- 684 // Function writeValue() [ContainerConcept] 685 // ---------------------------------------------------------------------------- 686 687 /*! 688 * @fn ContainerConcept#writeValue 689 * @brief Write a value at the end of a container. 690 * 691 * @signature void writeValue(container, val); 692 * 693 * @param[in,out] container to append to. 694 * @param[in] val The value to append. 695 * 696 * @see ContainerConcept#appendValue 697 */ 698 699 // resizable containers 700 template <typename TSequence, typename TValue> 701 inline SEQAN_FUNC_ENABLE_IF(Is<ContainerConcept<TSequence> >, void) 702 writeValue(TSequence &cont, TValue val) 703 { 704 appendValue(cont, val); 705 } 706 707 // ---------------------------------------------------------------------------- 708 // Function writeValue() [Range] 709 // ---------------------------------------------------------------------------- 710 711 /*! 712 * @fn Range#writeValue 713 * @brief Write a value to a @link Range @endlink. 714 * 715 * @signature void writeValue(range, val); 716 * 717 * <tt>val</tt> will be assigned to the first element of the range. Then, the beginning of the range will be advanced 718 * by one. 719 * 720 * @param[in,out] range to append to. 721 * @param[in] val The value to append. 722 */ 723 724 // Range 725 template <typename TIterator, typename TValue> 726 inline void 727 writeValue(Range<TIterator> &range, TValue val) 728 { 729 assignValue(range.begin, val); 730 ++range.begin; 731 } 732 733 // ---------------------------------------------------------------------------- 734 // Function writeValue() [Iter] 735 // ---------------------------------------------------------------------------- 736 737 /*! 738 * @fn OutputIteratorConcept#writeValue 739 * @brief Write a single value to a container by dereferencing its iterator. 740 * 741 * @signature void writeValue(iter, val); 742 * 743 * @param[in,out] iter The iterator to use for dereferenced writing. 744 * @param[in] val The value to write into the container. 745 * 746 * If the host of <tt>iter</tt> is a @link ContainerConcept @endlink then container is resized to make space for the 747 * item. 748 */ 749 750 // resizable containers 751 template <typename TSequence, typename TSpec, typename TValue> 752 inline SEQAN_FUNC_ENABLE_IF(Is<ContainerConcept<TSequence> >, void) 753 writeValue(Iter<TSequence, TSpec> & iter, TValue val) 754 { 755 typedef Iter<TSequence, TSpec> TIter; 756 757 TSequence &cont = container(iter); 758 typename Position<TIter>::Type pos = position(iter); 759 typename Size<TIter>::Type len = length(cont); 760 761 if (pos < len) 762 { 763 assignValue(iter, val); 764 ++iter; 765 } 766 else 767 { 768 if (pos > len) 769 resize(cont, pos - 1); 770 appendValue(cont, val); 771 setPosition(iter, pos + 1); 772 } 773 } 774 775 // non-resizable containers 776 template <typename TNoSequence, typename TSpec, typename TValue> 777 inline SEQAN_FUNC_DISABLE_IF(Is<ContainerConcept<TNoSequence> >, void) 778 writeValue(Iter<TNoSequence, TSpec> & iter, TValue val) 779 { 780 SEQAN_ASSERT_LT(position(iter), length(container(iter))); 781 782 assignValue(iter, val); 783 ++iter; 784 } 785 786 // ---------------------------------------------------------------------------- 787 // Function writeValue() [pointer] 788 // ---------------------------------------------------------------------------- 789 790 ///*! 791 // * @fn ContainerConcept#writeValue 792 // * @brief Write a value by dereferencing a pointer and incrementing its position by one. 793 // * 794 // * @signature void writeValue(pointer, val); 795 // * 796 // * @param[in,out] iter The pointer to dereference, usually a <tt>char *</tt>. 797 // * @param[in] val The value to write to the dereferenced pointer. 798 // * 799 // * This function is equivalent to <tt>*iter++ = val</tt>. 800 // */ 801 802 template <typename TTargetValue, typename TValue> 803 inline void 804 writeValue(TTargetValue * & iter, TValue val) 805 { 806 *iter++ = val; 807 } 808 809 // ---------------------------------------------------------------------------- 810 // Function _write(); Element-wise 811 // ---------------------------------------------------------------------------- 812 813 template <typename TTarget, typename TFwdIterator, typename TSize, typename TIChunk, typename TOChunk> 814 inline void _write(TTarget &target, TFwdIterator &iter, TSize n, TIChunk, TOChunk) 815 { 816 typedef typename GetValue<TFwdIterator>::Type TValue; 817 for (; n > (TSize)0; --n, ++iter) 818 writeValue(target, static_cast<TValue>(*iter)); 819 } 820 821 // ---------------------------------------------------------------------------- 822 // Function _write(); Chunked 823 // ---------------------------------------------------------------------------- 824 825 template <typename TTarget, typename TFwdIterator, typename TSize, typename TIValue, typename TOValue> 826 inline void _write(TTarget &target, TFwdIterator &iter, TSize n, Range<TIValue*> *, Range<TOValue*> *) 827 { 828 typedef Nothing* TNoChunking; 829 typedef typename Size<TTarget>::Type TTargetSize; 830 831 Range<TIValue*> ichunk; 832 Range<TOValue*> ochunk; 833 834 while (n != (TSize)0) 835 { 836 getChunk(ichunk, iter, Input()); 837 getChunk(ochunk, target, Output()); 838 839 TTargetSize minChunkSize = std::min((TTargetSize)length(ichunk), (TTargetSize)length(ochunk)); 840 841 if (SEQAN_UNLIKELY(minChunkSize == 0u)) 842 { 843 reserveChunk(target, n, Output()); 844 reserveChunk(iter, n, Input()); 845 getChunk(ochunk, target, Output()); 846 getChunk(ichunk, iter, Input()); 847 minChunkSize = std::min((TTargetSize)length(ichunk), (TTargetSize)length(ochunk)); 848 if (SEQAN_UNLIKELY(minChunkSize == 0u)) 849 { 850 _write(target, iter, n, TNoChunking(), TNoChunking()); 851 return; 852 } 853 } 854 855 if (minChunkSize > (TTargetSize)n) 856 minChunkSize = (TTargetSize)n; 857 858 arrayCopyForward(ichunk.begin, ichunk.begin + minChunkSize, ochunk.begin); 859 860 iter += minChunkSize; // advance input iterator 861 advanceChunk(target, minChunkSize); 862 n -= minChunkSize; 863 } 864 } 865 866 // chunked, target is pointer (e.g. readRawPod) 867 template <typename TOValue, typename TFwdIterator, typename TSize> 868 inline SEQAN_FUNC_DISABLE_IF(IsSameType<typename Chunk<TFwdIterator>::Type, Nothing>, void) 869 write(TOValue *ptr, TFwdIterator &iter, TSize n) 870 { 871 typedef Nothing* TNoChunking; 872 typedef typename Size<TFwdIterator>::Type TSourceSize; 873 typedef typename Chunk<TFwdIterator>::Type TIChunk; 874 875 TIChunk ichunk; 876 877 while (n != (TSize)0) 878 { 879 getChunk(ichunk, iter, Input()); 880 TSourceSize chunkSize = length(ichunk); 881 882 if (SEQAN_UNLIKELY(chunkSize == 0u)) 883 { 884 reserveChunk(iter, n, Input()); 885 getChunk(ichunk, iter, Input()); 886 TSourceSize chunkSize = length(ichunk); 887 if (SEQAN_UNLIKELY(chunkSize == 0u)) 888 { 889 _write(ptr, iter, n, TNoChunking(), TNoChunking()); 890 return; 891 } 892 } 893 894 if (chunkSize > (TSourceSize)n) 895 chunkSize = (TSourceSize)n; 896 897 arrayCopyForward(ichunk.begin, ichunk.begin + chunkSize, ptr); 898 899 iter += chunkSize; // advance input iterator 900 ptr += chunkSize; 901 n -= chunkSize; 902 } 903 } 904 905 // non-chunked fallback 906 template <typename TTarget, typename TIValue, typename TSize> 907 inline SEQAN_FUNC_ENABLE_IF(And< IsSameType<typename Chunk<TTarget>::Type, Nothing>, 908 Is<Convertible<typename Value<TTarget>::Type, TIValue> > >, void) 909 write(TTarget &target, TIValue *ptr, TSize n) 910 { 911 _write(target, ptr, n, Nothing(), Nothing()); 912 } 913 914 // ostream shortcut, source is pointer (e.g. readRawPod) 915 template <typename TTarget, typename TSize> 916 inline SEQAN_FUNC_ENABLE_IF(Is< OutputStreamConcept<TTarget> >, void) 917 write(TTarget &target, const char *ptr, TSize n) 918 { 919 target.write(ptr, n); 920 } 921 922 // ostream shortcut, source is pointer (e.g. readRawPod) 923 template <typename TTarget, typename TSize> 924 inline SEQAN_FUNC_ENABLE_IF(Is< OutputStreamConcept<TTarget> >, void) 925 write(TTarget &target, char *ptr, TSize n) 926 { 927 target.write(ptr, n); 928 } 929 930 // chunked, source is pointer (e.g. readRawPod) 931 template <typename TTarget, typename TIValue, typename TSize> 932 inline SEQAN_FUNC_ENABLE_IF(And< Not<IsSameType<typename Chunk<TTarget>::Type, Nothing> >, 933 Is<Convertible<typename Value<TTarget>::Type, TIValue> > >, void) 934 write(TTarget &target, TIValue *ptr, TSize n) 935 { 936 typedef Nothing* TNoChunking; 937 typedef typename Size<TTarget>::Type TTargetSize; 938 typedef typename Chunk<TTarget>::Type TOChunk; 939 940 TOChunk ochunk; 941 942 while (n != (TSize)0) 943 { 944 getChunk(ochunk, target, Output()); 945 TTargetSize chunkSize = length(ochunk); 946 947 if (SEQAN_UNLIKELY(chunkSize == 0u)) 948 { 949 reserveChunk(target, n, Output()); 950 getChunk(ochunk, target, Output()); 951 chunkSize = length(ochunk); 952 if (SEQAN_UNLIKELY(chunkSize == 0u)) 953 { 954 _write(target, ptr, n, TNoChunking(), TNoChunking()); 955 return; 956 } 957 } 958 959 if (chunkSize > (TTargetSize)n) 960 chunkSize = (TTargetSize)n; 961 962 arrayCopyForward(ptr, ptr + chunkSize, ochunk.begin); 963 964 ptr += chunkSize; // advance input iterator 965 advanceChunk(target, chunkSize); 966 n -= chunkSize; 967 } 968 } 969 970 template <typename TOValue, typename TIValue, typename TSize> 971 inline SEQAN_FUNC_ENABLE_IF(And< Is<CharConcept<TOValue> >, 972 Is<CharConcept<TIValue> > >, void) 973 write(TOValue * &optr, TIValue *iptr, TSize n) 974 { 975 std::memcpy(optr, iptr, n); 976 optr += n; 977 } 978 979 template <typename TOValue, typename TIValue, typename TSize> 980 inline SEQAN_FUNC_ENABLE_IF(And< Is<CharConcept<TOValue> >, 981 Is<CharConcept<TIValue> > >, void) 982 write(TOValue * optr, TIValue * &iptr, TSize n) 983 { 984 std::memcpy(optr, iptr, n); 985 iptr += n; 986 } 987 988 // ---------------------------------------------------------------------------- 989 // Function write(TValue *) 990 // ---------------------------------------------------------------------------- 991 // NOTE(esiragusa): should it be defined for Streams and Containers? 992 993 //template <typename TTarget, typename TValue, typename TSize> 994 //inline SEQAN_FUNC_ENABLE_IF(Or<Is<OutputStreamConcept<TTarget> >, Is<ContainerConcept<TTarget> > >, void) 995 //write(TTarget &target, TValue *ptr, TSize n) 996 //{ 997 // typedef Range<TValue*> TRange; 998 // typedef typename Iterator<TRange, Rooted>::Type TIterator; 999 // typedef typename Chunk<TIterator>::Type* TIChunk; 1000 // typedef typename Chunk<TTarget>::Type* TOChunk; 1001 // 1002 // TRange range(ptr, ptr + n); 1003 // TIterator iter = begin(range, Rooted()); 1004 // _write(target, iter, n, TIChunk(), TOChunk()); 1005 //} 1006 1007 // ---------------------------------------------------------------------------- 1008 // Function write(Iterator<Input>) 1009 // ---------------------------------------------------------------------------- 1010 1011 /*! 1012 * @fn ContainerConcept#write 1013 * @brief Write to a container. 1014 * 1015 * @signature void write(container, iter, n); 1016 * 1017 * @param[in,out] container The container to append to. 1018 * @param[in,out] iter The @link ForwardIteratorConcept forward iterator @endlink to take the values from. 1019 * @param[in] n Number of elements to write from <tt>iter</tt>. 1020 * 1021 * This function reads <tt>n</tt> values from <tt>iter</tt> and appends them to the back of <tt>container</tt>. 1022 */ 1023 1024 //TODO(singer): Enable this! 1025 template <typename TTarget, typename TFwdIterator, typename TSize> 1026 //inline SEQAN_FUNC_ENABLE_IF(Or<Is<OutputStreamConcept<TTarget> >, Is<ContainerConcept<TTarget> > >, void) 1027 inline SEQAN_FUNC_ENABLE_IF(And< Is<IntegerConcept<TSize> >, 1028 Is<Convertible<typename Value<TTarget>::Type, 1029 typename Value<TFwdIterator>::Type> > >, void) 1030 write(TTarget &target, TFwdIterator &iter, TSize n) 1031 { 1032 typedef typename Chunk<TFwdIterator>::Type* TIChunk; 1033 typedef typename Chunk<TTarget>::Type* TOChunk; 1034 1035 _write(target, iter, n, TIChunk(), TOChunk()); 1036 } 1037 1038 // write for more complex values (defer to write of iterator value) 1039 // used for Strings of Pairs 1040 template <typename TTarget, typename TFwdIterator, typename TSize> 1041 //inline SEQAN_FUNC_ENABLE_IF(Or<Is<OutputStreamConcept<TTarget> >, Is<ContainerConcept<TTarget> > >, void) 1042 inline SEQAN_FUNC_ENABLE_IF(And< 1043 Is<IntegerConcept<TSize> >, 1044 Not< Is<Convertible<typename Value<TTarget>::Type, 1045 typename Value<TFwdIterator>::Type> > > >, void) 1046 write(TTarget &target, TFwdIterator &iter, TSize n) 1047 { 1048 for (; n > (TSize)0; --n, ++iter) 1049 { 1050 write(target, *iter); 1051 writeValue(target, ' '); 1052 } 1053 } 1054 1055 // ---------------------------------------------------------------------------- 1056 // Function write(TContainer) but not container of container 1057 // ---------------------------------------------------------------------------- 1058 1059 template <typename TTarget, typename TContainer> 1060 inline SEQAN_FUNC_ENABLE_IF(And< Not<IsContiguous<TContainer> >, 1061 And< Is<ContainerConcept<TContainer> >, 1062 Not<Is<ContainerConcept<typename Value<TContainer>::Type> > > > >, void) 1063 write(TTarget &target, TContainer &cont) 1064 { 1065 typename DirectionIterator<TContainer, Input>::Type iter = directionIterator(cont, Input()); 1066 write(target, iter, length(cont)); 1067 } 1068 1069 template <typename TTarget, typename TContainer> 1070 inline SEQAN_FUNC_ENABLE_IF(And< IsContiguous<TContainer>, 1071 And< Is<ContainerConcept<TContainer> >, 1072 Not<Is<ContainerConcept<typename Value<TContainer>::Type> > > > >, void) 1073 write(TTarget &target, TContainer &cont) 1074 { 1075 typename Iterator<TContainer, Standard>::Type iter = begin(cont, Standard()); 1076 write(target, iter, length(cont)); 1077 } 1078 1079 template <typename TTarget, typename TContainer> 1080 inline SEQAN_FUNC_ENABLE_IF(And< Not<IsContiguous<TContainer> >, 1081 And< Is<ContainerConcept<TContainer> >, 1082 Not<Is<ContainerConcept<typename Value<TContainer>::Type> > > > >, void) 1083 write(TTarget &target, TContainer const &cont) 1084 { 1085 typename DirectionIterator<TContainer const, Input>::Type iter = directionIterator(cont, Input()); 1086 write(target, iter, length(cont)); 1087 } 1088 1089 template <typename TTarget, typename TContainer> 1090 inline SEQAN_FUNC_ENABLE_IF(And< IsContiguous<TContainer>, 1091 And< Is<ContainerConcept<TContainer> >, 1092 Not<Is<ContainerConcept<typename Value<TContainer>::Type> > > > >, void) 1093 write(TTarget &target, TContainer const &cont) 1094 { 1095 typename Iterator<TContainer const, Standard>::Type iter = begin(cont, Standard()); 1096 write(target, iter, length(cont)); 1097 } 1098 1099 template <typename TTarget, typename TValue> 1100 inline void 1101 write(TTarget &target, TValue * ptr) 1102 { 1103 write(target, ptr, length(ptr)); 1104 } 1105 1106 // ---------------------------------------------------------------------------- 1107 // Function appendNumber() 1108 // ---------------------------------------------------------------------------- 1109 // Generic version for integers. 1110 1111 template <typename TTarget, typename TInteger> 1112 inline SEQAN_FUNC_ENABLE_IF(Is<IntegerConcept<TInteger> >, typename Size<TTarget>::Type) 1113 appendNumber(TTarget & target, TInteger i) 1114 { 1115 typedef IntegerFormatString_<typename Is<UnsignedIntegerConcept<TInteger> >::Type, 1116 sizeof(TInteger)> TInt; 1117 1118 // 1 byte has at most 3 decimal digits (plus 2 for '-' and the NULL character) 1119 char buffer[sizeof(TInteger) * 3 + 2]; 1120 size_t len = snprintf(buffer, sizeof(buffer), 1121 TInt::VALUE, static_cast<typename TInt::Type>(i)); 1122 char *bufPtr = buffer; 1123 write(target, bufPtr, len); 1124 return len; 1125 } 1126 1127 // ---------------------------------------------------------------------------- 1128 // Function appendNumber(bool) 1129 // ---------------------------------------------------------------------------- 1130 1131 template <typename TTarget> 1132 inline typename Size<TTarget>::Type 1133 appendNumber(TTarget & target, bool source) 1134 { 1135 writeValue(target, '0' + source); 1136 return 1; 1137 } 1138 1139 // ---------------------------------------------------------------------------- 1140 // Function appendNumber(float) 1141 // ---------------------------------------------------------------------------- 1142 1143 template <typename TTarget> 1144 inline typename Size<TTarget>::Type 1145 appendNumber(TTarget & target, float source) 1146 { 1147 char buffer[32]; 1148 size_t len = snprintf(buffer, sizeof(buffer), "%g", source); 1149 write(target, (char *)buffer, len); 1150 return len; 1151 } 1152 1153 // ---------------------------------------------------------------------------- 1154 // Function appendNumber(double) 1155 // ---------------------------------------------------------------------------- 1156 1157 template <typename TTarget> 1158 inline typename Size<TTarget>::Type 1159 appendNumber(TTarget & target, double source) 1160 { 1161 char buffer[32]; 1162 size_t len = snprintf(buffer, sizeof(buffer), "%g", source); 1163 write(target, (char *)buffer, len); 1164 return len; 1165 } 1166 1167 // ---------------------------------------------------------------------------- 1168 // Function appendNumber(double) 1169 // ---------------------------------------------------------------------------- 1170 1171 template <typename TTarget, typename TValue> 1172 inline typename Size<TTarget>::Type 1173 appendNumber(TTarget & target, FormattedNumber<TValue> const & source) 1174 { 1175 char buffer[100]; 1176 size_t len = snprintf(buffer, sizeof(buffer), source.format, source.value); 1177 write(target, (char *)buffer, len); 1178 return len; 1179 } 1180 1181 template <typename TValue> 1182 inline FormattedNumber<TValue> 1183 formattedNumber(const char *format, TValue const & val) 1184 { 1185 return FormattedNumber<TValue>(format, val); 1186 } 1187 1188 // ---------------------------------------------------------------------------- 1189 // Function appendRawPod() 1190 // ---------------------------------------------------------------------------- 1191 1192 template <typename TTarget, typename TValue> 1193 inline void 1194 appendRawPodImpl(TTarget & target, TValue const & val) 1195 { 1196 write(target, (unsigned char*)&val, sizeof(TValue)); 1197 } 1198 1199 template <typename TTargetValue, typename TValue> 1200 inline void 1201 appendRawPodImpl(TTargetValue * &ptr, TValue const & val) 1202 { 1203 *reinterpret_cast<TValue* &>(ptr)++ = val; 1204 } 1205 1206 template <typename TTarget, typename TValue> 1207 inline std::enable_if_t<std::is_arithmetic<TValue>::value> 1208 appendRawPod(TTarget & target, TValue val) 1209 { 1210 enforceLittleEndian(val); 1211 appendRawPodImpl(target, val); 1212 } 1213 1214 template <typename TTarget, typename TValue> 1215 inline std::enable_if_t<!std::is_arithmetic<TValue>::value> 1216 appendRawPod(SEQAN_UNUSED TTarget & target, SEQAN_UNUSED TValue const & val) 1217 { 1218 #if SEQAN_BIG_ENDIAN 1219 static_assert(std::is_arithmetic<TValue>::value /*false*/, 1220 "You are serialising a data structure on big endian architecture that needs a custom writer. THIS IS A BUG!"); 1221 #else 1222 appendRawPodImpl(target, val); 1223 #endif 1224 } 1225 1226 // ---------------------------------------------------------------------------- 1227 // Function write(TNumber); write fundamental type 1228 // ---------------------------------------------------------------------------- 1229 1230 template <typename TTarget, typename TValue> 1231 inline SEQAN_FUNC_ENABLE_IF(And< Is<Convertible<typename Value<TTarget>::Type, TValue> >, 1232 Is<FundamentalConcept<TValue> > >, void) 1233 write(TTarget &target, TValue &number) 1234 { 1235 if (sizeof(TValue) == 1) 1236 writeValue(target, number); // write chars as chars 1237 else 1238 appendNumber(target, number); 1239 } 1240 1241 template <typename TTarget, typename TValue> 1242 inline SEQAN_FUNC_ENABLE_IF(And< Is<Convertible<typename Value<TTarget>::Type, TValue> >, 1243 Is<FundamentalConcept<TValue> > >, void) 1244 write(TTarget &target, TValue const &number) 1245 { 1246 if (sizeof(TValue) == 1) 1247 writeValue(target, number); // write chars as chars 1248 else 1249 appendNumber(target, number); 1250 } 1251 1252 // ---------------------------------------------------------------------------- 1253 // Function write(TNumber); write non-fundamental, convertible type 1254 // ---------------------------------------------------------------------------- 1255 1256 template <typename TTarget, typename TValue> 1257 inline SEQAN_FUNC_ENABLE_IF(And< Is<Convertible<typename Value<TTarget>::Type, TValue> >, 1258 Not<Is<FundamentalConcept<TValue> > > >, void) 1259 write(TTarget &target, TValue &number) 1260 { 1261 writeValue(target, number); 1262 } 1263 1264 template <typename TTarget, typename TValue> 1265 inline SEQAN_FUNC_ENABLE_IF(And< Is<Convertible<typename Value<TTarget>::Type, TValue const> >, 1266 Not<Is<FundamentalConcept<TValue const> > > >, void) 1267 write(TTarget &target, TValue const &number) 1268 { 1269 writeValue(target, number); 1270 } 1271 1272 // ---------------------------------------------------------------------------- 1273 // Function read(Iterator<Input>) 1274 // ---------------------------------------------------------------------------- 1275 1276 template <typename TTarget, typename TFwdIterator, typename TSize> 1277 inline SEQAN_FUNC_ENABLE_IF(Is<IntegerConcept<TSize> >, TSize) 1278 read(TTarget &target, TFwdIterator &iter, TSize n) 1279 { 1280 TSize i; 1281 for (i = 0; !atEnd(iter) && i < n; ++i, ++iter) 1282 writeValue(target, *iter); 1283 return i; 1284 } 1285 1286 // ---------------------------------------------------------------------------- 1287 // Function read(TContainer) 1288 // ---------------------------------------------------------------------------- 1289 1290 template <typename TTarget, typename TContainer> 1291 inline typename Size<TTarget>::Type 1292 read(TTarget &target, TContainer &cont) 1293 { 1294 typename DirectionIterator<TContainer, Input>::Type iter = directionIterator(cont, Input()); 1295 return read(target, iter, length(cont)); 1296 } 1297 1298 // ---------------------------------------------------------------------------- 1299 // operator<< 1300 // ---------------------------------------------------------------------------- 1301 1302 template <typename TStream, typename TIterator> 1303 inline TStream & 1304 operator<<(TStream & target, 1305 Range<TIterator> const & source) 1306 { 1307 typename DirectionIterator<TStream, Output>::Type it = directionIterator(target, Output()); 1308 write(it, source); 1309 return target; 1310 } 1311 1312 template <typename TStream, typename TValue> 1313 inline TStream & 1314 operator<<(TStream & target, 1315 FormattedNumber<TValue> const & source) 1316 { 1317 typename DirectionIterator<TStream, Output>::Type it = directionIterator(target, Output()); 1318 write(it, source); 1319 return target; 1320 } 1321 1322 } // namespace seqean 1323 1324 #endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_STREAM_H_ 1325