File indexing completed on 2025-01-18 09:52:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_TEST_UTILS_BASIC_CSTRING_HPP
0017 #define BOOST_TEST_UTILS_BASIC_CSTRING_HPP
0018
0019
0020 #include <boost/test/utils/basic_cstring/basic_cstring_fwd.hpp>
0021 #include <boost/test/utils/basic_cstring/bcs_char_traits.hpp>
0022
0023
0024 #include <boost/type_traits/remove_cv.hpp>
0025
0026
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
0043
0044
0045 template<typename CharT>
0046 class BOOST_SYMBOL_VISIBLE basic_cstring {
0047 typedef basic_cstring<CharT> self_type;
0048 public:
0049
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
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
0071
0072 static const size_type npos = -1 ;
0073 #endif
0074
0075 static pointer null_str();
0076
0077
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
0087 value_ret_type operator[]( size_type index ) const;
0088 value_ret_type at( size_type index ) const;
0089
0090
0091 size_type size() const;
0092 bool is_empty() const;
0093 void clear();
0094 void resize( size_type new_len );
0095
0096
0097 bool empty() const;
0098
0099
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
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
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
0149 void swap( self_type& s );
0150
0151
0152 iterator begin();
0153 const_iterator begin() const;
0154 iterator end();
0155 const_iterator end() const;
0156
0157
0158
0159
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
0168 iterator m_begin;
0169 iterator m_end;
0170 static CharT null;
0171 };
0172
0173
0174
0175
0176
0177
0178 #if defined(BOOST_TEST_STRING_VIEW)
0179
0180
0181
0182
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
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
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') };
0604
0605 return self_type( ws, 3 );
0606 }
0607
0608
0609
0610
0611
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
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
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
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 }
0776
0777 }
0778
0779
0780
0781 #include <boost/test/detail/enable_warnings.hpp>
0782
0783 #endif