Index: trunk/src/core/logger.cc
===================================================================
--- trunk/src/core/logger.cc	(revision 367)
+++ trunk/src/core/logger.cc	(revision 368)
@@ -142,8 +142,10 @@
 void log_console_sink::log( log_level level, const string_ref& message )
 {
+	char stamp[16];
+	size_t ssize = timestamp( stamp );
+
 #if NV_PLATFORM == NV_WINDOWS 
 	if ( m_color ) SetConsoleTextAttribute( m_handle, FOREGROUND_INTENSITY );
-	string_ref stamp( timestamp() );
-	WriteConsole( m_handle, stamp.data(), stamp.size(), nullptr, nullptr );
+	WriteConsole( m_handle, stamp, ssize, nullptr, nullptr );
 	WriteConsole( m_handle, " [", 2, nullptr, nullptr );
 	if (m_color) SetConsoleTextAttribute( m_handle, log_color[( level ) / 10] );
@@ -156,5 +158,5 @@
 #else
 	if ( m_color ) fwrite( "\33[30;1m", 7, 1, stdout );
-	fwrite( stamp.data(), stamp.size(), 1, stdout );
+	fwrite( stamp, ssize, 1, stdout );
 	fwrite( " [", 2, 1, stdout );
 	if ( m_color )
@@ -176,5 +178,6 @@
 void log_handle_sink::log( log_level level, const string_ref& message )
 {
-	string_ref stamp( timestamp() );
+	char stamp[16];
+	size_t ssize = timestamp( stamp );
 #if 0 // NV_PLATFORM == NV_WINDOWS
 	// Turns out WriteFile on Windows is unbuffered and quite slower than fwrite 
@@ -182,5 +185,5 @@
 	// If we want to get rid of C runtime, this would need a buffered I/O layer.
 	DWORD unused = 0;
-	WriteFile( m_handle, stamp.data(), stamp.size(), &unused, nullptr );
+	WriteFile( m_handle, stamp, ssize, &unused, nullptr );
 	WriteFile( m_handle, " [", 2, &unused, nullptr );
 	WriteFile( m_handle, NV_LOG_LEVEL_NAME_PAD( level ), 8, &unused, nullptr );
@@ -190,5 +193,5 @@
 	//if ( m_flush ) FlushFileBuffers( m_handle );
 #else
-	fwrite( stamp.data(), stamp.size(), 1, (FILE*)m_handle );
+	fwrite( stamp, ssize, 1, (FILE*)m_handle );
 	fwrite( " [", 2, 1, (FILE*)m_handle );
 	fwrite( NV_LOG_LEVEL_NAME_PAD( level ), 8, 1, (FILE*)m_handle );
@@ -237,5 +240,5 @@
 }
 
-string_ref nv::log_sink::timestamp() const
+size_t nv::log_sink::timestamp( char* buffer ) const
 {
 	uint32 ms = get_system_ms();
@@ -245,5 +248,4 @@
 	unsigned int m    = (unsigned int)(secs / 60) % 60;
 	unsigned int s    = secs % 60;
-	static char buffer[16];
 #if NV_PLATFORM == NV_WINDOWS 
 	sprintf_s( buffer, 16, "%02d:%02d:%02d.%02d", h, m, s, mm );
@@ -251,6 +253,5 @@
 	snprintf( buffer, 16, "%02d:%02d:%02d.%02d", h, m, s, mm );
 #endif
-	buffer[11] = '\0';
-	return string_ref( buffer, 10 );
+	return 11;
 }
 
Index: trunk/src/core/string.cc
===================================================================
--- trunk/src/core/string.cc	(revision 367)
+++ 	(revision )
@@ -1,182 +1,0 @@
-// Copyright (C) 2015 ChaosForge Ltd
-// http://chaosforge.org/
-//
-// This file is part of NV Libraries.
-// For conditions of distribution and use, see copyright notice in nv.hh
-//
-// TODO: speedup conversion by doing divisions by 100
-
-#include "nv/core/string.hh"
-
-#include <cstdio>
-#include <cstdlib>
-
-using namespace nv;
-
-static const double s_power_10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000,
-10000000, 100000000, 1000000000 };
-
-static inline void string_reverse( char* begin, char* end )
-{
-	char temp;
-	while ( end > begin )
-	{
-		temp = *end;
-		*end-- = *begin;
-		*begin++ = temp;
-	}
-}
-
-size_t nv::sint32_to_buffer( sint32 n, char* str )
-{
-	char* s = str;
-	uint32 abs = ( n < 0 ) ? (uint32)( -n ) : (uint32)( n );
-	do
-	{
-		*s++ = (char)( '0' + ( abs % 10 ) );
-		abs /= 10;
-	} while ( abs > 0 );
-	if ( n < 0 ) *s++ = '-';
-	*s = '\0';
-	string_reverse( str, s - 1 );
-	return (size_t)( s - str );
-}
-
-size_t nv::sint64_to_buffer( sint64 n, char* str )
-{
-	char* s = str;
-	uint64 abs = ( n < 0 ) ? (uint64)( -n ) : (uint64)( n );
-	do
-	{
-		*s++ = (char)( '0' + ( abs % 10 ) );
-		abs /= 10;
-	} while ( abs > 0 );
-	if ( n < 0 ) *s++ = '-';
-	*s = '\0';
-	string_reverse( str, s - 1 );
-	return (size_t)( s - str );
-}
-
-size_t nv::uint32_to_buffer( uint32 n, char* str )
-{
-	char* s = str;
-	do
-	{
-		*s++ = (char)( '0' + ( n % 10 ) );
-		n /= 10;
-	} while ( n > 0 );
-	*s = '\0';
-	string_reverse( str, s - 1 );
-	return (size_t)( s - str );
-}
-
-size_t nv::uint64_to_buffer( uint64 n, char* str )
-{
-	char* s = str;
-	do
-	{
-		*s++ = (char)( '0' + ( n % 10 ) );
-		n /= 10;
-	} while ( n > 0 );
-	*s = '\0';
-	string_reverse( str, s - 1 );
-	return (size_t)( s - str );
-}
-
-size_t nv::f32_to_buffer( f32 n, char* str )
-{
-#if NV_COMPILER == NV_MSVC
-	sprintf_s( str, 64, "%.*g", 6, n );
-#else
-	snprintf( str, 64, "%.*g", 6, n );
-#endif
-	sprintf( str, "%g", n );
-	return strlen( str );
-}
-
-size_t nv::f64_to_buffer( f64 n, char* str )
-{
-#if NV_COMPILER == NV_MSVC
-	sprintf_s( str, 64, "%.*g", 6, n );
-#else
-	snprintf( str, 64, "%.*g", 6, n );
-#endif
-	return strlen( str );
-}
-
-sint32 buffer_to_sint32( const char* str, char** end )
-{
-	const char* s = str;
-	while ( *s == ' ' ) ++s;
-	sint32 result = 0;
-	bool positive = true;
-	switch ( *s )
-	{
-	case '-': ++s; positive = false; break;
-	case '+': ++s; break;
-	default: break;
-	}
-	while ( *s >= '0' && *s <= '9' )
-	{
-		result = ( result * 10 ) + ( *s - '0' );
-		++s;
-	}
-	if ( end != nullptr ) *end = (char*)s;
-	return positive ? result : -result;
-}
-
-sint64 buffer_to_sint64( const char* s, char** end )
-{
-	while ( *s == ' ' ) ++s;
-	sint64 result = 0;
-	bool positive = true;
-	switch ( *s )
-	{
-	case '-': ++s; positive = false; break;
-	case '+': ++s; break;
-	default: break;
-	}
-	while ( *s >= '0' && *s <= '9' )
-	{
-		result = ( result * 10 ) + ( *s - '0' );
-		++s;
-	}
-	if ( end != nullptr ) *end = (char*)s;
-	return positive ? result : -result;
-}
-
-uint32 buffer_to_uint32( const char* s, char** end )
-{
-	while ( *s == ' ' ) ++s;
-	uint32 result = 0;
-	while ( *s >= '0' && *s <= '9' )
-	{
-		result = ( result * 10 ) + ( *s - '0' );
-		++s;
-	}
-	if ( end != nullptr ) *end = (char*)s;
-	return result;
-}
-
-uint64 buffer_to_uint64( const char* s, char** end )
-{
-	while ( *s == ' ' ) ++s;
-	uint64 result = 0;
-	while ( *s >= '0' && *s <= '9' )
-	{
-		result = ( result * 10 ) + ( *s - '0' );
-		++s;
-	}
-	if ( end != nullptr ) *end = (char*)s;
-	return result;
-}
-
-float buffer_to_f32( const char* s, char** end )
-{
-	return strtof( s, end );
-}
-
-double buffer_to_f64( const char* s, char** end )
-{
-	return strtod( s, end );
-}
Index: trunk/src/engine/program_manager.cc
===================================================================
--- trunk/src/engine/program_manager.cc	(revision 367)
+++ trunk/src/engine/program_manager.cc	(revision 368)
@@ -6,5 +6,5 @@
 
 #include "nv/engine/program_manager.hh"
