- Timestamp:
- 05/15/15 12:02:36 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/nv/core/string.hh
r360 r363 16 16 // TODO: WARNING: this code is centered around 8bit char. In particular, 17 17 // const_string wont work with non-8bit chars. 18 // TODO: remove templating on char type and TRAITS, make a string_utf8 instead.18 // TODO: remove templating on char type, make a string_utf8 instead. 19 19 20 20 #ifndef NV_CORE_STRING_HH … … 283 283 typename std::remove_cv < typename std::remove_reference< T >::type >::type >; 284 284 285 template<typename T, typename TRAITS = std::char_traits<T> > class basic_string_ref;286 285 class string_ref; 286 287 287 // string base class - will become a base for a string class later 288 template<typename T, typename TRAITS = std::char_traits<T> > 289 class basic_string_base 288 class string_base 290 289 { 291 290 public: 292 typedef Tvalue_type;293 typedef const T*pointer;294 typedef const T&reference;295 typedef const T&const_reference;291 typedef char value_type; 292 typedef const char* pointer; 293 typedef const char& reference; 294 typedef const char& const_reference; 296 295 typedef pointer const_iterator; 297 296 typedef const_iterator iterator; … … 305 304 306 305 // conversion to std::string 307 std::basic_string<T, TRAITS>to_string() const306 inline std::string to_string() const 308 307 { 309 return std:: basic_string<T, TRAITS>( m_data, m_size );308 return std::string( m_data, m_size ); 310 309 } 311 310 312 311 // iterators 313 NV_CONSTEXPR const_iterator cbegin() const { return m_data; }314 NV_CONSTEXPR const_iterator cend() const { return m_data + m_size; }315 const_reverse_iterator crbegin() const { return const_reverse_iterator(end() ); }316 const_reverse_iterator crend() const { return const_reverse_iterator(begin() ); }317 318 NV_CONSTEXPR size_type size() const { return m_size; }319 NV_CONSTEXPR size_type length() const { return m_size; }320 NV_CONSTEXPR size_type max_size() const { return m_size; }321 NV_CONSTEXPR bool empty() const { return m_size == 0; }312 inline NV_CONSTEXPR const_iterator cbegin() const { return m_data; } 313 inline NV_CONSTEXPR const_iterator cend() const { return m_data + m_size; } 314 inline const_reverse_iterator crbegin() const { return const_reverse_iterator( cend() ); } 315 inline const_reverse_iterator crend() const { return const_reverse_iterator( cbegin() ); } 316 317 inline NV_CONSTEXPR size_type size() const { return m_size; } 318 inline NV_CONSTEXPR size_type length() const { return m_size; } 319 inline NV_CONSTEXPR size_type max_size() const { return m_size; } 320 inline NV_CONSTEXPR bool empty() const { return m_size == 0; } 322 321 323 322 // access 324 NV_CONSTEXPR const T&operator[]( size_type i ) const { return m_data[i]; }325 const T&at( size_t i ) const323 inline NV_CONSTEXPR char operator[]( size_type i ) const { return m_data[i]; } 324 inline char at( size_t i ) const 326 325 { 327 326 // if ( i >= m_data ) NV_THROW( std::out_of_range( "string_ref::at" ) ); … … 329 328 } 330 329 331 NV_CONSTEXPR const T& front()const { return m_data[0]; }332 NV_CONSTEXPR const T& back()const { return m_data[m_size - 1]; }333 NV_CONSTEXPR const T* data() const { return m_data; }330 inline NV_CONSTEXPR const char front() const { return m_data[0]; } 331 inline NV_CONSTEXPR const char back() const { return m_data[m_size - 1]; } 332 inline NV_CONSTEXPR const char* data() const { return m_data; } 334 333 335 334 // string operations 336 int compare( basic_string_baserhs ) const337 { 338 int cmp = TRAITS::compare( m_data, rhs.m_data, ( std::min )( m_size, rhs.m_size ) );335 int compare( const string_base& rhs ) const 336 { 337 int cmp = std::memcmp( m_data, rhs.m_data, ( std::min )( m_size, rhs.m_size ) ); 339 338 return cmp != 0 ? cmp : ( m_size == rhs.m_size ? 0 : m_size < rhs.m_size ? -1 : 1 ); 340 339 } 341 bool starts_with( T c ) const { return !empty() && TRAITS::eq( c, front()); }342 bool starts_with( basic_string_bases ) const343 { 344 return m_size >= s.m_size && TRAITS::compare( m_data, s.m_data, s.m_size ) == 0;345 } 346 bool ends_with( T c ) const { return !empty() && TRAITS::eq( c, back()); }347 bool ends_with( basic_string_bases ) const348 { 349 return m_size >= s.m_size && TRAITS::compare( m_data + m_size - s.m_size, s.m_data, s.m_size ) == 0;350 } 351 size_type find( basic_string_bases, size_type pos = 0 ) const340 bool starts_with( char c ) const { return !empty() && c == front(); } 341 bool starts_with( const string_base& s ) const 342 { 343 return m_size >= s.m_size && std::memcmp( m_data, s.m_data, s.m_size ) == 0; 344 } 345 bool ends_with( char c ) const { return !empty() && c == back(); } 346 bool ends_with( const string_base& s ) const 347 { 348 return m_size >= s.m_size && std::memcmp( m_data + m_size - s.m_size, s.m_data, s.m_size ) == 0; 349 } 350 size_type find( const string_base& s, size_type pos = 0 ) const 352 351 { 353 352 if ( pos >= m_size ) return npos; 354 const_iterator it = std::search( this->cbegin() + pos, this->cend(), s.cbegin(), s.cend() , TRAITS::eq);353 const_iterator it = std::search( this->cbegin() + pos, this->cend(), s.cbegin(), s.cend() ); 355 354 return it == this->cend() ? npos : std::distance( this->cbegin(), it ); 356 355 } 357 size_type find( Tc, size_type pos = 0 ) const356 size_type find( char c, size_type pos = 0 ) const 358 357 { 359 358 if ( pos >= m_size ) return npos; 360 const_iterator it = std::find_if( this->cbegin() + pos, this->cend(), [=] ( T val ) { return TRAITS::eq( val, c ); } );359 const_iterator it = std::find_if( this->cbegin() + pos, this->cend(), [=] ( char val ) { return val == c; } ); 361 360 return it == this->cend() ? npos : std::distance( this->cbegin(), it ); 362 361 } 363 size_type rfind( basic_string_bases, size_type pos = 0 ) const362 size_type rfind( const string_base& s, size_type pos = 0 ) const 364 363 { 365 364 if ( pos >= m_size ) return npos; 366 const_reverse_iterator it = std::search( this->crbegin() + pos, this->crend(), s.crbegin(), s.crend() , TRAITS::eq);365 const_reverse_iterator it = std::search( this->crbegin() + pos, this->crend(), s.crbegin(), s.crend() ); 367 366 return it == this->crend() ? npos : m_size - 1 - std::distance( this->crbegin(), it ); 368 367 } 369 size_type rfind( Tc, size_type pos = 0 ) const368 size_type rfind( char c, size_type pos = 0 ) const 370 369 { 371 370 if ( pos >= m_size ) return npos; 372 const_reverse_iterator it = std::find_if( this->crbegin() + pos, this->crend(), [=] ( T val ) { return TRAITS::eq( val, c ); } );371 const_reverse_iterator it = std::find_if( this->crbegin() + pos, this->crend(), [=] ( char val ) { return val == c; } ); 373 372 return it == this->crend() ? npos : m_size - 1 - std::distance( this->crbegin(), it ); 374 373 } 375 size_type find_first_of( Tc ) const { return find( c ); }376 size_type find_first_of( basic_string_bases ) const377 { 378 const_iterator it = std::find_first_of( this->cbegin(), this->cend(), s.cbegin(), s.cend() , TRAITS::eq);374 size_type find_first_of( char c ) const { return find( c ); } 375 size_type find_first_of( const string_base& s ) const 376 { 377 const_iterator it = std::find_first_of( this->cbegin(), this->cend(), s.cbegin(), s.cend() ); 379 378 return it == this->cend() ? npos : std::distance( this->cbegin(), it ); 380 379 } 381 size_type find_last_of( Tc ) const { return rfind( c ); }382 size_type find_last_of( basic_string_bases ) const383 { 384 const_reverse_iterator it = std::find_first_of( this->crbegin(), this->crend(), s.cbegin(), s.cend() , TRAITS::eq);380 size_type find_last_of( char c ) const { return rfind( c ); } 381 size_type find_last_of( const string_base& s ) const 382 { 383 const_reverse_iterator it = std::find_first_of( this->crbegin(), this->crend(), s.cbegin(), s.cend() ); 385 384 return it == this->crend() ? npos : m_size - 1 - std::distance( this->crbegin(), it ); 386 385 } 387 size_type find_first_not_of( basic_string_bases ) const386 size_type find_first_not_of( const string_base& s ) const 388 387 { 389 388 for ( const_iterator it = this->cbegin(); it != this->cend(); ++it ) 390 if ( 0 == TRAITS::find( s.m_data, s.m_size, *first) )389 if ( 0 == std::memchr( s.m_data, *it, s.m_size ) ) 391 390 return std::distance( this->cbegin(), it ); 392 391 return npos; 393 392 } 394 size_type find_first_not_of( Tc ) const393 size_type find_first_not_of( char c ) const 395 394 { 396 395 for ( const_iterator it = this->cbegin(); it != this->cend(); ++it ) 397 if ( !TRAITS::eq( c, *it ))396 if ( c != *it ) 398 397 return std::distance( this->cbegin(), it ); 399 398 return npos; 400 399 } 401 size_type find_last_not_of( basic_string_bases ) const400 size_type find_last_not_of( const string_base& s ) const 402 401 { 403 402 for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it ) 404 if ( 0 == TRAITS::find( s.m_data, s.m_size, *it) )403 if ( 0 == std::memchr( s.m_data, *it, s.m_size ) ) 405 404 return m_size - 1 - std::distance( this->crbegin(), it );; 406 405 return npos; 407 406 } 408 size_type find_last_not_of( Tc ) const407 size_type find_last_not_of( char c ) const 409 408 { 410 409 for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it ) 411 if ( !TRAITS::eq( c, *it ))410 if ( c != *it ) 412 411 return m_size - 1 - std::distance( this->crbegin(), it ); 413 412 return npos; … … 415 414 416 415 // string operations 417 basic_string_ref< T, TRAITS > substr( size_type p, size_type n = npos ) const 418 { 419 if ( p > size() ) return basic_string_ref< T, TRAITS >(); // NV_THROW( std::out_of_range( "substr" ) ); 420 if ( n == p || p + n > size() ) n = size() - p; 421 return basic_string_ref< T, TRAITS >( data() + p, n ); 416 string_ref substr( size_type p, size_type n = npos ) const; 417 418 inline std::size_t hash() const 419 { 420 const char* str = m_data; 421 size_type sz = m_size; 422 int seed = 131; 423 int result = 0; 424 while ( sz ) 425 { 426 result = ( result * seed ) + ( *str ); 427 str++; 428 sz--; 429 } 430 return result & ( 0x7FFFFFFF ); 422 431 } 423 432 424 433 protected: 425 NV_CONSTEXPR basic_string_base() : m_data( nullptr ), m_size( 0 ) {}426 NV_CONSTEXPR basic_string_base( pointer a_data, size_type a_lenght )434 inline NV_CONSTEXPR string_base() : m_data( nullptr ), m_size( 0 ) {} 435 inline NV_CONSTEXPR string_base( pointer a_data, size_type a_lenght ) 427 436 : m_data( a_data ), m_size( a_lenght ) {} 428 437 … … 432 441 }; 433 442 434 #define NV_STRING_BASE_CAST_OPERATORS( OPERATOR )\ 435 template < typename T, typename TRAITS, typename ALLOCATOR >\ 436 inline bool operator OPERATOR ( basic_string_base< T, TRAITS > lhs, const std::basic_string< T, TRAITS, ALLOCATOR >& rhs )\ 437 {\ 438 return lhs OPERATOR basic_string_base< T, TRAITS >( rhs );\ 439 }\ 440 template < typename T, typename TRAITS, typename ALLOCATOR >\ 441 inline bool operator OPERATOR ( const std::basic_string< T, TRAITS, ALLOCATOR >& lhs, basic_string_base< T, TRAITS > rhs )\ 442 {\ 443 return basic_string_base< T, TRAITS >( lhs ) OPERATOR rhs;\ 444 }\ 445 template < typename T, typename TRAITS >\ 446 inline bool operator OPERATOR ( basic_string_base<T, TRAITS> lhs, const T* rhs )\ 447 {\ 448 return lhs OPERATOR basic_string_base< T, TRAITS >( rhs );\ 449 }\ 450 template < typename T, typename TRAITS >\ 451 inline bool operator OPERATOR ( const T* lhs, basic_string_base< T, TRAITS > rhs )\ 452 {\ 453 return basic_string_base< T, TRAITS >( lhs ) OPERATOR rhs;\ 454 }\ 455 456 // Base operators 457 template < typename T, typename TRAITS > 458 inline bool operator==( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs ) 459 { 460 return lhs.size() != rhs.size() ? false : ( lhs.compare( rhs ) == 0 ); 461 } 462 template < typename T, typename TRAITS > 463 inline bool operator!=( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs ) 464 { 465 return lhs.size() != rhs.size() ? true : ( lhs.compare( rhs ) != 0 ); 466 } 467 template < typename T, typename TRAITS > 468 inline bool operator<( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs ) 469 { 470 return lhs.compare( rhs ) < 0; 471 } 472 template < typename T, typename TRAITS > 473 inline bool operator>( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs ) 474 { 475 return lhs.compare( rhs ) > 0; 476 } 477 template < typename T, typename TRAITS > 478 inline bool operator<=( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs ) 479 { 480 return lhs.compare( rhs ) <= 0; 481 } 482 template < typename T, typename TRAITS > 483 inline bool operator>=( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs ) 484 { 485 return lhs.compare( rhs ) >= 0; 486 } 487 488 NV_STRING_BASE_CAST_OPERATORS( == ) 489 NV_STRING_BASE_CAST_OPERATORS( != ) 490 NV_STRING_BASE_CAST_OPERATORS( < ) 491 NV_STRING_BASE_CAST_OPERATORS( > ) 492 NV_STRING_BASE_CAST_OPERATORS( <= ) 493 NV_STRING_BASE_CAST_OPERATORS( >= ) 494 495 template < class T, class TRAITS > 496 inline std::basic_ostream<T, TRAITS>& operator<<( std::basic_ostream<T, TRAITS>& os, const basic_string_base<T, TRAITS>& str ) 497 { 498 if ( os.good() ) 499 { 500 os.write( str.data(), str.size() ); 501 } 502 return os; 503 } 504 505 #undef NV_STRING_REF_CAST_OPERATORS 506 507 template<typename T, typename TRAITS> 508 class basic_string_ref : public basic_string_base < T, TRAITS > 443 class string_ref : public string_base 509 444 { 510 445 public: 511 512 NV_CONSTEXPR basic_string_ref() {} 513 NV_CONSTEXPR basic_string_ref( const basic_string_ref &rhs ) 514 : basic_string_base( rhs.m_data, rhs.m_size ) 515 { 516 } 517 NV_CONSTEXPR basic_string_ref( const basic_string_base< T, TRAITS > &rhs ) 518 : basic_string_base( rhs.m_data, rhs.m_size ) 519 { 520 } 521 522 template< typename ALLOCATOR > 523 basic_string_ref( const std::basic_string<T, TRAITS, ALLOCATOR>& str ) 524 : basic_string_base( str.data(), str.length() ) 525 { 526 } 527 528 NV_CONSTEXPR basic_string_ref( const T* str, size_type len ) 529 : basic_string_base( str, len ) 446 inline NV_CONSTEXPR string_ref() {} 447 inline NV_CONSTEXPR string_ref( const string_ref& rhs ) 448 : string_base( rhs.m_data, rhs.m_size ) 449 { 450 } 451 inline NV_CONSTEXPR string_ref( const string_base& rhs ) 452 : string_base( rhs.data(), rhs.size() ) 453 { 454 } 455 456 inline string_ref( const std::string& str ) 457 : string_base( str.data(), str.size() ) 458 { 459 } 460 461 inline NV_CONSTEXPR string_ref( const char* str, size_type len ) 462 : string_base( str, len ) 530 463 { 531 464 } 532 465 533 466 // Literal constructors 534 template< size_t N , typename std::enable_if<std::is_same<T, char>::value>::type* = nullptr>535 basic_string_ref( T( &s )[N] ) : basic_string_base( s, N - 1 ) {}536 template< size_t N , typename std::enable_if<std::is_same<T, char>::value>::type* = nullptr>537 basic_string_ref( const T( &s )[N] ) : basic_string_base( s, N - 1 ) {}467 template< size_t N > 468 inline string_ref( char( &s )[N] ) : string_base( s, N - 1 ) {} 469 template< size_t N > 470 inline string_ref( const char( &s )[N] ) : string_base( s, N - 1 ) {} 538 471 539 472 // Non-literal constructors 540 473 template< typename U, typename std::enable_if<std::is_same<U, const char*>::value>::type* = nullptr > 541 basic_string_ref( U str ) : basic_string_base( str, TRAITS::length( str ) ) {}542 543 basic_string_ref& operator=( const basic_string_ref &rhs )474 inline string_ref( U str ) : string_base( str, std::strlen( str ) ) {} 475 476 inline string_ref& operator=( const string_ref &rhs ) 544 477 { 545 478 m_data = rhs.m_data; … … 549 482 550 483 // iterators 551 NV_CONSTEXPR const_iterator begin() const { return m_data; }552 NV_CONSTEXPR const_iterator end() const { return m_data + m_size; }553 const_reverse_iterator rbegin() const { return const_reverse_iterator( end() ); }554 const_reverse_iterator rend() const { return const_reverse_iterator( begin() ); }484 inline NV_CONSTEXPR const_iterator begin() const { return m_data; } 485 inline NV_CONSTEXPR const_iterator end() const { return m_data + m_size; } 486 inline const_reverse_iterator rbegin() const { return const_reverse_iterator( end() ); } 487 inline const_reverse_iterator rend() const { return const_reverse_iterator( begin() ); } 555 488 556 489 // modifiers 557 void clear()490 inline void clear() 558 491 { 559 492 m_size = 0; 560 493 m_data = nullptr; 561 494 } 562 void remove_prefix( size_type n )495 inline void remove_prefix( size_type n ) 563 496 { 564 497 if ( n > m_size ) n = m_size; … … 566 499 m_size -= n; 567 500 } 568 void remove_suffix( size_type n )501 inline void remove_suffix( size_type n ) 569 502 { 570 503 if ( n > m_size ) n = m_size; … … 574 507 }; 575 508 576 typedef basic_string_ref<char, std::char_traits<char> > string_ref;577 578 509 // const string is movable but not copyable 579 template<typename T, typename TRAITS> 580 class basic_const_string : public basic_string_base < T, TRAITS > 510 class const_string : public string_base 581 511 { 582 512 public: 583 basic_const_string() {}584 basic_const_string( const T* str, size_type len )513 NV_CONSTEXPR const_string() {} 514 const_string( const char* str, size_type len ) 585 515 { 586 516 initialize( str, len ); 587 517 } 588 explicit basic_const_string( const T* str )589 { 590 initialize( str, TRAITS::length( str ) );591 } 592 593 ~ basic_const_string()518 explicit const_string( const char* str ) 519 { 520 initialize( str, std::strlen( str ) ); 521 } 522 523 ~const_string() 594 524 { 595 525 if ( m_data ) delete m_data; 596 526 } 597 527 598 basic_const_string( const basic_const_string&& other ) 599 { 600 std::swap( m_data, other.m_data ); 528 inline const_string( const_string&& other ) 529 { 530 m_data = other.m_data; 531 other.m_data = nullptr; 532 } 533 534 inline const_string& operator=( const_string&& other ) 535 { 536 pointer temp = m_data; 537 m_data = other.m_data; 538 other.m_data = temp; 601 539 return *this; 602 540 } 603 541 604 basic_const_string& operator=( const basic_const_string&& other ) 605 { 606 std::swap( m_data, other.m_data ); 607 return *this; 608 } 542 // blocked copy constructor 543 const_string( const const_string & ) = delete; 544 // blocked copy operator 545 const_string& operator=( const const_string& ) = delete; 609 546 610 547 private: 611 // blocked copy constructor 612 basic_const_string( const basic_const_string & ); 613 // blocked copy operator 614 basic_const_string& operator=( const basic_const_string& ); 615 616 void assign( const T* p, size_type s ) 617 { 618 m_data = new T[s + 1]; 619 TRAITS::copy( m_data, p, s ); 620 m_data[s] = 0; 548 549 void initialize( const char* p, size_type s ) 550 { 551 char* data = new char[s + 1]; 552 std::memcpy( data, p, s ); 553 data[s] = 0; 554 m_data = data; 621 555 } 622 556 }; 623 557 558 inline string_ref string_base::substr( size_type p, size_type n ) const 559 { 560 if ( p > size() ) return string_ref(); // NV_THROW( std::out_of_range( "substr" ) ); 561 if ( n == p || p + n > size() ) n = size() - p; 562 return string_ref( data() + p, n ); 563 } 564 565 #define NV_STRING_BASE_CAST_OPERATORS( OPERATOR )\ 566 inline bool operator OPERATOR ( const string_base& lhs, const std::string& rhs )\ 567 {\ 568 return lhs OPERATOR string_ref( rhs );\ 569 }\ 570 inline bool operator OPERATOR ( const std::string& lhs, const string_base& rhs )\ 571 {\ 572 return string_ref( lhs ) OPERATOR rhs;\ 573 }\ 574 inline bool operator OPERATOR ( const string_base& lhs, const char* rhs )\ 575 {\ 576 return lhs OPERATOR string_ref( rhs );\ 577 }\ 578 inline bool operator OPERATOR ( const char* lhs, const string_base& rhs )\ 579 {\ 580 return string_ref( lhs ) OPERATOR rhs;\ 581 }\ 582 583 // Base operators 584 inline bool operator==( const string_base& lhs, const string_base& rhs ) 585 { 586 return lhs.size() != rhs.size() ? false : ( lhs.compare( rhs ) == 0 ); 587 } 588 inline bool operator!=( const string_base& lhs, const string_base& rhs ) 589 { 590 return lhs.size() != rhs.size() ? true : ( lhs.compare( rhs ) != 0 ); 591 } 592 inline bool operator<( const string_base& lhs, const string_base& rhs ) 593 { 594 return lhs.compare( rhs ) < 0; 595 } 596 inline bool operator>( const string_base& lhs, const string_base& rhs ) 597 { 598 return lhs.compare( rhs ) > 0; 599 } 600 inline bool operator<=( const string_base& lhs, const string_base& rhs ) 601 { 602 return lhs.compare( rhs ) <= 0; 603 } 604 inline bool operator>=( const string_base& lhs, const string_base& rhs ) 605 { 606 return lhs.compare( rhs ) >= 0; 607 } 608 609 NV_STRING_BASE_CAST_OPERATORS( == ) 610 NV_STRING_BASE_CAST_OPERATORS( != ) 611 NV_STRING_BASE_CAST_OPERATORS( < ) 612 NV_STRING_BASE_CAST_OPERATORS( > ) 613 NV_STRING_BASE_CAST_OPERATORS( <= ) 614 NV_STRING_BASE_CAST_OPERATORS( >= ) 615 616 inline std::ostream& operator<<( std::ostream& os, const string_base& str ) 617 { 618 if ( os.good() ) 619 { 620 os.write( str.data(), str.size() ); 621 } 622 return os; 623 } 624 625 #undef NV_STRING_REF_CAST_OPERATORS 626 624 627 625 628 } 626 629 630 namespace std 631 { 632 633 template<> 634 struct hash< nv::string_base > 635 { 636 std::size_t operator()( const nv::string_base& s ) const 637 { 638 return s.hash(); 639 } 640 }; 641 642 } 643 627 644 #endif // NV_CORE_STRING_HH
Note: See TracChangeset
for help on using the changeset viewer.