Index: trunk/nv/core/types.hh
===================================================================
--- trunk/nv/core/types.hh	(revision 430)
+++ trunk/nv/core/types.hh	(revision 431)
@@ -56,5 +56,5 @@
 	struct type_field
 	{
-		uint64  name;     //!< name of the field
+		shash64     name;     //!< name of the field
 		type_hash   hash; //!< typeinfo for later retrieval of type
 		type_entry* type;     //!< pointer to field type
@@ -65,6 +65,6 @@
 	struct type_enum
 	{
-		uint64 name;
-		sint32 value;
+		shash64 name;
+		sint32  value;
 	};
 
@@ -146,5 +146,5 @@
 		}
 
-		string_view resolve_name( uint64 name_hash )
+		string_view resolve_name( shash64 name_hash )
 		{
 			return m_names[name_hash];
Index: trunk/nv/engine/resource_system.hh
===================================================================
--- trunk/nv/engine/resource_system.hh	(revision 430)
+++ trunk/nv/engine/resource_system.hh	(revision 431)
@@ -37,5 +37,5 @@
 		virtual void clear() { m_names.clear(); }
 		void load_all();
-		resource_id load_resource( const std::string& id );
+		resource_id load_resource( const string_view& id );
 		virtual ~resource_manager_base() {}
 	protected:
@@ -43,5 +43,5 @@
 
 		lua::state* m_lua;
-		unordered_map< std::string, resource_id > m_names;
+		hashed_table< shash64, resource_id > m_names;
 	};
 
@@ -55,5 +55,5 @@
 			return ( id < m_data.size() ? m_data[ id ] : T() );
 		}
-		T get_resource( const std::string& id )
+		T get_resource( const string_view& id )
 		{
 			auto m = m_names.find( id );
@@ -93,11 +93,11 @@
 	public:
 		explicit resource_system() : m_lua_state( nullptr ) { m_managers.push_back(nullptr); }
-		resource_type_id register_resource_type( const std::string& name, resource_manager_base* manager );
-		resource_type_id get_resource_type_id( const std::string& name ) const;
+		resource_type_id register_resource_type( const string_view& name, resource_manager_base* manager );
+		resource_type_id get_resource_type_id( const string_view& name ) const;
 		void initialize( lua::state* a_lua_state );
 		virtual ~resource_system();
 	protected:
 		vector< resource_manager_base* >     m_managers;
-		unordered_map< std::string, resource_id > m_manager_names;
+		unordered_map< uint64, resource_id > m_manager_names;
 		lua::state* m_lua_state; 
 	};
Index: trunk/nv/formats/nmd_loader.hh
===================================================================
--- trunk/nv/formats/nmd_loader.hh	(revision 430)
+++ trunk/nv/formats/nmd_loader.hh	(revision 431)
@@ -56,5 +56,5 @@
 		uint16   children;
 		uint32   size;
-		uint64   name;
+		shash64  name;
 		mat4     transform;
 		sint16   parent_id;