-#include "nv/core/range.hh"
+#include "nv/stl/range.hh"
 #include "nv/core/logging.hh"
 #include "nv/lua/lua_nova.hh"
Index: trunk/src/engine/resource_system.cc
===================================================================
--- trunk/src/engine/resource_system.cc	(revision 367)
+++ trunk/src/engine/resource_system.cc	(revision 368)
@@ -6,5 +6,5 @@
 
 #include "nv/engine/resource_system.hh"
-#include "nv/core/range.hh"
+#include "nv/stl/range.hh"
 #include "nv/lua/lua_nova.hh"
 
Index: trunk/src/formats/nmd_loader.cc
===================================================================
--- trunk/src/formats/nmd_loader.cc	(revision 367)
+++ trunk/src/formats/nmd_loader.cc	(revision 368)
@@ -7,5 +7,5 @@
 #include "nv/formats/nmd_loader.hh"
 #include "nv/io/std_stream.hh"
-#include "nv/core/string.hh"
+#include "nv/stl/string.hh"
 
 using namespace nv;
Index: trunk/src/lib/gl.cc
===================================================================
--- trunk/src/lib/gl.cc	(revision 367)
+++ trunk/src/lib/gl.cc	(revision 368)
@@ -6,5 +6,5 @@
 
 #include "nv/core/common.hh"
