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 #if defined(BOOST_TEST_STRING_VIEW)
30 #include <string_view>
33 #include <boost/test/detail/suppress_warnings.hpp>
35 //____________________________________________________________________________//
41 // ************************************************************************** //
42 // ************** basic_cstring ************** //
43 // ************************************************************************** //
45 template<typename CharT>
46 class BOOST_SYMBOL_VISIBLE basic_cstring {
47 typedef basic_cstring<CharT> self_type;
50 typedef ut_detail::bcs_char_traits<CharT> traits_type;
51 typedef typename traits_type::std_string std_string;
53 typedef CharT value_type;
54 typedef typename remove_cv<value_type>::type value_ret_type;
55 typedef value_type* pointer;
56 typedef value_type const* const_pointer;
57 typedef value_type& reference;
58 typedef const value_type& const_reference;
59 typedef std::size_t size_type;
60 typedef std::ptrdiff_t difference_type;
62 typedef value_type const* const_iterator;
63 typedef value_type* iterator;
65 // !! should also present reverse_iterator, const_reverse_iterator
67 #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) && !defined(__DCC__)
68 BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
70 // IBM/VisualAge version 6 is not able to handle enums larger than 4 bytes.
71 // But size_type is 8 bytes in 64bit mode.
72 static const size_type npos = -1 ;
75 static pointer null_str();
77 // Constructors; default copy constructor is generated by compiler
79 basic_cstring( basic_cstring const & );
80 basic_cstring( std_string const& s );
81 basic_cstring( pointer s );
82 template<typename LenType>
83 basic_cstring( pointer s, LenType len ) : m_begin( s ), m_end( m_begin + len ) {}
84 basic_cstring( pointer first, pointer last );
86 // data access methods
87 value_ret_type operator[]( size_type index ) const;
88 value_ret_type at( size_type index ) const;
91 size_type size() const;
92 bool is_empty() const;
94 void resize( size_type new_len );
96 // !! only for STL container conformance use is_empty instead
100 self_type& trim_right( size_type trim_size );
101 self_type& trim_left( size_type trim_size );
102 self_type& trim_right( iterator it );
103 self_type& trim_left( iterator it );
104 #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(800))
105 self_type& trim_left( self_type exclusions = self_type() ) ;
106 self_type& trim_right( self_type exclusions = self_type() ) ;
107 self_type& trim( self_type exclusions = self_type() ) ;
109 // VA C++/XL C++ v6 and v8 has in this case a problem with the default arguments.
110 self_type& trim_left( self_type exclusions );
111 self_type& trim_right( self_type exclusions );
112 self_type& trim( self_type exclusions );
113 self_type& trim_left() { return trim_left( self_type() ); }
114 self_type& trim_right() { return trim_right( self_type() ); }
115 self_type& trim() { return trim( self_type() ); }
118 // Assignment operators
119 basic_cstring& operator=( self_type const& s );
120 basic_cstring& operator=( std_string const& s );
121 basic_cstring& operator=( pointer s );
123 template<typename CharT2>
124 basic_cstring& assign( basic_cstring<CharT2> const& s )
126 return *this = basic_cstring<CharT>( s.begin(), s.end() );
128 template<typename PosType, typename LenType>
129 basic_cstring& assign( self_type const& s, PosType pos, LenType len )
131 return *this = self_type( s.m_begin + pos, len );
134 basic_cstring& assign( std_string const& s );
135 template<typename PosType, typename LenType>
136 basic_cstring& assign( std_string const& s, PosType pos, LenType len )
138 return *this = self_type( s.c_str() + pos, len );
140 basic_cstring& assign( pointer s );
141 template<typename LenType>
142 basic_cstring& assign( pointer s, LenType len )
144 return *this = self_type( s, len );
146 basic_cstring& assign( pointer f, pointer l );
149 void swap( self_type& s );
153 const_iterator begin() const;
155 const_iterator end() const;
157 // !! should have rbegin, rend
159 // substring search operation
160 size_type find( basic_cstring ) const;
161 size_type rfind( basic_cstring ) const;
162 self_type substr( size_type beg_index, size_type end_index = npos ) const;
165 static self_type default_trim_ex();
173 // ************************************************************************** //
174 // ************** cstring_string_view_helper ************** //
175 // ************************************************************************** //
178 #if defined(BOOST_TEST_STRING_VIEW)
179 // Helper for instanciating a subclass of cstring using a string_view. We do not
180 // change the API of cstring using BOOST_TEST_STRING_VIEW as the code should remain
181 // compatible between boost.test and test module using different compiler options.
183 template <class CharT, class string_view_t = std::basic_string_view<CharT>>
184 class BOOST_SYMBOL_VISIBLE stringview_cstring_helper : public basic_cstring<CharT> {
186 stringview_cstring_helper(string_view_t const& sv)
187 : basic_cstring<CharT>(const_cast<CharT*>(sv.data()), sv.size())
193 // ************************************************************************** //
194 // ************** basic_cstring::impl ************** //
195 // ************************************************************************** //
197 //____________________________________________________________________________//
199 template<typename CharT>
200 CharT basic_cstring<CharT>::null = 0;
202 //____________________________________________________________________________//
204 template<typename CharT>
205 inline typename basic_cstring<CharT>::pointer
206 basic_cstring<CharT>::null_str()
211 //____________________________________________________________________________//
213 template<typename CharT>
215 basic_cstring<CharT>::basic_cstring()
216 : m_begin( null_str() )
221 //____________________________________________________________________________//
223 template<typename CharT>
225 basic_cstring<CharT>::basic_cstring(basic_cstring const & s)
226 : m_begin( s.m_begin )
231 //____________________________________________________________________________//
233 template<typename CharT>
235 basic_cstring<CharT>::basic_cstring( std_string const& s )
236 : m_begin( s.c_str() )
237 , m_end( m_begin + s.size() )
241 //____________________________________________________________________________//
243 template<typename CharT>
245 basic_cstring<CharT>::basic_cstring( pointer s )
246 : m_begin( s ? s : null_str() )
247 , m_end ( m_begin + (s ? traits_type::length( s ) : 0 ) )
251 //____________________________________________________________________________//
253 template<typename CharT>
255 basic_cstring<CharT>::basic_cstring( pointer first, pointer last )
261 //____________________________________________________________________________//
263 template<typename CharT>
264 inline typename basic_cstring<CharT>::value_ret_type
265 basic_cstring<CharT>::operator[]( size_type index ) const
267 return m_begin[index];
270 //____________________________________________________________________________//
272 template<typename CharT>
273 inline typename basic_cstring<CharT>::value_ret_type
274 basic_cstring<CharT>::at( size_type index ) const
276 if( m_begin + index >= m_end )
277 return static_cast<value_type>(0);
279 return m_begin[index];
282 //____________________________________________________________________________//
284 template<typename CharT>
285 inline typename basic_cstring<CharT>::size_type
286 basic_cstring<CharT>::size() const
288 return static_cast<size_type>(m_end - m_begin);
291 //____________________________________________________________________________//
293 template<typename CharT>
295 basic_cstring<CharT>::is_empty() const
297 return m_end == m_begin;
300 //____________________________________________________________________________//
302 template<typename CharT>
304 basic_cstring<CharT>::empty() const
309 //____________________________________________________________________________//
311 template<typename CharT>
313 basic_cstring<CharT>::clear()
318 //____________________________________________________________________________//
320 template<typename CharT>
322 basic_cstring<CharT>::resize( size_type new_len )
324 if( m_begin + new_len < m_end )
325 m_end = m_begin + new_len;
328 //____________________________________________________________________________//
330 template<typename CharT>
331 inline basic_cstring<CharT>&
332 basic_cstring<CharT>::trim_left( size_type trim_size )
334 m_begin += trim_size;
335 if( m_end <= m_begin )
341 //____________________________________________________________________________//
343 template<typename CharT>
344 inline basic_cstring<CharT>&
345 basic_cstring<CharT>::trim_left( iterator it )
348 if( m_end <= m_begin )
354 //____________________________________________________________________________//
356 template<typename CharT>
357 inline basic_cstring<CharT>&
358 basic_cstring<CharT>::trim_left( basic_cstring exclusions )
360 if( exclusions.is_empty() )
361 exclusions = default_trim_ex();
364 for( it = begin(); it != end(); ++it ) {
365 if( traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
369 return trim_left( it );
372 //____________________________________________________________________________//
374 template<typename CharT>
375 inline basic_cstring<CharT>&
376 basic_cstring<CharT>::trim_right( size_type trim_size )
379 if( m_end <= m_begin )
385 //____________________________________________________________________________//
387 template<typename CharT>
388 inline basic_cstring<CharT>&
389 basic_cstring<CharT>::trim_right( iterator it )
392 if( m_end <= m_begin )
398 //____________________________________________________________________________//
400 template<typename CharT>
401 inline basic_cstring<CharT>&
402 basic_cstring<CharT>::trim_right( basic_cstring exclusions )
404 if( exclusions.is_empty() )
405 exclusions = default_trim_ex();
409 for( it = end()-1; it != begin()-1; --it ) {
410 if( self_type::traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
414 return trim_right( it+1 );
417 //____________________________________________________________________________//
419 template<typename CharT>
420 inline basic_cstring<CharT>&
421 basic_cstring<CharT>::trim( basic_cstring exclusions )
423 trim_left( exclusions );
424 trim_right( exclusions );
429 //____________________________________________________________________________//
431 template<typename CharT>
432 inline basic_cstring<CharT>&
433 basic_cstring<CharT>::operator=( basic_cstring<CharT> const& s )
441 //____________________________________________________________________________//
443 template<typename CharT>
444 inline basic_cstring<CharT>&
445 basic_cstring<CharT>::operator=( std_string const& s )
447 return *this = self_type( s );
450 //____________________________________________________________________________//
452 template<typename CharT>
453 inline basic_cstring<CharT>&
454 basic_cstring<CharT>::operator=( pointer s )
456 return *this = self_type( s );
459 //____________________________________________________________________________//
461 template<typename CharT>
462 inline basic_cstring<CharT>&
463 basic_cstring<CharT>::assign( std_string const& s )
465 return *this = self_type( s );
468 //____________________________________________________________________________//
470 template<typename CharT>
471 inline basic_cstring<CharT>&
472 basic_cstring<CharT>::assign( pointer s )
474 return *this = self_type( s );
477 //____________________________________________________________________________//
479 template<typename CharT>
480 inline basic_cstring<CharT>&
481 basic_cstring<CharT>::assign( pointer f, pointer l )
483 return *this = self_type( f, l );
486 //____________________________________________________________________________//
488 template<typename CharT>
490 basic_cstring<CharT>::swap( basic_cstring<CharT>& s )
492 // do not want to include alogrithm
493 pointer tmp1 = m_begin;
494 pointer tmp2 = m_end;
503 //____________________________________________________________________________//
505 template<typename CharT>
506 inline typename basic_cstring<CharT>::iterator
507 basic_cstring<CharT>::begin()
512 //____________________________________________________________________________//
514 template<typename CharT>
515 inline typename basic_cstring<CharT>::const_iterator
516 basic_cstring<CharT>::begin() const
521 //____________________________________________________________________________//
523 template<typename CharT>
524 inline typename basic_cstring<CharT>::iterator
525 basic_cstring<CharT>::end()
530 //____________________________________________________________________________//
532 template<typename CharT>
533 inline typename basic_cstring<CharT>::const_iterator
534 basic_cstring<CharT>::end() const
539 //____________________________________________________________________________//
541 template<typename CharT>
542 inline typename basic_cstring<CharT>::size_type
543 basic_cstring<CharT>::find( basic_cstring<CharT> str ) const
545 if( str.is_empty() || str.size() > size() )
546 return static_cast<size_type>(npos);
548 const_iterator it = begin();
549 const_iterator last = end() - str.size() + 1;
551 while( it != last ) {
552 if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
558 return it == last ? npos : static_cast<size_type>(it - begin());
561 //____________________________________________________________________________//
563 template<typename CharT>
564 inline typename basic_cstring<CharT>::size_type
565 basic_cstring<CharT>::rfind( basic_cstring<CharT> str ) const
567 if( str.is_empty() || str.size() > size() )
568 return static_cast<size_type>(npos);
570 const_iterator it = end() - str.size();
571 const_iterator last = begin()-1;
573 while( it != last ) {
574 if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
580 return it == last ? static_cast<size_type>(npos) : static_cast<size_type>(it - begin());
583 //____________________________________________________________________________//
585 template<typename CharT>
586 inline basic_cstring<CharT>
587 basic_cstring<CharT>::substr( size_type beg_index, size_type end_index ) const
589 return beg_index > size()
592 ? self_type( m_begin + beg_index, m_end )
593 : self_type( m_begin + beg_index, m_begin + end_index );
596 //____________________________________________________________________________//
598 template<typename CharT>
599 inline basic_cstring<CharT>
600 basic_cstring<CharT>::default_trim_ex()
602 static CharT ws[3] = { CharT(' '), CharT('\t'), CharT('\n') }; // !! wide case
604 return self_type( ws, 3 );
607 //____________________________________________________________________________//
609 // ************************************************************************** //
610 // ************** comparison operators ************** //
611 // ************************************************************************** //
613 template<typename CharT1,typename CharT2>
615 operator==( basic_cstring<CharT1> const& s1, basic_cstring<CharT2> const& s2 )
617 typedef typename basic_cstring<CharT1>::traits_type traits_type;
618 return s1.size() == s2.size() &&
619 traits_type::compare( s1.begin(), s2.begin(), s1.size() ) == 0;
622 //____________________________________________________________________________//
624 template<typename CharT1,typename CharT2>
626 operator==( basic_cstring<CharT1> const& s1, CharT2* s2 )
628 #if !defined(__DMC__)
629 return s1 == basic_cstring<CharT2>( s2 );
631 return s1 == basic_cstring<CharT2 const>( s2 );
635 //____________________________________________________________________________//
637 template<typename CharT>
639 operator==( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
641 return s1 == basic_cstring<CharT>( s2 );
644 //____________________________________________________________________________//
646 template<typename CharT1,typename CharT2>
648 operator==( CharT1* s2, basic_cstring<CharT2> const& s1 )
653 //____________________________________________________________________________//
655 template<typename CharT>
657 operator==( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
662 //____________________________________________________________________________//
664 template<typename CharT>
666 operator!=( basic_cstring<CharT> const& s1, CharT* s2 )
671 //____________________________________________________________________________//
673 template<typename CharT>
675 operator!=( CharT* s2, basic_cstring<CharT> const& s1 )
680 //____________________________________________________________________________//
682 template<typename CharT>
684 operator!=( basic_cstring<CharT> const& s1, basic_cstring<CharT> const& s2 )
689 //____________________________________________________________________________//
691 template<typename CharT>
693 operator!=( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
698 //____________________________________________________________________________//
700 template<typename CharT>
702 operator!=( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
707 //____________________________________________________________________________//
709 // ************************************************************************** //
710 // ************** first_char ************** //
711 // ************************************************************************** //
713 template<typename CharT>
714 inline typename basic_cstring<CharT>::value_ret_type
715 first_char( basic_cstring<CharT> source )
717 typedef typename basic_cstring<CharT>::value_ret_type res_type;
719 return source.is_empty() ? static_cast<res_type>(0) : *source.begin();
722 //____________________________________________________________________________//
724 // ************************************************************************** //
725 // ************** last_char ************** //
726 // ************************************************************************** //
728 template<typename CharT>
729 inline typename basic_cstring<CharT>::value_ret_type
730 last_char( basic_cstring<CharT> source )
732 typedef typename basic_cstring<CharT>::value_ret_type res_type;
734 return source.is_empty() ? static_cast<res_type>(0) : *(source.end()-1);
737 //____________________________________________________________________________//
739 // ************************************************************************** //
740 // ************** assign_op ************** //
741 // ************************************************************************** //
743 template<typename CharT1, typename CharT2>
745 assign_op( std::basic_string<CharT1>& target, basic_cstring<CharT2> src, int )
747 target.assign( src.begin(), src.size() );
750 //____________________________________________________________________________//
752 template<typename CharT1, typename CharT2>
753 inline std::basic_string<CharT1>&
754 operator+=( std::basic_string<CharT1>& target, basic_cstring<CharT2> const& str )
756 target.append( str.begin(), str.end() );
760 //____________________________________________________________________________//
762 template<typename CharT1, typename CharT2>
763 inline std::basic_string<CharT1>
764 operator+( std::basic_string<CharT1> const& lhs, basic_cstring<CharT2> const& rhs )
766 std::basic_string<CharT1> res( lhs );
768 res.append( rhs.begin(), rhs.end() );
772 //____________________________________________________________________________//
774 } // namespace unit_test
778 //____________________________________________________________________________//
780 #include <boost/test/detail/enable_warnings.hpp>
782 #endif // BOOST_TEST_UTILS_BASIC_CSTRING_HPP