Index: trunk/nv/gfx/skeletal_mesh.hh
===================================================================
--- trunk/nv/gfx/skeletal_mesh.hh	(revision 430)
+++ trunk/nv/gfx/skeletal_mesh.hh	(revision 431)
@@ -38,10 +38,10 @@
 	{
 	public:
-		skeletal_animation_entry_cpu( uint64 name, const mesh_nodes_data* a_animation, bool a_looping )
+		skeletal_animation_entry_cpu( shash64 name, const mesh_nodes_data* a_animation, bool a_looping )
 			: animation_entry( name, a_looping, a_animation->get_frame_rate(), 0.0f, a_animation->get_duration() ), m_node_data( a_animation )
 		{
 			initialize();
 		}
-		skeletal_animation_entry_cpu( uint64 name, mesh_nodes_data* a_animation, float time_start, float time_end, bool a_looping )
+		skeletal_animation_entry_cpu( shash64 name, mesh_nodes_data* a_animation, float time_start, float time_end, bool a_looping )
 			: animation_entry( name, a_looping, a_animation->get_frame_rate(), time_start, time_end ), m_node_data( a_animation )
 		{
@@ -75,5 +75,5 @@
  	{
  	public:
- 		skeletal_animation_entry_gpu( uint64 name, const mesh_nodes_data* anim, bool a_looping )
+ 		skeletal_animation_entry_gpu( shash64 name, const mesh_nodes_data* anim, bool a_looping )
 			: animation_entry( name, a_looping, anim->get_frame_rate(), 0.0f, anim->get_duration() )
 			, m_node_data( anim )
@@ -82,5 +82,5 @@
 		}
 
-		skeletal_animation_entry_gpu( uint64 name, const mesh_nodes_data* anim, float time_start, float time_end, bool a_looping )
+		skeletal_animation_entry_gpu( shash64 name, const mesh_nodes_data* anim, float time_start, float time_end, bool a_looping )
 			: animation_entry( name, a_looping, anim->get_frame_rate(), time_start, time_end )
 			, m_node_data( anim )
Index: trunk/nv/interface/animated_mesh.hh
===================================================================
--- trunk/nv/interface/animated_mesh.hh	(revision 430)
+++ trunk/nv/interface/animated_mesh.hh	(revision 431)
@@ -25,7 +25,7 @@
 	{
 	public:
-		animation_entry( uint64 name, bool looping, uint32 frame_rate, float a_start, float a_end ) : m_name( name ), m_looping( looping ), m_frame_rate( frame_rate ),
+		animation_entry( shash64 name, bool looping, uint32 frame_rate, float a_start, float a_end ) : m_name( name ), m_looping( looping ), m_frame_rate( frame_rate ),
 		m_start( a_start ), m_end( a_end ), m_duration( m_end - m_start ), m_material_idx(0) {}
-		uint64 get_name() const { return m_name; }
+		shash64 get_name() const { return m_name; }
 		uint32 get_frame_rate() const { return m_frame_rate; }
 		float get_duration() const { return m_duration; }
@@ -47,11 +47,11 @@
 		virtual ~animation_entry() {}
 	protected:
-		uint64 m_name;
-		bool   m_looping;
-		uint32 m_frame_rate;
-		float  m_start;
-		float  m_end;
-		float  m_duration;
-		uint32 m_material_idx;
+		shash64 m_name;
+		bool    m_looping;
+		uint32  m_frame_rate;
+		float   m_start;
+		float   m_end;
+		float   m_duration;
+		uint32  m_material_idx;
 	};
 
Index: trunk/nv/interface/data_channel.hh
===================================================================
--- trunk/nv/interface/data_channel.hh	(revision 430)
+++ trunk/nv/interface/data_channel.hh	(revision 431)
@@ -91,8 +91,8 @@
 			for ( uint32 c = 0; c < other.m_size; ++c )
 				m_channels[c] = move( other.m_channels[c] );
-			m_size      = other.m_size;
-			m_parent_id = other.m_parent_id;
-			m_transform = other.m_transform;
-			m_name      = other.m_name;
+			m_size       = other.m_size;
+			m_parent_id  = other.m_parent_id;
+			m_transform  = other.m_transform;
+			m_name       = other.m_name;
 			other.m_size = 0;
 		}
@@ -209,5 +209,5 @@
 		const_iterator end()   const { return &m_channels[ m_size ]; }
 
-		uint64 get_name() const { return m_name; }
+		shash64 get_name() const { return m_name; }
 		sint16 get_parent_id() const { return m_parent_id; }
 		const mat4& get_transform() const { return m_transform; }
@@ -218,5 +218,4 @@
 		{
 			m_size      = 0;
-			m_name      = 0;
 			m_parent_id = -1;
 		}
@@ -224,8 +223,8 @@
 		raw_data_channel m_channels[4];
 
-		uint32 m_size;
-		uint64 m_name;
-		sint16 m_parent_id;
-		mat4   m_transform;
+		uint32  m_size;
+		shash64 m_name;
+		sint16  m_parent_id;
+		mat4    m_transform;
 	};
 
Index: trunk/nv/interface/data_channel_access.hh
===================================================================
--- trunk/nv/interface/data_channel_access.hh	(revision 430)
+++ trunk/nv/interface/data_channel_access.hh	(revision 431)
@@ -144,6 +144,6 @@
 		const mat4& get_transform() const { return m_set->m_transform; }
 
