Index: /trunk/nv/core/logging.hh
===================================================================
--- /trunk/nv/core/logging.hh	(revision 434)
+++ /trunk/nv/core/logging.hh	(revision 435)
@@ -40,26 +40,27 @@
 		void log_append( string_view ref )
 		{
-			nvmemcpy( m_pos, ref.data(), ref.size() );
-			m_pos += ref.size();
+			size_t count = ::nv::min< size_t >( ref.size(), space_left()-1 );
+			nvmemcpy( m_pos, ref.data(), count );
+			m_pos += count;
 		}
 		void log_append( uint32 u )
 		{
-			m_pos += uint32_to_buffer( u, m_pos );
+			m_pos += uint32_to_buffer( array_ref< char >( m_pos, space_left() ), u );
 		}
 		void log_append( sint32 s )
 		{
-			m_pos += sint32_to_buffer( s, m_pos );
+			m_pos += sint32_to_buffer( array_ref< char >( m_pos, space_left() ), s );
 		}
 		void log_append( uint64 u )
 		{
-			m_pos += uint64_to_buffer( u, m_pos );
+			m_pos += uint64_to_buffer( array_ref< char >( m_pos, space_left() ), u );
 		}
 		void log_append( sint64 s )
 		{
-			m_pos += sint64_to_buffer( s, m_pos );
+			m_pos += sint64_to_buffer( array_ref< char >( m_pos, space_left() ), s );
 		}
 		void log_append( f32 f )
 		{
-			m_pos += f32_to_buffer( f, m_pos );
+			m_pos += f32_to_buffer( array_ref< char >( m_pos, space_left() ), f );
 		}
 		static bool can_log( log_level level )
@@ -82,4 +83,9 @@
 		virtual ~logger_base() {}
 	protected:
+		inline size_t space_left() const
+		{
+			return 1024 - static_cast< size_t >( m_pos - m_message );
+		}
+
 		char m_message[1024];
 		char* m_pos;
Index: /trunk/nv/stl/container/contiguous_storage.hh
===================================================================
--- /trunk/nv/stl/container/contiguous_storage.hh	(revision 434)
+++ /trunk/nv/stl/container/contiguous_storage.hh	(revision 435)
@@ -49,5 +49,5 @@
 		~static_storage() = default;
 	protected:
-		alignas( T ) unsigned char m_data[ N * sizeof( N ) ];
+		alignas( T ) unsigned char m_data[ N * sizeof( T ) ];
 	};
 	
Index: /trunk/nv/stl/container/fixed_storage.hh
===================================================================
--- /trunk/nv/stl/container/fixed_storage.hh	(revision 434)
+++ /trunk/nv/stl/container/fixed_storage.hh	(revision 435)
@@ -50,9 +50,9 @@
 		}
 
-		static constexpr size_type max_size() { return N; }
-		static constexpr size_type capacity() { return N; }
-		static constexpr size_type size() { return N; }
+		static constexpr size_t max_size() { return N; }
+		static constexpr size_t capacity() { return N; }
+		static constexpr size_t size() { return N; }
 		static constexpr bool empty() { return N == 0; }
-		static constexpr size_type raw_size() { return sizeof( value_type ) * N; }
+		static constexpr size_t raw_size() { return sizeof( value_type ) * N; }
 
 		operator array_ref< value_type >() { return array_ref< value_type >( Storage::data(), N ); }
Index: /trunk/nv/stl/container/growing_storage.hh
===================================================================
--- /trunk/nv/stl/container/growing_storage.hh	(revision 434)
+++ /trunk/nv/stl/container/growing_storage.hh	(revision 435)
@@ -33,7 +33,42 @@
 	};
 
+	namespace detail
+	{
+		template < typename SizeType, size_t Capacity >
+		struct growing_storage_size
+		{
+			static constexpr size_t max_size() { return Capacity; }
+			static constexpr size_t capacity() { return Capacity; }
+			constexpr size_t size() const { return m_size; }
+
+			inline void size( size_t new_size ) { m_size = static_cast< SizeType >( new_size ); }
+
+			operator size_t( ) const { return m_size; }
+
+			SizeType m_size = 0;
+		};
+
+		template < typename SizeType >
+		struct growing_storage_size< SizeType, 0 >
+		{
+			static constexpr size_t max_size() { return size_t( 0x80000000 ); }
+			constexpr size_t capacity() const { return m_capacity; }
+			constexpr size_t size() const { return m_size; }
+
+			inline void capacity( size_t new_capacity ) { m_capacity = static_cast< SizeType >( new_capacity ); }
+			inline void size( size_t new_size ) { m_size = static_cast< SizeType >( new_size ); }
+
+			operator size_t() const { return m_size; }
+
+			SizeType m_size = 0;
+			SizeType m_capacity = 0;
+		};
+	}
+
 	template <
 		typename Storage,
 		typename InitializePolicy = policy_initialize_standard,
