1 // (C) Copyright Gennadiy Rozental 2001.
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)
6 // See http://www.boost.org/libs/test for the library home page.
10 // Version : $Revision$
12 // Description : class basic_cstring wraps C string and provide std_string like
14 // ***************************************************************************
16 #ifndef BOOST_TEST_UTILS_BASIC_CSTRING_HPP
17 #define BOOST_TEST_UTILS_BASIC_CSTRING_HPP
20 #include <boost/test/utils/basic_cstring/basic_cstring_fwd.hpp>
21 #include <boost/test/utils/basic_cstring/bcs_char_traits.hpp>
24 #include <boost/type_traits/remove_cv.hpp>
29 #include <boost/test/detail/suppress_warnings.hpp>
31 //____________________________________________________________________________//
37 // ************************************************************************** //
38 // ************** basic_cstring ************** //
39 // ************************************************************************** //
41 template<typename CharT>
43 typedef basic_cstring<CharT> self_type;
46 typedef ut_detail::bcs_char_traits<CharT> traits_type;
47 typedef typename traits_type::std_string std_string;
49 typedef CharT value_type;
50 typedef typename remove_cv<value_type>::type value_ret_type;
51 typedef value_type* pointer;
52 typedef value_type const* const_pointer;
53 typedef value_type& reference;
54 typedef const value_type& const_reference;
55 typedef std::size_t size_type;
56 typedef std::ptrdiff_t difference_type;
58 typedef value_type const* const_iterator;
59 typedef value_type* iterator;
61 // !! should also present reverse_iterator, const_reverse_iterator
63 #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
64 enum npos_type { npos = static_cast<size_type>(-1) };
66 // IBM/VisualAge version 6 is not able to handle enums larger than 4 bytes.
67 // But size_type is 8 bytes in 64bit mode.
68 static const size_type npos = -1 ;
71 static pointer null_str();
73 // Constructors; default copy constructor is generated by compiler
75 basic_cstring( basic_cstring const & );
76 basic_cstring( std_string const& s );
77 basic_cstring( pointer s );
78 template<typename LenType>
79 basic_cstring( pointer s, LenType len ) : m_begin( s ), m_end( m_begin + len ) {}
80 basic_cstring( pointer first, pointer last );
82 // data access methods
83 value_ret_type operator[]( size_type index ) const;
84 value_ret_type at( size_type index ) const;
87 size_type size() const;
88 bool is_empty() const;
90 void resize( size_type new_len );
92 // !! only for STL container conformance use is_empty instead
96 self_type& trim_right( size_type trim_size );
97 self_type& trim_left( size_type trim_size );
98 self_type& trim_right( iterator it );
99 self_type& trim_left( iterator it );
100 #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(800))
101 self_type& trim_left( self_type exclusions = self_type() ) ;
102 self_type& trim_right( self_type exclusions = self_type() ) ;
103 self_type& trim( self_type exclusions = self_type() ) ;
105 // VA C++/XL C++ v6 and v8 has in this case a problem with the default arguments.
106 self_type& trim_left( self_type exclusions );
107 self_type& trim_right( self_type exclusions );
108 self_type& trim( self_type exclusions );
109 self_type& trim_left() { return trim_left( self_type() ); }
110 self_type& trim_right() { return trim_right( self_type() ); }
111 self_type& trim() { return trim( self_type() ); }
114 // Assignment operators
115 basic_cstring& operator=( self_type const& s );
116 basic_cstring& operator=( std_string const& s );
117 basic_cstring& operator=( pointer s );
119 template<typename CharT2>
120 basic_cstring& assign( basic_cstring<CharT2> const& s )
122 return *this = basic_cstring<CharT>( s.begin(), s.end() );
124 template<typename PosType, typename LenType>
125 basic_cstring& assign( self_type const& s, PosType pos, LenType len )
127 return *this = self_type( s.m_begin + pos, len );
130 basic_cstring& assign( std_string const& s );
131 template<typename PosType, typename LenType>
132 basic_cstring& assign( std_string const& s, PosType pos, LenType len )
134 return *this = self_type( s.c_str() + pos, len );
136 basic_cstring& assign( pointer s );
137 template<typename LenType>
138 basic_cstring& assign( pointer s, LenType len )
140 return *this = self_type( s, len );
142 basic_cstring& assign( pointer f, pointer l );
145 void swap( self_type& s );
149 const_iterator begin() const;
151 const_iterator end() const;
153 // !! should have rbegin, rend
155 // substring search operation
156 size_type find( basic_cstring ) const;
157 size_type rfind( basic_cstring ) const;
158 self_type substr( size_type beg_index, size_type end_index = npos ) const;
161 static self_type default_trim_ex();
168 //____________________________________________________________________________//
170 template<typename CharT>
171 inline typename basic_cstring<CharT>::pointer
172 basic_cstring<CharT>::null_str()
174 static CharT null = 0;
178 //____________________________________________________________________________//
180 template<typename CharT>
182 basic_cstring<CharT>::basic_cstring()
183 : m_begin( null_str() )
188 //____________________________________________________________________________//
190 template<typename CharT>
192 basic_cstring<CharT>::basic_cstring(basic_cstring const & s)
193 : m_begin( s.m_begin )
198 //____________________________________________________________________________//
200 template<typename CharT>
202 basic_cstring<CharT>::basic_cstring( std_string const& s )
203 : m_begin( s.c_str() )
204 , m_end( m_begin + s.size() )
208 //____________________________________________________________________________//
210 template<typename CharT>
212 basic_cstring<CharT>::basic_cstring( pointer s )
213 : m_begin( s ? s : null_str() )
214 , m_end ( m_begin + (s ? traits_type::length( s ) : 0 ) )
218 //____________________________________________________________________________//
220 template<typename CharT>
222 basic_cstring<CharT>::basic_cstring( pointer first, pointer last )
228 //____________________________________________________________________________//
230 template<typename CharT>
231 inline typename basic_cstring<CharT>::value_ret_type
232 basic_cstring<CharT>::operator[]( size_type index ) const
234 return m_begin[index];
237 //____________________________________________________________________________//
239 template<typename CharT>
240 inline typename basic_cstring<CharT>::value_ret_type
241 basic_cstring<CharT>::at( size_type index ) const
243 if( m_begin + index >= m_end )
244 return static_cast<value_type>(0);
246 return m_begin[index];
249 //____________________________________________________________________________//
251 template<typename CharT>
252 inline typename basic_cstring<CharT>::size_type
253 basic_cstring<CharT>::size() const
255 return static_cast<size_type>(m_end - m_begin);
258 //____________________________________________________________________________//
260 template<typename CharT>
262 basic_cstring<CharT>::is_empty() const
264 return m_end == m_begin;
267 //____________________________________________________________________________//
269 template<typename CharT>
271 basic_cstring<CharT>::empty() const
276 //____________________________________________________________________________//
278 template<typename CharT>
280 basic_cstring<CharT>::clear()
285 //____________________________________________________________________________//
287 template<typename CharT>
289 basic_cstring<CharT>::resize( size_type new_len )
291 if( m_begin + new_len < m_end )
292 m_end = m_begin + new_len;
295 //____________________________________________________________________________//
297 template<typename CharT>
298 inline basic_cstring<CharT>&
299 basic_cstring<CharT>::trim_left( size_type trim_size )
301 m_begin += trim_size;
302 if( m_end <= m_begin )
308 //____________________________________________________________________________//
310 template<typename CharT>
311 inline basic_cstring<CharT>&
312 basic_cstring<CharT>::trim_left( iterator it )
315 if( m_end <= m_begin )
321 //____________________________________________________________________________//
323 template<typename CharT>
324 inline basic_cstring<CharT>&
325 basic_cstring<CharT>::trim_left( basic_cstring exclusions )
327 if( exclusions.is_empty() )
328 exclusions = default_trim_ex();
331 for( it = begin(); it != end(); ++it ) {
332 if( traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
336 return trim_left( it );
339 //____________________________________________________________________________//
341 template<typename CharT>
342 inline basic_cstring<CharT>&
343 basic_cstring<CharT>::trim_right( size_type trim_size )
346 if( m_end <= m_begin )
352 //____________________________________________________________________________//
354 template<typename CharT>
355 inline basic_cstring<CharT>&
356 basic_cstring<CharT>::trim_right( iterator it )
359 if( m_end <= m_begin )
365 //____________________________________________________________________________//
367 template<typename CharT>
368 inline basic_cstring<CharT>&
369 basic_cstring<CharT>::trim_right( basic_cstring exclusions )
371 if( exclusions.is_empty() )
372 exclusions = default_trim_ex();
376 for( it = end()-1; it != begin()-1; --it ) {
377 if( self_type::traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
381 return trim_right( it+1 );
384 //____________________________________________________________________________//
386 template<typename CharT>
387 inline basic_cstring<CharT>&
388 basic_cstring<CharT>::trim( basic_cstring exclusions )
390 trim_left( exclusions );
391 trim_right( exclusions );
396 //____________________________________________________________________________//
398 template<typename CharT>
399 inline basic_cstring<CharT>&
400 basic_cstring<CharT>::operator=( basic_cstring<CharT> const& s )
408 //____________________________________________________________________________//
410 template<typename CharT>
411 inline basic_cstring<CharT>&
412 basic_cstring<CharT>::operator=( std_string const& s )
414 return *this = self_type( s );
417 //____________________________________________________________________________//
419 template<typename CharT>
420 inline basic_cstring<CharT>&
421 basic_cstring<CharT>::operator=( pointer s )
423 return *this = self_type( s );
426 //____________________________________________________________________________//
428 template<typename CharT>
429 inline basic_cstring<CharT>&
430 basic_cstring<CharT>::assign( std_string const& s )
432 return *this = self_type( s );
435 //____________________________________________________________________________//
437 template<typename CharT>
438 inline basic_cstring<CharT>&
439 basic_cstring<CharT>::assign( pointer s )
441 return *this = self_type( s );
444 //____________________________________________________________________________//
446 template<typename CharT>
447 inline basic_cstring<CharT>&
448 basic_cstring<CharT>::assign( pointer f, pointer l )
450 return *this = self_type( f, l );
453 //____________________________________________________________________________//
455 template<typename CharT>
457 basic_cstring<CharT>::swap( basic_cstring<CharT>& s )
459 // do not want to include alogrithm
460 pointer tmp1 = m_begin;
461 pointer tmp2 = m_end;
470 //____________________________________________________________________________//
472 template<typename CharT>
473 inline typename basic_cstring<CharT>::iterator
474 basic_cstring<CharT>::begin()
479 //____________________________________________________________________________//
481 template<typename CharT>
482 inline typename basic_cstring<CharT>::const_iterator
483 basic_cstring<CharT>::begin() const
488 //____________________________________________________________________________//
490 template<typename CharT>
491 inline typename basic_cstring<CharT>::iterator
492 basic_cstring<CharT>::end()
497 //____________________________________________________________________________//
499 template<typename CharT>
500 inline typename basic_cstring<CharT>::const_iterator
501 basic_cstring<CharT>::end() const
506 //____________________________________________________________________________//
508 template<typename CharT>
509 inline typename basic_cstring<CharT>::size_type
510 basic_cstring<CharT>::find( basic_cstring<CharT> str ) const
512 if( str.is_empty() || str.size() > size() )
513 return static_cast<size_type>(npos);
515 const_iterator it = begin();
516 const_iterator last = end() - str.size() + 1;
518 while( it != last ) {
519 if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
525 return it == last ? npos : static_cast<size_type>(it - begin());
528 //____________________________________________________________________________//
530 template<typename CharT>
531 inline typename basic_cstring<CharT>::size_type
532 basic_cstring<CharT>::rfind( basic_cstring<CharT> str ) const
534 if( str.is_empty() || str.size() > size() )
535 return static_cast<size_type>(npos);
537 const_iterator it = end() - str.size();
538 const_iterator last = begin()-1;
540 while( it != last ) {
541 if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
547 return it == last ? static_cast<size_type>(npos) : static_cast<size_type>(it - begin());
550 //____________________________________________________________________________//
552 template<typename CharT>
553 inline basic_cstring<CharT>
554 basic_cstring<CharT>::substr( size_type beg_index, size_type end_index ) const
556 return beg_index > size()
559 ? self_type( m_begin + beg_index, m_end )
560 : self_type( m_begin + beg_index, m_begin + end_index );
563 //____________________________________________________________________________//
565 template<typename CharT>
566 inline basic_cstring<CharT>
567 basic_cstring<CharT>::default_trim_ex()
569 static CharT ws[3] = { CharT(' '), CharT('\t'), CharT('\n') }; // !! wide case
571 return self_type( ws, 3 );
574 //____________________________________________________________________________//
576 // ************************************************************************** //
577 // ************** comparison operators ************** //
578 // ************************************************************************** //
580 template<typename CharT1,typename CharT2>
582 operator==( basic_cstring<CharT1> const& s1, basic_cstring<CharT2> const& s2 )
584 typedef typename basic_cstring<CharT1>::traits_type traits_type;
585 return s1.size() == s2.size() &&
586 traits_type::compare( s1.begin(), s2.begin(), s1.size() ) == 0;
589 //____________________________________________________________________________//
591 template<typename CharT1,typename CharT2>
593 operator==( basic_cstring<CharT1> const& s1, CharT2* s2 )
595 #if !defined(__DMC__)
596 return s1 == basic_cstring<CharT2>( s2 );
598 return s1 == basic_cstring<CharT2 const>( s2 );
602 //____________________________________________________________________________//
604 template<typename CharT>
606 operator==( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
608 return s1 == basic_cstring<CharT>( s2 );
611 //____________________________________________________________________________//
613 template<typename CharT1,typename CharT2>
615 operator==( CharT1* s2, basic_cstring<CharT2> const& s1 )
620 //____________________________________________________________________________//
622 template<typename CharT>
624 operator==( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
629 //____________________________________________________________________________//
631 template<typename CharT>
633 operator!=( basic_cstring<CharT> const& s1, CharT* s2 )
638 //____________________________________________________________________________//
640 template<typename CharT>
642 operator!=( CharT* s2, basic_cstring<CharT> const& s1 )
647 //____________________________________________________________________________//
649 template<typename CharT>
651 operator!=( basic_cstring<CharT> const& s1, basic_cstring<CharT> const& s2 )
656 //____________________________________________________________________________//
658 template<typename CharT>
660 operator!=( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
665 //____________________________________________________________________________//
667 template<typename CharT>
669 operator!=( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
674 //____________________________________________________________________________//
676 // ************************************************************************** //
677 // ************** first_char ************** //
678 // ************************************************************************** //
680 template<typename CharT>
681 inline typename basic_cstring<CharT>::value_ret_type
682 first_char( basic_cstring<CharT> source )
684 typedef typename basic_cstring<CharT>::value_ret_type res_type;
686 return source.is_empty() ? static_cast<res_type>(0) : *source.begin();
689 //____________________________________________________________________________//
691 // ************************************************************************** //
692 // ************** last_char ************** //
693 // ************************************************************************** //
695 template<typename CharT>
696 inline typename basic_cstring<CharT>::value_ret_type
697 last_char( basic_cstring<CharT> source )
699 typedef typename basic_cstring<CharT>::value_ret_type res_type;
701 return source.is_empty() ? static_cast<res_type>(0) : *(source.end()-1);
704 //____________________________________________________________________________//
706 // ************************************************************************** //
707 // ************** assign_op ************** //
708 // ************************************************************************** //
710 template<typename CharT1, typename CharT2>
712 assign_op( std::basic_string<CharT1>& target, basic_cstring<CharT2> src, int )
714 target.assign( src.begin(), src.size() );
717 //____________________________________________________________________________//
719 template<typename CharT1, typename CharT2>
720 inline std::basic_string<CharT1>&
721 operator+=( std::basic_string<CharT1>& target, basic_cstring<CharT2> const& str )
723 target.append( str.begin(), str.end() );
727 //____________________________________________________________________________//
729 template<typename CharT1, typename CharT2>
730 inline std::basic_string<CharT1>
731 operator+( std::basic_string<CharT1> const& lhs, basic_cstring<CharT2> const& rhs )
733 std::basic_string<CharT1> res( lhs );
735 res.append( rhs.begin(), rhs.end() );
739 //____________________________________________________________________________//
741 } // namespace unit_test
745 //____________________________________________________________________________//
747 #include <boost/test/detail/enable_warnings.hpp>
749 #endif // BOOST_TEST_UTILS_BASIC_CSTRING_HPP