Changeset 363


Ignore:
Timestamp:
05/15/15 12:02:36 (10 years ago)
Author:
epyon
Message:
  • string_* classes are no longer templated
  • UTF-8 is assumed as only supported encoding (but not yet)
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/nv/core/string.hh

    r360 r363  
    1616// TODO: WARNING: this code is centered around 8bit char. In particular,
    1717//   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.
    1919
    2020#ifndef NV_CORE_STRING_HH
     
    283283                typename std::remove_cv < typename std::remove_reference< T >::type >::type >;
    284284
    285         template<typename T, typename TRAITS = std::char_traits<T> > class basic_string_ref;
    286        
     285        class string_ref;
     286
    287287        // 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
    290289        {
    291290        public:
    292                 typedef T              value_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;
    296295                typedef pointer        const_iterator;
    297296                typedef const_iterator iterator;
     
    305304
    306305                // conversion to std::string
    307                 std::basic_string<T, TRAITS> to_string() const
     306                inline std::string to_string() const
    308307                {
    309                         return std::basic_string<T, TRAITS>( m_data, m_size );
     308                        return std::string( m_data, m_size );
    310309                }
    311310
    312311                // 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; }
    322321
    323322                // access
    324                 NV_CONSTEXPR const T& operator[]( size_type i ) const { return m_data[i]; }
    325                 const T& at( size_t i ) const
     323                inline NV_CONSTEXPR char operator[]( size_type i ) const { return m_data[i]; }
     324                inline char at( size_t i ) const
    326325                {
    327326                        //      if ( i >= m_data ) NV_THROW( std::out_of_range( "string_ref::at" ) );
     
    329328                }
    330329
    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; }
    334333
    335334                // string operations
    336                 int compare( basic_string_base rhs ) const
    337                 {
    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 ) );
    339338                        return cmp != 0 ? cmp : ( m_size == rhs.m_size ? 0 : m_size < rhs.m_size ? -1 : 1 );
    340339                }
    341                 bool starts_with( T c ) const { return !empty() && TRAITS::eq( c, front() ); }
    342                 bool starts_with( basic_string_base s ) const
    343                 {
    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_base s ) const
    348                 {
    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_base s, size_type pos = 0 ) const
     340                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
    352351                {
    353352                        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() );
    355354                        return it == this->cend() ? npos : std::distance( this->cbegin(), it );
    356355                }
    357                 size_type find( T c, size_type pos = 0 ) const
     356                size_type find( char c, size_type pos = 0 ) const
    358357                {
    359358                        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; } );
    361360                        return it == this->cend() ? npos : std::distance( this->cbegin(), it );
    362361                }
    363                 size_type rfind( basic_string_base s, size_type pos = 0 ) const
     362                size_type rfind( const string_base& s, size_type pos = 0 ) const
    364363                {
    365364                        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() );
    367366                        return it == this->crend() ? npos : m_size - 1 - std::distance( this->crbegin(), it );
    368367                }
    369                 size_type rfind( T c, size_type pos = 0 ) const
     368                size_type rfind( char c, size_type pos = 0 ) const
    370369                {
    371370                        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; } );
    373372                        return it == this->crend() ? npos : m_size - 1 - std::distance( this->crbegin(), it );
    374373                }
    375                 size_type find_first_of( T c ) const { return find( c ); }
    376                 size_type find_first_of( basic_string_base s ) const
    377                 {
    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() );
    379378                        return it == this->cend() ? npos : std::distance( this->cbegin(), it );
    380379                }
    381                 size_type find_last_of( T c )  const { return rfind( c ); }
    382                 size_type find_last_of( basic_string_base s ) const
    383                 {
    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() );
    385384                        return it == this->crend() ? npos : m_size - 1 - std::distance( this->crbegin(), it );
    386385                }
    387                 size_type find_first_not_of( basic_string_base s ) const
     386                size_type find_first_not_of( const string_base& s ) const
    388387                {
    389388                        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 ) )
    391390                                        return std::distance( this->cbegin(), it );
    392391                        return npos;
    393392                }
    394                 size_type find_first_not_of( T c ) const
     393                size_type find_first_not_of( char c ) const
    395394                {
    396395                        for ( const_iterator it = this->cbegin(); it != this->cend(); ++it )
    397                                 if ( !TRAITS::eq( c, *it ) )
     396                                if ( c != *it )
    398397                                        return std::distance( this->cbegin(), it );
    399398                        return npos;
    400399                }
    401                 size_type find_last_not_of( basic_string_base s ) const
     400                size_type find_last_not_of( const string_base& s ) const
    402401                {
    403402                        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 ) )
    405404                                        return m_size - 1 - std::distance( this->crbegin(), it );;
    406405                        return npos;
    407406                }
    408                 size_type find_last_not_of( T c ) const
     407                size_type find_last_not_of( char c ) const
    409408                {
    410409                        for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it )
    411                                 if ( !TRAITS::eq( c, *it ) )
     410                                if ( c != *it )
    412411                                        return m_size - 1 - std::distance( this->crbegin(), it );
    413412                        return npos;
     
    415414
    416415                // 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 );
    422431                }
    423432
    424433        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 )
    427436                        : m_data( a_data ), m_size( a_lenght ) {}
    428437
     
    432441        };
    433442
    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
    509444        {
    510445        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 )
    530463                {
    531464                }
    532465
    533466                // 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 ) {}
    538471
    539472                // Non-literal constructors
    540473                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 )
    544477                {
    545478                        m_data = rhs.m_data;
     
    549482
    550483                // 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() ); }
    555488
    556489                // modifiers
    557                 void clear()
     490                inline void clear()
    558491                {
    559492                        m_size = 0;
    560493                        m_data = nullptr;
    561494                }
    562                 void remove_prefix( size_type n )
     495                inline void remove_prefix( size_type n )
    563496                {
    564497                        if ( n > m_size )       n = m_size;
     
    566499                        m_size -= n;
    567500                }
    568                 void remove_suffix( size_type n )
     501                inline void remove_suffix( size_type n )
    569502                {
    570503                        if ( n > m_size ) n = m_size;
     
    574507        };
    575508
    576         typedef basic_string_ref<char, std::char_traits<char> > string_ref;
    577 
    578509        // 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
    581511        {
    582512        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 )
    585515                {
    586516                        initialize( str, len );
    587517                }
    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()
    594524                {
    595525                        if ( m_data ) delete m_data;
    596526                }
    597527
    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;
    601539                        return *this;
    602540                }
    603541
    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;
    609546
    610547        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;
    621555                }
    622556        };
    623557
     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 )\
     566inline bool operator OPERATOR ( const string_base& lhs, const std::string& rhs )\
     567{\
     568        return lhs OPERATOR string_ref( rhs );\
     569}\
     570inline bool operator OPERATOR ( const std::string& lhs, const string_base& rhs )\
     571{\
     572        return string_ref( lhs ) OPERATOR rhs;\
     573}\
     574inline bool operator OPERATOR ( const string_base& lhs, const char* rhs )\
     575{\
     576        return lhs OPERATOR string_ref( rhs );\
     577}\
     578inline 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
     609NV_STRING_BASE_CAST_OPERATORS( == )
     610NV_STRING_BASE_CAST_OPERATORS( != )
     611NV_STRING_BASE_CAST_OPERATORS( < )
     612NV_STRING_BASE_CAST_OPERATORS( > )
     613NV_STRING_BASE_CAST_OPERATORS( <= )
     614NV_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
    624627
    625628}
    626629
     630namespace 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
    627644#endif // NV_CORE_STRING_HH
Note: See TracChangeset for help on using the changeset viewer.