-		void set_name( uint64 name ) {  m_set->m_name = name; }
-		uint64 get_name() const { return m_set->m_name; }
+		void set_name( shash64 name ) {  m_set->m_name = name; }
+		shash64 get_name() const { return m_set->m_name; }
 
 		void set_parent_id( sint16 name ) { m_set->m_parent_id = name; }
Index: trunk/nv/interface/map_area.hh
===================================================================
--- trunk/nv/interface/map_area.hh	(revision 430)
+++ trunk/nv/interface/map_area.hh	(revision 431)
@@ -16,5 +16,4 @@
 #include <nv/core/position.hh>
 #include <nv/stl/string.hh>
-#include <string>
 
 namespace nv
@@ -27,6 +26,6 @@
 		virtual uint32 get_cell( const position& p ) const = 0;
 		virtual void set_cell( const position& p, uint32 value ) = 0;
-		virtual uint32 string_to_id( const std::string& ) const { return 0; }
-		virtual std::string id_to_string( uint32 ) const { return std::string(); }
+		virtual uint32 string_to_id( const string_view& ) const { return 0; }
+		virtual string_view id_to_string( uint32 ) const { return string_view(); }
 		virtual dimension get_size() const = 0;
 		virtual position get_shift() const { return position(); }
@@ -48,6 +47,6 @@
 		virtual dimension get_size() const { return m_area.get_size(); }
 		virtual position get_shift() const { return m_area.ul + m_map_area->get_shift(); }
-		virtual uint32 string_to_id( const std::string& s ) const { return m_map_area->string_to_id( s ); }
-		virtual std::string id_to_string( uint32 id ) const { return m_map_area->id_to_string( id ); }
+		virtual uint32 string_to_id( const string_view& s ) const { return m_map_area->string_to_id( s ); }
+		virtual string_view id_to_string( uint32 id ) const { return m_map_area->id_to_string( id ); }
 	private:
 		map_area* m_map_area;
Index: trunk/nv/interface/mesh_data.hh
===================================================================
--- trunk/nv/interface/mesh_data.hh	(revision 430)
+++ trunk/nv/interface/mesh_data.hh	(revision 431)
@@ -32,10 +32,10 @@
 		typedef storage::const_iterator const_iterator;
 
-		explicit mesh_nodes_data( uint64 name )
+		explicit mesh_nodes_data( shash64 name )
 			: m_name( name ), m_frame_rate(0), m_duration(0.0f), m_flat( false )
 		{
 		}
 
-		explicit mesh_nodes_data( uint64 name, uint16 a_fps, float a_frames, bool a_flat )
+		explicit mesh_nodes_data( shash64 name, uint16 a_fps, float a_frames, bool a_flat )
 			: m_name( name ), m_frame_rate(a_fps), m_duration(a_frames), m_flat( a_flat )
 		{
@@ -56,5 +56,5 @@
 		}
 
-		const data_channel_set* get_by_hash( uint64 h ) const
+		const data_channel_set* get_by_hash( shash64 h ) const
 		{
 			for ( auto data : m_data )
@@ -65,5 +65,5 @@
 		}
 
