1 //  (C) Copyright Gennadiy Rozental 2004-2008.
2 //  Distributed under the Boost Software License, Version 1.0.
3 //  (See accompanying file LICENSE_1_0.txt or copy at
4 //  http://www.boost.org/LICENSE_1_0.txt)
5 
6 //  See http://www.boost.org/libs/test for the library home page.
7 //
8 //  File        : $RCSfile$
9 //
10 //  Version     : $Revision: 57992 $
11 //
12 //  Description : class basic_cstring wraps C string and provide std_string like
13 //                interface
14 // ***************************************************************************
15 
16 #ifndef BOOST_TEST_BASIC_CSTRING_HPP_071894GER
17 #define BOOST_TEST_BASIC_CSTRING_HPP_071894GER
18 
19 // Boost.Test
20 #include <boost/test/utils/basic_cstring/basic_cstring_fwd.hpp>
21 #include <boost/test/utils/basic_cstring/bcs_char_traits.hpp>
22 
23 // STL
24 #include <string>
25 
26 #include <boost/test/detail/suppress_warnings.hpp>
27 
28 //____________________________________________________________________________//
29 
30 namespace boost {
31 
32 namespace unit_test {
33 
34 // ************************************************************************** //
35 // **************                basic_cstring                 ************** //
36 // ************************************************************************** //
37 
38 template<typename CharT>
39 class basic_cstring {
40     typedef basic_cstring<CharT>                        self_type;
41 public:
42     // Subtypes
43     typedef ut_detail::bcs_char_traits<CharT>           traits_type;
44     typedef typename ut_detail::bcs_char_traits<CharT>::std_string  std_string;
45 
46     typedef CharT                                       value_type;
47     typedef value_type*                                 pointer;
48     typedef value_type const*                           const_pointer;
49     typedef value_type&                                 reference;
50     typedef const value_type&                           const_reference;
51     typedef std::size_t                                 size_type;
52     typedef std::ptrdiff_t                              difference_type;
53 
54     typedef value_type const*                           const_iterator;
55     typedef value_type*                                 iterator;
56 
57     // !! should also present reverse_iterator, const_reverse_iterator
58 
59 #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
60     enum npos_type { npos = static_cast<size_type>(-1) };
61 #else
62     // IBM/VisualAge version 6 is not able to handle enums larger than 4 bytes.
63     // But size_type is 8 bytes in 64bit mode.
64     static const size_type npos = -1 ;
65 #endif
66 
67     static pointer  null_str();
68 
69     // Constructors; default copy constructor is generated by compiler
70     basic_cstring();
71     basic_cstring( std_string const& s );
72     basic_cstring( pointer s );
73     basic_cstring( pointer s, size_type arg_size );
74     basic_cstring( pointer first, pointer last );
75 
76     // data access methods
77     value_type      operator[]( size_type index ) const;
78     value_type      at( size_type index ) const;
79 
80     // size operators
81     size_type       size() const;
82     bool            is_empty() const;
83     void            clear();
84     void            resize( size_type new_len );
85 
86     // !! only for STL container conformance use is_empty instead
87     bool            empty() const;
88 
89     // Trimming
90     self_type&      trim_right( size_type trim_size );
91     self_type&      trim_left( size_type trim_size );
92     self_type&      trim_right( iterator it );
93     self_type&      trim_left( iterator it );
94 #ifndef __IBMCPP__
95     self_type&      trim_left( self_type exclusions = self_type() ) ;
96     self_type&      trim_right( self_type exclusions = self_type() ) ;
97     self_type&      trim( self_type exclusions = self_type() ) ;
98 #else
99     // VisualAge version 6 has in this case a problem with the default arguments.
100     self_type&      trim_left( self_type exclusions ) ;
101     self_type&      trim_right( self_type exclusions ) ;
102     self_type&      trim( self_type exclusions ) ;
trim_left()103     self_type&      trim_left() { trim_left( self_type() ) ; }
trim_right()104     self_type&      trim_right() { trim_right( self_type() ) ; }
trim()105     self_type&      trim() { trim( self_type() ) ; }
106 #endif
107 
108     // Assignment operators
109     basic_cstring&  operator=( self_type const& s );
110     basic_cstring&  operator=( std_string const& s );
111     basic_cstring&  operator=( pointer s );
112 
113     template<typename CharT2>
assign(basic_cstring<CharT2> const & s)114     basic_cstring&  assign( basic_cstring<CharT2> const& s ) { *this = basic_cstring<CharT>( s.begin(), s.end() ); return *this; }
115     basic_cstring&  assign( self_type const& s, size_type pos, size_type len );
116     basic_cstring&  assign( std_string const& s );
117     basic_cstring&  assign( std_string const& s, size_type pos, size_type len );
118     basic_cstring&  assign( pointer s );
119     basic_cstring&  assign( pointer s, size_type len );
120     basic_cstring&  assign( pointer f, pointer l );
121 
122     // swapping
123     void            swap( self_type& s );
124 
125     // Iterators
126     iterator        begin();
127     const_iterator  begin() const;
128     iterator        end();
129     const_iterator  end() const;
130 
131     // !! should have rbegin, rend
132 
133     // substring search operation
134     size_type       find( basic_cstring ) const;
135     size_type       rfind( basic_cstring ) const;
136     self_type       substr( size_type beg_index, size_type end_index = npos ) const;
137 
138 private:
139     static self_type default_trim_ex();
140 
141     // Data members
142     iterator        m_begin;
143     iterator        m_end;
144 };
145 
146 //____________________________________________________________________________//
147 
148 template<typename CharT>
149 inline typename basic_cstring<CharT>::pointer
null_str()150 basic_cstring<CharT>::null_str()
151 {
152     static CharT null = 0;
153     return &null;
154 }
155 
156 //____________________________________________________________________________//
157 
158 template<typename CharT>
159 inline
basic_cstring()160 basic_cstring<CharT>::basic_cstring()
161 : m_begin( null_str() )
162 , m_end( m_begin )
163 {
164 }
165 
166 //____________________________________________________________________________//
167 
168 template<typename CharT>
169 inline
basic_cstring(std_string const & s)170 basic_cstring<CharT>::basic_cstring( std_string const& s )
171 : m_begin( s.c_str() )
172 , m_end( m_begin + s.size() )
173 {
174 }
175 
176 //____________________________________________________________________________//
177 
178 template<typename CharT>
179 inline
basic_cstring(pointer s)180 basic_cstring<CharT>::basic_cstring( pointer s )
181 : m_begin( s ? s : null_str() )
182 , m_end  ( m_begin + (s ? traits_type::length( s ) : 0 ) )
183 {
184 }
185 
186 //____________________________________________________________________________//
187 
188 template<typename CharT>
189 inline
basic_cstring(pointer s,size_type arg_size)190 basic_cstring<CharT>::basic_cstring( pointer s, size_type arg_size )
191 : m_begin( s ), m_end( m_begin + arg_size )
192 {
193 }
194 
195 //____________________________________________________________________________//
196 
197 template<typename CharT>
198 inline
basic_cstring(pointer first,pointer last)199 basic_cstring<CharT>::basic_cstring( pointer first, pointer last )
200 : m_begin( first )
201 , m_end( last )
202 {
203 }
204 
205 //____________________________________________________________________________//
206 
207 template<typename CharT>
208 inline typename basic_cstring<CharT>::value_type
operator [](size_type index) const209 basic_cstring<CharT>::operator[]( size_type index ) const
210 {
211     return m_begin[index];
212 }
213 
214 //____________________________________________________________________________//
215 
216 template<typename CharT>
217 inline typename basic_cstring<CharT>::value_type
at(size_type index) const218 basic_cstring<CharT>::at( size_type index ) const
219 {
220     if( m_begin + index >= m_end )
221         return static_cast<value_type>(0);
222 
223     return m_begin[index];
224 }
225 
226 //____________________________________________________________________________//
227 
228 template<typename CharT>
229 inline typename basic_cstring<CharT>::size_type
size() const230 basic_cstring<CharT>::size() const
231 {
232     return m_end - m_begin;
233 }
234 
235 //____________________________________________________________________________//
236 
237 template<typename CharT>
238 inline bool
is_empty() const239 basic_cstring<CharT>::is_empty() const
240 {
241     return m_end == m_begin;
242 }
243 
244 //____________________________________________________________________________//
245 
246 template<typename CharT>
247 inline bool
empty() const248 basic_cstring<CharT>::empty() const
249 {
250     return is_empty();
251 }
252 
253 //____________________________________________________________________________//
254 
255 template<typename CharT>
256 inline void
clear()257 basic_cstring<CharT>::clear()
258 {
259     m_begin = m_end;
260 }
261 
262 //____________________________________________________________________________//
263 
264 template<typename CharT>
265 inline void
resize(size_type new_len)266 basic_cstring<CharT>::resize( size_type new_len )
267 {
268     if( m_begin + new_len < m_end )
269         m_end = m_begin + new_len;
270 }
271 
272 //____________________________________________________________________________//
273 
274 template<typename CharT>
275 inline basic_cstring<CharT>&
trim_left(size_type trim_size)276 basic_cstring<CharT>::trim_left( size_type trim_size )
277 {
278     m_begin += trim_size;
279     if( m_end <= m_begin )
280         clear();
281 
282     return *this;
283 }
284 
285 //____________________________________________________________________________//
286 
287 template<typename CharT>
288 inline basic_cstring<CharT>&
trim_left(iterator it)289 basic_cstring<CharT>::trim_left( iterator it )
290 {
291     m_begin = it;
292     if( m_end <= m_begin )
293         clear();
294 
295     return *this;
296 }
297 
298 //____________________________________________________________________________//
299 
300 template<typename CharT>
301 inline basic_cstring<CharT>&
trim_left(basic_cstring exclusions)302 basic_cstring<CharT>::trim_left( basic_cstring exclusions )
303 {
304     if( exclusions.is_empty() )
305         exclusions = default_trim_ex();
306 
307     iterator it;
308     for( it = begin(); it != end(); ++it ) {
309         if( traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
310             break;
311     }
312 
313     return trim_left( it );
314 }
315 
316 //____________________________________________________________________________//
317 
318 template<typename CharT>
319 inline basic_cstring<CharT>&
trim_right(size_type trim_size)320 basic_cstring<CharT>::trim_right( size_type trim_size )
321 {
322     m_end  -= trim_size;
323     if( m_end <= m_begin )
324         clear();
325 
326     return *this;
327 }
328 
329 //____________________________________________________________________________//
330 
331 template<typename CharT>
332 inline basic_cstring<CharT>&
trim_right(iterator it)333 basic_cstring<CharT>::trim_right( iterator it )
334 {
335     m_end = it;
336     if( m_end <= m_begin )
337         clear();
338 
339     return *this;
340 }
341 
342 //____________________________________________________________________________//
343 
344 template<typename CharT>
345 inline basic_cstring<CharT>&
trim_right(basic_cstring exclusions)346 basic_cstring<CharT>::trim_right( basic_cstring exclusions )
347 {
348     if( exclusions.is_empty() )
349         exclusions = default_trim_ex();
350 
351     iterator it;
352 
353     for( it = end()-1; it != begin()-1; --it ) {
354         if( self_type::traits_type::find( exclusions.begin(),  exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
355             break;
356     }
357 
358     return trim_right( it+1 );
359 }
360 
361 //____________________________________________________________________________//
362 
363 template<typename CharT>
364 inline basic_cstring<CharT>&
trim(basic_cstring exclusions)365 basic_cstring<CharT>::trim( basic_cstring exclusions )
366 {
367     trim_left( exclusions );
368     trim_right( exclusions );
369 
370     return *this;
371 }
372 
373 //____________________________________________________________________________//
374 
375 template<typename CharT>
376 inline basic_cstring<CharT>&
operator =(basic_cstring<CharT> const & s)377 basic_cstring<CharT>::operator=( basic_cstring<CharT> const& s )
378 {
379     m_begin = s.m_begin;
380     m_end   = s.m_end;
381 
382     return *this;
383 }
384 
385 //____________________________________________________________________________//
386 
387 template<typename CharT>
388 inline basic_cstring<CharT>&
operator =(std_string const & s)389 basic_cstring<CharT>::operator=( std_string const& s )
390 {
391     return *this = self_type( s );
392 }
393 
394 //____________________________________________________________________________//
395 
396 template<typename CharT>
397 inline basic_cstring<CharT>&
operator =(pointer s)398 basic_cstring<CharT>::operator=( pointer s )
399 {
400     return *this = self_type( s );
401 }
402 
403 //____________________________________________________________________________//
404 
405 template<typename CharT>
406 inline basic_cstring<CharT>&
assign(basic_cstring<CharT> const & s,size_type pos,size_type len)407 basic_cstring<CharT>::assign( basic_cstring<CharT> const& s, size_type pos, size_type len )
408 {
409     return *this = self_type( s.m_begin + pos, len );
410 }
411 
412 //____________________________________________________________________________//
413 
414 template<typename CharT>
415 inline basic_cstring<CharT>&
assign(std_string const & s)416 basic_cstring<CharT>::assign( std_string const& s )
417 {
418     return *this = self_type( s );
419 }
420 
421 //____________________________________________________________________________//
422 
423 template<typename CharT>
424 inline basic_cstring<CharT>&
assign(std_string const & s,size_type pos,size_type len)425 basic_cstring<CharT>::assign( std_string const& s, size_type pos, size_type len )
426 {
427     return *this = self_type( s.c_str() + pos, len );
428 }
429 
430 //____________________________________________________________________________//
431 
432 template<typename CharT>
433 inline basic_cstring<CharT>&
assign(pointer s)434 basic_cstring<CharT>::assign( pointer s )
435 {
436     return *this = self_type( s );
437 }
438 
439 //____________________________________________________________________________//
440 
441 template<typename CharT>
442 inline basic_cstring<CharT>&
assign(pointer s,size_type len)443 basic_cstring<CharT>::assign( pointer s, size_type len )
444 {
445     return *this = self_type( s, len );
446 }
447 
448 //____________________________________________________________________________//
449 
450 template<typename CharT>
451 inline basic_cstring<CharT>&
assign(pointer f,pointer l)452 basic_cstring<CharT>::assign( pointer f, pointer l )
453 {
454     return *this = self_type( f, l );
455 }
456 
457 //____________________________________________________________________________//
458 
459 template<typename CharT>
460 inline void
swap(basic_cstring<CharT> & s)461 basic_cstring<CharT>::swap( basic_cstring<CharT>& s )
462 {
463     // do not want to include alogrithm
464     pointer tmp1    = m_begin;
465     pointer tmp2    = m_end;
466 
467     m_begin         = s.m_begin;
468     m_end           = s.m_end;
469 
470     s.m_begin       = tmp1;
471     s.m_end         = tmp2;
472 }
473 
474 //____________________________________________________________________________//
475 
476 template<typename CharT>
477 inline typename basic_cstring<CharT>::iterator
begin()478 basic_cstring<CharT>::begin()
479 {
480     return m_begin;
481 }
482 
483 //____________________________________________________________________________//
484 
485 template<typename CharT>
486 inline typename basic_cstring<CharT>::const_iterator
begin() const487 basic_cstring<CharT>::begin() const
488 {
489     return m_begin;
490 }
491 
492 //____________________________________________________________________________//
493 
494 template<typename CharT>
495 inline typename basic_cstring<CharT>::iterator
end()496 basic_cstring<CharT>::end()
497 {
498     return m_end;
499 }
500 
501 //____________________________________________________________________________//
502 
503 template<typename CharT>
504 inline typename basic_cstring<CharT>::const_iterator
end() const505 basic_cstring<CharT>::end() const
506 {
507     return m_end;
508 }
509 
510 //____________________________________________________________________________//
511 
512 template<typename CharT>
513 inline typename basic_cstring<CharT>::size_type
find(basic_cstring<CharT> str) const514 basic_cstring<CharT>::find( basic_cstring<CharT> str ) const
515 {
516     if( str.is_empty() || str.size() > size() )
517         return static_cast<size_type>(npos);
518 
519     const_iterator it   = begin();
520     const_iterator last = end() - str.size() + 1;
521 
522     while( it != last ) {
523         if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
524             break;
525 
526         ++it;
527     }
528 
529     return it == last ? static_cast<size_type>(npos) : it - begin();
530 }
531 
532 //____________________________________________________________________________//
533 
534 template<typename CharT>
535 inline typename basic_cstring<CharT>::size_type
rfind(basic_cstring<CharT> str) const536 basic_cstring<CharT>::rfind( basic_cstring<CharT> str ) const
537 {
538     if( str.is_empty() || str.size() > size() )
539         return static_cast<size_type>(npos);
540 
541     const_iterator it   = end() - str.size();
542     const_iterator last = begin()-1;
543 
544     while( it != last ) {
545         if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
546             break;
547 
548         --it;
549     }
550 
551     return it == last ? static_cast<size_type>(npos) : static_cast<size_type>(it - begin());
552 }
553 
554 //____________________________________________________________________________//
555 
556 template<typename CharT>
557 inline basic_cstring<CharT>
substr(size_type beg_index,size_type end_index) const558 basic_cstring<CharT>::substr( size_type beg_index, size_type end_index ) const
559 {
560     return beg_index > size()
561             ?       self_type()
562             : end_index > size()
563                 ?   self_type( m_begin + beg_index, m_end )
564                 :   self_type( m_begin + beg_index, m_begin + end_index );
565 }
566 
567 //____________________________________________________________________________//
568 
569 template<typename CharT>
570 inline basic_cstring<CharT>
default_trim_ex()571 basic_cstring<CharT>::default_trim_ex()
572 {
573     static CharT ws[3] = { CharT(' '), CharT('\t'), CharT('\n') }; // !! wide case
574 
575     return self_type( ws, 3 );
576 }
577 
578 //____________________________________________________________________________//
579 
580 // ************************************************************************** //
581 // **************             comparison operators             ************** //
582 // ************************************************************************** //
583 
584 template<typename CharT1,typename CharT2>
585 inline bool
operator ==(basic_cstring<CharT1> const & s1,basic_cstring<CharT2> const & s2)586 operator==( basic_cstring<CharT1> const& s1, basic_cstring<CharT2> const& s2 )
587 {
588     typedef typename basic_cstring<CharT1>::traits_type traits_type;
589     return s1.size() == s2.size() &&
590                traits_type::compare( s1.begin(), s2.begin(), s1.size() ) == 0;
591 }
592 
593 //____________________________________________________________________________//
594 
595 template<typename CharT1,typename CharT2>
596 inline bool
operator ==(basic_cstring<CharT1> const & s1,CharT2 * s2)597 operator==( basic_cstring<CharT1> const& s1, CharT2* s2 )
598 {
599 #if !defined(__DMC__)
600     return s1 == basic_cstring<CharT2>( s2 );
601 #else
602     return s1 == basic_cstring<CharT2 const>( s2 );
603 #endif
604 }
605 
606 //____________________________________________________________________________//
607 
608 template<typename CharT>
609 inline bool
operator ==(basic_cstring<CharT> const & s1,typename basic_cstring<CharT>::std_string const & s2)610 operator==( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
611 {
612     return s1 == basic_cstring<CharT>( s2 );
613 }
614 
615 //____________________________________________________________________________//
616 
617 template<typename CharT1,typename CharT2>
618 inline bool
operator ==(CharT1 * s2,basic_cstring<CharT2> const & s1)619 operator==( CharT1* s2, basic_cstring<CharT2> const& s1 )
620 {
621     return s1 == s2;
622 }
623 
624 //____________________________________________________________________________//
625 
626 template<typename CharT>
627 inline bool
operator ==(typename basic_cstring<CharT>::std_string const & s2,basic_cstring<CharT> const & s1)628 operator==( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
629 {
630     return s1 == s2;
631 }
632 
633 //____________________________________________________________________________//
634 
635 template<typename CharT>
636 inline bool
operator !=(basic_cstring<CharT> const & s1,CharT * s2)637 operator!=( basic_cstring<CharT> const& s1, CharT* s2 )
638 {
639     return !(s1 == s2);
640 }
641 
642 //____________________________________________________________________________//
643 
644 template<typename CharT>
645 inline bool
operator !=(CharT * s2,basic_cstring<CharT> const & s1)646 operator!=( CharT* s2, basic_cstring<CharT> const& s1 )
647 {
648     return !(s1 == s2);
649 }
650 
651 //____________________________________________________________________________//
652 
653 template<typename CharT>
654 inline bool
operator !=(basic_cstring<CharT> const & s1,basic_cstring<CharT> const & s2)655 operator!=( basic_cstring<CharT> const& s1, basic_cstring<CharT> const& s2 )
656 {
657     return !(s1 == s2);
658 }
659 
660 //____________________________________________________________________________//
661 
662 template<typename CharT>
663 inline bool
operator !=(basic_cstring<CharT> const & s1,typename basic_cstring<CharT>::std_string const & s2)664 operator!=( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
665 {
666     return !(s1 == s2);
667 }
668 
669 //____________________________________________________________________________//
670 
671 template<typename CharT>
672 inline bool
operator !=(typename basic_cstring<CharT>::std_string const & s2,basic_cstring<CharT> const & s1)673 operator!=( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
674 {
675     return !(s1 == s2);
676 }
677 
678 //____________________________________________________________________________//
679 
680 // ************************************************************************** //
681 // **************                  first_char                  ************** //
682 // ************************************************************************** //
683 
684 template<typename CharT>
685 inline typename basic_cstring<CharT>::value_type
first_char(basic_cstring<CharT> source)686 first_char( basic_cstring<CharT> source )
687 {
688     typedef typename basic_cstring<CharT>::value_type string_value_type;
689 
690     return source.is_empty() ? static_cast<string_value_type>(0) : *source.begin();
691 }
692 
693 //____________________________________________________________________________//
694 
695 // ************************************************************************** //
696 // **************                  last_char                   ************** //
697 // ************************************************************************** //
698 
699 template<typename CharT>
700 inline typename basic_cstring<CharT>::value_type
last_char(basic_cstring<CharT> source)701 last_char( basic_cstring<CharT> source )
702 {
703     typedef typename basic_cstring<CharT>::value_type string_value_type;
704 
705     return source.is_empty() ? static_cast<string_value_type>(0) : *(source.end()-1);
706 }
707 
708 //____________________________________________________________________________//
709 
710 // ************************************************************************** //
711 // **************                  assign_op                   ************** //
712 // ************************************************************************** //
713 
714 template<typename CharT1, typename CharT2>
715 inline void
assign_op(std::basic_string<CharT1> & target,basic_cstring<CharT2> src,int)716 assign_op( std::basic_string<CharT1>& target, basic_cstring<CharT2> src, int )
717 {
718     target.assign( src.begin(), src.size() );
719 }
720 
721 //____________________________________________________________________________//
722 
723 } // namespace unit_test
724 
725 } // namespace boost
726 
727 //____________________________________________________________________________//
728 
729 #include <boost/test/detail/enable_warnings.hpp>
730 
731 #endif // BOOST_TEST_BASIC_CSTRING_HPP_071894GER
732