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&lt;double&gt;("%.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&lt;TValue&gt;</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