Index: trunk/src/lua/lua_state.cc
===================================================================
--- trunk/src/lua/lua_state.cc	(revision 9)
+++ trunk/src/lua/lua_state.cc	(revision 9)
@@ -0,0 +1,308 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+#include "nv/lua/lua_state.hh"
+
+#include "nv/lib/lua.hh"
+#include "nv/logging.hh"
+#include "nv/string.hh"
+
+using namespace nv;
+
+// The following should be moved to lua_raw
+
+std::string lua_typecontent( lua_State* L, int idx )
+{
+	switch ( lua_type( L, idx ) )
+	{
+	case LUA_TNONE          : return "NONE"; 
+	case LUA_TNIL		    : return "NIL"; 
+	case LUA_TBOOLEAN		: return lua_toboolean( L, idx ) == 0 ? "false" : "true"; 
+	case LUA_TLIGHTUSERDATA	: return nv::to_string( uint64( lua_touserdata( L, idx ) ) ); 
+	case LUA_TNUMBER		: return nv::to_string( lua_tonumber( L, idx ) ); 
+	case LUA_TSTRING		: return lua_tostring( L, idx ); 
+	case LUA_TTABLE		    : return "TABLE"; 
+	case LUA_TFUNCTION		: return "FUNCTION"; 
+	case LUA_TUSERDATA		: return nv::to_string( uint64( lua_touserdata( L, idx ) ) ); 
+	case LUA_TTHREAD		: return "THREAD"; 
+	default : return "UNKNOWN!"; 
+	}
+}
+
+// -----
+
+lua::stack_guard::stack_guard( lua::state* L )
+	: L(L), m_level( lua_gettop(L->L) )
+{
+
+}
+
+lua::stack_guard::~stack_guard()
+{
+	lua_settop( L->L, m_level );
+}
+
+lua::state::state( bool is_main /*= false*/ )
+{
+	m_owner = true;
+	L = luaL_newstate( );
+
+	lua_pushcfunction(L, luaopen_base);
+	lua_pushliteral(L, LUA_TABLIBNAME);
+	lua_call(L, 1, 0);
+
+	if (is_main)
+	{
+		NV_ASSERT( this == get(), "lua_state : another main state created!" );
+		stack_guard guard( this );
+		luaopen_base( L );
+		luaopen_string( L );
+		luaopen_table( L );
+		luaopen_math( L );
+	}
+
+	NV_LOG( nv::LOG_TRACE, is_main ? "Main Lua state created" : "Secondary Lua state created");
+}
+
+int lua::state::load_string( const std::string& code, const std::string& name )
+{
+	NV_LOG( nv::LOG_TRACE, "Loading Lua string '" << name << "'");
+	return luaL_loadbuffer( L, code.c_str(), code.length(), name.c_str() );
+}
+
+int lua::state::load_stream( std::istream& stream, const std::string& name )
+{
+	NV_LOG( nv::LOG_NOTICE, "Loading Lua stream '" << name << "'");
+	return load_string( std::string(
+		(std::istreambuf_iterator<char>(stream)),
+		std::istreambuf_iterator<char>()), name );
+}
+
+int lua::state::load_file( const std::string& filename )
+{
+	NV_LOG( nv::LOG_NOTICE, "Loading Lua file '" << filename << "'");
+	return luaL_loadfile( L, filename.c_str() );
+}
+
+bool lua::state::do_string( const std::string& code, const std::string& name )
+{
+	lua::stack_guard( this );
+	int result = load_string(code,name);
+	if (result)
+	{
+		NV_LOG( nv::LOG_WARNING, "Failed to load string " << name << ": " << lua_tostring(L, -1));
+		return false;
+	}
+	return do_current( name ) == 0;
+}
+
+bool lua::state::do_stream( std::istream& stream, const std::string& name )
+{
+	lua::stack_guard( this );
+	int result = load_stream(stream,name);
+	if (result)
+	{
+		NV_LOG( nv::LOG_WARNING, "Failed to open stream " << name << ": " << lua_tostring(L, -1));
+		return false;
+	}
+	return do_current( name ) == 0;
+}
+
+bool lua::state::do_file( const std::string& filename )
+{
+	lua::stack_guard( this );
+	int result = load_file(filename);
+	if (result) 
+	{
+		NV_LOG( nv::LOG_WARNING, "Failed to open file " << filename << ": " << lua_tostring(L, -1));
+		return false;
+	}
+	return do_current( filename ) == 0;
+}
+
+int lua::state::do_current( const std::string& name )
+{
+	int result = lua_pcall(L, 0, 0, 0);
+	if (result) 
+	{
+		NV_LOG( nv::LOG_WARNING, "Failed to run script " << name << ": " << lua_tostring(L, -1));
+		lua_pop( L, 1 );
+	}
+	return result;
+}
+
+lua::state::~state()
+{
+	if (m_owner)
+	{
+		lua_close( L );
+	}
+}
+
+lua::state* lua::state::get()
+{
+	static lua::state main_state(true);
+	return &main_state;
+}
+
+bool lua::state::push( const std::string& path, bool global )
+{
+	size_t point = path.find('.');
+
+	if (point == std::string::npos)
+	{
+		if (global)
+		{
+			lua_getglobal( L, path.c_str() );
+		}
+		else
+		{
+			lua_getfield( L, -1, path.c_str() );
+		}
+		return !lua_isnil( L, -1 );
+	}
+
+	size_t idx = 0;
+	size_t start = 0;
+
+	while( point != std::string::npos )
+	{
+		if (idx == 0)
+		{
+			if (global)
+			{
+				lua_getglobal( L, path.substr(start,point-start).c_str() );
+			}
+			else
+			{
+				lua_getfield( L, -1, path.substr(start,point-start).c_str() );
+			}
+		}
+		else
+		{
+			if ( lua_istable( L, -1 ) )
+			{
+				lua_pushstring( L, path.substr(start,point-start).c_str() );
+				lua_gettable( L, -2 );
+				lua_insert( L, -2 );
+				lua_pop( L, 1 );
+			}
+			else
+			{
+				lua_pop(L, 1);
+				lua_pushnil(L);
+				return false;
+			}
+		}
+		start = point+1;
+		point = path.find( '.', start );
+	}
+	return true;
+}
+
+
+int lua::state::get_stack_size()
+{
+	return lua_gettop( L );
+}
+
+lua::table_guard::table_guard( lua::state* lstate, const std::string& table, bool global )
+	: L(lstate), m_guard(lstate)
+{
+	L->push( table, global );
+}
+
+lua::table_guard::table_guard( lua::state* lstate, const std::string& table, int index, bool global )
+	: L(lstate), m_guard(lstate)
+{
+	L->push( table, global );
+	lua_rawgeti( L->L, -1, index );
+}
+
+lua::table_guard::table_guard( lua::state* lstate, const std::string& table, const std::string& index, bool global /*= true */ )
+	: L(lstate), m_guard(lstate)
+{
+	L->push( table, global );
+	lua_pushstring( L->L, index.c_str() );
+	lua_rawget( L->L, -2 );
+}
+
+lua::table_guard::table_guard( const table_guard& parent, const std::string& index )
+	: L( parent.L ), m_guard( parent.L )
+{
+	lua_getfield( L->L, -1, index.c_str() );
+}
+
+lua::table_guard::table_guard( const table_guard& parent, int index )
+	: L( parent.L ), m_guard( parent.L )
+{
+	lua_rawgeti( L->L, -1, index );
+}
+
+bool lua::table_guard::has_field( const string& element )
+{
+	lua_getfield( L->L, -1, element.c_str() );
+	bool result = lua_isnil( L->L, -1 );
+	lua_pop( L->L, 1 );
+	return result;
+}
+
+string lua::table_guard::get_string( const string& element, const string& defval /*= "" */ )
+{
+	lua_getfield( L->L, -1, element.c_str() );
+	string result( ( lua_type( L->L, -1 ) == LUA_TSTRING ) ? lua_tostring( L->L, -1 ) : defval );
+	lua_pop( L->L, 1 );
+	return result;
+}
+
+char lua::table_guard::get_char( const string& element, char defval /*= "" */ )
+{
+	lua_getfield( L->L, -1, element.c_str() );
+	char result = ( lua_type( L->L, -1 ) == LUA_TSTRING && lua_rawlen( L->L, -1 ) > 0 ) ? lua_tostring( L->L, -1 )[0] : defval;
+	lua_pop( L->L, 1 );
+	return result;
+}
+
+int lua::table_guard::get_integer( const string& element, int defval /*= "" */ )
+{
+	lua_getfield( L->L, -1, element.c_str() );
+	int result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tointeger( L->L, -1 ) : defval;
+	lua_pop( L->L, 1 );
+	return result;
+}
+
+double lua::table_guard::get_double( const string& element, double defval /*= "" */ )
+{
+	lua_getfield( L->L, -1, element.c_str() );
+	double result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tonumber( L->L, -1 ) : defval;
+	lua_pop( L->L, 1 );
+	return result;
+}
+
+bool lua::table_guard::get_boolean( const string& element, bool defval /*= "" */ )
+{
+	lua_getfield( L->L, -1, element.c_str() );
+	bool result = lua_type( L->L, -1 ) == LUA_TBOOLEAN ? lua_toboolean( L->L, -1 ) != 0 : defval;
+	lua_pop( L->L, 1 );
+	return result;
+}
+
+void lua::state::log_stack()
+{
+	int top = lua_gettop(L);
+	NV_LOG( LOG_DEBUG, "Stack dump (" << top << ")");
+	for ( int i = 0; i < top; ++i )
+	{
+		NV_LOG( LOG_DEBUG, "#" << i+1 << " - " << lua_typename(L, i+1) << " = " << lua_typecontent(L, i+1) );
+	}
+}
+
+lua_State* lua::state::get_raw()
+{
+	return L;
+}
+
+