+		typename SizeType = size_t,
+		size_t Capacity = 0,
 		typename NextCapacity = default_next_capacity< size_t >
 	>
@@ -41,6 +76,8 @@
 	{
 	public:
+		typedef detail::growing_storage_size< SizeType, Capacity > size_impl_type;
 		typedef typename Storage::value_type value_type;
 		typedef size_t                       size_type;
+		typedef SizeType                     size_store_type;
 		typedef value_type*                  iterator;
 		typedef const value_type*            const_iterator;
@@ -48,17 +85,17 @@
 		static constexpr bool is_fixed = false;
 
-		static constexpr size_type max_size() { return size_type( 0x80000000 ); }
-		constexpr size_t capacity() const { return m_capacity; }
-		constexpr size_t size() const { return m_size; }
+		static constexpr size_type max_size() { return size_impl_type::max_size(); }
+		constexpr size_type capacity() const { return m_size.capacity(); }
+		constexpr size_type size() const { return m_size; }
 		constexpr bool empty() const { return m_size == 0; }
-		constexpr size_t raw_size() const { return sizeof( value_type ) * m_size; }
+		constexpr size_type raw_size() const { return sizeof( value_type ) * m_size; }
 
 		operator array_ref< value_type >() { return array_ref< value_type >( Storage::data(), size() ); }
 		operator array_view< value_type >() const { return array_view< value_type >( Storage::data(), size() ); }
 
-		inline growing_storage() : m_size( 0 ), m_capacity( 0 ) {}
-		inline explicit growing_storage( size_type new_size ) : m_size( 0 ), m_capacity( 0 ) { resize( new_size ); }
-		inline explicit growing_storage( default_init ) : m_size( 0 ), m_capacity( 0 ) { resize( default_init() ); }
-		inline growing_storage( size_type new_size, const value_type& v ) : m_size( 0 ), m_capacity( 0 ) { resize( new_size, v ); }
+		inline growing_storage() {}
+		inline explicit growing_storage( size_type new_size ) { resize( new_size ); }
+		inline explicit growing_storage( default_init ) { resize( default_init() ); }
+		inline growing_storage( size_type new_size, const value_type& v ) { resize( new_size, v ); }
 
 		// prevent copying 
@@ -68,18 +105,15 @@
 		// allow move
 		growing_storage( growing_storage&& other )
-			: Storage( nv::move( other ) ), m_size( other.m_size ), m_capacity( other.m_capacity )
-		{
-			other.m_size = 0;
-			other.m_capacity = 0;
+			: Storage( nv::move( other ) ), m_size( other.m_size )
+		{
+			other.m_size = size_impl_type();
 		}
 
 		inline growing_storage& operator=( growing_storage&& other )
 		{
-			if ( m_capacity > 0 ) Storage::reallocate( 0, false );
+			Storage::reallocate( 0, false );
 			m_size = other.m_size;
-			m_capacity = other.m_capacity;
 			Storage::operator=( nv::move( other ) );
-			other.m_size = 0;
-			other.m_capacity = 0;
+			other.m_size = size_impl_type();
 			return *this;
 		}
@@ -108,5 +142,5 @@
 			if ( m_size == 0 ) return;
 			InitializePolicy::destroy( Storage::data() + m_size - 1 );
-			m_size--;
+			m_size.size( m_size - 1 );
 		}
 
@@ -119,5 +153,5 @@
 			if ( ( position + 1 ) < iend )
 				raw_alias_copy( position + 1, iend, position );
-			m_size--;
+			m_size.size( m_size - 1 );
 			return position;
 		}
@@ -195,5 +229,5 @@
 					InitializePolicy::copy( ptr, ptr + sz, Storage::data() );
 			}
-			else m_size = 0;
+			else m_size.size( 0 );
 		}
 
@@ -220,5 +254,5 @@
 			{
 				InitializePolicy::destroy( Storage::data(), Storage::data() + m_size );
-				m_size = 0;
+				m_size = size_impl_type();
 			}
 		}
@@ -248,52 +282,60 @@
 		}
 
+		template< size_t C = Capacity >
+		enable_if_t< C != 0, bool > try_reallocate( size_t, bool )
+		{
+			return false;
+		}
+
+		template< size_t C = Capacity >
+		enable_if_t< C == 0, bool > try_reallocate( size_t new_capacity, bool copy_needed )
+		{
+			if ( new_capacity > 0 && Storage::reallocate( new_capacity, copy_needed ) )
+			{
+				m_size.capacity( new_capacity );
+				return true;
+			}
+			else return false;
+		}
+
 		// TODO: return type error checking