-#include "nv/core/range.hh"
+#include "nv/stl/range.hh"
 #include "nv/core/logging.hh"
 #include "nv/lib/gl.hh"
Index: trunk/src/lua/lua_area.cc
===================================================================
--- trunk/src/lua/lua_area.cc	(revision 367)
+++ trunk/src/lua/lua_area.cc	(revision 368)
@@ -8,5 +8,5 @@
 
 #include "nv/lua/lua_raw.hh"
-#include "nv/core/string.hh"
+#include "nv/stl/string.hh"
 #include "nv/core/random.hh"
 
Index: trunk/src/lua/lua_flags.cc
===================================================================
--- trunk/src/lua/lua_flags.cc	(revision 367)
+++ trunk/src/lua/lua_flags.cc	(revision 368)
@@ -8,5 +8,5 @@
 
 #include "nv/lua/lua_raw.hh"
-#include "nv/core/string.hh"
+#include "nv/stl/string.hh"
 
 
Index: trunk/src/lua/lua_glm.cc
===================================================================
--- trunk/src/lua/lua_glm.cc	(revision 367)
+++ trunk/src/lua/lua_glm.cc	(revision 368)
@@ -8,5 +8,5 @@
 
 #include "nv/lua/lua_raw.hh"
-#include "nv/core/string.hh"
+#include "nv/stl/string.hh"
 #include "nv/core/random.hh"
 
