Home | History | Annotate | Download | only in basic_cstring
      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 ) ;
    103     self_type&      trim_left() { trim_left( self_type() ) ; }
    104     self_type&      trim_right() { trim_right( self_type() ) ; }
    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>
    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
    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
    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
    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
    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
    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
    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
    209 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
    218 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
    230 basic_cstring<CharT>::size() const
    231 {
    232     return m_end - m_begin;
    233 }
    234 
    235 //____________________________________________________________________________//
    236 
    237 template<typename CharT>
    238 inline bool
    239 basic_cstring<CharT>::is_empty() const
    240 {
    241     return m_end == m_begin;
    242 }
    243 
    244 //____________________________________________________________________________//
    245 
    246 template<typename CharT>
    247 inline bool
    248 basic_cstring<CharT>::empty() const
    249 {
    250     return is_empty();
    251 }
    252 
    253 //____________________________________________________________________________//
    254 
    255 template<typename CharT>
    256 inline void
    257 basic_cstring<CharT>::clear()
    258 {
    259     m_begin = m_end;
    260 }
    261 
    262 //____________________________________________________________________________//
    263 
    264 template<typename CharT>
    265 inline void
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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>&
    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
    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
    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
    487 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
    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
    505 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
    514 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
    536 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>
    558 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>
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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