-		bool try_grow( size_t amount )
-		{
-			size_type new_size = amount + m_size;
-			if ( new_size > m_capacity )
-			{
-				size_type new_capacity = NextCapacity::get( new_size - m_capacity, m_capacity, max_size() );
-				if ( new_capacity > 0 && Storage::reallocate( new_capacity, true ) )
-				{
-					m_capacity = new_capacity;
-				}
-				else return false;
-			}
-			m_size = new_size;
+		bool try_grow( size_t amount, size_t extra = 0 )
+		{
+			size_type new_size = amount + m_size + extra;
+			if ( new_size > m_size.capacity() )
+			{
+				size_type new_capacity = NextCapacity::get( new_size - m_size.capacity(), m_size.capacity(), max_size() );
+				if ( !try_reallocate( new_capacity, true ) ) return false;
+			}
+			m_size.size( new_size - extra );
 			return true;
 		}
+
 		// TODO: return type error checking
 		bool try_reserve( size_t new_capacity, bool copy_needed )
 		{
-			if ( new_capacity > m_capacity )
-			{
-				if ( new_capacity > 0 && Storage::reallocate( new_capacity, copy_needed ) )
+			if ( new_capacity > m_size.capacity() )
+			{
+				return try_reallocate( new_capacity, copy_needed );
+			}
+			return true;
+		}
+		// TODO: return type error checking
+		bool try_resize( size_t new_size, bool copy_needed, size_t extra = 0 )
+		{
+			if ( new_size > m_size )
+			{
+				if ( try_reserve( new_size + extra, copy_needed ) )
 				{
-					m_capacity = new_capacity;
-				}
-				else return false;
-			}
-			return true;
-		}
-		// TODO: return type error checking
-		bool try_resize( size_t new_size, bool copy_needed )
-		{
-			if ( new_size > m_size )
-			{
-				if ( try_reserve( new_size, copy_needed ) )
-				{
-					m_size = new_size;
+					m_size.size( new_size );
 					return true;
 				}
 				return false;
 			}
-			m_size = new_size;
+			m_size.size( new_size );
 			return true;
 		}
 	protected:
-		size_type m_size;
-		size_type m_capacity;
-
+		size_impl_type m_size;
 	};
 
Index: /trunk/nv/stl/container/random_access.hh
===================================================================
--- /trunk/nv/stl/container/random_access.hh	(revision 435)
+++ /trunk/nv/stl/container/random_access.hh	(revision 435)
@@ -0,0 +1,121 @@
+// Copyright (C) 2015 ChaosForge Ltd
+// http://chaosforge.org/
+//
+// This file is part of Nova libraries. 
+// For conditions of distribution and use, see copying.txt file in root folder.
+
+/**
+* @file random_access.hh
+* @author Kornel Kisielewicz epyon@chaosforge.org
+* @brief random_access classes
+*/
+
+#ifndef NV_STL_CONTAINER_RANDOM_ACCESS_HH
+#define NV_STL_CONTAINER_RANDOM_ACCESS_HH
+
+#include <nv/common.hh>
+#include <nv/stl/algorithm/fill.hh>
+#include <nv/stl/iterator.hh>
+
+
+namespace nv
+{
+	template < typename Super, bool Const = Super::is_const >
+	class random_access {};
+
+	template < typename Super >
+	class random_access < Super, true > : public Super
+	{
+	public:
+		typedef typename Super::value_type           value_type;
+		typedef typename Super::size_type            size_type;
+		typedef ptrdiff_t                            difference_type;
+		typedef const value_type*                    pointer;
+		typedef const value_type*                    const_pointer;
+		typedef const value_type*                    iterator;
+		typedef const value_type*                    const_iterator;
+		typedef const value_type*                    reference;
+		typedef const value_type*                    const_reference;
+		typedef nv::reverse_iterator<iterator>       reverse_iterator;
+		typedef nv::reverse_iterator<const_iterator> const_reverse_iterator;
+
+		using Super::Super;
+
+		inline const_reference front() const { NV_ASSERT( !Super::empty(), "front() called on empty data!" ); return Super::data()[0]; }
+		inline const_reference back() const { NV_ASSERT( !Super::empty(), "front() called on empty data!" ); return Super::data()[Super::size() - 1]; }
+
+		const_reference operator[]( size_type i ) const
+		{
+			NV_ASSERT( i < Super::size(), "Out of range" );
+			return Super::data()[i];
+		}
+
+		inline const_iterator begin() const { return const_iterator( Super::data() ); }
+		inline const_iterator end() const { return const_iterator( Super::data() + Super::size() ); }
+		inline const_iterator cbegin() const { return const_iterator( Super::data() ); }
+		inline const_iterator cend() const { return const_iterator( Super::data() + Super::size() ); }
+		inline const_reverse_iterator rbegin() const { return const_reverse_iterator( end() ); }
+		inline const_reverse_iterator crbegin() const { return const_reverse_iterator( end() ); }
+		inline const_reverse_iterator rend() const { return const_reverse_iterator( begin() ); }
+		inline const_reverse_iterator crend() const { return const_reverse_iterator( begin() ); }
+		inline const_iterator iat( size_t i ) const { NV_ASSERT( i <= Super::size(), "Index out of range" ); return begin() + i; }
+	};
+
+	template < typename Super >
+	class random_access < Super, false > : public Super
+	{
+	public:
+		typedef typename Super::value_type           value_type;
+		typedef typename Super::size_type            size_type;
+		typedef ptrdiff_t                            difference_type;
+		typedef value_type*                          pointer;
+		typedef const value_type*                    const_pointer;
+		typedef value_type*					         iterator;
+		typedef const value_type*                    const_iterator;
+		typedef value_type&                          reference;
+		typedef const value_type&                    const_reference;
+		typedef nv::reverse_iterator<iterator>       reverse_iterator;
+		typedef nv::reverse_iterator<const_iterator> const_reverse_iterator;
+
+		using Super::Super;
+
+		inline reference       front() { NV_ASSERT( !Super::empty(), "front() called on empty data!" );  return Super::data()[0]; }
+		inline const_reference front() const { NV_ASSERT( !Super::empty(), "front() called on empty data!" ); return Super::data()[0]; }
+		inline reference       back() { NV_ASSERT( !Super::empty(), "front() called on empty data!" ); return Super::data()[Super::size() - 1]; }
+		inline const_reference back() const { NV_ASSERT( !Super::empty(), "front() called on empty data!" ); return Super::data()[Super::size() - 1]; }
+
+		reference operator[]( size_type i )
+		{
+			NV_ASSERT( i < Super::size(), "Out of range" );
+			return Super::data()[i];
+		}
+
+		const_reference operator[]( size_type i ) const
+		{
+			NV_ASSERT( i < Super::size(), "Out of range" );
+			return Super::data()[i];
+		}
+
+		inline void fill( const value_type& value )
+		{
+			fill_n( iterator( Super::data() ), iterator( Super::data() + this->size() ), value );
+		}
+
+		inline const_iterator begin() const { return const_iterator( Super::data() ); }
+		inline const_iterator end() const { return const_iterator( Super::data() + Super::size() ); }
+		inline iterator begin() { return iterator( Super::data() ); }
+		inline iterator end() { return iterator( Super::data() + Super::size() ); }
+		inline const_iterator cbegin() const { return const_iterator( Super::data() ); }
+		inline const_iterator cend() const { return const_iterator( Super::data() + Super::size() ); }
+		inline reverse_iterator rbegin() { return reverse_iterator( end() ); }
+		inline const_reverse_iterator rbegin() const { return const_reverse_iterator( end() ); }
+		inline const_reverse_iterator crbegin() const { return const_reverse_iterator( end() ); }
+		inline reverse_iterator rend() { return reverse_iterator( begin() ); }
+		inline const_reverse_iterator rend() const { return const_reverse_iterator( begin() ); }
+		inline const_reverse_iterator crend() const { return const_reverse_iterator( begin() ); }
+		inline const_iterator iat( size_t i ) const { NV_ASSERT( i <= Super::size(), "Index out of range" ); return begin() + i; }
+		inline iterator       iat( size_t i ) { NV_ASSERT( i <= Super::size(), "Index out of range" ); return begin() + i; }
+	};
+}
+
+#endif // NV_STL_CONTAINER_RANDOM_ACCESS_HH
Index: /trunk/nv/stl/container/sized_storage.hh
===================================================================
--- /trunk/nv/stl/container/sized_storage.hh	(revision 434)
+++ /trunk/nv/stl/container/sized_storage.hh	(revision 435)
@@ -22,5 +22,6 @@
 	template <
 		typename Storage,
-		typename InitializePolicy = policy_initialize_standard
+		typename InitializePolicy = policy_initialize_standard,
+		typename SizeType = size_t
 	>
 	class sized_storage : public Storage
@@ -28,4 +29,5 @@
 	public:
 		typedef size_t                       size_type;
+		typedef SizeType                     size_store_type;
 		typedef typename Storage::value_type value_type;
 
@@ -33,8 +35,8 @@
 
 		static constexpr size_type max_size() { return size_type( 0x80000000 ); }
-		constexpr size_t capacity() const { return m_size; }
-		constexpr size_t size() const { return m_size; }
+		constexpr size_type capacity() const { return m_size; }
+		constexpr size_type size() const { return m_size; }
 		constexpr bool empty() const { return m_size == 0; }
-		constexpr size_t raw_size() const { return sizeof( value_type ) * m_size; }
+		constexpr size_type raw_size() const { return sizeof( value_type ) * m_size; }
 
 		operator array_ref< value_type >() { return array_ref< value_type >( Storage::data(), m_size ); }
@@ -160,5 +162,5 @@
 		}
 	protected:
