1 // ==========================================================================
2 //                 SeqAn - The Library for Sequence Analysis
3 // ==========================================================================
4 // Copyright (c) 2006-2015, 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-Doering <andreas.doering@mdc-berlin.de>
33 // ==========================================================================
34 // Tags, declarations and generic code for the String class and its
35 // specializations.
36 // ==========================================================================
37 
38 #ifndef SEQAN_SEQUENCE_STRING_ARRAY_BASE_H_
39 #define SEQAN_SEQUENCE_STRING_ARRAY_BASE_H_
40 
41 namespace seqan {
42 
43 // ============================================================================
44 // Forwards
45 // ============================================================================
46 
47 // ============================================================================
48 // Tags, Classes, Enums
49 // ============================================================================
50 
51 template <typename TSpec = void>
52 struct Alloc {};
53 
54 // TODO(holtgrew): This requires some work: explain it, maybe rather put this into a group since the text object appears in no function's signatures.
55 
56 /*!
57  * @concept TextConcept
58  * @brief Concept for a type that can be as text of an index.
59  * @headerfile <seqan/sequence.h>
60  *
61  * @signature concept TextConcept;
62  *
63  * Certain algorithms and data structures can work for both strings and string sets but need to treat these two
64  * types slightly different.  Examples are index data structures and algorithms that build the indices and use
65  * the indices for lookup.
66  *
67  * To facilitate writing of generic algorithms, the TextConcept concept gives a common interface to both for this
68  * kind of algorithms.
69  *
70  * @see String
71  * @see StringSet
72  */
73 
74 /*!
75  * @mfn TextConcept#StringSetLimits
76  * @brief Return type of string set limits for TextConcept types.
77  *
78  * @signature StringSetLimits<TText>::Type;
79  *
80  * @tparam TText The type of the text.
81  *
82  * @return Type The type of string set limits objects.
83  */
84 
85 /*!
86  * @mfn TextConcept#SAValue
87  * @brief The default alphabet type of a suffix array, i.e. the type to store a
88  *        position of a string or string set.
89  *
90  * @signature SAValue<TText>::Type
91  *
92  * @tparam TText The text type to query.
93  *
94  * @return TReturn A type to store a position in a <tt>TText</tt>.  This could be an integer for strings or a
95  *                 pair of integers for string sets.
96  *
97  * @section Usage
98  *
99  * This type should be removed for functions returning positions in texts such as online or index-based search.
100  * Thus, always use this metafunction for declaring position variables.
101  *
102  * Use the functions @link TextConcept#posLocalize @endlink, @link TextConcept#posGlobalize @endlink, @link
103  * TextConcept#getSeqNo @endlink, and @link TextConcept#getSeqOffset @endlink for conversion between local
104  * and global positions in texts.
105  *
106  * @section Examples
107  *
108  * The following shows the original definition of the SAValue metafunction in SeqAn.
109  *
110  * @code{.cpp}
111  * template <typename TString, typename TSpec>
112  * struct SAValue<StringSet<TString, TSpec> >
113  * {
114  *     typedef Pair<
115  *             typename Size<StringSet<TString, TSpec> >::Type,
116  *             typename SAValue<TString>::Type,
117  *             Pack
118  *         > Type;
119  * };
120  * @endcode
121  */
122 
123 /*!
124  * @fn TextConcept#stringSetLimits
125  * @brief Return string delimiter positions for TextConcept types.
126  *
127  * @signature TStringSetLimits stringSetLimits(text);
128  *
129  * @param[in] text The text to query for its string set limits.
130  *
131  * @return TStringSetLimits The string set limits (of type @link TextConcept#StringSetLimits @endlink).
132  */
133 
134 /*!
135  * @fn TextConcept#posLocalToX
136  * @brief Converts a local to a local/global position.
137  *
138  * @signature void posLocalToX(dst, localPos, limits);
139  *
140  * @param[in] dst      The local or global position (pair or integer value) is written here.
141  * @param[in] localPos The local position.
142  * @param[in] limits   The string limits as returned by @link TextConcept#stringSetLimits @endlink.
143  */
144 
145 /*!
146  * @class String
147  * @implements StringConcept
148  * @implements TextConcept
149  * @implements SegmentableConcept
150  * @headerfile <seqan/sequence.h>
151  * @brief @link StringConcept Sequence @endlink container class.
152  *
153  * @signature template <typename TValue, typename TSpec>
154  *            class String<TValue, TSpec>;
155  *
156  * @tparam TValue The element type of the string.
157  * @tparam TSpec  The tag for selecting the string specialization.
158  *
159  * The String class is for storing sequences and thus at the core of the sequence analysis library SeqAn.  They
160  * are models for the @link StringConcept sequence concept @endlink but extend the sequence concept by allowing
161  * implicit conversion of other sequence into strings as long as the element conversion works:
162  *
163  * @snippet demos/sequence/string.cpp initializing strings
164  *
165  * Aside from that, the usual operations (appending, insertion, removing, element access) are available as well.
166  *
167  * @snippet demos/sequence/string.cpp usual operations
168  *
169  * Strings have a size (the actual number of elements) and a capacity (the number of elements that memory has been
170  * allocated for).  Note that clearing a string does not free the memory (as the STL, SeqAn assumes that strings will
171  * later require a similar amount of memory as before).  Using @link ContainerConcept#shrinkToFit @endlink, the user can
172  * force a re-allocation of the memory such that the string afterward uses the minimal amount of memory to accomodate
173  * all of its objects.
174  *
175  * @snippet demos/sequence/string.cpp clear and resize
176  *
177  * @section Examples
178  *
179  * This example shows a brute force pattern matching scheme for two character Strings.  Creation of String "text" shows
180  * the usage of some available String operating functions.  See class @link StringSet @endlink for an example of a
181  * String container with other than simple type values.  See class @link Index @endlink example for efficiently finding
182  * the same pattern matches using an index.
183  *
184  * @include demos/sequence/string2.cpp
185  *
186  * The output is as follows:
187  *
188  * @include demos/sequence/string2.cpp.stdout
189  *
190  * @see StringSet
191  */
192 
193 /*!
194  * @fn String::String
195  * @brief Constructor.
196  *
197  * @signature String::String()
198  * @signature String::String(other)
199  *
200  * @param[in] other The source for the copy constructor.  Can be of any @link StringConcept sequence @endlink type
201  *                  as long as <tt>other</tt>'s elements are convertible to the value type of this string.
202  *
203  * Default and copy constructor are implemented.
204  */
205 
206 /*!
207  * @fn String::operator=
208  * @brief The String assignment operator allows assignment of convertible sequences.
209  *
210  * @signature TString String::operator=(other)
211  *
212  * @param[in] other The other string.  Must be a sequence whose elements are convertible into this String's type.
213  *
214  * @return TString Reference to the String objecta after assignment.
215  */
216 
217 // TODO(holtgrew): The conversion functions rather belong into their own group than to the concept. The original documentation was a bit misleading and needs to be updated.
218 
219 /*!
220  * @fn TextConcept#posLocalize
221  * @brief Converts a local/global to a local position.
222  * @headerfile <seqan/sequence.h>
223  *
224  * @signature void posLocalize(result, pos, limits)
225  *
226  * @param[in] pos    A local or global position (pair or integer value).
227  * @param[in] limits The limits string returned by @link TextConcept#stringSetLimits @endlink.
228  * @param[in] result Reference to the resulting corresponding local position of
229  *                   <tt>pos</tt>.
230  */
231 
232 /*!
233  * @fn TextConcept#posGlobalize
234  * @brief Converts a local/global to a global position.
235  * @headerfile <seqan/sequence.h>
236  *
237  * @signature TPos posGlobalize(pos, limits)
238  *
239  * @param[in] pos A local or global position (pair or integer value). Types: Pair
240  * @param[in] limits The limits string returned by @link TextConcept#stringSetLimits @endlink.
241  *
242  * @return TPos The corresponding global position of <tt>pos</tt>. If
243  *                 <tt>pos</tt> is an integral type <tt>pos</tt> is returned. If
244  *                 not, <tt>limits[getSeqNo(pos, limits)] + getSeqOffset(pos,
245  *                 limits)</tt> is returned.
246  */
247 
248 /*!
249  * @fn TextConcept#getSeqNo
250  * @brief Returns the sequence number of a position.
251  * @headerfile <seqan/sequence.h>
252  *
253  * @signature TSeqNo getSeqNo(pos[, limits]);
254  *
255  * @param[in] pos A position. Types: Pair
256  * @param[in] limits The limits string returned by @link TextConcept#stringSetLimits @endlink.
257  *
258  * @return TSeqNo A single integer value that identifies the string within the stringset <tt>pos</tt> points at. If
259  *                <tt>limits</tt> is omitted or @link Nothing @endlink <tt>getSeqNo</tt> returns 0.If <tt>pos</tt> is a
260  *                local position (of class @link Pair @endlink) then <tt>i1</tt> is returned.If <tt>pos</tt> is a global
261  *                position (integer type and <tt>limits</tt> is a @link String @endlink) then <tt>pos</tt> is converted
262  *                to a local position and <tt>i1</tt> is returned.
263  */
264 
265 /*!
266  * @fn TextConcept#getSeqOffset
267  * @brief Returns the local sequence offset of a position.
268  * @headerfile <seqan/sequence.h>
269  *
270  * @signature TOffset getSeqOffset(pos[, limits]);
271  *
272  * @param[in] pos A position. Types: Pair
273  * @param[in] limits The limits string returned by @link TextConcept#stringSetLimits @endlink.
274  *
275  * @return TOffset A single integer value that identifies the position within the string <tt>pos</tt> points at.If
276  *                 <tt>limits</tt> is omitted or @link Nothing @endlink <tt>getSeqNo</tt> returns <tt>pos</tt>.  If
277  *                 <tt>pos</tt> is a local position (of class @link Pair @endlink) then <tt>i2</tt> is returned.If
278  *                 <tt>pos</tt> is a global position (integer type and <tt>limits</tt> is a @link String @endlink) then
279  *                 <tt>pos</tt> is converted to a local position and <tt>i2</tt> is returned.
280  */
281 
282 template <typename TValue, typename TSpec = Alloc<> >
283 class String;
284 
285 // ============================================================================
286 // Metafunctions
287 // ============================================================================
288 
289 // ----------------------------------------------------------------------------
290 // Metafunction Value
291 // ----------------------------------------------------------------------------
292 
293 template <typename TValue, typename TSpec>
294 struct Value<String<TValue, TSpec> >
295 {
296     typedef TValue Type;
297 };
298 
299 template <typename TValue, typename TSpec>
300 struct Value<String<TValue, TSpec> const >
301         : public Value<String<TValue, TSpec> >
302 {};
303 
304 // ----------------------------------------------------------------------------
305 // Metafunction Spec
306 // ----------------------------------------------------------------------------
307 
308 template <typename TValue, typename TSpec>
309 struct Spec<String<TValue, TSpec> >
310 {
311     typedef TSpec Type;
312 };
313 template <typename TValue, typename TSpec>
314 struct Spec<String<TValue, TSpec> const>:
315     public Spec<String<TValue, TSpec> >
316 {
317 };
318 
319 // ----------------------------------------------------------------------------
320 // Metafunction StringSpec
321 // ----------------------------------------------------------------------------
322 
323 template <typename T>
324 struct StringSpec
325 {
326     typedef Alloc<> Type;
327 };
328 
329 template <typename T>
330 struct StringSpec<T const> : StringSpec<T> {};
331 
332 template <typename TValue, typename TSpec>
333 struct StringSpec<String<TValue, TSpec> >
334 {
335     typedef TSpec   Type;
336 };
337 
338 // ----------------------------------------------------------------------------
339 // Metafunction Chunk
340 // ----------------------------------------------------------------------------
341 
342 template <typename TValue, typename TSpec>
343 struct Chunk<String<TValue, TSpec> >:
344     Chunk<typename Iterator<String<TValue, TSpec>, Rooted>::Type> {};
345 
346 // ----------------------------------------------------------------------------
347 // Metafunction IsSequence
348 // ----------------------------------------------------------------------------
349 
350 template <typename TValue, typename TSpec>
351 struct IsSequence<String<TValue, TSpec> > : True {};
352 
353 // ----------------------------------------------------------------------------
354 // Concept StringConcept
355 // ----------------------------------------------------------------------------
356 
357 template <typename TValue, typename TSpec>
358 SEQAN_CONCEPT_IMPL((String<TValue, TSpec>), (StringConcept));         // resizable container
359 
360 template <typename TValue, typename TSpec>
361 SEQAN_CONCEPT_IMPL((String<TValue, TSpec> const), (ContainerConcept));  // read-only container
362 
363 // ----------------------------------------------------------------------------
364 // Internal Metafunction TempCopy_
365 // ----------------------------------------------------------------------------
366 
367 template <typename T>
368 struct TempCopy_
369 {
370     typedef typename Value<T>::Type TValue_;
371     typedef typename RemoveConst_<TValue_>::Type TValueNotConst_;
372     typedef String<TValueNotConst_, Alloc<> > Type;
373 };
374 
375 // ============================================================================
376 // Functions
377 // ============================================================================
378 
379 // TODO(holtgrew): Where to move this documentation/specification-only stuff?
380 
381 // ----------------------------------------------------------------------------
382 // Function swap()
383 // ----------------------------------------------------------------------------
384 
385 template <typename TAlphabet, typename TSpec>
386 inline void
387 swap(String<TAlphabet, TSpec> & left,
388      String<TAlphabet, TSpec> & right)
389 {
390 
391     typedef String<TAlphabet, TSpec> TString;
392 
393     TString tmp(left, Move());
394     move(left, right);
395     move(right, tmp);
396 }
397 
398 // ----------------------------------------------------------------------------
399 // Function shareResources()
400 // ----------------------------------------------------------------------------
401 
402 template <typename TValue, typename TSpec>
403 inline bool
404 shareResources(String<TValue, TSpec> const & obj1,
405                TValue const & obj2)
406 {
407     return (begin(obj1) >= &obj2) && (end(obj1) <= &obj2);
408 }
409 
410 template <typename TValue, typename TSpec>
411 inline bool
412 shareResources(TValue const & obj1,
413                String<TValue, TSpec> const & obj2)
414 {
415     return (begin(obj2) >= &obj1) && (end(obj2) <= &obj1);
416 }
417 
418 // TODO(holtgrew): Where to move this documentation/specification-only stuff?
419 // ----------------------------------------------------------------------------
420 // Function value()
421 // ----------------------------------------------------------------------------
422 
423 template <typename TValue, typename TSpec, typename TPos>
424 SEQAN_HOST_DEVICE inline typename Reference< String<TValue, TSpec> >::Type
425 value(String<TValue, TSpec> & me,
426       TPos const & pos)
427 {
428 #if SEQAN_ENABLE_DEBUG
429     typedef typename Position< String<TValue, TSpec> >::Type TStringPos SEQAN_TYPEDEF_FOR_DEBUG;
430 #endif
431     SEQAN_ASSERT_LT_MSG(static_cast<TStringPos>(pos), static_cast<TStringPos>(length(me)), "Trying to access an element behind the last one!");
432     return *(begin(me, Standard()) + pos);
433 }
434 
435 template <typename TValue, typename TSpec, typename TPos>
436 SEQAN_HOST_DEVICE inline typename Reference< String<TValue, TSpec> const >::Type
437 value(String<TValue, TSpec> const & me,
438       TPos const & pos)
439 {
440 #if SEQAN_ENABLE_DEBUG
441     typedef typename Position< String<TValue, TSpec> const >::Type TStringPos SEQAN_TYPEDEF_FOR_DEBUG;
442 #endif
443     SEQAN_ASSERT_LT_MSG(static_cast<TStringPos>(pos), static_cast<TStringPos>(length(me)), "Trying to access an element behind the last one!");
444     return *(begin(me, Standard()) + pos);
445 }
446 
447 // ----------------------------------------------------------------------------
448 // Function length()
449 // ----------------------------------------------------------------------------
450 
451 template <typename TValue, typename TSpec>
452 SEQAN_HOST_DEVICE inline typename Size< String<TValue, TSpec> const>::Type
453 length(String<TValue, TSpec> const & me)
454 {
455     return end(me, Standard()) - begin(me, Standard());
456 }
457 
458 // ----------------------------------------------------------------------------
459 // Function empty()
460 // ----------------------------------------------------------------------------
461 
462 template <typename TValue, typename TSpec>
463 SEQAN_HOST_DEVICE inline bool
464 empty(String<TValue, TSpec> const & me)
465 {
466     return end(me, Standard()) == begin(me, Standard());
467 }
468 
469 // ----------------------------------------------------------------------------
470 // Function clear()
471 // ----------------------------------------------------------------------------
472 
473 template <typename TValue, typename TSpec>
474 inline void
475 clear(String<TValue, TSpec> & me)
476 {
477     arrayDestruct(begin(me, Standard()), end(me, Standard()));
478     _setLength(me, 0);
479 }
480 
481 // ----------------------------------------------------------------------------
482 // Function length()
483 // ----------------------------------------------------------------------------
484 
485 template <typename TExpand>
486 struct ClearSpaceStringBase_
487 {
488 };
489 
490 // ----------------------------------------------------------------------------
491 // Internal Function _clearSpace()
492 // ----------------------------------------------------------------------------
493 
494 template <>
495 struct ClearSpaceStringBase_<Insist>
496 {
497     template <typename T>
498     static inline typename Size<T>::Type
499     _clearSpace_(
500         T & seq,
501         typename Size<T>::Type size)
502     {
503         arrayDestruct(begin(seq, Standard()), end(seq, Standard()));
504         _setLength(seq, size);
505         return size;
506     }
507 
508     template <typename T>
509     static inline typename Size<T>::Type
510     _clearSpace_(
511         T & seq,
512         typename Size<T>::Type size,
513         typename Size<T>::Type limit)
514     {
515         arrayDestruct(begin(seq, Standard()), end(seq, Standard()));
516         if (limit < size)
517         {
518             size = limit;
519         }
520         _setLength(seq, size);
521         return size;
522     }
523 
524     template <typename T>
525     static inline typename Size<T>::Type
526     _clearSpace_(
527         T & seq,
528         typename Size<T>::Type size,
529         typename Size<T>::Type start,
530         typename Size<T>::Type end)
531     {
532         typename Size<T>::Type new_length = length(seq) + size - (end - start);
533         arrayClearSpace(begin(seq, Standard()) + start, length(seq) - start, end - start, size);
534         _setLength(seq, new_length);
535         return size;
536     }
537 
538     template <typename T>
539     static typename Size<T>::Type
540     _clearSpace_(
541         T & seq,
542         typename Size<T>::Type size,
543         typename Size<T>::Type start,
544         typename Size<T>::Type end,
545         typename Size<T>::Type limit)
546     {
547         typename Value<T>::Type * seq_buffer = begin(seq);
548         typename Size<T>::Type seq_length = length(seq);
549 
550         if (limit > start + size)
551         {
552             typename Size<T>::Type removed_size = end - start;
553             typename Size<T>::Type new_length = seq_length - removed_size + size;
554             if (limit < new_length)
555             {
556                 arrayDestruct(seq_buffer + limit, seq_buffer + new_length);
557                 seq_length -= new_length - limit;
558             }
559             arrayClearSpace(seq_buffer + start, seq_length - start, end - start, size);
560             _setLength(seq, new_length);
561             return size;
562         }
563         else
564         {
565             arrayDestruct(seq_buffer + start, seq_buffer + seq_length);
566             _setLength(seq, limit);
567             if (limit > start) return limit - start;
568             else return 0;
569         }
570     }
571 /*
572     template <typename T>
573     static inline typename Size<T>::Type
574     _clearSpace_(
575         T & seq,
576         typename Size<T>::Type size,
577         typename Iterator<T>::Type start,
578         typename Iterator<T>::Type end)
579     {
580         typename Iterator<T>::Type seq_begin = begin(seq);
581         return _clearSpace(seq, size, start - seq_begin, end - seq_begin, Insist());
582     }
583 
584     template <typename T>
585     static inline typename Size<T>::Type
586     _clearSpace_(
587         T & seq,
588         typename Size<T>::Type size,
589         typename Iterator<T>::Type start,
590         typename Iterator<T>::Type end,
591         typename Size<T>::Type limit)
592     {
593         typename Iterator<T>::Type seq_begin = begin(seq);
594         return _clearSpace(seq, size, start - seq_begin, end - seq_begin, limit, Insist());
595     }
596 */
597 };
598 
599 
600 template <>
601 struct ClearSpaceStringBase_<Limit>
602 {
603 
604     template <typename T>
605     static inline typename Size<T>::Type
606     _clearSpace_(
607         T & seq,
608         typename Size<T>::Type size)
609     {
610         return _clearSpace(seq, size, capacity(seq), Insist());
611     }
612 
613     template <typename T>
614     static inline typename Size<T>::Type
615     _clearSpace_(
616         T & seq,
617         typename Size<T>::Type size,
618         typename Size<T>::Type limit)
619     {
620         typename Size<T>::Type seq_capacity = capacity(seq);
621         if (limit > seq_capacity)
622         {
623             limit = seq_capacity;
624         }
625         return _clearSpace(seq, size, limit, Insist());
626     }
627 
628     template <typename T>
629     static inline typename Size<T>::Type
630     _clearSpace_(
631         T & seq,
632         typename Size<T>::Type size,
633         typename Size<T>::Type start,
634         typename Size<T>::Type end)
635     {
636         return _clearSpace(seq, size, start, end, capacity(seq), Insist());
637     }
638 
639     template <typename T>
640     static typename Size<T>::Type
641     _clearSpace_(
642         T & seq,
643         typename Size<T>::Type size,
644         typename Size<T>::Type start,
645         typename Size<T>::Type end,
646         typename Size<T>::Type limit)
647     {
648         typename Size<T>::Type seq_capacity = capacity(seq);
649         if (limit > seq_capacity)
650         {
651             limit = seq_capacity;
652         }
653         return _clearSpace(seq, size, start, end, limit, Insist());
654     }
655 
656 /*
657     template <typename T>
658     static inline typename Size<T>::Type
659     _clearSpace_(
660         T & seq,
661         typename Size<T>::Type size,
662         typename Iterator<T>::Type start,
663         typename Iterator<T>::Type end)
664     {
665         typename Iterator<T>::Type seq_begin = begin(seq);
666         return _clearSpace(seq, size, start - seq_begin, end - seq_begin, Insist());
667     }
668 
669     template <typename T>
670     static inline typename Size<T>::Type
671     _clearSpace_(
672         T & seq,
673         typename Size<T>::Type size,
674         typename Iterator<T>::Type start,
675         typename Iterator<T>::Type end,
676         typename Size<T>::Type limit)
677     {
678         typename Iterator<T>::Type seq_begin = begin(seq);
679         return _clearSpace(seq, size, start - seq_begin, end - seq_begin, limit, Insist());
680     }
681 */
682 };
683 
684 template <typename TExpand>
685 struct ClearSpaceExpandStringBase_
686 {
687     template <typename T>
688     static inline typename Size<T>::Type
689     _clearSpace_(
690         T & seq,
691         typename Size<T>::Type size)
692     {
693         arrayDestruct(begin(seq, Standard()), end(seq, Standard()));
694         typename Size<T>::Type old_capacity = capacity(seq);
695         typename Value<T>::Type * old_array = _reallocateStorage(seq, size, TExpand());
696         if (old_array)
697         {
698             _deallocateStorage(seq, old_array, old_capacity);
699         }
700         _setLength(seq, size);
701         return size;
702     }
703 
704     template <typename T>
705     static inline typename Size<T>::Type
706     _clearSpace_(
707         T & seq,
708         typename Size<T>::Type size,
709         typename Size<T>::Type limit)
710     {
711         arrayDestruct(begin(seq, Standard()), end(seq, Standard()));
712         if (limit < size)
713         {
714             size = limit;
715         }
716         typename Size<T>::Type old_capacity = capacity(seq);
717         typename Value<T>::Type * old_array = _reallocateStorage(seq, size, limit, TExpand());
718         if (old_array)
719         {
720             _deallocateStorage(seq, old_array, old_capacity);
721         }
722         _setLength(seq, size);
723         return size;
724     }
725 
726     template <typename T>
727     static typename Size<T>::Type
728     _clearSpace_(
729         T & seq,
730         typename Size<T>::Type size,
731         typename Size<T>::Type start,
732         typename Size<T>::Type end)
733     {
734         typename Size<T>::Type old_length = length(seq);
735         typename Size<T>::Type removed_size = end - start;
736         typename Size<T>::Type new_length = old_length - removed_size + size;
737 
738         SEQAN_ASSERT_LEQ(start, end);
739         SEQAN_ASSERT_LEQ(start, old_length);
740 
741         typename Size<T>::Type old_capacity = capacity(seq);
742         typename Value<T>::Type * old_array = _reallocateStorage(seq, new_length, TExpand());
743         typename Value<T>::Type * seq_array = begin(seq);
744 
745         if (old_array)
746         {
747             arrayConstructMove(old_array, old_array + start, seq_array);
748             arrayConstructMove(old_array + end, old_array + old_length, seq_array + start + size);
749             _deallocateStorage(seq, old_array, old_capacity);
750             // TODO(weese:) Did we miss to destruct the old_array here, e.g. with arrayDestruct
751         }
752         else
753         {
754             arrayClearSpace(seq_array + start, old_length - start, removed_size, size);
755         }
756 
757         _setLength(seq, new_length);
758 
759         return size;
760     }
761 
762     template <typename T>
763     static typename Size<T>::Type
764     _clearSpace_(
765         T & seq,
766         typename Size<T>::Type size,
767         typename Size<T>::Type start,
768         typename Size<T>::Type end,
769         typename Size<T>::Type limit)
770     {
771         typename Size<T>::Type old_length = length(seq);
772         typename Size<T>::Type removed_size = end - start;
773         typename Size<T>::Type need_length = old_length - removed_size + size;
774 
775         SEQAN_ASSERT_LEQ(start, end);
776         SEQAN_ASSERT_LEQ(start, old_length);
777 
778         typename Size<T>::Type new_length = need_length;
779         typename Size<T>::Type length_to_copy = old_length;
780         if (limit < need_length)
781         {
782             new_length = limit;
783             length_to_copy = new_length - size + removed_size;
784         }
785 
786         bool keep_second_part = (new_length > start + size);
787 
788         typename Size<T>::Type old_capacity = capacity(seq);
789         typename Value<T>::Type * old_array = _reallocateStorage(seq, new_length, limit, TExpand());
790         typename Value<T>::Type * seq_array = begin(seq);
791 
792         if (old_array)
793         {//new buffer allocated
794             typename Size<T>::Type keep_start_length = (start > new_length) ? new_length : start;
795             arrayConstructMove(old_array, old_array + keep_start_length, seq_array);
796             if (keep_second_part)
797             {
798                 arrayConstructMove(old_array + end, old_array + length_to_copy, seq_array + start + size);
799             }
800             _deallocateStorage(seq, old_array, old_capacity);
801         }
802         else
803         {
804             if (keep_second_part)
805             {
806                 arrayClearSpace(seq_array + start, length_to_copy - start, end - start, size);
807                 if (length_to_copy < old_length)
808                 {
809                     arrayDestruct(seq_array + length_to_copy, seq_array + old_length);
810                 }
811             }
812             else
813             {
814                 arrayDestruct(seq_array + start, seq_array + old_length);
815             }
816         }
817 
818         _setLength(seq, new_length);
819 
820         if (keep_second_part) return size;
821         else if (new_length > start) return new_length - start;
822         else return 0;
823     }
824 
825 /*
826     template <typename T>
827     static inline typename Size<T>::Type
828     _clearSpace_(
829         T & seq,
830         typename Size<T>::Type size,
831         typename Iterator<T>::Type start,
832         typename Iterator<T>::Type end)
833     {
834         typename Iterator<T>::Type seq_begin = begin(seq);
835         return _clearSpace(seq, size, start - seq_begin, end - seq_begin, TExpand());
836     }
837 
838     template <typename T>
839     static inline typename Size<T>::Type
840     _clearSpace_(
841         T & seq,
842         typename Size<T>::Type size,
843         typename Iterator<T>::Type start,
844         typename Iterator<T>::Type end,
845         typename Size<T>::Type limit)
846     {
847         typename Iterator<T>::Type seq_begin = begin(seq);
848         return _clearSpace(seq, size, start - seq_begin, end - seq_begin, limit, TExpand());
849     }
850 */
851 };
852 
853 template <>
854 struct ClearSpaceStringBase_<Exact>:
855     ClearSpaceExpandStringBase_<Exact>
856 {
857 };
858 
859 template <>
860 struct ClearSpaceStringBase_<Generous>:
861     ClearSpaceExpandStringBase_<Generous>
862 {
863 };
864 
865 template<typename TValue, typename TSpec, typename TSize, typename TExpand>
866 inline typename Size< String<TValue, TSpec> >::Type
867 _clearSpace(String<TValue, TSpec> & me,
868         TSize size,
869         Tag<TExpand>)
870 {
871     return ClearSpaceStringBase_<Tag<TExpand> >::_clearSpace_(me, size);
872 }
873 
874 template<typename TValue, typename TSpec, typename TSize, typename TCapacity, typename TExpand>
875 inline typename Size< String<TValue, TSpec> >::Type
876 _clearSpace(String<TValue, TSpec> & me,
877         TSize size,
878         TCapacity limit,
879         Tag<TExpand>)
880 {
881     return ClearSpaceStringBase_<Tag<TExpand> >::_clearSpace_(me, size, limit);
882 }
883 
884 template<typename TValue, typename TSpec, typename TSize, typename TPosition, typename TExpand>
885 inline typename Size< String<TValue, TSpec> >::Type
886 _clearSpace(String<TValue, TSpec> & me,
887             TSize size,
888             TPosition pos_begin,
889             TPosition pos_end,
890             Tag<TExpand>)
891 {
892     return ClearSpaceStringBase_<Tag<TExpand> >::_clearSpace_(me, size, pos_begin, pos_end);
893 }
894 
895 template<typename TValue, typename TSpec, typename TSize, typename TPosition, typename TCapacity, typename TExpand>
896 inline typename Size< String<TValue, TSpec> >::Type
897 _clearSpace(String<TValue, TSpec> & me,
898             TSize size,
899             TPosition pos_begin,
900             TPosition pos_end,
901             TCapacity limit,
902             Tag<TExpand>)
903 {
904     return ClearSpaceStringBase_<Tag<TExpand> >::_clearSpace_(me, size, pos_begin, pos_end, limit);
905 }
906 
907 // ----------------------------------------------------------------------------
908 // Function resizeSpace()
909 // ----------------------------------------------------------------------------
910 
911 template<typename TValue, typename TSpec, typename TSize, typename TBeginPosition, typename TEndPosition, typename TExpand>
912 inline typename Size< String<TValue, TSpec> >::Type
913 resizeSpace(String<TValue, TSpec> & me,
914             TSize size,
915             TBeginPosition pos_begin,
916             TEndPosition pos_end,
917             Tag<TExpand> tag)
918 {
919     typedef typename Size< String<TValue, TSpec> >::Type TSize_;
920     typedef typename Position<String<TValue, TSpec> >::Type TPos_;
921     TSize_ ret_ = _clearSpace(
922         me,
923         static_cast<TSize_>(size),
924         static_cast<TPos_>(pos_begin),
925         static_cast<TPos_>(pos_end),
926         tag);
927     arrayConstruct(iter(me, pos_begin), iter(me, pos_begin) + ret_);
928     return ret_;
929 }
930 
931 template<typename TValue, typename TSpec, typename TSize, typename TBeginPosition, typename TEndPosition, typename TCapacity, typename TExpand>
932 inline typename Size< String<TValue, TSpec> >::Type
933 resizeSpace(String<TValue, TSpec> & me,
934             TSize size,
935             TBeginPosition pos_begin,
936             TEndPosition pos_end,
937             TCapacity limit,
938             Tag<TExpand> tag)
939 {
940     typedef typename Size< String<TValue, TSpec> >::Type TSize_;
941     typedef typename Position<String<TValue, TSpec> >::Type TPos_;
942     TSize_ ret_ = _clearSpace(
943         me,
944         static_cast<TSize_>(size),
945         static_cast<TPos_>(pos_begin),
946         static_cast<TPos_>(pos_end),
947         static_cast<TSize_>(limit),
948         tag);
949     arrayConstruct(iter(me, pos_begin), iter(me, pos_begin) + ret_);
950     return ret_;
951 }
952 
953 // ----------------------------------------------------------------------------
954 // Function assign()
955 // ----------------------------------------------------------------------------
956 
957 // Facade version without overflow tag.  Forwards to version with overflow
958 // tag, using Metafunction.DefaultOverflowImplicity.
959 
960 template<typename TTargetValue, typename TTargetSpec, typename TSource>
961 inline void
962 assign(String<TTargetValue, TTargetSpec> & target,
963        TSource & source)
964 {
965     typedef String<TTargetValue, TTargetSpec> TTarget;
966     assign(target, source, typename DefaultOverflowImplicit<TTarget>::Type());
967 }
968 
969 template<typename TTargetValue, typename TTargetSpec, typename TSource>
970 inline void
971 assign(String<TTargetValue, TTargetSpec> & target,
972        TSource const & source)
973 {
974     typedef String<TTargetValue, TTargetSpec> TTarget;
975     assign(target, source, typename DefaultOverflowImplicit<TTarget>::Type());
976 }
977 
978 // Helper struct for assigning strings.
979 
980 template <typename TExpand>
981 struct AssignString_
982 {
983     template <typename TTarget, typename TSource>
984     static inline void
985     assign_(
986         TTarget & target,
987         TSource & source)
988     {
989         if (empty(source) && empty(target))
990             return;  // Do nothing if both source and target are empty.
991         if (!getObjectId(source) || !shareResources(target, source))
992         {
993             typename Size<TTarget>::Type part_length = _clearSpace(target, length(source), TExpand());
994             arrayConstructCopy(begin(source, Standard()), begin(source, Standard()) + part_length, begin(target, Standard()));
995         }
996         else
997         {
998             if ((void *) &target == (void *) &source) return;
999 
1000             typename TempCopy_<TSource>::Type temp(source, length(source));
1001             assign(target, temp, TExpand());
1002         }
1003     }
1004 
1005     template <typename TTarget, typename TSource>
1006     static inline void
1007     assign_(
1008         TTarget & target,
1009         TSource & source,
1010         typename Size<TTarget>::Type limit)
1011     {
1012         if (!getObjectId(source) || !shareResources(target, source))
1013         {
1014             typename Size<TTarget>::Type part_length = _clearSpace(target, typename Size<TTarget>::Type(length(source)), limit, TExpand());
1015             arrayConstructCopy(begin(source, Standard()), begin(source, Standard()) + part_length, begin(target, Standard()));
1016         }
1017         else
1018         {
1019             if ((void *) &target == (void *) &source) return;
1020 
1021             typename Size<TTarget>::Type source_length = length(source);
1022             if (source_length > limit) source_length = limit;
1023 
1024             typename TempCopy_<TSource>::Type temp(source, source_length);
1025             assign(target, temp, TExpand());
1026         }
1027     }
1028 };
1029 
1030 // Interface for assign with overflow strategy tag.  Forwards to static
1031 // functions of helper struct.
1032 
1033 template<typename TTargetValue, typename TTargetSpec, typename TSource, typename TExpand>
1034 inline void
1035 assign(String<TTargetValue, TTargetSpec> & target,
1036        TSource const & source,
1037        Tag<TExpand>)
1038 {
1039     AssignString_<Tag<TExpand> >::assign_(target, source);
1040 }
1041 template<typename TTargetValue, typename TTargetSpec, typename TSource, typename TSize, typename TExpand>
1042 inline void
1043 assign(String<TTargetValue, TTargetSpec> & target,
1044        TSource const & source,
1045        TSize limit,
1046        Tag<TExpand>)
1047 {
1048     AssignString_<Tag<TExpand> >::assign_(target, source, limit);
1049 }
1050 
1051 //// TODO(holtgrew): Still required with dropped VC++ 2003 support?
1052 ////this variant is a workaround for the "const array"-bug of VC++
1053 //
1054 //template<typename TTargetValue, typename TTargetSpec, typename TSourceValue, typename TExpand>
1055 //inline void
1056 //assign(String<TTargetValue, TTargetSpec> & target,
1057 //       TSourceValue const * source,
1058 //       Tag<TExpand>)
1059 //{
1060 //    AssignString_<Tag<TExpand> >::assign_(target, source);
1061 //}
1062 //template<typename TTargetValue, typename TTargetSpec, typename TSourceValue, typename TSize, typename TExpand>
1063 //inline void
1064 //assign(String<TTargetValue, TTargetSpec> & target,
1065 //       TSourceValue const * source,
1066 //       TSize limit,
1067 //       Tag<TExpand>)
1068 //{
1069 //    AssignString_<Tag<TExpand> >::assign_(target, source, limit);
1070 //}
1071 
1072 // ----------------------------------------------------------------------------
1073 // Function move()
1074 // ----------------------------------------------------------------------------
1075 
1076 //implementation of move for contiguous sequences
1077 //note: there is a problem, if sizeof(TSourceValue) and sizeof(TTargetValue) are not a multiple
1078 //  of each other, since in this case the correct size cannot be determined afterwards
1079 //  when calling the deallocate function.
1080 //  ???TODO
1081 template <typename TTarget, typename TSource>
1082 void
1083 _moveContiguous(TTarget & target,
1084                 TSource & source)
1085 {
1086     typedef typename Value<TSource>::Type TSourceValue;
1087     typedef typename Value<TTarget>::Type TTargetValue;
1088 
1089     clear(target);
1090 
1091     typename Iterator<TSource, Standard>::Type source_begin = begin(source, Standard());
1092     typename Iterator<TTarget, Standard>::Type target_begin = (typename Iterator<TTarget, Standard>::Type) begin(source, Standard());
1093 
1094     typename Size<TTarget>::Type size = sizeof(TSourceValue) * capacity(source);
1095     if (size >= sizeof(TTargetValue))
1096     {
1097         if (sizeof(TSourceValue) <= 2) ++size; //regard the "end of string termination" case
1098         typename Size<TTarget>::Type target_capacity = size / sizeof(TTargetValue);
1099         if (sizeof(TTargetValue) <= 2) --target_capacity; //regard the "end of string termination" case
1100 
1101         typename Size<TTarget>::Type target_length = length(source);
1102         if (target_length > target_capacity)
1103         {
1104             target_length = target_capacity;
1105         }
1106 
1107         if (sizeof(TSourceValue) >= sizeof(TTargetValue))
1108         {
1109             arrayMoveForward(source_begin, source_begin + target_length, target_begin);
1110         }
1111         else
1112         {
1113             arrayMoveBackward(source_begin, source_begin + target_length, target_begin);
1114         }
1115 
1116         _setBegin(target, target_begin);
1117         _setLength(target, target_length);
1118         _setCapacity(target, target_capacity);
1119 
1120         typedef typename Iterator<TSource, Standard>::Type TSourceIterator;
1121         _setBegin(source, TSourceIterator(0));
1122         _setLength(source, 0);
1123         _setCapacity(source, 0);
1124     }
1125     else
1126     {
1127         clear(source);
1128     }
1129 }
1130 
1131 template<typename TTargetValue, typename TTargetSpec, typename TSource>
1132 inline void
1133 move(String<TTargetValue, TTargetSpec> & target,
1134      TSource & source)
1135 {
1136     typedef String<TTargetValue, TTargetSpec> TTarget;
1137     move(target, source, typename DefaultOverflowImplicit<TTarget>::Type());
1138 }
1139 
1140 template<typename TTargetValue, typename TTargetSpec, typename TSource>
1141 inline void
1142 move(String<TTargetValue, TTargetSpec> & target,
1143      TSource const & source)
1144 {
1145     typedef String<TTargetValue, TTargetSpec> TTarget;
1146     move(target, source, typename DefaultOverflowImplicit<TTarget>::Type());
1147 }
1148 
1149 template<typename TTargetValue, typename TTargetSpec, typename TSource, typename TTag>
1150 inline void
1151 move(String<TTargetValue, TTargetSpec> & target,
1152      TSource & source,
1153      Tag<TTag> const & tag)
1154 {
1155     assign(target, source, tag);
1156 }
1157 
1158 template<typename TTargetValue, typename TTargetSpec, typename TSource, typename TTag>
1159 inline void
1160 move(String<TTargetValue, TTargetSpec> & target,
1161      TSource const & source,
1162      Tag<TTag> const & tag)
1163 {
1164     assign(target, source, tag);
1165 }
1166 
1167 // TODO(holtgrew): Garbage?
1168 
1169 //////////////////////////////////////////////////////////////////////////////
1170 // valueConstructMove:
1171 // it is usually better for strings to default construct and move instead of
1172 // copy construct strings
1173 
1174 /*
1175 template <typename TIterator, typename TValue, typename TSpec>
1176 inline void
1177 valueConstructMove(TIterator it,
1178                    String<TValue, TSpec> const & value)
1179 {
1180     valueConstruct(it);
1181     move(*it, value);
1182 }
1183 */
1184 
1185 // ----------------------------------------------------------------------------
1186 // Function _stringCheckForOverlap
1187 // ----------------------------------------------------------------------------
1188 
1189 template <typename TIter1, typename TIter2, typename TSize>
1190 inline bool
1191 _stringCheckForPossibleOverlap(TIter1 const &, TIter2 const &, TSize)
1192 {
1193     return true;
1194 }
1195 
1196 template <typename TIter, typename TSize>
1197 inline bool
1198 _stringCheckForPossibleOverlap(TIter const &it1, TIter const &it2, TSize length)
1199 {
1200     // return false if [it1,it1+length) and [it2,it2+length) are not overlapping
1201     return !(it2 + length <= it1 || it1 + length <= it2);
1202 }
1203 
1204 // ----------------------------------------------------------------------------
1205 // Function append()
1206 // ----------------------------------------------------------------------------
1207 
1208 template <typename TExpand>
1209 struct AppendString_
1210 {
1211     template <typename TTarget, typename TSource>
1212     static inline void
1213     append_(TTarget & target,
1214             TSource & source)
1215     {
1216         if (!getObjectId(source) || !shareResources(target, source) ||
1217             !_stringCheckForPossibleOverlap(begin(source, Standard()), end(target, Standard()), length(source)))
1218         {
1219             typename Size<TTarget>::Type target_length = length(target);
1220             typename Size<TTarget>::Type part_length = _clearSpace(target, length(source), target_length, target_length, TExpand());
1221             arrayConstructCopy(begin(source, Standard()), begin(source, Standard()) + part_length, begin(target, Standard()) + target_length);
1222         }
1223         else
1224         {
1225             typename TempCopy_<TSource>::Type temp(source, length(source));
1226             append(target, temp, TExpand());
1227         }
1228     }
1229 
1230     template <typename TTarget, typename TSource>
1231     static inline void
1232     append_(TTarget & target,
1233             TSource & source,
1234             typename Size<TTarget>::Type limit)
1235     {
1236         typename Iterator<TTarget, Standard>::Type target_begin = begin(target, Standard());
1237         if (!getObjectId(source) || !shareResources(target, source))
1238         {
1239             typename Size<TTarget>::Type target_length = length(target);
1240             typename Size<TTarget>::Type part_length = _clearSpace(target, length(source), target_length, target_length, limit, TExpand());
1241             arrayConstructCopy(begin(source, Standard()), begin(source, Standard()) + part_length, begin(target, Standard()) + target_length);
1242         }
1243         else
1244         {
1245             typename Size<TTarget>::Type target_length = length(target);
1246             if (target_length >= limit)
1247             {
1248                 arrayDestruct(target_begin + limit, target_begin + target_length);
1249                 _setLength(target, limit);
1250             }
1251             else
1252             {
1253                 limit -= target_length;
1254                 typename Size<TTarget>::Type source_length = length(source) ;
1255                 if (source_length > limit) source_length = limit;
1256 
1257                 typename TempCopy_<TSource>::Type temp(source, source_length);
1258                 append(target, temp, TExpand());
1259             }
1260         }
1261     }
1262 };
1263 
1264 template<typename TTargetValue, typename TTargetSpec, typename TSource, typename TExpand>
1265 inline void
1266 append(String<TTargetValue, TTargetSpec> & target,
1267        TSource const & source,
1268        Tag<TExpand>)
1269 {
1270     AppendString_<Tag<TExpand> >::append_(target, source);
1271 }
1272 
1273 template<typename TTargetValue, typename TTargetSpec, typename TSource, typename TExpand>
1274 inline void
1275 append(String<TTargetValue, TTargetSpec> & target,
1276        TSource const & source,
1277        typename Size< String<TTargetValue, TTargetSpec> >::Type limit,
1278        Tag<TExpand>)
1279 {
1280     AppendString_<Tag<TExpand> >::append_(target, source, limit);
1281 }
1282 
1283 // TODO(holtgrew): Still required with dropped VC++ 2003 support?
1284 //this variant is a workaround for the "const array"-bug of VC++
1285 
1286 template<typename TTargetValue, typename TTargetSpec, typename TSourceValue, typename TExpand>
1287 inline void
1288 append(String<TTargetValue, TTargetSpec> & target,
1289        TSourceValue * source,
1290        Tag<TExpand>)
1291 {
1292     AppendString_<Tag<TExpand> >::append_(target, source);
1293 }
1294 
1295 template<typename TTargetValue, typename TTargetSpec, typename TSourceValue, typename TExpand>
1296 inline void
1297 append(String<TTargetValue, TTargetSpec> & target,
1298        TSourceValue * source,
1299        typename Size< String<TTargetValue, TTargetSpec> >::Type limit,
1300        Tag<TExpand>)
1301 {
1302     AppendString_<Tag<TExpand> >::append_(target, source, limit);
1303 }
1304 
1305 // ----------------------------------------------------------------------------
1306 // Function appendValue()
1307 // ----------------------------------------------------------------------------
1308 
1309 template <typename TExpand>
1310 struct AppendValueToString_
1311 {
1312     template <typename T, typename TValue>
1313     static inline void
1314     appendValue_(T & me,
1315                  TValue SEQAN_FORWARD_CARG _value)
1316     {
1317         typedef typename Value<T>::Type TTargetValue;
1318         typedef typename Size<T>::Type TSize;
1319 
1320         TSize me_length = length(me);
1321         if (capacity(me) <= me_length)
1322         {
1323             TTargetValue temp_copy(SEQAN_FORWARD(TValue, _value)); //temp copy because resize could invalidate _value
1324             // TODO(holtgrew): The resize() function will default construct the last element. This is slow. Get rid of this.
1325             TSize new_length = reserve(me, me_length + 1, TExpand());
1326             if (me_length < new_length)
1327             {
1328                 // *(begin(me) + me_length) = temp_copy;
1329                 valueConstruct(begin(me, Standard()) + me_length, SEQAN_FORWARD(TTargetValue, temp_copy)); //??? this should be valueMoveConstruct
1330                 _setLength(me, me_length + 1);
1331             }
1332         }
1333         else
1334         {
1335             valueConstruct(begin(me, Standard()) + me_length, SEQAN_FORWARD(TValue, _value));
1336             _setLength(me, me_length + 1);
1337         }
1338     }
1339 };
1340 
1341 template <typename TTargetValue, typename TTargetSpec, typename TValue, typename TExpand>
1342 inline void
1343 appendValue(String<TTargetValue, TTargetSpec> & me,
1344             TValue SEQAN_FORWARD_CARG _value,
1345             Tag<TExpand>)
1346 {
1347     AppendValueToString_<Tag<TExpand> >::appendValue_(me, SEQAN_FORWARD(TValue, _value));
1348 }
1349 
1350 // ----------------------------------------------------------------------------
1351 // Function appendValue(Serial)
1352 // ----------------------------------------------------------------------------
1353 
1354 template <typename TTargetValue, typename TTargetSpec, typename TValue, typename TExpand>
1355 inline void
1356 appendValue(String<TTargetValue, TTargetSpec> & me,
1357             TValue SEQAN_FORWARD_CARG _value,
1358             Tag<TExpand> const & expandTag,
1359             Serial)
1360 {
1361     appendValue(me, SEQAN_FORWARD(TValue, _value), expandTag);
1362 }
1363 
1364 //////////////////////////////////////////////////////////////////////////////
1365 // insertValue
1366 //////////////////////////////////////////////////////////////////////////////
1367 
1368 template <typename TExpand>
1369 struct InsertValueToString_
1370 {
1371     template <typename T, typename TPosition, typename TValue>
1372     static inline void
1373     insertValue_(T & me,
1374                 TPosition pos,
1375                 TValue & _value)
1376     {
1377         typename Value<T>::Type temp_copy = _value; //temp copy because resizeSpace could invalidate _value
1378         resizeSpace(me, 1, pos, pos, TExpand());
1379         if ((typename Size<T>::Type) pos < length(me))
1380             moveValue(me, pos, temp_copy);
1381     }
1382 };
1383 
1384 template <typename TTargetValue, typename TTargetSpec, typename TPosition, typename TValue, typename TExpand>
1385 inline void
1386 insertValue(String<TTargetValue, TTargetSpec> & me,
1387             TPosition pos,
1388             TValue const & _value,
1389             Tag<TExpand>)
1390 {
1391     InsertValueToString_<Tag<TExpand> >::insertValue_(me, pos, _value);
1392 }
1393 
1394 // ----------------------------------------------------------------------------
1395 // Function replace()
1396 // ----------------------------------------------------------------------------
1397 
1398 template <typename TExpand>
1399 struct ReplaceString_
1400 {
1401     template <typename TTarget, typename TSource>
1402     static inline void
1403     replace_(TTarget & target,
1404              typename Size<TTarget>::Type pos_begin,
1405              typename Size<TTarget>::Type pos_end,
1406              TSource & source)
1407     {
1408         if (!getObjectId(source) || !shareResources(target, source))
1409         {
1410             typename Size<TTarget>::Type part_length = _clearSpace(target, length(source), pos_begin, pos_end, TExpand());
1411             arrayConstructCopy(begin(source, Standard()), begin(source, Standard()) + part_length, begin(target, Standard()) + pos_begin);
1412         }
1413         else
1414         {
1415             typename TempCopy_<TSource>::Type temp(source, length(source));
1416             replace(target, pos_begin, pos_end, temp, TExpand());
1417         }
1418     }
1419 
1420     template <typename TTarget, typename TSource>
1421     static inline void
1422     replace_(TTarget & target,
1423              typename Size<TTarget>::Type pos_begin,
1424              typename Size<TTarget>::Type pos_end,
1425              TSource & source,
1426              typename Size<TTarget>::Type limit)
1427     {
1428         if (!getObjectId(source) || !shareResources(target, source))
1429         {
1430             typename Size<TTarget>::Type part_length = _clearSpace(target, length(source), pos_begin, pos_end, limit, TExpand());
1431             arrayConstructCopy(begin(source, Standard()), begin(source, Standard()) + part_length, begin(target, Standard()) + pos_begin);
1432         }
1433         else
1434         {
1435             if (pos_begin >= limit)
1436             {
1437                 arrayDestruct(begin(target) + limit, end(target));
1438                 _setLength(target, limit);
1439             }
1440             else
1441             {
1442                 limit -= pos_begin;
1443                 typename Size<TTarget>::Type source_length = length(source) ;
1444                 if (source_length > limit) source_length = limit;
1445 
1446                 typename TempCopy_<TSource>::Type temp(source, source_length);
1447                 replace(target, pos_begin, pos_end, temp, limit, TExpand());
1448             }
1449         }
1450     }
1451 
1452 };
1453 
1454 template<typename TTargetValue, typename TTargetSpec, typename TPositionBegin, typename TPositionEnd, typename TSource, typename TExpand>
1455 inline void
1456 replace(String<TTargetValue, TTargetSpec> & target,
1457         TPositionBegin pos_begin,
1458         TPositionEnd pos_end,
1459         TSource const & source,
1460         Tag<TExpand>)
1461 {
1462     ReplaceString_<Tag<TExpand> >::replace_(target, pos_begin, pos_end, source);
1463 }
1464 
1465 template<typename TTargetValue, typename TTargetSpec, typename TPositionBegin, typename TPositionEnd, typename TSource, typename TExpand>
1466 inline void
1467 replace(String<TTargetValue, TTargetSpec> & target,
1468         TPositionBegin pos_begin,
1469         TPositionEnd pos_end,
1470         TSource const & source,
1471         typename Size< String<TTargetValue, TTargetSpec> >::Type limit,
1472         Tag<TExpand>)
1473 {
1474     ReplaceString_<Tag<TExpand> >::replace_(target, pos_begin, pos_end, source, limit);
1475 }
1476 
1477 // TODO(holtgrew): Still required with dropped VC++ 2003 support?
1478 //this variant is a workaround for the "const array"-bug of VC++
1479 
1480 template<typename TTargetValue, typename TTargetSpec, typename TPositionBegin, typename TPositionEnd, typename TSourceValue, typename TExpand>
1481 inline void
1482 replace(String<TTargetValue, TTargetSpec> & target,
1483         TPositionBegin pos_begin,
1484         TPositionEnd pos_end,
1485         TSourceValue const * source,
1486         Tag<TExpand>)
1487 {
1488     ReplaceString_<Tag<TExpand> >::replace_(target, pos_begin, pos_end, source);
1489 }
1490 
1491 template<typename TTargetValue, typename TTargetSpec, typename TPositionBegin, typename TPositionEnd, typename TSourceValue, typename TExpand>
1492 inline void
1493 replace(String<TTargetValue, TTargetSpec> & target,
1494         TPositionBegin pos_begin,
1495         TPositionEnd pos_end,
1496         TSourceValue const * source,
1497         typename Size< String<TTargetValue, TTargetSpec> >::Type limit,
1498         Tag<TExpand>)
1499 {
1500     ReplaceString_<Tag<TExpand> >::replace_(target, pos_begin, pos_end, source, limit);
1501 }
1502 
1503 // ----------------------------------------------------------------------------
1504 // Internal Function _reallocateStorage()
1505 // ----------------------------------------------------------------------------
1506 
1507 template <typename TValue, typename TSpec, typename TSize>
1508 inline typename Value<String<TValue, TSpec> >::Type *
1509 _reallocateStorage(
1510     String<TValue, TSpec> & me,
1511     TSize new_capacity)
1512 {
1513     return _allocateStorage(me, new_capacity);
1514 }
1515 
1516 template <typename TValue, typename TSpec, typename TSize>
1517 inline typename Value<String<TValue, TSpec> >::Type *
1518 _reallocateStorage(
1519     String<TValue, TSpec> & me,
1520     TSize new_capacity,
1521     Exact)
1522 {
1523     typedef typename Size<String<TValue, TSpec> >::Type TStringSize;
1524     if (static_cast<TStringSize>(new_capacity) <= capacity(me))
1525         return 0;
1526 
1527     return _reallocateStorage(me, new_capacity);
1528 }
1529 
1530 template <typename TValue, typename TSpec, typename TSize, typename TSize2>
1531 inline typename Value<String<TValue, TSpec> >::Type *
1532 _reallocateStorage(
1533     String<TValue, TSpec> & me,
1534     TSize new_capacity,
1535     TSize2 limit,
1536     Exact)
1537 {
1538     typedef typename Size<String<TValue, TSpec> >::Type TStringSize;
1539     if (static_cast<TStringSize>(new_capacity) <= capacity(me))
1540         return 0;
1541 
1542     if (new_capacity > limit) new_capacity = limit;
1543     return _reallocateStorage(me, new_capacity);
1544 }
1545 
1546 template <typename TValue, typename TSpec, typename TSize>
1547 inline typename Value<String<TValue, TSpec> >::Type *
1548 _reallocateStorage(
1549     String<TValue, TSpec> & me,
1550     TSize new_capacity,
1551     Generous)
1552 {
1553     typedef typename Size<String<TValue, TSpec> >::Type TStringSize;
1554     if (static_cast<TStringSize>(new_capacity) <= capacity(me))
1555         return 0;
1556 
1557     new_capacity = computeGenerousCapacity(me, new_capacity);
1558     return _reallocateStorage(me, new_capacity);
1559 }
1560 
1561 template <typename TValue, typename TSpec, typename TSize, typename TSize2>
1562 inline typename Value<String<TValue, TSpec> >::Type *
1563 _reallocateStorage(
1564     String<TValue, TSpec> & me,
1565     TSize new_capacity,
1566     TSize2 limit,
1567     Generous)
1568 {
1569     typedef typename Size<String<TValue, TSpec> >::Type TStringSize;
1570     if (static_cast<TStringSize>(new_capacity) <= capacity(me))
1571         return 0;
1572 
1573     new_capacity = computeGenerousCapacity(me, new_capacity);
1574     if (new_capacity > limit) new_capacity = limit;
1575     return _reallocateStorage(me, new_capacity);
1576 }
1577 
1578 template <typename TValue, typename TSpec, typename TSize>
1579 inline typename Value<String<TValue, TSpec> >::Type *
1580 _reallocateStorage(
1581     String<TValue, TSpec> &,
1582     TSize,
1583     Insist)
1584 {
1585     return 0;
1586 }
1587 
1588 template <typename TValue, typename TSpec, typename TSize, typename TSize2>
1589 inline typename Value<String<TValue, TSpec> >::Type *
1590 _reallocateStorage(
1591     String<TValue, TSpec> &,
1592     TSize,
1593     TSize2,
1594     Insist)
1595 {
1596     return 0;
1597 }
1598 
1599 template <typename TValue, typename TSpec, typename TSize>
1600 inline typename Value<String<TValue, TSpec> >::Type *
1601 _reallocateStorage(
1602     String<TValue, TSpec> &,
1603     TSize,
1604     Limit)
1605 {
1606     return 0;
1607 }
1608 
1609 template <typename TValue, typename TSpec, typename TSize, typename TSize2>
1610 inline typename Value<String<TValue, TSpec> >::Type *
1611 _reallocateStorage(
1612     String<TValue, TSpec> &,
1613     TSize,
1614     TSize2,
1615     Limit)
1616 {
1617     return 0;
1618 }
1619 
1620 // ----------------------------------------------------------------------------
1621 // Function reserve()
1622 // ----------------------------------------------------------------------------
1623 
1624 template <typename TValue, typename TSpec, typename TSize_>
1625 inline void
1626 _reserveStorage(
1627     String<TValue, TSpec> & /*seq*/,
1628     TSize_ /*new_capacity*/,
1629     Insist)
1630 {
1631     // do nothing
1632 }
1633 
1634 template <typename TValue, typename TSpec, typename TSize_>
1635 inline void
1636 _reserveStorage(
1637     String<TValue, TSpec> & /*seq*/,
1638     TSize_ /*new_capacity*/,
1639     Limit)
1640 {
1641     // do nothing
1642 }
1643 
1644 template <typename TValue, typename TSpec, typename TSize_, typename TExpand>
1645 inline void
1646 _reserveStorage(
1647     String<TValue, TSpec> & seq,
1648     TSize_ new_capacity,
1649     Tag<TExpand> tag)
1650 {
1651     typedef typename Size< String<TValue, TSpec> >::Type TSize;
1652 
1653     TSize old_capacity = capacity(seq);
1654 
1655 //  if (old_capacity == (TSize)new_capacity) return;
1656 //  if (!IsSameType<TExpand,TagExact_>::VALUE && old_capacity > (TSize)new_capacity) return;
1657     if (old_capacity >= (TSize)new_capacity) return;
1658 
1659     TSize seq_length = length(seq);
1660     typename Value< String<TValue, TSpec> >::Type * old_array = _reallocateStorage(seq, new_capacity, tag);
1661     if (old_array)
1662     {//buffer was replaced, destruct old buffer
1663 //        arrayConstructCopy(old_array, old_array + seq_length, begin(seq, Standard()));
1664         arrayConstructMove(old_array, old_array + seq_length, begin(seq, Standard()));
1665         arrayDestruct(old_array, old_array + seq_length);
1666         _deallocateStorage(seq, old_array, old_capacity);
1667     }
1668     _setLength(seq, seq_length);
1669 }
1670 
1671 template <typename TValue, typename TSpec, typename TSize_, typename TExpand>
1672 inline typename Size< String<TValue, TSpec> >::Type
1673 reserve(
1674     String<TValue, TSpec> & seq,
1675     TSize_ new_capacity,
1676     Tag<TExpand> tag)
1677 {
1678     _reserveStorage(seq, new_capacity, tag);
1679     return _capacityReturned(seq, new_capacity, tag);
1680 }
1681 
1682 // ----------------------------------------------------------------------------
1683 // Function resize()
1684 // ----------------------------------------------------------------------------
1685 
1686 template <typename TExpand>
1687 struct _Resize_String
1688 {
1689     template <typename T>
1690     static inline typename Size<T>::Type
1691     resize_(
1692         T & me,
1693         typename Size<T>::Type new_length)
1694     {
1695         typedef typename Size<T>::Type TSize;
1696         TSize me_length = length(me);
1697         if (new_length < me_length)
1698         {
1699             arrayDestruct(begin(me, Standard()) + new_length, begin(me, Standard()) + me_length);
1700         }
1701         else
1702         {
1703             typename Size<T>::Type me_capacity = capacity(me);
1704             if (new_length > me_capacity)
1705             {
1706                 TSize new_capacity = reserve(me, new_length, TExpand());
1707                 if (new_capacity < new_length)
1708                 {
1709                     new_length = new_capacity;
1710                 }
1711             }
1712             if (new_length > me_length)
1713             {
1714                 arrayConstruct(begin(me, Standard()) + me_length, begin(me, Standard()) + new_length);
1715             }
1716         }
1717 
1718         _setLength(me, new_length);
1719         return new_length;
1720     }
1721 
1722     template <typename T, typename TValue>
1723     static inline typename Size<T>::Type
1724     resize_(
1725         T & me,
1726         typename Size<T>::Type new_length,
1727         TValue const & val)
1728     {
1729         typedef typename Size<T>::Type TSize;
1730         TSize me_length = length(me);
1731         if (new_length < me_length)
1732         {
1733             arrayDestruct(begin(me, Standard()) + new_length, begin(me, Standard()) + me_length);
1734         }
1735         else
1736         {
1737             TSize me_capacity = capacity(me);
1738             if (new_length > me_capacity)
1739             {
1740                 TValue tempCopy = val;  // reserve could invalidate val
1741                 TSize new_capacity = reserve(me, new_length, TExpand());
1742                 if (new_capacity < new_length)
1743                 {
1744                     new_length = new_capacity;
1745                 }
1746                 arrayConstruct(begin(me, Standard()) + me_length, begin(me, Standard()) + new_length, tempCopy);
1747             } else
1748                 if (new_length > me_length)
1749                 {
1750                     arrayConstruct(begin(me, Standard()) + me_length, begin(me, Standard()) + new_length, val);
1751                 }
1752         }
1753 
1754         _setLength(me, new_length);
1755         return new_length;
1756     }
1757 };
1758 
1759 template <typename TValue, typename TSpec, typename TSize, typename TExpand>
1760 inline typename Size< String<TValue, TSpec> >::Type
1761 resize(
1762     String<TValue, TSpec> & me,
1763     TSize new_length,
1764     Tag<TExpand>)
1765 {
1766     return _Resize_String<Tag<TExpand> >::resize_(me, new_length);
1767 }
1768 
1769 template <typename TValue, typename TSpec, typename TSize, typename TValue2, typename TExpand>
1770 inline typename Size< String<TValue, TSpec> >::Type
1771 resize(
1772     String<TValue, TSpec> & me,
1773     TSize new_length,
1774     TValue2 const & val,
1775     Tag<TExpand>)
1776 {
1777     return _Resize_String<Tag<TExpand> >::resize_(me, new_length, val);
1778 }
1779 
1780 // ----------------------------------------------------------------------------
1781 // Function operator+=(), shortcut to append()
1782 // ----------------------------------------------------------------------------
1783 
1784 // TODO(holtgrew): Maybe move to a string_shortcuts.h?
1785 
1786 template <typename TLeftValue, typename TLeftSpec, typename TRight >
1787 inline
1788 String<TLeftValue, TLeftSpec> &
1789 operator+=(String<TLeftValue, TLeftSpec> & left,
1790            TRight const & right)
1791 {
1792     append(left, right);
1793     return left;
1794 }
1795 
1796 // The comparator functions forward to the code in sequence_lexical.h.
1797 
1798 // ----------------------------------------------------------------------------
1799 // Function operator==()
1800 // ----------------------------------------------------------------------------
1801 
1802 template <typename TLeftValue, typename TLeftSpec, typename TRight >
1803 inline bool
1804 operator==(String<TLeftValue, TLeftSpec> const & left,
1805            TRight const & right)
1806 {
1807     typename Comparator<String<TLeftValue, TLeftSpec> >::Type _lex(left, right);
1808     return isEqual(_lex);
1809 }
1810 
1811 template <typename TLeftValue, typename TRightValue, typename TRightSpec >
1812 inline bool
1813 operator==(TLeftValue * left,
1814            String<TRightValue, TRightSpec> const & right)
1815 {
1816     typename Comparator<String<TRightValue, TRightSpec> >::Type _lex(left, right);
1817     return isEqual(_lex);
1818 }
1819 
1820 // ----------------------------------------------------------------------------
1821 // Function operator!=()
1822 // ----------------------------------------------------------------------------
1823 
1824 template <typename TLeftValue, typename TLeftSpec, typename TRight >
1825 inline bool
1826 operator!=(String<TLeftValue, TLeftSpec> const & left,
1827            TRight const & right)
1828 {
1829     typename Comparator<String<TLeftValue, TLeftSpec> >::Type _lex(left, right);
1830     return isNotEqual(_lex);
1831 }
1832 
1833 template <typename TLeftValue, typename TRightValue, typename TRightSpec >
1834 inline bool
1835 operator!=(TLeftValue * left,
1836            String<TRightValue, TRightSpec> const & right)
1837 {
1838     typename Comparator<String<TRightValue, TRightSpec> >::Type _lex(left, right);
1839     return isNotEqual(_lex);
1840 }
1841 
1842 // ----------------------------------------------------------------------------
1843 // Function operator<()
1844 // ----------------------------------------------------------------------------
1845 
1846 template <typename TLeftValue, typename TLeftSpec, typename TRight>
1847 inline bool
1848 operator<(String<TLeftValue, TLeftSpec> const & left,
1849           TRight const & right)
1850 {
1851     return isLess(left, right, typename DefaultPrefixOrder<String<TLeftValue, TLeftSpec> >::Type());
1852 }
1853 
1854 template <typename TLeftValue, typename TRightValue, typename TRightSpec >
1855 inline bool
1856 operator<(TLeftValue * left,
1857           String<TRightValue, TRightSpec> const & right)
1858 {
1859     return isLess(left, right, typename DefaultPrefixOrder<TLeftValue *>::Type());
1860 }
1861 
1862 // ----------------------------------------------------------------------------
1863 // Function operator<=()
1864 // ----------------------------------------------------------------------------
1865 
1866 template <typename TLeftValue, typename TLeftSpec, typename TRight>
1867 inline bool
1868 operator<=(String<TLeftValue, TLeftSpec> const & left,
1869            TRight const & right)
1870 {
1871     return isLessOrEqual(left, right, typename DefaultPrefixOrder<String<TLeftValue, TLeftSpec> >::Type());
1872 }
1873 
1874 template <typename TLeftValue, typename TRightValue, typename TRightSpec >
1875 inline bool
1876 operator<=(TLeftValue * left,
1877            String<TRightValue, TRightSpec> const & right)
1878 {
1879     return isLessOrEqual(left, right, typename DefaultPrefixOrder<TLeftValue *>::Type());
1880 }
1881 
1882 // ----------------------------------------------------------------------------
1883 // Function operator>()
1884 // ----------------------------------------------------------------------------
1885 
1886 template <typename TLeftValue, typename TLeftSpec, typename TRight>
1887 inline bool
1888 operator>(String<TLeftValue, TLeftSpec> const & left,
1889           TRight const & right)
1890 {
1891     return isGreater(left, right, typename DefaultPrefixOrder<String<TLeftValue, TLeftSpec> >::Type());
1892 }
1893 template <typename TLeftValue, typename TRightValue, typename TRightSpec >
1894 inline bool
1895 operator>(TLeftValue * left,
1896           String<TRightValue, TRightSpec> const & right)
1897 {
1898     return isGreater(left, right, typename DefaultPrefixOrder<TLeftValue *>::Type());
1899 }
1900 
1901 // ----------------------------------------------------------------------------
1902 // Function operator>=()
1903 // ----------------------------------------------------------------------------
1904 
1905 template <typename TLeftValue, typename TLeftSpec, typename TRight>
1906 inline bool
1907 operator>=(String<TLeftValue, TLeftSpec> const & left,
1908            TRight const & right)
1909 {
1910     return isGreaterOrEqual(left, right, typename DefaultPrefixOrder<String<TLeftValue, TLeftSpec> >::Type());
1911 }
1912 template <typename TLeftValue, typename TRightValue, typename TRightSpec>
1913 inline bool
1914 operator>=(TLeftValue * left,
1915              String<TRightValue, TRightSpec> const & right)
1916 {
1917     return isGreaterOrEqual(left, right, typename DefaultPrefixOrder<TLeftValue *>::Type());
1918 }
1919 
1920 // ----------------------------------------------------------------------------
1921 // Function beginPosition()
1922 // ----------------------------------------------------------------------------
1923 
1924 /*!
1925  * @fn String#beginPosition
1926  * @headerfile <seqan/sequence.h>
1927  * @brief Return 0 for compatibility with @link Segment @endlink.
1928  *
1929  * @signature TPos beginPosition(str);
1930  *
1931  * @param[in] seg The String to use.
1932  *
1933  * @return TPos Always 0.
1934  */
1935 
1936 
1937 // ----------------------------------------------------------------------------
1938 // Function endPosition()
1939 // ----------------------------------------------------------------------------
1940 
1941 /*!
1942  * @fn String#endPosition
1943  * @headerfile <seqan/sequence.h>
1944  * @brief Return length of string for compatibility with @link Segment @endlink.
1945  *
1946  * @signature TPos endPosition(str);
1947  *
1948  * @param[in] seg The string to use.
1949  *
1950  * @return TPos Length of the string.
1951  */
1952 
1953 // ----------------------------------------------------------------------------
1954 // Function reserveChunk()
1955 // ----------------------------------------------------------------------------
1956 
1957 template <typename TValue, typename TSpec, typename TSize>
1958 inline void reserveChunk(String<TValue, TSpec> &str, TSize size, Output)
1959 {
1960     reserve(str, length(str) + size);
1961 }
1962 
1963 template <typename TValue, typename TSpec, typename TSize>
1964 inline void reserveChunk(String<TValue, TSpec> const &, TSize, Input)
1965 {}
1966 
1967 // ----------------------------------------------------------------------------
1968 // Function getChunk()
1969 // ----------------------------------------------------------------------------
1970 
1971 template <typename TChunk, typename TValue, typename TSpec>
1972 inline void
1973 getChunk(TChunk &result, String<TValue, TSpec> &cont, Output)
1974 {
1975     return assignRange(result, end(cont, Standard()), begin(cont, Standard()) + capacity(cont));
1976 }
1977 
1978 // ----------------------------------------------------------------------------
1979 // Function advanceChunk()
1980 // ----------------------------------------------------------------------------
1981 
1982 // extend target string size
1983 template <typename TValue, typename TSpec, typename TSize>
1984 inline void advanceChunk(String<TValue, TSpec> &str, TSize size)
1985 {
1986     _setLength(str, length(str) + size);
1987 }
1988 
1989 template <typename TValue, typename TStringSpec, typename TSpec, typename TSize>
1990 inline void advanceChunk(Iter<String<TValue, TStringSpec>, TSpec> &iter, TSize size)
1991 {
1992     typedef String<TValue, TStringSpec> TContainer;
1993     typedef Iter<TContainer, TSpec> TIter;
1994 
1995     iter += size;
1996 
1997     TContainer &cont = container(iter);
1998     typename Position<TIter>::Type pos = position(iter);
1999 
2000     if (pos > length(cont))
2001         _setLength(cont, pos);
2002 }
2003 
2004 // ----------------------------------------------------------------------------
2005 // Function operator<<() for streams.
2006 // ----------------------------------------------------------------------------
2007 
2008 template <typename TStream, typename TValue, typename TSpec>
2009 inline TStream &
2010 operator<<(TStream & target,
2011            String<TValue, TSpec> const & source)
2012 {
2013     typename DirectionIterator<TStream, Output>::Type it = directionIterator(target, Output());
2014     write(it, source);
2015     return target;
2016 }
2017 
2018 // ----------------------------------------------------------------------------
2019 // Function operator>>() for streams.
2020 // ----------------------------------------------------------------------------
2021 
2022 template <typename TStream, typename TValue, typename TSpec>
2023 inline TStream &
2024 operator>>(TStream & source,
2025            String<TValue, TSpec> & target)
2026 {
2027     typename DirectionIterator<TStream, Input>::Type it = directionIterator(source, Input());;
2028     read(it, target);
2029     return source;
2030 }
2031 
2032 // ----------------------------------------------------------------------------
2033 // Function assignValueById
2034 // ----------------------------------------------------------------------------
2035 
2036 template<typename TValue, typename TSpec, typename TId, typename TValue2>
2037 inline SEQAN_FUNC_ENABLE_IF(Is<IntegerConcept<TId> >, void)
2038 assignValueById(String<TValue, TSpec> & me,
2039                 TId id,
2040                 TValue2 const & obj)
2041 {
2042     if (length(me) <= id)
2043         resize(me, id + 1, TValue());
2044     assignValue(me, id, obj);
2045 }
2046 
2047 // ----------------------------------------------------------------------------
2048 // Function getValueById
2049 // ----------------------------------------------------------------------------
2050 
2051 template<typename TValue, typename TSpec, typename TId>
2052 inline SEQAN_FUNC_ENABLE_IF(Is<IntegerConcept<TId> >, TValue)
2053 getValueById(String<TValue, TSpec> & me,
2054              TId id)
2055 {
2056     if (id < length(me))
2057         return getValue(me, id);
2058     else
2059         return TValue();
2060 }
2061 
2062 }  // namespace seqan
2063 
2064 #endif  // #ifndef SEQAN_SEQUENCE_STRING_ARRAY_BASE_H_
2065