-		int get_index_by_hash( uint64 h ) const
+		int get_index_by_hash( shash64 h ) const
 		{
 			for ( uint32 i = 0; i < m_data.size(); ++i )
@@ -86,6 +86,5 @@
 		uint16 get_frame_rate() const { return m_frame_rate; }
 		float get_duration() const { return m_duration; }
-		void set_name( uint64 name ) { m_name = name; }
-		uint64 get_name() const { return m_name; }
+		shash64 get_name() const { return m_name; }
 
 		~mesh_nodes_data()
@@ -96,5 +95,5 @@
 	private:
 		vector< data_channel_set* > m_data;
-		uint64 m_name;
+		shash64 m_name;
 		uint16  m_frame_rate;
 		float   m_duration;
Index: trunk/nv/interface/mesh_loader.hh
===================================================================
--- trunk/nv/interface/mesh_loader.hh	(revision 430)
+++ trunk/nv/interface/mesh_loader.hh	(revision 431)
@@ -37,7 +37,7 @@
 		virtual mesh_nodes_data* release_mesh_nodes_data( size_t = 0 ) { return nullptr; }
 	protected:
-		inline uint64 make_name( const string_view& name )
+		inline shash64 make_name( const string_view& name )
 		{
-			return m_strings ? m_strings->insert( name ) : name.get_hash< uint64 >();
+			return m_strings ? m_strings->insert( name ) : shash64( name.get_hash< uint64 >() );
 		}
 		string_table* m_strings;
Index: trunk/nv/lua/lua_state.hh
===================================================================
--- trunk/nv/lua/lua_state.hh	(revision 430)
+++ trunk/nv/lua/lua_state.hh	(revision 431)
@@ -15,4 +15,5 @@
 #include <nv/stl/flags.hh>
 #include <nv/stl/handle.hh>
+#include <nv/stl/string_table.hh>
 #include <nv/stl/type_traits/function.hh>
 
@@ -294,5 +295,6 @@
 			size_t get_size();
 			bool has_field( string_view element );
-			uint64 get_string_hash_64( string_view element, uint64 defval = 0 );
+			shash64 get_string_hash_64( string_view element, uint64 defval = 0 );
+			shash64 get_string( string_view element, string_table& table, uint64 defval = 0 );
 			std::string get_std_string( string_view element, string_view defval = string_view() );
 			const_string get_string( string_view element, string_view defval = string_view() );
Index: trunk/nv/stl/functional/hash.hh
===================================================================
--- trunk/nv/stl/functional/hash.hh	(revision 430)
+++ trunk/nv/stl/functional/hash.hh	(revision 431)
@@ -135,10 +135,4 @@
 
 	template < typename H, typename T >
-	constexpr H hash_value( const T& value )
-	{
-		return hash<T, H>::get( value );
-	}
-
-	template < typename H, typename T >
 	constexpr H hash_combine( H seed, const T& h )
 	{
@@ -168,4 +162,63 @@
 	}
 
+	template < typename H, typename Tag = void >
+	class hash_value
+	{
+	public:
+		typedef H hash_type;
+		typedef H value_type;
+		typedef hash_value< H, Tag > this_type;
+
+
+		// TODO: enforce exact type?
+		constexpr hash_value() : m_value( 0 ) {}
+		constexpr explicit hash_value( hash_type value ) : m_value( value ) {}
+ 		constexpr hash_value( const hash_value& ) = default;
+
+		constexpr bool valid() const { return m_value != 0; }
+
+		template < typename H, typename Tag >
+		friend constexpr bool operator==( hash_value< H, Tag > lhs, hash_value< H, Tag > rhs );
+		template < typename H, typename Tag >
+		friend constexpr bool operator!=( hash_value< H, Tag > lhs, hash_value< H, Tag > rhs );
+
+		constexpr H value() const { return m_value; }
+	protected:
+		hash_type m_value;
+	};
+
+	template < typename T >
+	struct is_hash_value : is_template_base_of< T, hash_value > {};
+
+	template< typename T, typename H >
+	struct hash< T, H, 
+		typename enable_if< 
+			is_hash_value<T>::value && 
+			is_same< H, typename T::hash_type >::value, 
+			void 
+		>::type > : detail::hash_base< T, H >
+	{
+		typedef H hash_type;
+		static H get( const T& value )
+		{
+			return value.value();
+		}
+		inline H operator()( const T& value ) const { return get( value ); }
+	};
+
+	template < typename H, typename Tag >
+	constexpr bool operator==( hash_value< H, Tag > lhs, hash_value< H, Tag > rhs )
+	{
+		return lhs.m_value == rhs.m_value;
+	}
+
+	template < typename H, typename Tag >
+	constexpr bool operator!=( hash_value< H, Tag > lhs, hash_value< H, Tag > rhs )
+	{
+		return lhs.m_value != rhs.m_value;
+	}
+
+	typedef hash_value< uint32 > hash32;
+	typedef hash_value< uint64 > hash64;
 
 	template < typename T, typename H, bool StoreElement = true >
Index: trunk/nv/stl/string.hh
===================================================================
--- trunk/nv/stl/string.hh	(revision 430)
+++ trunk/nv/stl/string.hh	(revision 431)
@@ -42,12 +42,12 @@
 	// 	string
 
-	template<>
-	struct hash< std::string, size_t >
-	{
-		static size_t get( const std::string& value )
-		{
-			return hash_string< size_t >( value.c_str(), value.length() );
-		}
-		inline size_t operator()( const std::string& value ) const { return get( value ); }
+	template< typename H >
+	struct hash< std::string, H > : detail::hash_base< std::string, H >
+	{
+		static H get( const std::string& value )
+		{
+			return hash_string< H >( value.c_str(), value.length() );
+		}
+		inline H operator()( const std::string& value ) const { return get( value ); }
 	};
 
@@ -164,4 +164,5 @@
 	template< typename T, typename H >
 	struct hash< T, H, typename enable_if< is_string_base<T>::value, void >::type >
+		: detail::hash_base< T, H >
 	{
 		static H get( const T& value )
@@ -615,4 +616,34 @@
 	}
 
+	struct string_hash_tag {};
+
+	template < typename H >
+	class string_hash : public hash_value< H, string_hash_tag >
+	{
+	public:
+		typedef H hash_type;
+		typedef H value_type;
+		typedef string_hash< H > this_type;
+		typedef hash_value< H, string_hash_tag > inherited_type;
+
+		// TODO: enforce exact type?
+		constexpr string_hash() : inherited_type() {}
+		inline string_hash( const string_view& rhs ) : inherited_type( hash_string< H >( rhs.data(), rhs.size() ) ) {}
+		template < typename S >
+		inline string_hash( const string_base<S>& rhs ) : inherited_type( hash_string< H >( rhs.data(), rhs.size() ) ) {}
+		constexpr string_hash( const char* str, size_t len ) : inherited_type( hash_string< H >( str, len ) ) {}
+
+		// Literal constructors
+		template< size_t N >
+		constexpr string_hash( char( &s )[N] ) : inherited_type( hash_string< H >( s, N - 1 ) ) {}
+		template< size_t N >
+		constexpr string_hash( const char( &s )[N] ) : inherited_type( hash_string< H >( s, N - 1 ) ) {}
+
+		constexpr explicit string_hash( hash_type value ) : inherited_type( value ) {}
+  		constexpr string_hash( const string_hash& value ) = default;
+	};
+
+	typedef string_hash< uint32 > shash32;
+	typedef string_hash< uint64 > shash64;
 }
 
Index: trunk/nv/stl/string_table.hh
===================================================================
--- trunk/nv/stl/string_table.hh	(revision 430)
+++ trunk/nv/stl/string_table.hh	(revision 431)
@@ -26,9 +26,9 @@
 	public:
 		typedef string_view value_type;
-		typedef uint64 key_type;
+		typedef shash64 key_type;
 		typedef uint64 hash_type;
 		typedef uint32 size_type;
 		typedef uint16 length_type;
-		typedef unordered_map< key_type, size_type > indexer_type;
+		typedef unordered_map< hash_type, size_type > indexer_type;
 		typedef vector< char > storage_type;
 		typedef indexer_type::const_iterator const_iterator;
@@ -39,17 +39,17 @@
 		key_type insert( const value_type& str )
 		{
-			key_type hash_value = str.get_hash< uint64 >();
+			hash_type hash_value = str.get_hash< uint64 >();
 			insert( hash_value, str );
-			return hash_value;
+			return key_type( hash_value );
 		}
 
 		bool exists( key_type i ) const 
 		{
-			return m_map.find( i ) != m_map.end();
+			return m_map.find( i.value() ) != m_map.end();
 		}
 
 		value_type at( key_type i ) const
 		{
-			const auto& it = m_map.find( i );
+			const auto& it = m_map.find( i.value() );
 			NV_ASSERT_ALWAYS( it != m_map.end(), "Key not found in string_table!" );
 			return extract_raw( it->second );
@@ -58,5 +58,5 @@
 		value_type operator[]( key_type i ) const
 		{
-			const auto& it = m_map.find( i );
+			const auto& it = m_map.find( i.value() );
 			return it != m_map.end() ? extract_raw( it->second ) : value_type();
 		}
Index: trunk/nv/stl/unordered_map.hh
===================================================================
--- trunk/nv/stl/unordered_map.hh	(revision 430)
+++ trunk/nv/stl/unordered_map.hh	(revision 431)
@@ -227,5 +227,5 @@
 		typename Hash = hash< Key >,
 		typename KeyEqual = equal_to< Key >,
-		typename HashEntryPolicy = hash_table_stl_map_policy< Key, T, size_t, KeyEqual, Hash >
+		typename HashEntryPolicy = hash_table_stl_map_policy< Key, T, typename Hash::result_type, KeyEqual, Hash >
 	>
 	class unordered_map
@@ -324,4 +324,52 @@
 	};
 
+	// TODO: remove and make a proper hashed map
+	template <
+		typename Key,
+		typename T,
+		typename Hasher = hash< Key, typename Key::value_type >,
+		typename KeyEqual = equal_to< Key >,
+		typename HashEntryPolicy = hash_table_stl_map_policy< Key, T, typename Key::value_type, KeyEqual, Hasher >
+	>
+	class hashed_table
+		: public hash_table<
+		HashEntryPolicy,
+		hash_table_no_extra_types_policy,
+		hash_table_prime_rehash_policy,
+		HashEntryPolicy
+		>
+	{
+	public:
+		typedef hash_table<
+			HashEntryPolicy,
+			hash_table_no_extra_types_policy,
+			hash_table_prime_rehash_policy,
+			HashEntryPolicy
+		> base_type;
+		typedef typename base_type::value_type                                           value_type;
+		typedef typename base_type::pointer                                              pointer;
+		typedef typename base_type::const_pointer                                        const_pointer;
+		typedef typename base_type::reference                                            reference;
+		typedef typename base_type::const_reference                                      const_reference;
+		typedef typename base_type::iterator                                             iterator;
+		typedef typename base_type::const_iterator                                       const_iterator;
+		typedef typename base_type::size_type                                            size_type;
+		typedef typename base_type::difference_type                                      difference_type;
+		typedef typename base_type::key_type                                             key_type;
+		typedef typename base_type::mapped_type                                          mapped_type;
+		typedef typename base_type::node_type                                            node_type;
+		typedef typename base_type::insert_return_type                                   insert_return_type;
+		typedef Hasher                                                                   hasher;
+		typedef KeyEqual                                                                 key_equal;
+
+		using base_type::base_type;
+
+		mapped_type& operator[]( const key_type& key )
+		{
+			return ( *base_type::insert_key( key ).first ).second;
+		}
+	};
+
+
 }
 