-		size_type m_size;
+		size_store_type m_size;
 	};
 
Index: /trunk/nv/stl/memory.hh
===================================================================
--- /trunk/nv/stl/memory.hh	(revision 434)
+++ /trunk/nv/stl/memory.hh	(revision 435)
@@ -60,4 +60,7 @@
 		constexpr array_ref( value_type* a_data, size_type a_size )
 			: m_data( a_data ), m_size( a_size ) {}
+		template< size_t N >
+		constexpr explicit array_ref( value_type( &a_data )[N] )
+			: m_data( a_data ), m_size( N ) {}
 
 		void assign( value_type* a_data, size_type a_size )
@@ -130,4 +133,7 @@
 		constexpr array_view( const array_ref<T>& view )
 			: m_data( view.data() ), m_size( view.size() ) {}
+		template< size_t N >
+		constexpr explicit array_view( const value_type( &a_data )[N] )
+			: m_data( a_data ), m_size( N ) {}
 
 		void assign( const value_type* a_data, size_type a_size )
Index: /trunk/nv/stl/string.hh
===================================================================
--- /trunk/nv/stl/string.hh	(revision 434)
+++ /trunk/nv/stl/string.hh	(revision 435)
@@ -76,17 +76,4 @@
 	};
 
-	size_t sint32_to_buffer( sint32 n, char* str );
-	size_t sint64_to_buffer( sint64 n, char* str );
-	size_t uint32_to_buffer( uint32 n, char* str );
-	size_t uint64_to_buffer( uint64 n, char* str );
-	size_t f32_to_buffer( f32 n, char* str );
-	size_t f64_to_buffer( f64 n, char* str );
-	sint32 buffer_to_sint32( const char* str, char** end );
-	sint64 buffer_to_sint64( const char* s, char** end );
-	uint32 buffer_to_uint32( const char* s, char** end );
-	uint64 buffer_to_uint64( const char* s, char** end );
-	float buffer_to_f32( const char* s, char** end );
-	double buffer_to_f64( const char* s, char** end );
-
 	inline string_view trimmed( const string_view& str )
 	{
Index: /trunk/nv/stl/string/common.hh
===================================================================
--- /trunk/nv/stl/string/common.hh	(revision 434)
+++ /trunk/nv/stl/string/common.hh	(revision 435)
@@ -37,4 +37,5 @@
 	struct is_string_base : detail::is_string_base_impl< T > {};
 
+
 }
 
