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