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: Andreas Gogol-Döring <andreas.doering@mdc-berlin.de> 33 // Author: David Weese <david.weese@fu-berlin.de> 34 // ========================================================================== 35 // Global (future: generic) tag definitions. 36 // ========================================================================== 37 38 // TODO(holtgrew): This should probably be minimalized, tags should be moved to single modules whenever possible. 39 40 #ifndef SEQAN_BASIC_BASIC_TAGS_H_ 41 #define SEQAN_BASIC_BASIC_TAGS_H_ 42 43 namespace seqan { 44 45 // ============================================================================ 46 // Forwards 47 // ============================================================================ 48 49 // ============================================================================ 50 // Tags, Classes, Enums 51 // ============================================================================ 52 53 // ---------------------------------------------------------------------------- 54 // Tag Tag<T> 55 // ---------------------------------------------------------------------------- 56 57 /*! 58 * @class Tag 59 * @headerfile <seqan/basic.h> 60 * @brief Template for tag definition. 61 * 62 * @signature template <typename T> 63 * struct Tag; 64 * 65 * @tparam T Any parameterless types. 66 * 67 * This <tt>struct</tt> is defined such that parameter less tags are easier recognizeable. This is best explained with 68 * the example below. 69 * 70 * @section Examples 71 * 72 * Usually, tags are defined in the following way. 73 * 74 * @code{.cpp} 75 * struct SomeTag_; 76 * typedef Tag<SomeTag_> SomeTag; 77 * @endcode 78 * 79 * They are then used as follows. 80 * 81 * @code{.cpp} 82 * template <typename T> 83 * void f(T const & x, SomeTag const & tag) 84 * { 85 * // ... 86 * } 87 * 88 * // Somewhere else: 89 * f(3, SomeTag()); 90 * @endcode 91 * 92 * This has the advantages that (1) the type of tag parameters is printed as <tt>Tag<SomeTag_></tt> in compiler error 93 * traces. Furthermore, (2) parameter less tags can be defined redundantly in multiple headers and we can still 94 * instantiate them anywhere where they are declared. The latter (2) cannot be achieved with only forward declaration 95 * (<tt>struct SomeTag;</tt>) or full declarations (<tt>struct SomeTag {};</tt>) everywhere. 96 */ 97 98 template <typename T> 99 struct Tag {}; 100 101 // ---------------------------------------------------------------------------- 102 // Tag Default 103 // ---------------------------------------------------------------------------- 104 105 /*! 106 * @tag Default 107 * @headerfile <seqan/basic.h> 108 * @brief Tag that specifies default behaviour. 109 * 110 * @signature typedef Tag<Default_> Default; 111 */ 112 113 struct Default_; 114 typedef Tag<Default_> Default; 115 116 // ---------------------------------------------------------------------------- 117 // Tag Nothing 118 // ---------------------------------------------------------------------------- 119 120 // TODO(holtgrew): Should use Tag<>. 121 122 /*! 123 * @tag Nothing 124 * @headerfile <seqan/basic.h> 125 * @brief Tag tha trepresents an absent parameter or absent type. 126 * 127 * @signature struct Nothing {}; 128 */ 129 130 struct Nothing_; 131 typedef Tag<Nothing_> Nothing; 132 133 // -------------------------------------------------------------------------- 134 // Tag Raw 135 // -------------------------------------------------------------------------- 136 137 struct Raw_; 138 typedef Tag<Raw_> Raw; 139 140 // ---------------------------------------------------------------------------- 141 // Tag Move 142 // ---------------------------------------------------------------------------- 143 144 // TODO(holtgrew): This should probably go into basic_transport.h. 145 146 /*! 147 * @tag Move 148 * @headerfile <seqan/align.h> 149 * @brief Switch to force move. 150 * 151 * @signature typedef Tag<Move_> Move; 152 * 153 * The difference between move constructor and copy constructor is that the source object is not copied but moved into 154 * the target object. The source object can lose its content and will be empty after this operation in this case. A 155 * move constructor can sigificantly faster than a copy constructor. 156 * 157 * @section Examples 158 * 159 * @code{.cpp} 160 * String source("hello"); 161 * String target(source, Move()); // source is moved to target 162 * std::cout << source; //nothing printed since source lost content 163 * std::cout << target; //"hello" 164 * @endcode 165 * 166 * Move constructors are like copy-constructors. However, their argument is not const. 167 * 168 * @code{.cpp} 169 * class Klass 170 * { 171 * public: 172 * seqan::String m; 173 * 174 * // Copy constructor, other is left untouched. 175 * Klass(Klass const & other) { ... } 176 * 177 * // Move constructor, leaves other and its members in an "empty" state. 178 * Klass(Klass & other, seqan::Move const &) { ... } 179 * }; 180 * @endcode 181 * 182 * @see AssignableConcept#move 183 */ 184 185 struct Move_; 186 typedef Tag<Move_> Move; 187 188 // ---------------------------------------------------------------------------- 189 // Tag MinimalCtor 190 // ---------------------------------------------------------------------------- 191 192 // TODO(holtgrew): This should go into initialization part of alphabet header set. 193 194 //construct without initializing 195 struct MinimalCtor_; 196 typedef Tag<MinimalCtor_> MinimalCtor; 197 198 // ---------------------------------------------------------------------------- 199 // Tag MinimalCtor 200 // ---------------------------------------------------------------------------- 201 202 // TODO(holtgrew): This should go into initialization part of alphabet header set. 203 204 //construct with initializing 205 struct NonMinimalCtor_; 206 typedef Tag<NonMinimalCtor_> NonMinimalCtor; 207 208 // ---------------------------------------------------------------------------- 209 // Tag MinimalCtor 210 // ---------------------------------------------------------------------------- 211 212 // TODO(holtgrew): This should go into the iterators header set? 213 214 //Pass to c'tor of iterator to move it to the end 215 struct GoEnd_; 216 typedef Tag<GoEnd_> GoEnd; 217 218 // ---------------------------------------------------------------------------- 219 // Tag Serial 220 // ---------------------------------------------------------------------------- 221 222 struct Serial_; 223 typedef Tag<Serial_> Serial; 224 225 // ---------------------------------------------------------------------------- 226 // Tag TagList<TTag, TNext> 227 // ---------------------------------------------------------------------------- 228 229 /*! 230 * @class TagList 231 * @headerfile <seqan/basic.h> 232 * @brief A structure to represent a list of tags. 233 * 234 * @signature template <[typename TTag[, typename TSubList]]> 235 * struct TagList; 236 * 237 * @tparam TTag The tag of the front for the list. 238 * @tparam TSubList Nested list. 239 */ 240 241 template <typename TTag = void, typename TSubList = void> 242 struct TagList 243 { 244 typedef TTag Type; 245 }; 246 247 // ---------------------------------------------------------------------------- 248 // Class TagSelector 249 // ---------------------------------------------------------------------------- 250 251 /*! 252 * @class TagSelector 253 * @headerfile <seqan/basic.h> 254 * @brief A structure to select a tag from a @link TagList @endlink. 255 * 256 * @signature template <typename TTagList> 257 * struct TagSelector; 258 * 259 * @tparam TTagList A tag list. 260 */ 261 262 /*! 263 * @var T TagSelector::tagId 264 * @headerfile <seqan/basic.h> 265 * @brief Stores the index of a Tag in the tag list. 266 */ 267 268 template <typename TTagList = void> 269 struct TagSelector 270 { 271 int tagId; 272 TagSelectorTagSelector273 TagSelector() : 274 tagId(-1) {} // -1 is an important initialization to signal a not yet selected tag (used for file format auto-detection) 275 276 inline bool 277 operator==(TagSelector const & other) const 278 { 279 return other.tagId == tagId; 280 } 281 }; 282 283 template <typename TTag, typename TSubList> 284 struct TagSelector< TagList<TTag, TSubList> > 285 : TagSelector<TSubList> 286 { 287 typedef TTag Type; 288 typedef TagSelector<TSubList> Base; 289 }; 290 291 292 template <typename TTagList> 293 struct Value<TagSelector<TTagList> > 294 { 295 typedef int Type; 296 }; 297 298 template <typename TTagList> 299 inline typename Reference<TagSelector<TTagList> >::Type 300 value(TagSelector<TTagList> &selector) 301 { 302 return selector.tagId; 303 } 304 305 template <typename TTagList> 306 inline typename Reference<TagSelector<TTagList> const>::Type 307 value(TagSelector<TTagList> const &selector) 308 { 309 return selector.tagId; 310 } 311 312 // ---------------------------------------------------------------------------- 313 // Tag DotDrawing 314 // ---------------------------------------------------------------------------- 315 316 // TODO(holtgrew): Should probably not be defined here. 317 318 /*! 319 * @tag DotDrawing 320 * @headerfile <seqan/basic.h> 321 * @brief Switch to trigger drawing in dot format. 322 * 323 * @signature typedef Tag<DotDrawing_> DotDrawing; 324 */ 325 326 struct DotDrawing_; 327 typedef Tag<DotDrawing_> DotDrawing; 328 329 // TODO(holtgrew): Should probably not be defined here. 330 // TODO(holtgrew): Are these used at all? 331 332 /*! 333 * @tag HammingDistance 334 * @headerfile <seqan/basic.h> 335 * @brief Hamming distance. 336 * 337 * @signature typedef Tag<HammingDistance_> HammingDistance; 338 */ 339 340 // TODO(holtgrew): Why ambiguous here? Edit distance is the more common name. 341 342 /*! 343 * @tag LevenshteinDistance 344 * @headerfile <seqan/basic.h> 345 * @brief Levenshtein distance. 346 * 347 * @signature typedef Tag<LevenshteinDistance_> LevenshteinDistance; 348 */ 349 350 /*! 351 * @tag EditDistance 352 * @headerfile <seqan/basic.h> 353 * @brief Edit distance. 354 * 355 * @signature typedef Tag<LevenshteinDistance_> EditDistance; 356 */ 357 358 struct HammingDistance_; 359 struct LevenshteinDistance_; 360 361 typedef Tag<HammingDistance_> HammingDistance; 362 typedef Tag<LevenshteinDistance_> LevenshteinDistance; 363 typedef Tag<LevenshteinDistance_> EditDistance; 364 365 366 // ---------------------------------------------------------------------------- 367 // Tag Blat 368 // ---------------------------------------------------------------------------- 369 370 // TODO(holtgrew): Should probably not be defined here. 371 372 struct Blat_; 373 typedef Tag<Blat_> Blat; 374 375 // ============================================================================ 376 // Metafunctions 377 // ============================================================================ 378 379 // ---------------------------------------------------------------------------- 380 // Metafunction LENGTH for TagLists 381 // ---------------------------------------------------------------------------- 382 383 /*! 384 * @mfn TagList#LENGTH 385 * @brief Return the length of a tag list. 386 * 387 * @signature LENGTH<TTagList>::VALUE; 388 * 389 * @tparam TTagList The TagList to query for its length. 390 * 391 * @return VALUE The length of the TagList. 392 */ 393 394 template <> 395 struct LENGTH<void> 396 { 397 enum { VALUE = 0 }; 398 }; 399 400 template <typename TTag> 401 struct LENGTH<TagList<TTag, void> > 402 { 403 enum { VALUE = 1 }; 404 }; 405 406 template <typename TTag, typename TSubList> 407 struct LENGTH<TagList<TTag, TSubList> > 408 { 409 enum { VALUE = LENGTH<TSubList>::VALUE + 1 }; 410 }; 411 412 // ---------------------------------------------------------------------------- 413 // Metafunction TagListValue 414 // ---------------------------------------------------------------------------- 415 416 /*! 417 * @mfn TagList#TagListValue 418 * @brief A metafunction to retrieve a tag from a TagList. 419 * 420 * @signature TagListValue<TagList, TAG_ID>::Type; 421 * 422 * @tparam TagList The TagList to query. 423 * @tparam TAG_ID An index of a tag in the tag list (<tt>int</tt>. This value must be in 424 * <tt>0..LENGTH<TTagList>::VALUE -1</tt>. 425 */ 426 427 template <typename TList, int I> 428 struct TagListValue 429 { 430 typedef void Type; 431 }; 432 433 template <typename TTag, typename TSubList, int I> 434 struct TagListValue<TagList<TTag, TSubList>, I>: 435 public If<Eval<I == LENGTH<TSubList>::VALUE>, 436 TTag, 437 typename TagListValue<TSubList, I>::Type> {}; 438 439 //template <typename TTag, typename TSubList, int I> 440 //struct TagListValue<TagList<TTag, TSubList>, I> : 441 // public typename TagListValue<TSubList, I - 1> {}; 442 // 443 //template <typename TTagList, int I> 444 //struct TagListValue<TagSelector<TTagList>, I> : 445 // public typename TagListValue<TTagList, I> {}; 446 447 // ---------------------------------------------------------------------------- 448 // Metafunction Find 449 // ---------------------------------------------------------------------------- 450 451 /*! 452 * @mfn Find 453 * @headerfile <seqan/basic.h> 454 * @brief A metafunction to retrieve the index of a tag in the TagList. 455 * 456 * @signature Find<TTagList, TSearchTag>::VALUE; 457 * 458 * @tparam TSearchTag A tag to retrieve the index of. 459 * @tparam TTagList A tag list. 460 * 461 * @return VALUE This meta-function can be used to test whether the value of a TagSelector equals a specific tag. 462 * 463 * @section Examples 464 * 465 * @code{.cpp} 466 * AutoSeqFormat format; 467 * if (format.tagId == Find<AutoSeqFormat, Fasta>::VALUE) 468 * { 469 * // do something specific to Fasta format 470 * } 471 * 472 * // or even shorter: 473 * 474 * if (isEqual(format.tagId, Fasta())) 475 * { 476 * // do something specific to Fasta format 477 * } 478 * @endcode 479 */ 480 481 template <typename TList, typename TSearchTag> 482 struct Find; 483 484 template <typename TTag, typename TSearchTag> 485 struct Find<TagList<TTag, void>, TSearchTag> 486 { 487 enum { VALUE = -1 }; // not found 488 }; 489 490 template <typename TSearchTag> 491 struct Find<TagList<TSearchTag, void>, TSearchTag> 492 { 493 enum { VALUE = 0 }; 494 }; 495 496 template <typename TTag, typename TSubList, typename TSearchTag> 497 struct Find<TagList<TTag, TSubList>, TSearchTag> 498 { 499 enum { VALUE = Find<TSubList, TSearchTag>::VALUE }; 500 }; 501 502 template <typename TSubList, typename TSearchTag> 503 struct Find<TagList<TSearchTag, TSubList>, TSearchTag> 504 { 505 enum { VALUE = LENGTH<TSubList>::VALUE }; 506 }; 507 508 template <typename TTagList, typename TSearchTag> 509 struct Find<TagSelector<TTagList>, TSearchTag>: 510 public Find<TTagList, TSearchTag> {}; 511 512 template <typename TTagList, typename TSearchTag> 513 inline int find(TagSelector<TTagList> const &, TSearchTag const &) 514 { 515 return Find<TTagList, TSearchTag>::VALUE; 516 } 517 518 // ============================================================================ 519 // Functions 520 // ============================================================================ 521 522 // isEqual() 523 template <typename TTagList, typename TTag> 524 inline bool isEqual(TagSelector<TTagList> const &selector, TTag const &) 525 { 526 return selector.tagId == Find<TTagList, TTag>::VALUE; 527 } 528 529 /*! 530 * @fn TagSelector#tagSelectIntersect 531 * @brief Selects a tag in a @link TagSelector @endlink based on the selected tag of another TagSelector if that same tag exists in the destination. 532 * 533 * @signature bool tagSelectIntersect(outTagList, inTagList); 534 * 535 * @param[out] outTagList The @link TagSelector @endlink file format a tag will be selected for 536 * @param[in] inTagList The @link TagSelector @endlink object where to read the sequence information into. 537 * 538 * @return VALUE <tt>true</tt> if the selected tag of inTagList is available in outTagList and <tt>false</tt> otherwise. 539 */ 540 541 template <typename TagSpec> 542 inline bool tagSelectIntersect(TagSelector<> &, Tag<TagSpec> const &) 543 { 544 return false; 545 } 546 547 template <typename TOutTagList, typename TagSpec> 548 inline bool tagSelectIntersect(TagSelector<TOutTagList> & outTagList, Tag<TagSpec> const & inTag) 549 { 550 typedef typename TOutTagList::Type TFormat; 551 552 SEQAN_IF_CONSTEXPR (IsSameType<Tag<TagSpec>, TFormat>::VALUE) 553 { 554 outTagList.tagId = LENGTH<TOutTagList>::VALUE - 1; 555 return true; 556 } 557 else 558 { 559 return tagSelectIntersect(static_cast<typename TagSelector<TOutTagList>::Base & >(outTagList), inTag); 560 } 561 } 562 563 template <typename TOutTagList> 564 inline bool tagSelectIntersect(TagSelector<TOutTagList> & outTagList, TagSelector<> const &) 565 { 566 outTagList.tagId = -1; 567 return true; 568 } 569 570 template <typename TOutTagList, typename TInTagList> 571 inline bool tagSelectIntersect(TagSelector<TOutTagList> & outTagList, TagSelector<TInTagList> const & inTagList) 572 { 573 typedef typename TInTagList::Type TFormat; 574 575 if (isEqual(inTagList, TFormat())) 576 { 577 return tagSelectIntersect(outTagList, TFormat()); 578 } 579 else 580 { 581 return tagSelectIntersect(outTagList, static_cast<typename TagSelector<TInTagList>::Base const & >(inTagList)); 582 } 583 } 584 585 // assign() 586 template <typename TTagList, typename TTag> 587 inline void assign(TagSelector<TTagList> &selector, TTag &) 588 { 589 SEQAN_ASSERT_NEQ(int(Find<TTagList, TTag>::VALUE), -1); 590 selector.tagId = Find<TTagList, TTag>::VALUE; 591 } 592 593 template <typename TTagList, typename TTag> 594 inline void assign(TagSelector<TTagList> &selector, TTag const &) 595 { 596 SEQAN_ASSERT_NEQ(int(Find<TTagList, TTag>::VALUE), -1); 597 selector.tagId = Find<TTagList, TTag>::VALUE; 598 } 599 600 template <typename TTagList> 601 inline void assign(TagSelector<TTagList> &selector, TagSelector<TTagList> &other) 602 { 603 selector.tagId = other.tagId; 604 } 605 606 template <typename TTagList> 607 inline void assign(TagSelector<TTagList> &selector, TagSelector<TTagList> const &other) 608 { 609 selector.tagId = other.tagId; 610 } 611 612 // -------------------------------------------------------------------------- 613 // Function tagApply() 614 // -------------------------------------------------------------------------- 615 616 template <typename TFunctor, typename TTag> 617 inline bool 618 tagApply(TFunctor &func, TagList<TTag>) 619 { 620 return func(TTag()); 621 } 622 623 template <typename TFunctor, typename TTag, typename TSubList> 624 inline bool 625 tagApply(TFunctor &func, TagList<TTag, TSubList>) 626 { 627 if (func(TTag())) 628 return true; 629 return tagApply(func, TSubList()); 630 } 631 632 // -------------------------------------------------------------------------- 633 // Function tagApply() 634 // -------------------------------------------------------------------------- 635 636 template <typename TContext> 637 inline typename Value<TContext>::Type 638 tagApply(TContext &, TagSelector<>) 639 { 640 return typename Value<TContext>::Type(); 641 } 642 643 template <typename TContext, typename TTagList> 644 inline typename Value<TContext>::Type 645 tagApply(TContext &ctx, TagSelector<TTagList> &format) 646 { 647 typedef typename TTagList::Type TFormatTag; 648 649 if (isEqual(format, TFormatTag())) 650 return tagApply(ctx, TFormatTag()); 651 652 return tagApply(ctx, static_cast<typename TagSelector<TTagList>::Base &>(format)); 653 } 654 655 656 } // namespace seqan 657 658 #endif // #ifndef SEQAN_BASIC_BASIC_TAGS_H_ 659