Index: trunk/src/engine/resource_system.cc
===================================================================
--- trunk/src/engine/resource_system.cc	(revision 430)
+++ trunk/src/engine/resource_system.cc	(revision 431)
@@ -15,5 +15,5 @@
 }
 
-nv::resource_id nv::resource_manager_base::load_resource( const std::string& id )
+nv::resource_id nv::resource_manager_base::load_resource( const string_view& id )
 {
 	lua::table_guard table( m_lua, lua::path( get_storage_name(), id ) );
@@ -32,14 +32,14 @@
 		lua::table_guard sub_table( table, i+1 );
 		resource_id rid = load_resource( sub_table );
-		if ( rid != 0 ) m_names[ sub_table.get_std_string("id") ] = rid;
+		if ( rid != 0 ) m_names[ sub_table.get_string_hash_64("id") ] = rid;
 	}
 }
 
-nv::resource_type_id nv::resource_system::register_resource_type( const std::string& /*name*/, resource_manager_base* /*manager*/ )
+nv::resource_type_id nv::resource_system::register_resource_type( const string_view& /*name*/, resource_manager_base* /*manager*/ )
 {
 	return 0;
 }
 
-nv::resource_type_id nv::resource_system::get_resource_type_id( const std::string& /*name*/ ) const
+nv::resource_type_id nv::resource_system::get_resource_type_id( const string_view& /*name*/ ) const
 {
 	return 0;
Index: trunk/src/formats/assimp_loader.cc
===================================================================
--- trunk/src/formats/assimp_loader.cc	(revision 430)
+++ trunk/src/formats/assimp_loader.cc	(revision 431)
@@ -288,5 +288,5 @@
 	const aiScene* scene = reinterpret_cast<const aiScene*>( m_scene );
 	mesh_nodes_data* result = new mesh_nodes_data( make_name( "bones" ) );
-	unordered_map< uint64, uint16 > names;
+	hashed_table< shash64, uint16 > names;
 	for ( unsigned int m = 0; m < m_mesh_count; ++m )
 	{
Index: trunk/src/formats/md3_loader.cc
===================================================================
--- trunk/src/formats/md3_loader.cc	(revision 430)
+++ trunk/src/formats/md3_loader.cc	(revision 431)
@@ -420,5 +420,5 @@
 	uint32 node_count = uint32( md3->header.num_tags );
 	if ( node_count == 0 ) return nullptr;
-	mesh_nodes_data* result = new mesh_nodes_data( m_strings ? m_strings->insert( "tags" ) : 0 );
+	mesh_nodes_data* result = new mesh_nodes_data( m_strings ? m_strings->insert( "tags" ) : shash64() );
 	for ( uint32 i = 0; i < node_count; ++i )
 	{
Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 430)
+++ trunk/src/formats/nmd_loader.cc	(revision 431)
@@ -233,5 +233,5 @@
 	sheader.children   = 0;
 	sheader.size       = strings.dump_size();
-	sheader.name       = 0;
+	sheader.name       = shash64();
 	sheader.parent_id  = -1;
     sheader.attributes = 0;
Index: trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- trunk/src/gfx/skeletal_mesh.cc	(revision 430)
+++ trunk/src/gfx/skeletal_mesh.cc	(revision 431)
@@ -177,5 +177,5 @@
 	{
 		const data_channel_set* bone = (*bones)[ bi ];
-		bone_names[ bone->get_name() ] = bi;
+		bone_names[ bone->get_name().value() ] = bi;
 		m_offsets[bi] = bone->get_transform();
 	}
@@ -186,5 +186,5 @@
 		sint16 bone_id = -1;
 
-		auto bi = bone_names.find( node->get_name() );
+		auto bi = bone_names.find( node->get_name().value() );
 		if ( bi != bone_names.end() )
 		{
Index: trunk/src/lua/lua_map_area.cc
===================================================================
--- trunk/src/lua/lua_map_area.cc	(revision 430)
+++ trunk/src/lua/lua_map_area.cc	(revision 431)
@@ -137,5 +137,6 @@
 {
 	nv::map_area* ma = to_map_area( L, 1 );
-	lua_pushstring( L, ma->id_to_string( ma->get_cell( to_coord( L, 2 ) ) ).c_str() );
+	nv::string_view result( ma->id_to_string( ma->get_cell( to_coord( L, 2 ) ) ) );
+	lua_pushlstring( L, result.data(), result.size() );
 	return 1;
 }
Index: trunk/src/lua/lua_state.cc
===================================================================
--- trunk/src/lua/lua_state.cc	(revision 430)
+++ trunk/src/lua/lua_state.cc	(revision 431)
@@ -184,5 +184,5 @@
 }
 
-uint64 nv::lua::table_guard::get_string_hash_64( string_view element, uint64 defval /*= 0 */ )
+shash64 nv::lua::table_guard::get_string_hash_64( string_view element, uint64 defval /*= 0 */ )
 {
 	lua_getfield( m_state, -1, element.data() );
@@ -196,5 +196,20 @@
 	}
 	lua_pop( m_state, 1 );
-	return result;
+	return shash64( result );
+}
+
+shash64 nv::lua::table_guard::get_string( string_view element, string_table& table, uint64 defval /*= 0 */ )
+{
+	lua_getfield( m_state, -1, element.data() );
+	size_t l = 0;
+	const char* str = nullptr;
+	uint64 result = defval;
+	if ( lua_type( m_state, -1 ) == LUA_TSTRING )
+	{
+		str = lua_tolstring( m_state, -1, &l );
+		result = table.insert( string_view( str, l ) ).value();
+	}
+	lua_pop( m_state, 1 );
+	return shash64( result );
 }
 
