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&lt;SomeTag_&gt;</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&lt;TTagList&gt;::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