Index: trunk/nv/core/string.hh
===================================================================
--- trunk/nv/core/string.hh	(revision 362)
+++ trunk/nv/core/string.hh	(revision 363)
@@ -16,5 +16,5 @@
 // TODO: WARNING: this code is centered around 8bit char. In particular, 
 //   const_string wont work with non-8bit chars.
-// TODO: remove templating on char type and TRAITS, make a string_utf8 instead.
+// TODO: remove templating on char type, make a string_utf8 instead.
 
 #ifndef NV_CORE_STRING_HH
@@ -283,15 +283,14 @@
 		typename std::remove_cv < typename std::remove_reference< T >::type >::type >;
 
-	template<typename T, typename TRAITS = std::char_traits<T> > class basic_string_ref;
-	
+	class string_ref;
+
 	// string base class - will become a base for a string class later
-	template<typename T, typename TRAITS = std::char_traits<T> >
-	class basic_string_base
+	class string_base
 	{
 	public:
-		typedef T              value_type;
-		typedef const T*       pointer;
-		typedef const T&       reference;
-		typedef const T&       const_reference;
+		typedef char           value_type;
+		typedef const char*    pointer;
+		typedef const char&    reference;
+		typedef const char&    const_reference;
 		typedef pointer        const_iterator;
 		typedef const_iterator iterator;
@@ -305,23 +304,23 @@
 
 		// conversion to std::string
- 		std::basic_string<T, TRAITS> to_string() const
+ 		inline std::string to_string() const
  		{
- 			return std::basic_string<T, TRAITS>( m_data, m_size );
+ 			return std::string( m_data, m_size );
  		}
 
 		// iterators
-		NV_CONSTEXPR const_iterator  cbegin() const { return m_data; }
-		NV_CONSTEXPR const_iterator    cend() const { return m_data + m_size; }
-		const_reverse_iterator crbegin() const { return const_reverse_iterator( end() ); }
-		const_reverse_iterator   crend() const { return const_reverse_iterator( begin() ); }
-
-		NV_CONSTEXPR size_type size()     const { return m_size; }
-		NV_CONSTEXPR size_type length()   const { return m_size; }
-		NV_CONSTEXPR size_type max_size() const { return m_size; }
-		NV_CONSTEXPR bool empty()         const { return m_size == 0; }
+		inline NV_CONSTEXPR const_iterator  cbegin() const { return m_data; }
+		inline NV_CONSTEXPR const_iterator    cend() const { return m_data + m_size; }
+		inline const_reverse_iterator crbegin() const { return const_reverse_iterator( cend() ); }
+		inline const_reverse_iterator   crend() const { return const_reverse_iterator( cbegin() ); }
+
+		inline NV_CONSTEXPR size_type size()     const { return m_size; }
+		inline NV_CONSTEXPR size_type length()   const { return m_size; }
+		inline NV_CONSTEXPR size_type max_size() const { return m_size; }
+		inline NV_CONSTEXPR bool empty()         const { return m_size == 0; }
 
 		// access
-		NV_CONSTEXPR const T& operator[]( size_type i ) const { return m_data[i]; }
-		const T& at( size_t i ) const
+		inline NV_CONSTEXPR char operator[]( size_type i ) const { return m_data[i]; }
+		inline char at( size_t i ) const
 		{
 			//	if ( i >= m_data ) NV_THROW( std::out_of_range( "string_ref::at" ) );
@@ -329,85 +328,85 @@
 		}
 
-		NV_CONSTEXPR const T& front() const { return m_data[0]; }
-		NV_CONSTEXPR const T& back()  const { return m_data[m_size - 1]; }
-		NV_CONSTEXPR const T* data()  const { return m_data; }
+		inline NV_CONSTEXPR const char front()  const { return m_data[0]; }
+		inline NV_CONSTEXPR const char back()   const { return m_data[m_size - 1]; }
+		inline NV_CONSTEXPR const char* data()  const { return m_data; }
 
 		// string operations
-		int compare( basic_string_base rhs ) const
-		{
-			int cmp = TRAITS::compare( m_data, rhs.m_data, ( std::min )( m_size, rhs.m_size ) );
+		int compare( const string_base& rhs ) const
+		{
+			int cmp = std::memcmp( m_data, rhs.m_data, ( std::min )( m_size, rhs.m_size ) );
 			return cmp != 0 ? cmp : ( m_size == rhs.m_size ? 0 : m_size < rhs.m_size ? -1 : 1 );
 		}
-		bool starts_with( T c ) const { return !empty() && TRAITS::eq( c, front() ); }
-		bool starts_with( basic_string_base s ) const
-		{
-			return m_size >= s.m_size && TRAITS::compare( m_data, s.m_data, s.m_size ) == 0;
-		}
-		bool ends_with( T c ) const { return !empty() && TRAITS::eq( c, back() ); }
-		bool ends_with( basic_string_base s ) const
-		{
-			return m_size >= s.m_size && TRAITS::compare( m_data + m_size - s.m_size, s.m_data, s.m_size ) == 0;
-		}
-		size_type find( basic_string_base s, size_type pos = 0 ) const
+		bool starts_with( char c ) const { return !empty() && c == front(); }
+		bool starts_with( const string_base& s ) const
+		{
+			return m_size >= s.m_size && std::memcmp( m_data, s.m_data, s.m_size ) == 0;
+		}
+		bool ends_with( char c ) const { return !empty() && c == back(); }
+		bool ends_with( const string_base& s ) const
+		{
+			return m_size >= s.m_size && std::memcmp( m_data + m_size - s.m_size, s.m_data, s.m_size ) == 0;
+		}
+		size_type find( const string_base& s, size_type pos = 0 ) const
 		{
 			if ( pos >= m_size ) return npos;
-			const_iterator it = std::search( this->cbegin() + pos, this->cend(), s.cbegin(), s.cend(), TRAITS::eq );
+			const_iterator it = std::search( this->cbegin() + pos, this->cend(), s.cbegin(), s.cend() );
 			return it == this->cend() ? npos : std::distance( this->cbegin(), it );
 		}
-		size_type find( T c, size_type pos = 0 ) const
+		size_type find( char c, size_type pos = 0 ) const
 		{
 			if ( pos >= m_size ) return npos;
-			const_iterator it = std::find_if( this->cbegin() + pos, this->cend(), [=] ( T val ) { return TRAITS::eq( val, c ); } );
+			const_iterator it = std::find_if( this->cbegin() + pos, this->cend(), [=] ( char val ) { return val == c; } );
 			return it == this->cend() ? npos : std::distance( this->cbegin(), it );
 		}
-		size_type rfind( basic_string_base s, size_type pos = 0 ) const
+		size_type rfind( const string_base& s, size_type pos = 0 ) const
 		{
 			if ( pos >= m_size ) return npos;
-			const_reverse_iterator it = std::search( this->crbegin() + pos, this->crend(), s.crbegin(), s.crend(), TRAITS::eq );
+			const_reverse_iterator it = std::search( this->crbegin() + pos, this->crend(), s.crbegin(), s.crend() );
 			return it == this->crend() ? npos : m_size - 1 - std::distance( this->crbegin(), it );
 		}
-		size_type rfind( T c, size_type pos = 0 ) const
+		size_type rfind( char c, size_type pos = 0 ) const
 		{
 			if ( pos >= m_size ) return npos;
-			const_reverse_iterator it = std::find_if( this->crbegin() + pos, this->crend(), [=] ( T val ) { return TRAITS::eq( val, c ); } );
+			const_reverse_iterator it = std::find_if( this->crbegin() + pos, this->crend(), [=] ( char val ) { return val == c; } );
 			return it == this->crend() ? npos : m_size - 1 - std::distance( this->crbegin(), it );
 		}
-		size_type find_first_of( T c ) const { return find( c ); }
-		size_type find_first_of( basic_string_base s ) const
-		{
-			const_iterator it = std::find_first_of( this->cbegin(), this->cend(), s.cbegin(), s.cend(), TRAITS::eq );
+		size_type find_first_of( char c ) const { return find( c ); }
+		size_type find_first_of( const string_base& s ) const
+		{
+			const_iterator it = std::find_first_of( this->cbegin(), this->cend(), s.cbegin(), s.cend() );
 			return it == this->cend() ? npos : std::distance( this->cbegin(), it );
 		}
-		size_type find_last_of( T c )  const { return rfind( c ); }
-		size_type find_last_of( basic_string_base s ) const
-		{
-			const_reverse_iterator it = std::find_first_of( this->crbegin(), this->crend(), s.cbegin(), s.cend(), TRAITS::eq );
+		size_type find_last_of( char c )  const { return rfind( c ); }
+		size_type find_last_of( const string_base& s ) const
+		{
+			const_reverse_iterator it = std::find_first_of( this->crbegin(), this->crend(), s.cbegin(), s.cend() );
 			return it == this->crend() ? npos : m_size - 1 - std::distance( this->crbegin(), it );
 		}
-		size_type find_first_not_of( basic_string_base s ) const
+		size_type find_first_not_of( const string_base& s ) const
 		{
 			for ( const_iterator it = this->cbegin(); it != this->cend(); ++it )
-				if ( 0 == TRAITS::find( s.m_data, s.m_size, *first ) )
+				if ( 0 == std::memchr( s.m_data, *it, s.m_size ) )
 					return std::distance( this->cbegin(), it );
 			return npos;
 		}
-		size_type find_first_not_of( T c ) const
+		size_type find_first_not_of( char c ) const
 		{
 			for ( const_iterator it = this->cbegin(); it != this->cend(); ++it )
-				if ( !TRAITS::eq( c, *it ) )
+				if ( c != *it )
 					return std::distance( this->cbegin(), it );
 			return npos;
 		}
-		size_type find_last_not_of( basic_string_base s ) const
+		size_type find_last_not_of( const string_base& s ) const
 		{
 			for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it )
-				if ( 0 == TRAITS::find( s.m_data, s.m_size, *it ) )
+				if ( 0 == std::memchr( s.m_data, *it, s.m_size ) )
 					return m_size - 1 - std::distance( this->crbegin(), it );;
 			return npos;
 		}
-		size_type find_last_not_of( T c ) const
+		size_type find_last_not_of( char c ) const
 		{
 			for ( const_reverse_iterator it = this->crbegin(); it != this->crend(); ++it )
-				if ( !TRAITS::eq( c, *it ) )
+				if ( c != *it )
 					return m_size - 1 - std::distance( this->crbegin(), it );
 			return npos;
@@ -415,14 +414,24 @@
 
 		// string operations
-		basic_string_ref< T, TRAITS > substr( size_type p, size_type n = npos ) const
-		{
-			if ( p > size() ) return basic_string_ref< T, TRAITS >(); // NV_THROW( std::out_of_range( "substr" ) );
-			if ( n == p || p + n > size() ) n = size() - p;
-			return basic_string_ref< T, TRAITS >( data() + p, n );
+		string_ref substr( size_type p, size_type n = npos ) const;
+
+		inline std::size_t hash() const
+		{
+			const char* str = m_data;
+			size_type   sz  = m_size;
+			int seed = 131;
+			int result = 0;
+			while ( sz )
+			{
+				result = ( result * seed ) + ( *str );
+				str++;
+				sz--;
+			}
+			return result & ( 0x7FFFFFFF );
 		}
 
 	protected:
-		NV_CONSTEXPR basic_string_base() : m_data( nullptr ), m_size( 0 ) {}
-		NV_CONSTEXPR basic_string_base( pointer a_data, size_type a_lenght )
+		inline NV_CONSTEXPR string_base() : m_data( nullptr ), m_size( 0 ) {}
+		inline NV_CONSTEXPR string_base( pointer a_data, size_type a_lenght )
 			: m_data( a_data ), m_size( a_lenght ) {}
 
@@ -432,114 +441,38 @@
 	};
 
-#define NV_STRING_BASE_CAST_OPERATORS( OPERATOR )\
-template < typename T, typename TRAITS, typename ALLOCATOR >\
-inline bool operator OPERATOR ( basic_string_base< T, TRAITS > lhs, const std::basic_string< T, TRAITS, ALLOCATOR >& rhs )\
-		{\
-	return lhs OPERATOR basic_string_base< T, TRAITS >( rhs );\
-		}\
-template < typename T, typename TRAITS, typename ALLOCATOR >\
-inline bool operator OPERATOR ( const std::basic_string< T, TRAITS, ALLOCATOR >& lhs, basic_string_base< T, TRAITS > rhs )\
-		{\
-	return basic_string_base< T, TRAITS >( lhs ) OPERATOR rhs;\
-		}\
-template < typename T, typename TRAITS >\
-inline bool operator OPERATOR ( basic_string_base<T, TRAITS> lhs, const T* rhs )\
-		{\
-	return lhs OPERATOR basic_string_base< T, TRAITS >( rhs );\
-		}\
-template < typename T, typename TRAITS >\
-inline bool operator OPERATOR ( const T* lhs, basic_string_base< T, TRAITS > rhs )\
-		{\
-	return basic_string_base< T, TRAITS >( lhs ) OPERATOR rhs;\
-		}\
-
-	// Base operators
-	template < typename T, typename TRAITS >
-	inline bool operator==( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs )
-	{
-		return lhs.size() != rhs.size() ? false : ( lhs.compare( rhs ) == 0 );
-	}
-	template < typename T, typename TRAITS >
-	inline bool operator!=( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs )
-	{
-		return lhs.size() != rhs.size() ? true : ( lhs.compare( rhs ) != 0 );
-	}
-	template < typename T, typename TRAITS >
-	inline bool operator<( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs )
-	{
-		return lhs.compare( rhs ) < 0;
-	}
-	template < typename T, typename TRAITS >
-	inline bool operator>( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs )
-	{
-		return lhs.compare( rhs ) > 0;
-	}
-	template < typename T, typename TRAITS >
-	inline bool operator<=( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs )
-	{
-		return lhs.compare( rhs ) <= 0;
-	}
-	template < typename T, typename TRAITS >
-	inline bool operator>=( basic_string_base< T, TRAITS > lhs, basic_string_base< T, TRAITS > rhs )
-	{
-		return lhs.compare( rhs ) >= 0;
-	}
-
-	NV_STRING_BASE_CAST_OPERATORS( == )
-	NV_STRING_BASE_CAST_OPERATORS( != )
-	NV_STRING_BASE_CAST_OPERATORS( < )
-	NV_STRING_BASE_CAST_OPERATORS( > )
-	NV_STRING_BASE_CAST_OPERATORS( <= )
-	NV_STRING_BASE_CAST_OPERATORS( >= )
-
-	template < class T, class TRAITS >
-	inline std::basic_ostream<T, TRAITS>& operator<<( std::basic_ostream<T, TRAITS>& os, const basic_string_base<T, TRAITS>& str )
-	{
-		if ( os.good() )
-		{
-			os.write( str.data(), str.size() );
-		}
-		return os;
-	}
-
-#undef NV_STRING_REF_CAST_OPERATORS
-
-	template<typename T, typename TRAITS>
-	class basic_string_ref : public basic_string_base < T, TRAITS >
+	class string_ref : public string_base
 	{
 	public:
-
-		NV_CONSTEXPR basic_string_ref() {}
-		NV_CONSTEXPR basic_string_ref( const basic_string_ref &rhs )
-			: basic_string_base( rhs.m_data, rhs.m_size )
-		{
-		}
-		NV_CONSTEXPR basic_string_ref( const basic_string_base< T, TRAITS > &rhs )
-			: basic_string_base( rhs.m_data, rhs.m_size )
-		{
-		}
-
-		template< typename ALLOCATOR >
-		basic_string_ref( const std::basic_string<T, TRAITS, ALLOCATOR>& str )
-			: basic_string_base( str.data(), str.length() )
-		{
-		}
-
-		NV_CONSTEXPR basic_string_ref( const T* str, size_type len )
-			: basic_string_base( str, len )
+		inline NV_CONSTEXPR string_ref() {}
+		inline NV_CONSTEXPR string_ref( const string_ref& rhs )
+			: string_base( rhs.m_data, rhs.m_size )
+		{
+		}
+		inline NV_CONSTEXPR string_ref( const string_base& rhs )
+			: string_base( rhs.data(), rhs.size() )
+		{
+		}
+
+		inline string_ref( const std::string& str )
+			: string_base( str.data(), str.size() )
+		{
+		}
+
+		inline NV_CONSTEXPR string_ref( const char* str, size_type len )
+			: string_base( str, len )
 		{
 		}
 
 		// Literal constructors
-		template< size_t N, typename std::enable_if<std::is_same<T, char>::value>::type* = nullptr >
-		basic_string_ref( T( &s )[N] ) : basic_string_base( s, N - 1 ) {}
-		template< size_t N, typename std::enable_if<std::is_same<T, char>::value>::type* = nullptr >
-		basic_string_ref( const T( &s )[N] ) : basic_string_base( s, N - 1 ) {}
+		template< size_t N >
+		inline string_ref( char( &s )[N] ) : string_base( s, N - 1 ) {}
+		template< size_t N >
+		inline string_ref( const char( &s )[N] ) : string_base( s, N - 1 ) {}
 
 		// Non-literal constructors
 		template< typename U, typename std::enable_if<std::is_same<U, const char*>::value>::type* = nullptr >
-		basic_string_ref( U str ) : basic_string_base( str, TRAITS::length( str ) ) {}
-
-		basic_string_ref& operator=( const basic_string_ref &rhs )
+		inline string_ref( U str ) : string_base( str, std::strlen( str ) ) {}
+
+		inline string_ref& operator=( const string_ref &rhs )
 		{
 			m_data = rhs.m_data;
@@ -549,16 +482,16 @@
 
 		// iterators
-		NV_CONSTEXPR const_iterator   begin() const { return m_data; }
-		NV_CONSTEXPR const_iterator     end() const { return m_data + m_size; }
-		const_reverse_iterator  rbegin() const { return const_reverse_iterator( end() ); }
-		const_reverse_iterator    rend() const { return const_reverse_iterator( begin() ); }
+		inline NV_CONSTEXPR const_iterator   begin() const { return m_data; }
+		inline NV_CONSTEXPR const_iterator     end() const { return m_data + m_size; }
+		inline const_reverse_iterator  rbegin() const { return const_reverse_iterator( end() ); }
+		inline const_reverse_iterator    rend() const { return const_reverse_iterator( begin() ); }
 
 		// modifiers
-		void clear()
+		inline void clear()
 		{
 			m_size = 0;
 			m_data = nullptr;
 		}
-		void remove_prefix( size_type n )
+		inline void remove_prefix( size_type n )
 		{
 			if ( n > m_size )	n = m_size;
@@ -566,5 +499,5 @@
 			m_size -= n;
 		}
-		void remove_suffix( size_type n )
+		inline void remove_suffix( size_type n )
 		{
 			if ( n > m_size ) n = m_size;
@@ -574,54 +507,138 @@
 	};
 
-	typedef basic_string_ref<char, std::char_traits<char> > string_ref;
-
 	// const string is movable but not copyable
-	template<typename T, typename TRAITS>
-	class basic_const_string : public basic_string_base < T, TRAITS >
+	class const_string : public string_base
 	{
 	public:
-		basic_const_string() {}
-		basic_const_string( const T* str, size_type len )
+		NV_CONSTEXPR const_string() {}
+		const_string( const char* str, size_type len )
 		{
 			initialize( str, len );
 		}
-		explicit basic_const_string( const T* str )
-		{
-			initialize( str, TRAITS::length( str ) );
-		}
-
-		~basic_const_string()
+		explicit const_string( const char* str )
+		{
+			initialize( str, std::strlen( str ) );
+		}
+
+		~const_string()
 		{
 			if ( m_data ) delete m_data;
 		}
 
-		basic_const_string( const basic_const_string&& other )
-		{
-			std::swap( m_data, other.m_data );
+		inline const_string( const_string&& other )
+		{
+			m_data = other.m_data;
+			other.m_data = nullptr;
+		}
+
+		inline const_string& operator=( const_string&& other )
+		{
+			pointer temp = m_data;
+			m_data = other.m_data;
+			other.m_data = temp;
 			return *this;
 		}
 
-		basic_const_string& operator=( const basic_const_string&& other )
-		{
-			std::swap( m_data, other.m_data );
-			return *this;
-		}
+		// blocked copy constructor
+		const_string( const const_string & ) = delete;
+		// blocked copy operator
+		const_string& operator=( const const_string& ) = delete;
 
 	private:
-		// blocked copy constructor
-		basic_const_string( const basic_const_string & );
-		// blocked copy operator
-		basic_const_string& operator=( const basic_const_string& );
-
-		void assign( const T* p, size_type s )
-		{
-			m_data = new T[s + 1];
-			TRAITS::copy( m_data, p, s );
-			m_data[s] = 0;
+
+		void initialize( const char* p, size_type s )
+		{
+			char* data = new char[s + 1];
+			std::memcpy( data, p, s );
+			data[s] = 0;
+			m_data = data;
 		}
 	};
 
+	inline string_ref string_base::substr( size_type p, size_type n ) const
+	{
+		if ( p > size() ) return string_ref(); // NV_THROW( std::out_of_range( "substr" ) );
+		if ( n == p || p + n > size() ) n = size() - p;
+		return string_ref( data() + p, n );
+	}
+
+#define NV_STRING_BASE_CAST_OPERATORS( OPERATOR )\
+inline bool operator OPERATOR ( const string_base& lhs, const std::string& rhs )\
+{\
+	return lhs OPERATOR string_ref( rhs );\
+}\
+inline bool operator OPERATOR ( const std::string& lhs, const string_base& rhs )\
+{\
+	return string_ref( lhs ) OPERATOR rhs;\
+}\
+inline bool operator OPERATOR ( const string_base& lhs, const char* rhs )\
+{\
+	return lhs OPERATOR string_ref( rhs );\
+}\
+inline bool operator OPERATOR ( const char* lhs, const string_base& rhs )\
+{\
+	return string_ref( lhs ) OPERATOR rhs;\
+}\
+
+	// Base operators
+	inline bool operator==( const string_base& lhs, const string_base& rhs )
+	{
+		return lhs.size() != rhs.size() ? false : ( lhs.compare( rhs ) == 0 );
+	}
+	inline bool operator!=( const string_base& lhs, const string_base& rhs )
+	{
+		return lhs.size() != rhs.size() ? true : ( lhs.compare( rhs ) != 0 );
+	}
+	inline bool operator<( const string_base& lhs, const string_base& rhs )
+	{
+		return lhs.compare( rhs ) < 0;
+	}
+	inline bool operator>( const string_base& lhs, const string_base& rhs )
+	{
+		return lhs.compare( rhs ) > 0;
+	}
+	inline bool operator<=( const string_base& lhs, const string_base& rhs )
+	{
+		return lhs.compare( rhs ) <= 0;
+	}
+	inline bool operator>=( const string_base& lhs, const string_base& rhs )
+	{
+		return lhs.compare( rhs ) >= 0;
+	}
+
+NV_STRING_BASE_CAST_OPERATORS( == )
+NV_STRING_BASE_CAST_OPERATORS( != )
+NV_STRING_BASE_CAST_OPERATORS( < )
+NV_STRING_BASE_CAST_OPERATORS( > )
+NV_STRING_BASE_CAST_OPERATORS( <= )
+NV_STRING_BASE_CAST_OPERATORS( >= )
+
+	inline std::ostream& operator<<( std::ostream& os, const string_base& str )
+	{
+		if ( os.good() )
+		{
+			os.write( str.data(), str.size() );
+		}
+		return os;
+	}
+
+#undef NV_STRING_REF_CAST_OPERATORS
+
 
 }
 
+namespace std
+{
+
+	template<>
+	struct hash< nv::string_base >
+	{
+		std::size_t operator()( const nv::string_base& s ) const
+		{
+			return s.hash();
+		}
+	};
+
+}
+
 #endif // NV_CORE_STRING_HH