Index: /trunk/nv/stl/string/short_string.hh
===================================================================
--- /trunk/nv/stl/string/short_string.hh	(revision 434)
+++ /trunk/nv/stl/string/short_string.hh	(revision 435)
@@ -17,24 +17,154 @@
 {
 	template < typename Storage >
-	class string_buffer_ops : Storage
+	class string_buffer_base : public string_base< Storage >
 	{
+	public:
+		typedef string_buffer_base< Storage >               this_type;
+		typedef string_base< Storage >                      base_type;
+		typedef typename Storage::iterator                  iterator;
+		typedef typename Storage::const_iterator            const_iterator;
 
+		constexpr string_buffer_base() : base_type() {}
+		inline string_buffer_base( const char* data, size_t sz )
+			: base_type()
+		{
+			append( data, sz );
+		}
+
+		inline explicit string_buffer_base( const string_view& s ) : this_type( s.data(), s.size() ) {}
+		template < typename S >
+		inline string_buffer_base( const string_base<S>& rhs ) : this_type( rhs.data(), rhs.size() ) {}
+		inline string_buffer_base( string_buffer_base&& copy ) = default;
+		inline string_buffer_base& operator=( string_buffer_base&& other ) = default;
+		inline string_buffer_base& operator=( const string_view& other )
+		{
+			clear();
+			append( other );
+		}
+
+		size_t append( const char* data, size_t sz )
+		{
+			size_t pos    = size();
+			size_t amount = expand_by( sz );
+			raw_copy_n( data, amount, this->begin() + pos );
+			return amount;
+		}
+
+		size_t append( const_iterator first, const_iterator last )
+		{
+			return append( first, last - first );
+		}
+
+		size_t append( const string_view& s )
+		{
+			return append( s.data(), s.size() );
+		}
+
+		template < typename S >
+		size_t append( const string_base<S>& s )
+		{
+			return append( s.data(), s.size() );
+		}
+
+		size_t append( sint32 s )
+		{
+			char buffer[8];
+			size_t result = sint32_to_buffer( array_ref< char >( buffer ), s );
+			return ( result > 0 ? append( buffer.data(), result ) : 0 );
+		}
+
+		size_t append( uint32 u )
+		{
+			char buffer[8];
+			size_t result = uint32_to_buffer( array_ref< char >( buffer ), u );
+			return ( result > 0 ? append( buffer, result ) : 0 );
+		}
+
+		size_t append( sint64 s )
+		{
+			char buffer[16];
+			size_t result = sint64_to_buffer( array_ref< char >( buffer ), s );
+			return ( result > 0 ? append( buffer, result ) : 0 );
+		}
+
+		size_t append( uint64 u )
+		{
+			char buffer[16];
+			size_t result = uint64_to_buffer( array_ref< char >( buffer ), u );
+			return ( result > 0 ? append( buffer, result ) : 0 );
+		}
+
+		size_t append( f32 u )
+		{
+			char buffer[64];
+			size_t result = uint64_to_buffer( array_ref< char >( buffer ), u );
+			return ( result > 0 ? append( buffer, result ) : 0 );
+		}
+
+		size_t append( f64 s )
+		{
+			char buffer[64];
+			size_t result = uint64_to_buffer( array_ref< char >( buffer ), u );
+			return ( result > 0 ? append( buffer, result ) : 0 );
+		}
+
+		void reserve( size_type new_capacity )
+		{
+			Storage::reserve( new_capacity + 1, true );
+			this->data()[this->size()] = 0;
+		}
+
+		void resize( size_type new_size )
+		{
+			Storage::reserve( new_size + 1, true );
+			Storage::resize( min( new_size, capacity() - 1 ) );
+			this->data()[this->size()] = 0;
+		}
+
+	protected:
+
+		size_t expand_by( size_t sz )
+		{
+			size_t result = 0;
+			if ( Storage::try_grow( sz, 1 ) )
+				result = sz;
+			else
+			{
+				result = capacity() - size() - 1;
+				Storage::try_resize( capacity() - 1, true, 1 );
+			}
+			this->data()[this->size()] = 0;
+			return result;
+		}
+	private: // blocked, because not taking care of trailing zero
+		using Storage::assign;
+		using Storage::insert;
+		using Storage::erase;
+		using Storage::pop_back;
+		using Storage::push_back;
+		using Storage::emplace_back;
 	};
 
-	template < typename T, size_t N >
+	template < size_t N >
 	using short_string = 
-		string_buffer_ops< 
+		string_buffer_base<
 			random_access <
-				string_base< 
-					growing_storage<
-						static_storage< T, N > > > > >;
+				growing_storage<
+					static_storage< char, N >,
+						policy_initialize_never,
+							uint8, N > > >;
 
-	template < typename T >
-	using buffer_string = 
-		string_buffer_ops< 
+	using string_buffer = 
+		string_buffer_base<
 			random_access <
-				string_base< 
-					growing_storage< 
-						dynamic_storage< T > > > > >;
+				growing_storage<
+					dynamic_storage< char >,
+						policy_initialize_never,
+							uint16 > > >;
+
+	using string32  = short_string< 31 >;
+	using string64  = short_string< 63 >;
+	using string128 = short_string< 127 >;
+	using string256 = short_string< 255 >;
 
 
Index: /trunk/nv/stl/string/string_base.hh
===================================================================
--- /trunk/nv/stl/string/string_base.hh	(revision 434)
+++ /trunk/nv/stl/string/string_base.hh	(revision 435)
@@ -14,4 +14,18 @@
 namespace nv
 {
+
+	size_t sint32_to_buffer( array_ref< char > buffer, sint32 n );
+	size_t sint64_to_buffer( array_ref< char > buffer, sint64 n );
+	size_t uint32_to_buffer( array_ref< char > buffer, uint32 n );
+	size_t uint64_to_buffer( array_ref< char > buffer, uint64 n );
+	size_t f32_to_buffer( array_ref< char > buffer, f32 n );
+	size_t f64_to_buffer( array_ref< char > buffer, f64 n );
+
+	sint32 buffer_to_sint32( const char* str, char** end );
+	sint64 buffer_to_sint64( const char* s, char** end );
+	uint32 buffer_to_uint32( const char* s, char** end );
+	uint64 buffer_to_uint64( const char* s, char** end );
+	float buffer_to_f32( const char* s, char** end );
+	double buffer_to_f64( const char* s, char** end );
 	
 	// string base class - will become a base for a string class later
@@ -69,6 +83,4 @@
 	protected:
 		using base_type::base_type;
-		constexpr string_base() : base_type() {}
-		constexpr string_base( pointer str, size_type len ) : base_type( str, len ) {}
 
 		template < typename ReverseIterator >
Index: /trunk/src/gui/gui_gfx_renderer.cc
===================================================================
--- /trunk/src/gui/gui_gfx_renderer.cc	(revision 434)
+++ /trunk/src/gui/gui_gfx_renderer.cc	(revision 435)
@@ -147,5 +147,5 @@
 	size_t wsize = m_atlas.get_depth() * 4 * 4;
 	uint8* wfill = new uint8[m_atlas.get_depth() * 4 * 4];
-	std::fill( wfill, wfill + wsize, 255 );
+	raw_fill( wfill, wfill + wsize, 255 );
 	white.pos = ivec2();
 	m_atlas.set_region( white, wfill );
@@ -189,8 +189,6 @@
 nv::size_t gfx_renderer::load_font( const string_view& filename, nv::size_t size )
 {
-	std::string id_name( filename.data(), filename.size() );
-	char buffer[8]; size_t len = nv::sint32_to_buffer( sint32( size ), buffer );
-	id_name.append( std::string( buffer, len ) );
-	string_view id( id_name.c_str(), id_name.size() );
+	string128 id( filename );
+	id.append( size );
 	auto i = m_font_names.find( id );
 	if ( i != m_font_names.end() )
Index: /trunk/src/lua/lua_path.cc
===================================================================
--- /trunk/src/lua/lua_path.cc	(revision 434)
+++ /trunk/src/lua/lua_path.cc	(revision 435)
@@ -88,5 +88,5 @@
 		{
 			*current++ = '[';
-			current += uint32_to_buffer( e.value, current );
+			current += uint32_to_buffer( array_ref< char >( current, current - start ), e.value );
 			*current++ = ']';
 			dot = false;
Index: /trunk/src/lua/lua_raw.cc
===================================================================
--- /trunk/src/lua/lua_raw.cc	(revision 434)
+++ /trunk/src/lua/lua_raw.cc	(revision 435)
@@ -26,14 +26,15 @@
 	default : break; 
 	}
-	char buffer[64];
+	char buffer_data[64];
+	nv::array_ref< char > buffer( buffer_data, 64 );
 	if ( type == LUA_TLIGHTUSERDATA || type == LUA_TUSERDATA )
 	{
-		size_t l = nv::uint64_to_buffer( nv::uint64( lua_touserdata( L, idx ) ), buffer );
-		return std::string( buffer, l );
+		size_t l = nv::uint64_to_buffer( buffer, nv::uint64( lua_touserdata( L, idx ) ) );
+		return std::string( buffer_data, l );
 	}
 	else if ( type == LUA_TNUMBER )
 	{
-		size_t l = nv::f64_to_buffer( lua_tonumber( L, idx ), buffer );
-		return std::string( buffer, l );
+		size_t l = nv::f64_to_buffer( buffer, lua_tonumber( L, idx ) );
+		return std::string( buffer_data, l );
 	}
 	return "UNKNOWN!";
Index: /trunk/src/stl/string.cc
===================================================================
--- /trunk/src/stl/string.cc	(revision 434)
+++ /trunk/src/stl/string.cc	(revision 435)
@@ -37,76 +37,96 @@
 }
 
-nv::size_t nv::sint32_to_buffer( sint32 n, char* str )
-{
-	char* s = str;
-	uint32 abs = static_cast< uint32 >( n < 0 ? -n : n );
-	do
-	{
+nv::size_t nv::sint32_to_buffer( array_ref< char > buffer, sint32 n )
+{
+	if ( buffer.size() < 2 ) return 0;
+	char* last = buffer.end() - 1;
+	char* s = buffer.begin();
+	uint32 abs = static_cast<uint32>( n < 0 ? -n : n );
+	do
+	{
+		if ( s == last ) { *buffer.begin() = '\0'; return 0;  }
 		*s++ = static_cast<char>( '0' + ( abs % 10 ) );
 		abs /= 10;
 	} while ( abs > 0 );
-	if ( n < 0 ) *s++ = '-';
-	*s = '\0';
-	string_reverse( str, s - 1 );
-	return static_cast<nv::size_t>( s - str );
-}
-
-nv::size_t nv::sint64_to_buffer( sint64 n, char* str )
-{
-	char* s = str;
-	uint64 abs = static_cast< uint64 >( n < 0 ? -n : n );
-	do
-	{
+	if ( n < 0 )
+	{
+		if ( s == last ) { *buffer.begin() = '\0'; return 0; }
+		*s++ = '-';
+	}
+	*s = '\0';
+	string_reverse( buffer.begin(), s - 1 );
+	return static_cast<nv::size_t>( s - buffer.begin() );
+}
+
+nv::size_t nv::sint64_to_buffer( array_ref< char > buffer, sint64 n )
+{
+	if ( buffer.size() < 2 ) return 0;
+	char* last = buffer.end() - 1;
+	char* s = buffer.begin();
+	uint64 abs = static_cast<uint64>( n < 0 ? -n : n );
+	do
+	{
+		if ( s == last ) { *buffer.begin() = '\0'; return 0; }
 		*s++ = static_cast<char>( '0' + ( abs % 10 ) );
 		abs /= 10;
 	} while ( abs > 0 );
-	if ( n < 0 ) *s++ = '-';
-	*s = '\0';
-	string_reverse( str, s - 1 );
-	return static_cast<nv::size_t>( s - str );
-}
-
-nv::size_t nv::uint32_to_buffer( uint32 n, char* str )
-{
-	char* s = str;
-	do
-	{
+	if ( n < 0 )
+	{
+		if ( s == last ) { *buffer.begin() = '\0'; return 0; }
+		*s++ = '-';
+	}
+	*s = '\0';
+	string_reverse( buffer.begin(), s - 1 );
+	return static_cast<nv::size_t>( s - buffer.begin() );
+}
+
+nv::size_t nv::uint32_to_buffer( array_ref< char > buffer, uint32 n )
+{
+	if ( buffer.size() < 2 ) return 0;
+	char* last = buffer.end() - 1;
+	char* s = buffer.begin();
+	do
+	{
+		if ( s == last ) { *buffer.begin() = '\0'; return 0; }
 		*s++ = static_cast<char>( '0' + ( n % 10 ) );
 		n /= 10;
 	} while ( n > 0 );
 	*s = '\0';
-	string_reverse( str, s - 1 );
-	return static_cast<nv::size_t>( s - str );
-}
-
-nv::size_t nv::uint64_to_buffer( uint64 n, char* str )
-{
-	char* s = str;
-	do
-	{
+	string_reverse( buffer.begin(), s - 1 );
+	return static_cast<nv::size_t>( s - buffer.begin() );
+}
+
+nv::size_t nv::uint64_to_buffer( array_ref< char > buffer, uint64 n )
+{
+	if ( buffer.size() < 2 ) return 0;
+	char* last = buffer.end() - 1;
+	char* s = buffer.begin();
+	do
+	{
+		if ( s == last ) { *buffer.begin() = '\0'; return 0; }
 		*s++ = static_cast<char>( '0' + ( n % 10 ) );
 		n /= 10;
 	} while ( n > 0 );
 	*s = '\0';
-	string_reverse( str, s - 1 );
-	return static_cast<nv::size_t>( s - str );
-}
-
-nv::size_t nv::f32_to_buffer( f32 n, char* str )
+	string_reverse( buffer.begin(), s - 1 );
+	return static_cast<nv::size_t>( s - buffer.begin() );
+}
+
+nv::size_t nv::f32_to_buffer( array_ref< char > buffer, f32 n )
 {
 #if NV_COMPILER == NV_MSVC
-	int result = sprintf_s( str, 64, "%.*g", 6, n );
+	int result = sprintf_s( buffer.data(), buffer.size(), "%.*g", 6, n );
 #else
-	int result = snprintf( str, 64, "%.*g", 6, n );
+	int result = snprintf( buffer.data(), buffer.size(), "%.*g", 6, n );
 #endif
 	return static_cast<nv::size_t>( result > 0 ? result : 0 );
 }
 
-nv::size_t nv::f64_to_buffer( f64 n, char* str )
+nv::size_t nv::f64_to_buffer( array_ref< char > buffer, f64 n )
 {
 #if NV_COMPILER == NV_MSVC
-	int result = sprintf_s( str, 64, "%.*g", 6, n );
+	int result = sprintf_s( buffer.data(), buffer.size(), "%.*g", 6, n );
 #else
-	int result = snprintf( str, 64, "%.*g", 6, n );
+	int result = snprintf( buffer.data(), buffer.size(), "%.*g", 6, n );
 #endif
 	return static_cast<nv::size_t>( result > 0 ? result : 0 );
