1 /*==========================================================================
2 SeqAn - The Library for Sequence Analysis
4 ============================================================================
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.
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.
17 ============================================================================
18 $Id: string_cstyle.h,v 1.1 2008/08/25 16:20:04 langmead Exp $
19 ==========================================================================*/
21 #ifndef SEQAN_HEADER_SEQUENCE_CSTYLE_H
22 #define SEQAN_HEADER_SEQUENCE_CSTYLE_H
24 namespace SEQAN_NAMESPACE_MAIN
27 //////////////////////////////////////////////////////////////////////////////
28 //string that exports an interface to cstyle 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)
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
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.
54 ...code://Create a string str:
55 String<char> str = "this is a test string";
57 //Create a c-style string object for str:
58 String<char, CStyle> c_style = str;
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");
69 template <typename TValue>
70 class String <TValue, CStyle >
75 size_t data_size; //if data_size > 0, then the buffer is owned by me and must be deallocated
78 static TValue EMPTY_STRING;
79 //____________________________________________________________________________
83 data_begin(&EMPTY_STRING),
84 data_end(&EMPTY_STRING),
90 //____________________________________________________________________________
92 template <typename TString>
93 String(TString & str):
99 template <typename TString>
100 String(TString const & str):
107 String(String & str):
113 String(String const & str):
120 String(TValue * str):
128 //____________________________________________________________________________
130 template <typename TString>
131 String & operator = (TString & str)
137 template <typename TString>
138 String & operator = (TString const & str)
144 String & operator = (String & str)
150 String & operator = (String const & str)
163 //____________________________________________________________________________
171 operator TValue const * () const
177 //____________________________________________________________________________
187 target.data_begin = source.data_begin;
188 target.data_end = source.data_end;
189 target.data_size = source.data_size;
191 source.data_begin = 0;
193 source.data_size = 0;
196 //____________________________________________________________________________
198 friend inline typename Iterator<String, Standard>::Type
203 return me.data_begin;
205 friend inline typename Iterator<String const, Standard>::Type
206 begin(String const & me,
210 return me.data_begin;
213 //____________________________________________________________________________
216 _setBegin(String & me, TValue * new_begin)
219 me.data_begin = new_begin;
222 //____________________________________________________________________________
224 friend inline typename Iterator<String, Standard>::Type
231 friend inline typename Iterator<String const, Standard>::Type
232 end(String const & me,
239 //____________________________________________________________________________
242 _setEnd(String & me, TValue * new_end)
245 me.data_end = new_end;
246 *new_end = TValue(); //??? ist das wirklich sinnvoll fuer typen, die weder char noch wchar_t sind?
249 //____________________________________________________________________________
252 capacity(String const & me)
255 if (me.data_size) return me.data_size -1;
256 else return me.data_end - me.data_begin;
260 //____________________________________________________________________________
268 // arrayDestruct(me, length(me));
269 deallocate(me, me.data_begin, me.data_size);
272 me.data_begin = me.data_end = &EMPTY_STRING;
274 //____________________________________________________________________________
278 //____________________________________________________________________________
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 *
290 TValue * return_value;
293 return_value = me.data_begin;
300 me.data_size = new_capacity + 1; //+1 for zero termination
301 allocate(me, me.data_begin, me.data_size, TagAllocateStorage());
304 //____________________________________________________________________________
306 ///.Internal._deallocateStorage.param.object.type:Spec.CStyle String
315 size_t size = capacity + 1;
316 deallocate(me, ptr, size, TagAllocateStorage());
319 //____________________________________________________________________________
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$".
333 dependent(String & me)
336 return (me.data_size == 0);
338 //____________________________________________________________________________
340 //special implementation for char array sources
342 assign(String & target,
347 target.data_begin = source;
348 target.data_end = end(source);
351 //____________________________________________________________________________
355 //////////////////////////////////////////////////////////////////////////////
356 // Define the static member
358 template <typename TValue>
359 TValue String<TValue, CStyle >::EMPTY_STRING = TValue();
361 //////////////////////////////////////////////////////////////////////////////
363 //////////////////////////////////////////////////////////////////////////////
365 template <typename TValue>
366 struct DefaultOverflowImplicit<String<TValue, CStyle> >
371 //////////////////////////////////////////////////////////////////////////////
373 template <typename TValue>
374 struct IsContiguous< String<TValue, CStyle > >
377 enum { VALUE = true };
380 //////////////////////////////////////////////////////////////////////////////
382 //////////////////////////////////////////////////////////////////////////////
384 template <typename TTargetValue, typename TSource, typename TExpand>
386 assign(String<TTargetValue, CStyle> & target,
388 Tag<TExpand> const tag)
391 create(target, source, tag);
394 template <typename TTargetValue, typename TSource, typename TExpand>
396 assign(String<TTargetValue, CStyle> & target,
397 TSource const & source,
398 Tag<TExpand> const tag)
401 create(target, source, tag);
404 template <typename TTargetValue, typename TSource, typename TSize, typename TExpand>
406 assign(String<TTargetValue, CStyle> & target,
409 Tag<TExpand> const tag)
412 create(target, source, tag);
415 template <typename TTargetValue, typename TSource, typename TSize, typename TExpand>
417 assign(String<TTargetValue, CStyle> & target,
418 TSource const & source,
420 Tag<TExpand> const tag)
423 create(target, source, limit, tag);
427 //____________________________________________________________________________
428 //this variant is a workaround for the "const array"-bug of VC++
430 template <typename TTargetValue, typename TSourceValue, typename TExpand>
432 assign(String<TTargetValue, CStyle> & target,
433 TSourceValue const * source,
434 Tag<TExpand> const tag)
437 create(target, source, tag);
440 template <typename TTargetValue, typename TSourceValue, typename TSize, typename TExpand>
442 assign(String<TTargetValue, CStyle> & target,
443 TSourceValue const * source,
445 Tag<TExpand> const tag)
448 create(target, source, limit, tag);
451 //////////////////////////////////////////////////////////////////////////////
453 //If source is non-const String, then there could be the possibility
454 //to use the source buffer
456 template <typename TExpand, bool IS_CONTIGUOUS>
457 struct _Assign_String_2_StringArray;
459 //____________________________________________________________________________
461 template <typename TExpand>
462 struct _Assign_String_2_StringArray<TExpand, true>
464 template <typename TValue, typename TSourceSpec>
466 assign_(String<TValue, CStyle> & target,
467 String<TValue, TSourceSpec> & source)
469 if (capacity(source) > length(source))
470 {//use source's buffer
473 _setBegin(target, begin(source));
474 _setEnd(target, end(source));
478 create(target, source, TExpand());
482 //special treatment of char:
483 //_computeSize4Capacity is specialized for char such that there
484 //is enough place for the zero termination
486 template <typename TSourceSpec>
488 assign_(String<char, CStyle> & target,
489 String<char, TSourceSpec> & source)
493 _setBegin(target, begin(source));
494 _setEnd(target, end(source));
498 //____________________________________________________________________________
500 template <typename TExpand>
501 struct _Assign_String_2_StringArray<TExpand, false>
503 template <typename TValue, typename TSourceSpec>
505 assign_(String<TValue, CStyle> & target,
506 String<TValue, TSourceSpec> & source)
509 create(target, source, TExpand());
513 //____________________________________________________________________________
515 template <typename TValue, typename TSourceSpec, typename TExpand>
517 assign(String<TValue, CStyle> & target,
518 String<TValue, TSourceSpec> & source,
521 typedef String<TValue, TSourceSpec> TSource;
522 _Assign_String_2_StringArray<Tag<TExpand> const, IsContiguous<TSource>::VALUE>::assign_(target, source);
526 //////////////////////////////////////////////////////////////////////////////
528 //////////////////////////////////////////////////////////////////////////////
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
545 template <typename TExpand>
546 struct _Create_ArrayString_Expand
548 template <typename TTarget, typename TSource>
550 create_(TTarget & target,
553 typename Size<TTarget>::Type source_length = length(source);
554 if (dependent(target) || (capacity(target) < source_length))
557 typename Size<TTarget>::Type old_target_capacity = capacity(target);
558 typename Value<TTarget>::Type * buf = _reallocateStorage(target, source_length, TExpand());
561 _deallocateStorage(target, buf, old_target_capacity);
564 if (length(source) > 0)
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);
572 template <typename TTarget, typename TSource, typename TLimit>
574 create_(TTarget & target,
578 typename Size<TTarget>::Type copy_length = length(source);
579 if (limit < copy_length)
583 if (dependent(target) || (capacity(target) < copy_length))
586 typename Size<TTarget>::Type old_target_capacity = capacity(target);
587 TTarget * buf = _reallocateStorage(target, copy_length, TExpand());
590 _deallocateStorage(target, buf, old_target_capacity);
593 assign(begin(target, Standard()), source, copy_length, Insist());
594 _setEnd(target, begin(target, Standard()) + copy_length);
597 //____________________________________________________________________________
599 template <typename TExpand>
600 struct _Create_ArrayString;
601 //____________________________________________________________________________
604 struct _Create_ArrayString<Insist>
606 template <typename TTarget, typename TSource>
608 create_(TTarget & target,
612 typename Size<TTarget>::Type source_length = length(source);
613 if (dependent(target))
615 TTarget * buf = _reallocateStorage(target, source_length, Exact());
617 assign(begin(target, Standard()), source, source_length, Insist());
618 _setEnd(target, begin(target, Standard()) + source_length);
621 template <typename TTarget, typename TSource, typename TSize>
623 create_(TTarget & target,
628 typename Size<TTarget>::Type copy_size = length(source);
629 if (limit < copy_size)
633 if (dependent(target))
635 TTarget * buf = _reallocateStorage(target, copy_size, Exact());
637 assign(begin(target, Standard()), source, copy_size, Insist());
638 _setEnd(target, begin(target, Standard()) + copy_size);
642 //____________________________________________________________________________
645 struct _Create_ArrayString<Limit>
647 template <typename TTarget, typename TSource>
649 create_(TTarget & target,
653 _Create_ArrayString<Insist>::create_(target, source, capacity(target));
656 template <typename TTarget, typename TSource, typename TSize>
658 create_(TTarget & target,
663 typename Size<TTarget>::Type copy_size = capacity(target);
664 if (copy_size > limit)
668 _Create_ArrayString<Insist>::create_(target, source, copy_size);
671 //____________________________________________________________________________
674 struct _Create_ArrayString<Exact>:
675 _Create_ArrayString_Expand<Exact>
679 //____________________________________________________________________________
682 struct _Create_ArrayString<Generous>:
683 _Create_ArrayString_Expand<Generous>
687 //____________________________________________________________________________
689 template <typename TTargetValue, typename TSource>
691 create(String<TTargetValue, CStyle> & target,
695 typedef String<TTargetValue, CStyle> TTarget;
696 create(target, source, typename DefaultOverflowImplicit<TTarget>::Type());
699 template <typename TTargetValue, typename TSource, typename TSize>
701 create(String<TTargetValue, CStyle> & target,
706 typedef String<TTargetValue, CStyle> TTarget;
707 create(target, source, limit, typename DefaultOverflowImplicit<TTarget>::Type());
710 //____________________________________________________________________________
712 template <typename TTargetValue, typename TSource, typename TExpand>
714 create(String<TTargetValue, CStyle> & target,
719 _Create_ArrayString<Tag<TExpand> const>::create_(target, source);
722 template <typename TTargetValue, typename TSource, typename TSize, typename TExpand>
724 create(String<TTargetValue, CStyle> & target,
730 _Create_ArrayString<Tag<TExpand> const>::create_(target, source, limit);
733 template <typename TTargetValue, typename TSource, typename TExpand>
735 create(String<TTargetValue, CStyle> & target,
736 TSource const & source,
740 _Create_ArrayString<Tag<TExpand> const>::create_(target, source);
743 template <typename TTargetValue, typename TSource, typename TSize, typename TExpand>
745 create(String<TTargetValue, CStyle> & target,
746 TSource const & source,
751 _Create_ArrayString<Tag<TExpand> const>::create_(target, source, limit);
754 //____________________________________________________________________________
755 //this variant is a workaround for the "const array"-bug of VC++
757 template <typename TTargetValue, typename TSourceValue, typename TExpand>
759 create(String<TTargetValue, CStyle> & target,
760 TSourceValue const * source,
764 _Create_ArrayString<Tag<TExpand> const>::create_(target, source);
767 template <typename TTargetValue, typename TSourceValue, typename TSize, typename TExpand>
769 create(String<TTargetValue, CStyle> & target,
770 TSourceValue const * source,
775 _Create_ArrayString<Tag<TExpand> const>::create_(target, source, limit);
778 //////////////////////////////////////////////////////////////////////////////
784 ..summary:Access sequence as c-style string.
785 ..signature:toCString(object)
786 ..param.object:A sequence.
788 ...type:Adaption.char array
789 ..returns:A temporary @Spec.CStyle String@ object of that was constructed for $object$.
790 ..remarks:Notational sugar.
793 template <typename T>
794 inline typename Value<T>::Type *
798 return String<typename Value<T>::Type, CStyle>(me);
802 //////////////////////////////////////////////////////////////////////////////
804 } //namespace SEQAN_NAMESPACE_MAIN
806 //____________________________________________________________________________
808 #endif //#ifndef SEQAN_HEADER_...