Index: trunk/src/lua/lua_map_area.cc
===================================================================
--- trunk/src/lua/lua_map_area.cc	(revision 367)
+++ trunk/src/lua/lua_map_area.cc	(revision 368)
@@ -6,5 +6,5 @@
 
 #include "nv/lua/lua_map_area.hh"
-#include "nv/core/flags.hh"
+#include "nv/stl/flags.hh"
 #include "nv/lua/lua_area.hh"
 #include "nv/lua/lua_glm.hh"
Index: trunk/src/lua/lua_map_tile.cc
===================================================================
--- trunk/src/lua/lua_map_tile.cc	(revision 367)
+++ trunk/src/lua/lua_map_tile.cc	(revision 368)
@@ -9,5 +9,5 @@
 #include <numeric>
 #include "nv/lua/lua_map_area.hh"
-#include "nv/core/flags.hh"
+#include "nv/stl/flags.hh"
 #include "nv/core/random.hh"
 #include "nv/lua/lua_area.hh"
Index: trunk/src/lua/lua_raw.cc
===================================================================
--- trunk/src/lua/lua_raw.cc	(revision 367)
+++ trunk/src/lua/lua_raw.cc	(revision 368)
@@ -7,5 +7,5 @@
 #include "nv/lua/lua_raw.hh"
 
-#include "nv/core/string.hh"
+#include "nv/stl/string.hh"
 
 std::string nlua_typecontent( lua_State* L, int idx )
Index: trunk/src/lua/lua_state.cc
===================================================================
--- trunk/src/lua/lua_state.cc	(revision 367)
+++ trunk/src/lua/lua_state.cc	(revision 368)
@@ -10,5 +10,5 @@
 #include "nv/lua/lua_nova.hh"
 #include "nv/core/logging.hh"
-#include "nv/core/string.hh"
+#include "nv/stl/string.hh"
 
 using namespace nv;
Index: trunk/src/rogue/fov_recursive_shadowcasting.cc
===================================================================
--- trunk/src/rogue/fov_recursive_shadowcasting.cc	(revision 367)
+++ trunk/src/rogue/fov_recursive_shadowcasting.cc	(revision 368)
@@ -7,5 +7,5 @@
 #include "nv/rogue/fov_recursive_shadowcasting.hh"
 
