Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:52:41

0001 //  (C) Copyright Gennadiy Rozental 2001.
0002 //  Distributed under the Boost Software License, Version 1.0.
0003 //  (See accompanying file LICENSE_1_0.txt or copy at
0004 //  http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 //  See http://www.boost.org/libs/test for the library home page.
0007 //
0008 //  File        : $RCSfile$
0009 //
0010 //  Version     : $Revision$
0011 //
0012 //  Description : class basic_cstring wraps C string and provide std_string like
0013 //                interface
0014 // ***************************************************************************
0015 
0016 #ifndef BOOST_TEST_UTILS_BASIC_CSTRING_HPP
0017 #define BOOST_TEST_UTILS_BASIC_CSTRING_HPP
0018 
0019 // Boost.Test
0020 #include <boost/test/utils/basic_cstring/basic_cstring_fwd.hpp>
0021 #include <boost/test/utils/basic_cstring/bcs_char_traits.hpp>
0022 
0023 // Boost
0024 #include <boost/type_traits/remove_cv.hpp>
0025 
0026 // STL
0027 #include <string>
0028 
0029 #if defined(BOOST_TEST_STRING_VIEW)
0030 #include <string_view>
0031 #endif
0032 
0033 #include <boost/test/detail/suppress_warnings.hpp>
0034 
0035 //____________________________________________________________________________//
0036 
0037 namespace boost {
0038 
0039 namespace unit_test {
0040 
0041 // ************************************************************************** //
0042 // **************                basic_cstring                 ************** //
0043 // ************************************************************************** //
0044 
0045 template<typename CharT>
0046 class BOOST_SYMBOL_VISIBLE basic_cstring {
0047     typedef basic_cstring<CharT>                        self_type;
0048 public:
0049     // Subtypes
0050     typedef ut_detail::bcs_char_traits<CharT>           traits_type;
0051     typedef typename traits_type::std_string            std_string;
0052 
0053     typedef CharT                                       value_type;
0054     typedef typename remove_cv<value_type>::type        value_ret_type;
0055     typedef value_type*                                 pointer;
0056     typedef value_type const*                           const_pointer;
0057     typedef value_type&                                 reference;
0058     typedef const value_type&                           const_reference;
0059     typedef std::size_t                                 size_type;
0060     typedef std::ptrdiff_t                              difference_type;
0061 
0062     typedef value_type const*                           const_iterator;
0063     typedef value_type*                                 iterator;
0064 
0065     // !! should also present reverse_iterator, const_reverse_iterator
0066 
0067 #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) && !defined(__DCC__)
0068     BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
0069 #else
0070     // IBM/VisualAge version 6 is not able to handle enums larger than 4 bytes.
0071     // But size_type is 8 bytes in 64bit mode.
0072     static const size_type npos = -1 ;
0073 #endif
0074 
0075     static pointer  null_str();
0076 
0077     // Constructors; default copy constructor is generated by compiler
0078     basic_cstring();
0079     basic_cstring( basic_cstring const & );
0080     basic_cstring( std_string const& s );
0081     basic_cstring( pointer s );
0082     template<typename LenType>
0083     basic_cstring( pointer s, LenType len ) : m_begin( s ), m_end( m_begin + len ) {}
0084     basic_cstring( pointer first, pointer last );
0085 
0086     // data access methods
0087     value_ret_type  operator[]( size_type index ) const;
0088     value_ret_type  at( size_type index ) const;
0089 
0090     // size operators
0091     size_type       size() const;
0092     bool            is_empty() const;
0093     void            clear();
0094     void            resize( size_type new_len );
0095 
0096     // !! only for STL container conformance use is_empty instead
0097     bool            empty() const;
0098 
0099     // Trimming
0100     self_type&      trim_right( size_type trim_size );
0101     self_type&      trim_left( size_type trim_size );
0102     self_type&      trim_right( iterator it );
0103     self_type&      trim_left( iterator it );
0104 #if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(800))
0105     self_type&      trim_left( self_type exclusions = self_type() ) ;
0106     self_type&      trim_right( self_type exclusions = self_type() ) ;
0107     self_type&      trim( self_type exclusions = self_type() ) ;
0108 #else
0109     // VA C++/XL C++ v6 and v8 has in this case a problem with the default arguments.
0110     self_type&      trim_left( self_type exclusions );
0111     self_type&      trim_right( self_type exclusions );
0112     self_type&      trim( self_type exclusions );
0113     self_type&      trim_left()     { return trim_left( self_type() ); }
0114     self_type&      trim_right()    { return trim_right( self_type() ); }
0115     self_type&      trim()          { return trim( self_type() ); }
0116 #endif
0117 
0118     // Assignment operators
0119     basic_cstring&  operator=( self_type const& s );
0120     basic_cstring&  operator=( std_string const& s );
0121     basic_cstring&  operator=( pointer s );
0122 
0123     template<typename CharT2>
0124     basic_cstring&  assign( basic_cstring<CharT2> const& s )
0125     {
0126         return *this = basic_cstring<CharT>( s.begin(), s.end() );
0127     }
0128     template<typename PosType, typename LenType>
0129     basic_cstring&  assign( self_type const& s, PosType pos, LenType len )
0130     {
0131         return *this = self_type( s.m_begin + pos, len );
0132     }
0133 
0134     basic_cstring&  assign( std_string const& s );
0135     template<typename PosType, typename LenType>
0136     basic_cstring&  assign( std_string const& s, PosType pos, LenType len )
0137     {
0138         return *this = self_type( s.c_str() + pos, len );
0139     }
0140     basic_cstring&  assign( pointer s );
0141     template<typename LenType>
0142     basic_cstring&  assign( pointer s, LenType len )
0143     {
0144         return *this = self_type( s, len );
0145     }
0146     basic_cstring&  assign( pointer f, pointer l );
0147 
0148     // swapping
0149     void            swap( self_type& s );
0150 
0151     // Iterators
0152     iterator        begin();
0153     const_iterator  begin() const;
0154     iterator        end();
0155     const_iterator  end() const;
0156 
0157     // !! should have rbegin, rend
0158 
0159     // substring search operation
0160     size_type       find( basic_cstring ) const;
0161     size_type       rfind( basic_cstring ) const;
0162     self_type       substr( size_type beg_index, size_type end_index = npos ) const;
0163 
0164 private:
0165     static self_type default_trim_ex();
0166 
0167     // Data members
0168     iterator        m_begin;
0169     iterator        m_end;
0170     static CharT null;
0171 };
0172 
0173 // ************************************************************************** //
0174 // **************         cstring_string_view_helper           ************** //
0175 // ************************************************************************** //
0176 
0177 
0178 #if defined(BOOST_TEST_STRING_VIEW)
0179 // Helper for instanciating a subclass of cstring using a string_view. We do not
0180 // change the API of cstring using BOOST_TEST_STRING_VIEW as the code should remain
0181 // compatible between boost.test and test module using different compiler options.
0182 //! @internal
0183 template <class CharT, class string_view_t = std::basic_string_view<CharT>>
0184 class BOOST_SYMBOL_VISIBLE stringview_cstring_helper : public basic_cstring<CharT> {
0185 public:
0186   stringview_cstring_helper(string_view_t const& sv)
0187   : basic_cstring<CharT>(const_cast<CharT*>(sv.data()), sv.size())
0188   {}
0189 };
0190 #endif
0191 
0192 
0193 // ************************************************************************** //
0194 // **************            basic_cstring::impl               ************** //
0195 // ************************************************************************** //
0196 
0197 //____________________________________________________________________________//
0198 
0199 template<typename CharT>
0200 CharT basic_cstring<CharT>::null = 0;
0201 
0202 //____________________________________________________________________________//
0203 
0204 template<typename CharT>
0205 inline typename basic_cstring<CharT>::pointer
0206 basic_cstring<CharT>::null_str()
0207 {
0208     return &null;
0209 }
0210 
0211 //____________________________________________________________________________//
0212 
0213 template<typename CharT>
0214 inline
0215 basic_cstring<CharT>::basic_cstring()
0216 : m_begin( null_str() )
0217 , m_end( m_begin )
0218 {
0219 }
0220 
0221 //____________________________________________________________________________//
0222 
0223 template<typename CharT>
0224 inline
0225 basic_cstring<CharT>::basic_cstring(basic_cstring const & s)
0226 : m_begin( s.m_begin )
0227 , m_end( s.m_end )
0228 {
0229 }
0230 
0231 //____________________________________________________________________________//
0232 
0233 template<typename CharT>
0234 inline
0235 basic_cstring<CharT>::basic_cstring( std_string const& s )
0236 : m_begin( s.c_str() )
0237 , m_end( m_begin + s.size() )
0238 {
0239 }
0240 
0241 //____________________________________________________________________________//
0242 
0243 template<typename CharT>
0244 inline
0245 basic_cstring<CharT>::basic_cstring( pointer s )
0246 : m_begin( s ? s : null_str() )
0247 , m_end  ( m_begin + (s ? traits_type::length( s ) : 0 ) )
0248 {
0249 }
0250 
0251 //____________________________________________________________________________//
0252 
0253 template<typename CharT>
0254 inline
0255 basic_cstring<CharT>::basic_cstring( pointer first, pointer last )
0256 : m_begin( first )
0257 , m_end( last )
0258 {
0259 }
0260 
0261 //____________________________________________________________________________//
0262 
0263 template<typename CharT>
0264 inline typename basic_cstring<CharT>::value_ret_type
0265 basic_cstring<CharT>::operator[]( size_type index ) const
0266 {
0267     return m_begin[index];
0268 }
0269 
0270 //____________________________________________________________________________//
0271 
0272 template<typename CharT>
0273 inline typename basic_cstring<CharT>::value_ret_type
0274 basic_cstring<CharT>::at( size_type index ) const
0275 {
0276     if( m_begin + index >= m_end )
0277         return static_cast<value_type>(0);
0278 
0279     return m_begin[index];
0280 }
0281 
0282 //____________________________________________________________________________//
0283 
0284 template<typename CharT>
0285 inline typename basic_cstring<CharT>::size_type
0286 basic_cstring<CharT>::size() const
0287 {
0288     return static_cast<size_type>(m_end - m_begin);
0289 }
0290 
0291 //____________________________________________________________________________//
0292 
0293 template<typename CharT>
0294 inline bool
0295 basic_cstring<CharT>::is_empty() const
0296 {
0297     return m_end == m_begin;
0298 }
0299 
0300 //____________________________________________________________________________//
0301 
0302 template<typename CharT>
0303 inline bool
0304 basic_cstring<CharT>::empty() const
0305 {
0306     return is_empty();
0307 }
0308 
0309 //____________________________________________________________________________//
0310 
0311 template<typename CharT>
0312 inline void
0313 basic_cstring<CharT>::clear()
0314 {
0315     m_begin = m_end;
0316 }
0317 
0318 //____________________________________________________________________________//
0319 
0320 template<typename CharT>
0321 inline void
0322 basic_cstring<CharT>::resize( size_type new_len )
0323 {
0324     if( m_begin + new_len < m_end )
0325         m_end = m_begin + new_len;
0326 }
0327 
0328 //____________________________________________________________________________//
0329 
0330 template<typename CharT>
0331 inline basic_cstring<CharT>&
0332 basic_cstring<CharT>::trim_left( size_type trim_size )
0333 {
0334     m_begin += trim_size;
0335     if( m_end <= m_begin )
0336         clear();
0337 
0338     return *this;
0339 }
0340 
0341 //____________________________________________________________________________//
0342 
0343 template<typename CharT>
0344 inline basic_cstring<CharT>&
0345 basic_cstring<CharT>::trim_left( iterator it )
0346 {
0347     m_begin = it;
0348     if( m_end <= m_begin )
0349         clear();
0350 
0351     return *this;
0352 }
0353 
0354 //____________________________________________________________________________//
0355 
0356 template<typename CharT>
0357 inline basic_cstring<CharT>&
0358 basic_cstring<CharT>::trim_left( basic_cstring exclusions )
0359 {
0360     if( exclusions.is_empty() )
0361         exclusions = default_trim_ex();
0362 
0363     iterator it;
0364     for( it = begin(); it != end(); ++it ) {
0365         if( traits_type::find( exclusions.begin(), exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
0366             break;
0367     }
0368 
0369     return trim_left( it );
0370 }
0371 
0372 //____________________________________________________________________________//
0373 
0374 template<typename CharT>
0375 inline basic_cstring<CharT>&
0376 basic_cstring<CharT>::trim_right( size_type trim_size )
0377 {
0378     m_end  -= trim_size;
0379     if( m_end <= m_begin )
0380         clear();
0381 
0382     return *this;
0383 }
0384 
0385 //____________________________________________________________________________//
0386 
0387 template<typename CharT>
0388 inline basic_cstring<CharT>&
0389 basic_cstring<CharT>::trim_right( iterator it )
0390 {
0391     m_end = it;
0392     if( m_end <= m_begin )
0393         clear();
0394 
0395     return *this;
0396 }
0397 
0398 //____________________________________________________________________________//
0399 
0400 template<typename CharT>
0401 inline basic_cstring<CharT>&
0402 basic_cstring<CharT>::trim_right( basic_cstring exclusions )
0403 {
0404     if(!size()) {
0405         return *this;
0406     }
0407 
0408     if( exclusions.is_empty() )
0409         exclusions = default_trim_ex();
0410 
0411     iterator it = end();
0412 
0413     do {
0414         --it;
0415         if( self_type::traits_type::find( exclusions.begin(),  exclusions.size(), *it ) == reinterpret_cast<pointer>(0) )
0416             break;
0417     } while(it != begin());
0418 
0419     return trim_right( it + 1 );
0420 }
0421 
0422 //____________________________________________________________________________//
0423 
0424 template<typename CharT>
0425 inline basic_cstring<CharT>&
0426 basic_cstring<CharT>::trim( basic_cstring exclusions )
0427 {
0428     trim_left( exclusions );
0429     trim_right( exclusions );
0430 
0431     return *this;
0432 }
0433 
0434 //____________________________________________________________________________//
0435 
0436 template<typename CharT>
0437 inline basic_cstring<CharT>&
0438 basic_cstring<CharT>::operator=( basic_cstring<CharT> const& s )
0439 {
0440     m_begin = s.m_begin;
0441     m_end   = s.m_end;
0442 
0443     return *this;
0444 }
0445 
0446 //____________________________________________________________________________//
0447 
0448 template<typename CharT>
0449 inline basic_cstring<CharT>&
0450 basic_cstring<CharT>::operator=( std_string const& s )
0451 {
0452     return *this = self_type( s );
0453 }
0454 
0455 //____________________________________________________________________________//
0456 
0457 template<typename CharT>
0458 inline basic_cstring<CharT>&
0459 basic_cstring<CharT>::operator=( pointer s )
0460 {
0461     return *this = self_type( s );
0462 }
0463 
0464 //____________________________________________________________________________//
0465 
0466 template<typename CharT>
0467 inline basic_cstring<CharT>&
0468 basic_cstring<CharT>::assign( std_string const& s )
0469 {
0470     return *this = self_type( s );
0471 }
0472 
0473 //____________________________________________________________________________//
0474 
0475 template<typename CharT>
0476 inline basic_cstring<CharT>&
0477 basic_cstring<CharT>::assign( pointer s )
0478 {
0479     return *this = self_type( s );
0480 }
0481 
0482 //____________________________________________________________________________//
0483 
0484 template<typename CharT>
0485 inline basic_cstring<CharT>&
0486 basic_cstring<CharT>::assign( pointer f, pointer l )
0487 {
0488     return *this = self_type( f, l );
0489 }
0490 
0491 //____________________________________________________________________________//
0492 
0493 template<typename CharT>
0494 inline void
0495 basic_cstring<CharT>::swap( basic_cstring<CharT>& s )
0496 {
0497     // do not want to include alogrithm
0498     pointer tmp1    = m_begin;
0499     pointer tmp2    = m_end;
0500 
0501     m_begin         = s.m_begin;
0502     m_end           = s.m_end;
0503 
0504     s.m_begin       = tmp1;
0505     s.m_end         = tmp2;
0506 }
0507 
0508 //____________________________________________________________________________//
0509 
0510 template<typename CharT>
0511 inline typename basic_cstring<CharT>::iterator
0512 basic_cstring<CharT>::begin()
0513 {
0514     return m_begin;
0515 }
0516 
0517 //____________________________________________________________________________//
0518 
0519 template<typename CharT>
0520 inline typename basic_cstring<CharT>::const_iterator
0521 basic_cstring<CharT>::begin() const
0522 {
0523     return m_begin;
0524 }
0525 
0526 //____________________________________________________________________________//
0527 
0528 template<typename CharT>
0529 inline typename basic_cstring<CharT>::iterator
0530 basic_cstring<CharT>::end()
0531 {
0532     return m_end;
0533 }
0534 
0535 //____________________________________________________________________________//
0536 
0537 template<typename CharT>
0538 inline typename basic_cstring<CharT>::const_iterator
0539 basic_cstring<CharT>::end() const
0540 {
0541     return m_end;
0542 }
0543 
0544 //____________________________________________________________________________//
0545 
0546 template<typename CharT>
0547 inline typename basic_cstring<CharT>::size_type
0548 basic_cstring<CharT>::find( basic_cstring<CharT> str ) const
0549 {
0550     if( str.is_empty() || str.size() > size() )
0551         return npos;
0552 
0553     const_iterator last = end() - str.size() + 1;
0554 
0555     for( const_iterator it = begin(); it != last; ++it ) {
0556         if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
0557             return static_cast<size_type>(it - begin());
0558     }
0559 
0560     return npos;
0561 }
0562 
0563 //____________________________________________________________________________//
0564 
0565 template<typename CharT>
0566 inline typename basic_cstring<CharT>::size_type
0567 basic_cstring<CharT>::rfind( basic_cstring<CharT> str ) const
0568 {
0569     if( str.is_empty() || str.size() > size() )
0570         return npos;
0571 
0572     const_iterator first = begin();
0573 
0574     for( const_iterator it = end() - str.size(); it != first; --it ) {
0575         if( traits_type::compare( it, str.begin(), str.size() ) == 0 )
0576             return static_cast<size_type>(it - begin());
0577     }
0578     if( traits_type::compare( first, str.begin(), str.size() ) == 0 )
0579         return static_cast<size_type>(0);
0580     else
0581         return npos;
0582 }
0583 
0584 //____________________________________________________________________________//
0585 
0586 template<typename CharT>
0587 inline basic_cstring<CharT>
0588 basic_cstring<CharT>::substr( size_type beg_index, size_type end_index ) const
0589 {
0590     return beg_index > size()
0591             ?       self_type()
0592             : end_index > size()
0593                 ?   self_type( m_begin + beg_index, m_end )
0594                 :   self_type( m_begin + beg_index, m_begin + end_index );
0595 }
0596 
0597 //____________________________________________________________________________//
0598 
0599 template<typename CharT>
0600 inline basic_cstring<CharT>
0601 basic_cstring<CharT>::default_trim_ex()
0602 {
0603     static CharT ws[3] = { CharT(' '), CharT('\t'), CharT('\n') }; // !! wide case
0604 
0605     return self_type( ws, 3 );
0606 }
0607 
0608 //____________________________________________________________________________//
0609 
0610 // ************************************************************************** //
0611 // **************             comparison operators             ************** //
0612 // ************************************************************************** //
0613 
0614 template<typename CharT1,typename CharT2>
0615 inline bool
0616 operator==( basic_cstring<CharT1> const& s1, basic_cstring<CharT2> const& s2 )
0617 {
0618     typedef typename basic_cstring<CharT1>::traits_type traits_type;
0619     return s1.size() == s2.size() &&
0620                traits_type::compare( s1.begin(), s2.begin(), s1.size() ) == 0;
0621 }
0622 
0623 //____________________________________________________________________________//
0624 
0625 template<typename CharT1,typename CharT2>
0626 inline bool
0627 operator==( basic_cstring<CharT1> const& s1, CharT2* s2 )
0628 {
0629 #if !defined(__DMC__)
0630     return s1 == basic_cstring<CharT2>( s2 );
0631 #else
0632     return s1 == basic_cstring<CharT2 const>( s2 );
0633 #endif
0634 }
0635 
0636 //____________________________________________________________________________//
0637 
0638 template<typename CharT>
0639 inline bool
0640 operator==( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
0641 {
0642     return s1 == basic_cstring<CharT>( s2 );
0643 }
0644 
0645 //____________________________________________________________________________//
0646 
0647 template<typename CharT1,typename CharT2>
0648 inline bool
0649 operator==( CharT1* s2, basic_cstring<CharT2> const& s1 )
0650 {
0651     return s1 == s2;
0652 }
0653 
0654 //____________________________________________________________________________//
0655 
0656 template<typename CharT>
0657 inline bool
0658 operator==( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
0659 {
0660     return s1 == s2;
0661 }
0662 
0663 //____________________________________________________________________________//
0664 
0665 template<typename CharT>
0666 inline bool
0667 operator!=( basic_cstring<CharT> const& s1, CharT* s2 )
0668 {
0669     return !(s1 == s2);
0670 }
0671 
0672 //____________________________________________________________________________//
0673 
0674 template<typename CharT>
0675 inline bool
0676 operator!=( CharT* s2, basic_cstring<CharT> const& s1 )
0677 {
0678     return !(s1 == s2);
0679 }
0680 
0681 //____________________________________________________________________________//
0682 
0683 template<typename CharT>
0684 inline bool
0685 operator!=( basic_cstring<CharT> const& s1, basic_cstring<CharT> const& s2 )
0686 {
0687     return !(s1 == s2);
0688 }
0689 
0690 //____________________________________________________________________________//
0691 
0692 template<typename CharT>
0693 inline bool
0694 operator!=( basic_cstring<CharT> const& s1, typename basic_cstring<CharT>::std_string const& s2 )
0695 {
0696     return !(s1 == s2);
0697 }
0698 
0699 //____________________________________________________________________________//
0700 
0701 template<typename CharT>
0702 inline bool
0703 operator!=( typename basic_cstring<CharT>::std_string const& s2, basic_cstring<CharT> const& s1 )
0704 {
0705     return !(s1 == s2);
0706 }
0707 
0708 //____________________________________________________________________________//
0709 
0710 // ************************************************************************** //
0711 // **************                  first_char                  ************** //
0712 // ************************************************************************** //
0713 
0714 template<typename CharT>
0715 inline typename basic_cstring<CharT>::value_ret_type
0716 first_char( basic_cstring<CharT> source )
0717 {
0718     typedef typename basic_cstring<CharT>::value_ret_type res_type;
0719 
0720     return source.is_empty() ? static_cast<res_type>(0) : *source.begin();
0721 }
0722 
0723 //____________________________________________________________________________//
0724 
0725 // ************************************************************************** //
0726 // **************                  last_char                   ************** //
0727 // ************************************************************************** //
0728 
0729 template<typename CharT>
0730 inline typename basic_cstring<CharT>::value_ret_type
0731 last_char( basic_cstring<CharT> source )
0732 {
0733     typedef typename basic_cstring<CharT>::value_ret_type res_type;
0734 
0735     return source.is_empty() ? static_cast<res_type>(0) : *(source.end()-1);
0736 }
0737 
0738 //____________________________________________________________________________//
0739 
0740 // ************************************************************************** //
0741 // **************                  assign_op                   ************** //
0742 // ************************************************************************** //
0743 
0744 template<typename CharT1, typename CharT2>
0745 inline void
0746 assign_op( std::basic_string<CharT1>& target, basic_cstring<CharT2> src, int )
0747 {
0748     target.assign( src.begin(), src.size() );
0749 }
0750 
0751 //____________________________________________________________________________//
0752 
0753 template<typename CharT1, typename CharT2>
0754 inline std::basic_string<CharT1>&
0755 operator+=( std::basic_string<CharT1>& target, basic_cstring<CharT2> const& str )
0756 {
0757     target.append( str.begin(), str.end() );
0758     return target;
0759 }
0760 
0761 //____________________________________________________________________________//
0762 
0763 template<typename CharT1, typename CharT2>
0764 inline std::basic_string<CharT1>
0765 operator+( std::basic_string<CharT1> const& lhs, basic_cstring<CharT2> const& rhs )
0766 {
0767     std::basic_string<CharT1> res( lhs );
0768 
0769     res.append( rhs.begin(), rhs.end() );
0770     return res;
0771 }
0772 
0773 //____________________________________________________________________________//
0774 
0775 } // namespace unit_test
0776 
0777 } // namespace boost
0778 
0779 //____________________________________________________________________________//
0780 
0781 #include <boost/test/detail/enable_warnings.hpp>
0782 
0783 #endif // BOOST_TEST_UTILS_BASIC_CSTRING_HPP