Imported Upstream version 0.12.7
[bowtie.git] / SeqAn-1.1 / seqan / sequence / string_cstyle.h
1  /*==========================================================================
2                 SeqAn - The Library for Sequence Analysis
3                           http://www.seqan.de 
4  ============================================================================
5   Copyright (C) 2007
6
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10   version 3 of the License, or (at your option) any later version.
11
12   This library is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17  ============================================================================
18   $Id: string_cstyle.h,v 1.1 2008/08/25 16:20:04 langmead Exp $
19  ==========================================================================*/
20
21 #ifndef SEQAN_HEADER_SEQUENCE_CSTYLE_H
22 #define SEQAN_HEADER_SEQUENCE_CSTYLE_H
23
24 namespace SEQAN_NAMESPACE_MAIN
25 {
26
27 //////////////////////////////////////////////////////////////////////////////
28 //string that exports an interface to cstyle strings.
29
30 /**
31 .Spec.CStyle String:
32 ..cat:Strings
33 ..general:Class.String
34 ..summary:Allows adaption of strings to C-style strings.
35 ..signature:String<TValue, CStyle>
36 ..param.TValue:The value type, that is the type of the items/characters stored in the string.
37 ...remarks:Use @Metafunction.Value@ to get the value type for a given class.
38 ...note:$TValue$ must be a simple type.???(Link)
39 ..remarks:
40 ...text:The purpose of this class is to access to the content of a sequence 
41 in a "zero terminated string" style. 
42 This can be useful if SEQAN classes has to be integrated in programs that use $char$ arrays
43 to store strings.
44 Instances of $String<TValue, CStyle>$ can implicitely converted to a $TValue *$ that
45 points to a zero terminated CStyle of $TValue$. 
46 ...text:The stored c-style string object can be set by constructors or assignment. 
47 The content of a c-style string can eighter be stored in a separate buffer, that is the source string
48 is copied. Or the buffer of the source string itself is used instead, in this case the c-style string
49 depends on the source string and gets invalid as soon as the buffer of the source string is destroyed.
50 ...text:Hence, this class is a kind of adaptor from an arbitrary SEQAN string to char arrays.
51 Of course, the opposite way is possible too: 
52 Read @Adaption.char array.here@ about adapting char arrays to SEQAN strings.
53 ..example:
54 ...code://Create a string str:
55 String<char> str = "this is a test string";
56
57 //Create a c-style string object for str:
58 String<char, CStyle> c_style = str;
59
60 //Now use c_style as char array:
61 strcmp(c_style, "compare it to this string");
62 ...text:If the c-style string is needed only temporarily, the function $toCString$ can be used:
63 ...code:String<char> str = "this is a test string";
64 strcmp(toCString(str), "compare it to this string");
65 */
66
67 struct CStyle;
68
69 template <typename TValue>
70 class String <TValue, CStyle >
71 {
72 protected:
73         TValue * data_begin;
74         TValue * data_end;
75         size_t data_size; //if data_size > 0, then the buffer is owned by me and must be deallocated
76
77 public:
78         static TValue EMPTY_STRING;
79 //____________________________________________________________________________
80
81 public:
82         String():
83                 data_begin(&EMPTY_STRING),
84                 data_end(&EMPTY_STRING),
85                 data_size(0)
86         {
87 SEQAN_CHECKPOINT
88         }
89
90 //____________________________________________________________________________
91
92         template <typename TString>
93         String(TString & str):
94                 data_size(0)
95         {
96 SEQAN_CHECKPOINT
97                 assign(*this, str);
98         }
99         template <typename TString>
100         String(TString const & str):
101                 data_size(0)
102         {
103 SEQAN_CHECKPOINT
104                 assign(*this, str);
105         }
106
107         String(String & str):
108                 data_size(0)
109         {
110 SEQAN_CHECKPOINT
111                 assign(*this, str);
112         }
113         String(String const & str):
114                 data_size(0)
115         {
116 SEQAN_CHECKPOINT
117                 assign(*this, str);
118         }
119
120         String(TValue * str):
121                 data_begin(str),
122                 data_end(end(str)),
123                 data_size(0)
124         {
125 SEQAN_CHECKPOINT
126         }
127
128 //____________________________________________________________________________
129
130         template <typename TString>
131         String & operator = (TString & str)
132         {
133 SEQAN_CHECKPOINT
134                 assign(*this, str);
135                 return *this;
136         }
137         template <typename TString>
138         String & operator = (TString const & str)
139         {
140 SEQAN_CHECKPOINT
141                 assign(*this, str);
142                 return *this;
143         }
144         String & operator = (String & str)
145         {
146 SEQAN_CHECKPOINT
147                 assign(*this, str);
148                 return *this;
149         }
150         String & operator = (String const & str)
151         {
152 SEQAN_CHECKPOINT
153                 assign(*this, str);
154                 return *this;
155         }
156
157         ~String()
158         {
159 SEQAN_CHECKPOINT
160                 clear(*this);
161         }
162
163 //____________________________________________________________________________
164
165         operator TValue * ()
166         {
167 SEQAN_CHECKPOINT
168                 return data_begin;
169         }
170
171         operator TValue const * () const
172         {
173 SEQAN_CHECKPOINT
174                 return data_begin;
175         }
176
177 //____________________________________________________________________________
178
179         friend inline void 
180         move(
181                 String & target,
182                 String & source)
183         {
184 SEQAN_CHECKPOINT
185                 clear(target);
186
187                 target.data_begin = source.data_begin;
188                 target.data_end = source.data_end;
189                 target.data_size = source.data_size;
190
191                 source.data_begin = 0;
192                 source.data_end = 0;
193                 source.data_size = 0;
194         }
195
196 //____________________________________________________________________________
197
198         friend inline typename Iterator<String, Standard>::Type
199         begin(String & me,
200                 Standard)
201         {
202 SEQAN_CHECKPOINT
203                 return me.data_begin;
204         }
205         friend inline typename Iterator<String const, Standard>::Type
206         begin(String const & me,
207                 Standard)
208         {
209 SEQAN_CHECKPOINT
210                 return me.data_begin;
211         }
212
213 //____________________________________________________________________________
214
215         friend inline void
216         _setBegin(String & me, TValue * new_begin)
217         {
218 SEQAN_CHECKPOINT
219                 me.data_begin = new_begin;
220         }
221
222 //____________________________________________________________________________
223
224         friend inline typename Iterator<String, Standard>::Type
225         end(String & me,
226                 Standard)
227         {
228 SEQAN_CHECKPOINT
229                 return me.data_end;
230         }
231         friend inline typename Iterator<String const, Standard>::Type
232         end(String const & me,
233                 Standard)
234         {
235 SEQAN_CHECKPOINT
236                 return me.data_end;
237         }
238
239 //____________________________________________________________________________
240
241         friend inline void
242         _setEnd(String & me, TValue * new_end)
243         {
244 SEQAN_CHECKPOINT
245                 me.data_end = new_end;
246                 *new_end = TValue(); //??? ist das wirklich sinnvoll fuer typen, die weder char noch wchar_t sind?
247         }
248
249 //____________________________________________________________________________
250
251         friend inline size_t 
252         capacity(String const & me)
253         {
254 SEQAN_CHECKPOINT
255                 if (me.data_size) return me.data_size -1;
256                 else return me.data_end - me.data_begin;
257         }
258
259
260 //____________________________________________________________________________
261
262         friend inline void
263         clear(String & me)
264         {
265                 if (me.data_size)
266                 {
267 SEQAN_CHECKPOINT
268 //                      arrayDestruct(me, length(me)); 
269                         deallocate(me, me.data_begin, me.data_size);
270                         me.data_size = 0;
271                 }
272                 me.data_begin = me.data_end = &EMPTY_STRING;
273         }
274 //____________________________________________________________________________
275
276 //??? TODO: reserve
277
278 //____________________________________________________________________________
279
280 ///.Internal._reallocateStorage.param.object.type:Spec.CStyle String
281 ///.Internal._reallocateStorage.param.resize_tag.remarks:@Spec.CStyle String@ only supports @Tag.Overflow Strategy.exact@.
282 //this function works also for dependent buffers
283         friend inline TValue *
284         _reallocateStorage(
285                 String & me, 
286                 size_t new_capacity,
287                 Exact)
288         {
289 SEQAN_CHECKPOINT
290                 TValue * return_value;
291                 if (me.data_size)
292                 {//dependent
293                         return_value = me.data_begin;
294                 }
295                 else
296                 {//not dependent
297                         return_value = 0;
298                 }
299
300                 me.data_size = new_capacity + 1; //+1 for zero termination
301                 allocate(me, me.data_begin, me.data_size, TagAllocateStorage());
302                 return return_value;
303         }
304 //____________________________________________________________________________
305
306 ///.Internal._deallocateStorage.param.object.type:Spec.CStyle String
307
308         friend inline void 
309         _deallocateStorage(
310                 String & me, 
311                 TValue * ptr, 
312                 size_t capacity)
313         {
314 SEQAN_CHECKPOINT
315                 size_t size = capacity + 1;
316                 deallocate(me, ptr, size, TagAllocateStorage());
317         }
318
319 //____________________________________________________________________________
320
321 /**
322 .Function.dependent:
323 ..summary:Test whether object depends on other objects.
324 ..cat:Dependent Objects
325 ..signature:bool dependent(object)
326 ..param.object:An object.
327 ...type:Spec.CStyle String
328 ..returns:$true$ if $object$ depends one some other object, $false$ otherwise.
329 ..remarks:An object "$a$" depends on another object "$b$", if changing "$b$" can invalidate "$a$";
330 especially the destruction of "$b$" invalidates "$a$".
331 */
332         friend inline bool
333         dependent(String & me)
334         {
335 SEQAN_CHECKPOINT
336                 return (me.data_size == 0);
337         }
338 //____________________________________________________________________________
339
340 //special implementation for char array sources
341         friend inline void
342         assign(String & target,
343                 TValue * source)
344         {
345         SEQAN_CHECKPOINT
346                 clear(target);
347                 target.data_begin = source;
348                 target.data_end = end(source);
349         }
350
351 //____________________________________________________________________________
352
353 };
354
355 //////////////////////////////////////////////////////////////////////////////
356 // Define the static member
357
358 template <typename TValue>
359 TValue String<TValue, CStyle >::EMPTY_STRING = TValue();
360
361 //////////////////////////////////////////////////////////////////////////////
362 // Metafunctions
363 //////////////////////////////////////////////////////////////////////////////
364
365 template <typename TValue>
366 struct DefaultOverflowImplicit<String<TValue, CStyle> >
367 {
368         typedef Exact Type;
369 };
370
371 //////////////////////////////////////////////////////////////////////////////
372
373 template <typename TValue>
374 struct IsContiguous< String<TValue, CStyle > >
375 {
376     typedef True Type;
377         enum { VALUE = true };
378 };
379
380 //////////////////////////////////////////////////////////////////////////////
381 // assign
382 //////////////////////////////////////////////////////////////////////////////
383
384 template <typename TTargetValue, typename TSource, typename TExpand>
385 inline void
386 assign(String<TTargetValue, CStyle> & target,
387            TSource & source,
388            Tag<TExpand> const tag)
389 {
390 SEQAN_CHECKPOINT
391         create(target, source, tag);
392 }
393
394 template <typename TTargetValue, typename TSource, typename TExpand>
395 inline void
396 assign(String<TTargetValue, CStyle> & target,
397            TSource const & source,
398            Tag<TExpand> const tag)
399 {
400 SEQAN_CHECKPOINT
401         create(target, source, tag);
402 }
403
404 template <typename TTargetValue, typename TSource, typename TSize, typename TExpand>
405 inline void
406 assign(String<TTargetValue, CStyle> & target,
407            TSource & source,
408            TSize limit,
409            Tag<TExpand> const tag)
410 {
411 SEQAN_CHECKPOINT
412         create(target, source, tag);
413 }
414
415 template <typename TTargetValue, typename TSource, typename TSize, typename TExpand>
416 inline void
417 assign(String<TTargetValue, CStyle> & target,
418            TSource const & source,
419            TSize limit,
420            Tag<TExpand> const tag)
421 {
422 SEQAN_CHECKPOINT
423         create(target, source, limit, tag);
424 }
425
426
427 //____________________________________________________________________________
428 //this variant is a workaround for the "const array"-bug of VC++
429
430 template <typename TTargetValue, typename TSourceValue, typename TExpand>
431 inline void
432 assign(String<TTargetValue, CStyle> & target,
433            TSourceValue const * source, 
434            Tag<TExpand> const tag)
435 {
436 SEQAN_CHECKPOINT
437         create(target, source, tag);
438 }
439
440 template <typename TTargetValue, typename TSourceValue, typename TSize, typename TExpand>
441 inline void
442 assign(String<TTargetValue, CStyle> & target,
443            TSourceValue const * source,
444            TSize limit,
445            Tag<TExpand> const tag)
446 {
447 SEQAN_CHECKPOINT
448         create(target, source, limit, tag);
449 }
450
451 //////////////////////////////////////////////////////////////////////////////
452
453 //If source is non-const String, then there could be the possibility
454 //to use the source buffer
455
456 template <typename TExpand, bool IS_CONTIGUOUS>
457 struct _Assign_String_2_StringArray;
458
459 //____________________________________________________________________________
460
461 template <typename TExpand>
462 struct _Assign_String_2_StringArray<TExpand, true>
463 {
464         template <typename TValue, typename TSourceSpec>
465         static inline void
466         assign_(String<TValue, CStyle> & target,
467                 String<TValue, TSourceSpec> & source)
468         {
469                 if (capacity(source) > length(source))
470                 {//use source's buffer
471 SEQAN_CHECKPOINT
472                         clear(target);
473                         _setBegin(target, begin(source));
474                         _setEnd(target, end(source));
475                 }
476                 else
477                 {
478                         create(target, source, TExpand());
479                 }
480         }
481
482 //special treatment of char:
483 //_computeSize4Capacity is specialized for char such that there
484 //is enough place for the zero termination
485
486         template <typename TSourceSpec>
487         static inline void
488         assign_(String<char, CStyle> & target,
489                 String<char, TSourceSpec> & source)
490         {
491 SEQAN_CHECKPOINT
492                 clear(target);
493                 _setBegin(target, begin(source));
494                 _setEnd(target, end(source));
495         }
496 };
497
498 //____________________________________________________________________________
499
500 template <typename TExpand>
501 struct _Assign_String_2_StringArray<TExpand, false>
502 {
503         template <typename TValue, typename TSourceSpec>
504         static inline void
505         assign_(String<TValue, CStyle> & target,
506                 String<TValue, TSourceSpec> & source)
507         {
508 SEQAN_CHECKPOINT
509                 create(target, source, TExpand());
510         }
511 };
512
513 //____________________________________________________________________________
514
515 template <typename TValue, typename TSourceSpec, typename TExpand>
516 inline void
517 assign(String<TValue, CStyle> & target,
518         String<TValue, TSourceSpec> & source,
519         Tag<TExpand> const)
520 {
521         typedef String<TValue, TSourceSpec> TSource;
522         _Assign_String_2_StringArray<Tag<TExpand> const, IsContiguous<TSource>::VALUE>::assign_(target, source);
523 }
524
525
526 //////////////////////////////////////////////////////////////////////////////
527 // create
528 //////////////////////////////////////////////////////////////////////////////
529
530 //see basic_holder
531 /**
532 .Function.create:
533 ..signature:create(target, source [, limit] [,resize_tag])
534 ..param.target: Gets a copy of the content of $source$.
535 ...type:Spec.CStyle String
536 ..param.source: Is copied to $target$.
537 ..param.limit: The maximal length of $target$ after the operation. (optional)
538 ..param.resize_tag: Specifies the strategy that is applied if $target$ has not enough capacity to store the complete content. (optional)
539 ...type:Tag.Overflow Strategy
540 ...default:Specified by @Metafunction.DefaultOverflowImplicit@ of the $target$ type.
541 ..remarks.text:It is guaranteed, that after calling this function $source$ and $target$ can be used independently.
542 ..see:Spec.CStyle String
543 */
544
545 template <typename TExpand>
546 struct _Create_ArrayString_Expand
547 {
548         template <typename TTarget, typename TSource>
549         static inline void
550         create_(TTarget & target, 
551                 TSource & source)
552         {
553                 typename Size<TTarget>::Type source_length = length(source);
554                 if (dependent(target) || (capacity(target) < source_length))
555                 {
556 SEQAN_CHECKPOINT
557                         typename Size<TTarget>::Type old_target_capacity = capacity(target);
558                         typename Value<TTarget>::Type * buf = _reallocateStorage(target, source_length, TExpand());
559                         if (buf)
560                         {
561                                 _deallocateStorage(target, buf, old_target_capacity);
562                         }
563                 }
564                 if (length(source) > 0)
565                 {
566                         assignValue(begin(target, Standard()), 0); //set target length to 0
567                         assign(begin(target, Standard()), source, Insist());
568                         _setEnd(target, begin(target) + source_length);
569                 }
570         }
571
572         template <typename TTarget, typename TSource, typename TLimit>
573         static inline void
574         create_(TTarget & target, 
575                 TSource & source,
576                 TLimit limit)
577         {
578                 typename Size<TTarget>::Type copy_length = length(source);
579                 if (limit < copy_length)
580                 {
581                         copy_length = limit;
582                 }
583                 if (dependent(target) || (capacity(target) < copy_length))
584                 {
585 SEQAN_CHECKPOINT
586                         typename Size<TTarget>::Type old_target_capacity = capacity(target);
587                         TTarget * buf = _reallocateStorage(target, copy_length, TExpand());
588                         if (buf)
589                         {
590                                 _deallocateStorage(target, buf, old_target_capacity);
591                         }
592                 }
593                 assign(begin(target, Standard()), source, copy_length, Insist());
594                 _setEnd(target, begin(target, Standard()) + copy_length);
595         }
596 };
597 //____________________________________________________________________________
598
599 template <typename TExpand>
600 struct _Create_ArrayString;
601 //____________________________________________________________________________
602
603 template <>
604 struct _Create_ArrayString<Insist>
605 {
606         template <typename TTarget, typename TSource>
607         static inline void
608         create_(TTarget & target, 
609                 TSource & source)
610         {
611 SEQAN_CHECKPOINT
612                 typename Size<TTarget>::Type source_length = length(source);
613                 if (dependent(target))
614                 {
615                         TTarget * buf = _reallocateStorage(target, source_length, Exact());
616                 }
617                 assign(begin(target, Standard()), source, source_length, Insist());
618                 _setEnd(target, begin(target, Standard()) + source_length);
619         }
620
621         template <typename TTarget, typename TSource, typename TSize>
622         static inline void
623         create_(TTarget & target, 
624                 TSource & source,
625                 TSize limit)
626         {
627 SEQAN_CHECKPOINT
628                 typename Size<TTarget>::Type copy_size = length(source);
629                 if (limit < copy_size)
630                 {
631                         copy_size = limit;
632                 }
633                 if (dependent(target))
634                 {
635                         TTarget * buf = _reallocateStorage(target, copy_size, Exact());
636                 }
637                 assign(begin(target, Standard()), source, copy_size, Insist());
638                 _setEnd(target, begin(target, Standard()) + copy_size);
639         }
640 };
641
642 //____________________________________________________________________________
643
644 template <>
645 struct _Create_ArrayString<Limit>
646 {
647         template <typename TTarget, typename TSource>
648         static inline void
649         create_(TTarget & target, 
650                 TSource & source)
651         {
652 SEQAN_CHECKPOINT
653                 _Create_ArrayString<Insist>::create_(target, source, capacity(target));
654         }
655
656         template <typename TTarget, typename TSource, typename TSize>
657         static inline void
658         create_(TTarget & target, 
659                 TSource & source,
660                 TSize & limit)
661         {
662 SEQAN_CHECKPOINT
663                 typename Size<TTarget>::Type copy_size = capacity(target);
664                 if (copy_size > limit)
665                 {
666                         copy_size = limit;
667                 }
668                 _Create_ArrayString<Insist>::create_(target, source, copy_size);
669         }
670 };
671 //____________________________________________________________________________
672
673 template <>
674 struct _Create_ArrayString<Exact>:
675         _Create_ArrayString_Expand<Exact>
676 {
677 };
678
679 //____________________________________________________________________________
680
681 template <>
682 struct _Create_ArrayString<Generous>:
683         _Create_ArrayString_Expand<Generous>
684 {
685 };
686
687 //____________________________________________________________________________
688
689 template <typename TTargetValue, typename TSource>
690 inline void
691 create(String<TTargetValue, CStyle> & target,
692            TSource & source)
693 {
694 SEQAN_CHECKPOINT
695         typedef String<TTargetValue, CStyle> TTarget;
696         create(target, source, typename DefaultOverflowImplicit<TTarget>::Type()); 
697 }
698
699 template <typename TTargetValue, typename TSource, typename TSize>
700 inline void
701 create(String<TTargetValue, CStyle> & target,
702            TSource & source,
703            TSize limit)
704 {
705 SEQAN_CHECKPOINT
706         typedef String<TTargetValue, CStyle> TTarget;
707         create(target, source, limit, typename DefaultOverflowImplicit<TTarget>::Type()); 
708 }
709
710 //____________________________________________________________________________
711
712 template <typename TTargetValue, typename TSource, typename TExpand>
713 inline void
714 create(String<TTargetValue, CStyle> & target,
715            TSource & source, 
716            Tag<TExpand> const)
717 {
718 SEQAN_CHECKPOINT
719         _Create_ArrayString<Tag<TExpand> const>::create_(target, source);
720 }
721
722 template <typename TTargetValue, typename TSource, typename TSize, typename TExpand>
723 inline void
724 create(String<TTargetValue, CStyle> & target,
725            TSource & source,
726            TSize limit,
727            Tag<TExpand> const)
728 {
729 SEQAN_CHECKPOINT
730         _Create_ArrayString<Tag<TExpand> const>::create_(target, source, limit);
731 }
732
733 template <typename TTargetValue, typename TSource, typename TExpand>
734 inline void
735 create(String<TTargetValue, CStyle> & target,
736            TSource const & source, 
737            Tag<TExpand> const)
738 {
739 SEQAN_CHECKPOINT
740         _Create_ArrayString<Tag<TExpand> const>::create_(target, source);
741 }
742
743 template <typename TTargetValue, typename TSource, typename TSize, typename TExpand>
744 inline void
745 create(String<TTargetValue, CStyle> & target,
746            TSource const & source,
747            TSize limit,
748            Tag<TExpand> const)
749 {
750 SEQAN_CHECKPOINT
751         _Create_ArrayString<Tag<TExpand> const>::create_(target, source, limit);
752 }
753
754 //____________________________________________________________________________
755 //this variant is a workaround for the "const array"-bug of VC++
756
757 template <typename TTargetValue, typename TSourceValue, typename TExpand>
758 inline void
759 create(String<TTargetValue, CStyle> & target,
760            TSourceValue const * source, 
761            Tag<TExpand> const)
762 {
763 SEQAN_CHECKPOINT
764         _Create_ArrayString<Tag<TExpand> const>::create_(target, source);
765 }
766
767 template <typename TTargetValue, typename TSourceValue, typename TSize, typename TExpand>
768 inline void
769 create(String<TTargetValue, CStyle> & target,
770            TSourceValue const * source,
771            TSize limit,
772            Tag<TExpand> const)
773 {
774 SEQAN_CHECKPOINT
775         _Create_ArrayString<Tag<TExpand> const>::create_(target, source, limit);
776 }
777
778 //////////////////////////////////////////////////////////////////////////////
779 // Shotcut
780
781 /**
782 .Function.toCString:
783 ..cat:Containers
784 ..summary:Access sequence as c-style string.
785 ..signature:toCString(object)
786 ..param.object:A sequence.
787 ...type:Class.String
788 ...type:Adaption.char array
789 ..returns:A temporary @Spec.CStyle String@ object of that was constructed for $object$.
790 ..remarks:Notational sugar.
791 */
792
793 template <typename T>
794 inline typename Value<T>::Type *
795 toCString(T & me)
796 {
797 SEQAN_CHECKPOINT
798         return String<typename Value<T>::Type, CStyle>(me);
799 }
800
801
802 //////////////////////////////////////////////////////////////////////////////
803
804 } //namespace SEQAN_NAMESPACE_MAIN
805
806 //____________________________________________________________________________
807
808 #endif //#ifndef SEQAN_HEADER_...