-#include "nv/core/math.hh"
+#include "nv/stl/math.hh"
 
 static int nv_rogue_rs_mult[4][8] = {
Index: trunk/src/sdl/sdl_audio.cc
===================================================================
--- trunk/src/sdl/sdl_audio.cc	(revision 367)
+++ trunk/src/sdl/sdl_audio.cc	(revision 368)
@@ -7,5 +7,5 @@
 #include "nv/sdl/sdl_audio.hh"
 
-#include "nv/core/math.hh"
+#include "nv/stl/math.hh"
 #include "nv/lib/sdl_mixer.hh"
 #include "nv/core/logging.hh"
Index: trunk/src/stl/string.cc
===================================================================
--- trunk/src/stl/string.cc	(revision 368)
+++ trunk/src/stl/string.cc	(revision 368)
@@ -0,0 +1,182 @@
+// Copyright (C) 2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+//
+// TODO: speedup conversion by doing divisions by 100
+
+#include "nv/stl/string.hh"
+
+#include <cstdio>
+#include <cstdlib>
+
+using namespace nv;
+
+static const double s_power_10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000,
+10000000, 100000000, 1000000000 };
+
+static inline void string_reverse( char* begin, char* end )
+{
+	char temp;
+	while ( end > begin )
+	{
+		temp = *end;
+		*end-- = *begin;
+		*begin++ = temp;
+	}
+}
+
+size_t nv::sint32_to_buffer( sint32 n, char* str )
+{
+	char* s = str;
+	uint32 abs = ( n < 0 ) ? (uint32)( -n ) : (uint32)( n );
+	do
+	{
+		*s++ = (char)( '0' + ( abs % 10 ) );
+		abs /= 10;
+	} while ( abs > 0 );
+	if ( n < 0 ) *s++ = '-';
+	*s = '\0';
+	string_reverse( str, s - 1 );
+	return (size_t)( s - str );
+}
+
+size_t nv::sint64_to_buffer( sint64 n, char* str )
+{
+	char* s = str;
+	uint64 abs = ( n < 0 ) ? (uint64)( -n ) : (uint64)( n );
+	do
+	{
+		*s++ = (char)( '0' + ( abs % 10 ) );
+		abs /= 10;
+	} while ( abs > 0 );
+	if ( n < 0 ) *s++ = '-';
+	*s = '\0';
+	string_reverse( str, s - 1 );
+	return (size_t)( s - str );
+}
+
+size_t nv::uint32_to_buffer( uint32 n, char* str )
+{
+	char* s = str;
+	do
+	{
+		*s++ = (char)( '0' + ( n % 10 ) );
+		n /= 10;
+	} while ( n > 0 );
+	*s = '\0';
+	string_reverse( str, s - 1 );
+	return (size_t)( s - str );
+}
+
+size_t nv::uint64_to_buffer( uint64 n, char* str )
+{
+	char* s = str;
+	do
+	{
+		*s++ = (char)( '0' + ( n % 10 ) );
+		n /= 10;
+	} while ( n > 0 );
+	*s = '\0';
+	string_reverse( str, s - 1 );
+	return (size_t)( s - str );
+}
+
+size_t nv::f32_to_buffer( f32 n, char* str )
+{
+#if NV_COMPILER == NV_MSVC
+	sprintf_s( str, 64, "%.*g", 6, n );
+#else
+	snprintf( str, 64, "%.*g", 6, n );
+#endif
+	sprintf( str, "%g", n );
+	return strlen( str );
+}
+
+size_t nv::f64_to_buffer( f64 n, char* str )
+{
+#if NV_COMPILER == NV_MSVC
+	sprintf_s( str, 64, "%.*g", 6, n );
+#else
+	snprintf( str, 64, "%.*g", 6, n );
+#endif
+	return strlen( str );
+}
+
+sint32 buffer_to_sint32( const char* str, char** end )
+{
+	const char* s = str;
+	while ( *s == ' ' ) ++s;
+	sint32 result = 0;
+	bool positive = true;
+	switch ( *s )
+	{
+	case '-': ++s; positive = false; break;
+	case '+': ++s; break;
+	default: break;
+	}
+	while ( *s >= '0' && *s <= '9' )
+	{
+		result = ( result * 10 ) + ( *s - '0' );
+		++s;
+	}
+	if ( end != nullptr ) *end = (char*)s;
+	return positive ? result : -result;
+}
+
+sint64 buffer_to_sint64( const char* s, char** end )
+{
+	while ( *s == ' ' ) ++s;
+	sint64 result = 0;
+	bool positive = true;
+	switch ( *s )
+	{
+	case '-': ++s; positive = false; break;
+	case '+': ++s; break;
+	default: break;
+	}
+	while ( *s >= '0' && *s <= '9' )
+	{
+		result = ( result * 10 ) + ( *s - '0' );
+		++s;
+	}
+	if ( end != nullptr ) *end = (char*)s;
+	return positive ? result : -result;
+}
+
+uint32 buffer_to_uint32( const char* s, char** end )
+{
+	while ( *s == ' ' ) ++s;
+	uint32 result = 0;
+	while ( *s >= '0' && *s <= '9' )
+	{
+		result = ( result * 10 ) + ( *s - '0' );
+		++s;
+	}
+	if ( end != nullptr ) *end = (char*)s;
+	return result;
+}
+
+uint64 buffer_to_uint64( const char* s, char** end )
+{
+	while ( *s == ' ' ) ++s;
+	uint64 result = 0;
+	while ( *s >= '0' && *s <= '9' )
+	{
+		result = ( result * 10 ) + ( *s - '0' );
+		++s;
+	}
+	if ( end != nullptr ) *end = (char*)s;
+	return result;
+}
+
+float buffer_to_f32( const char* s, char** end )
+{
+	return strtof( s, end );
+}
+
+double buffer_to_f64( const char* s, char** end )
+{
+	return strtod( s, end );
+}
