source: trunk/src/lua/lua_state.cc @ 9

Last change on this file since 9 was 9, checked in by epyon, 12 years ago
  • rudimentary lua support classes (lua::state, lua::table_guard, lua::stack_guard)
File size: 7.6 KB
Line 
1// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
6
7#include "nv/lua/lua_state.hh"
8
9#include "nv/lib/lua.hh"
10#include "nv/logging.hh"
11#include "nv/string.hh"
12
13using namespace nv;
14
15// The following should be moved to lua_raw
16
17std::string lua_typecontent( lua_State* L, int idx )
18{
19        switch ( lua_type( L, idx ) )
20        {
21        case LUA_TNONE          : return "NONE";
22        case LUA_TNIL               : return "NIL";
23        case LUA_TBOOLEAN               : return lua_toboolean( L, idx ) == 0 ? "false" : "true";
24        case LUA_TLIGHTUSERDATA : return nv::to_string( uint64( lua_touserdata( L, idx ) ) );
25        case LUA_TNUMBER                : return nv::to_string( lua_tonumber( L, idx ) );
26        case LUA_TSTRING                : return lua_tostring( L, idx );
27        case LUA_TTABLE             : return "TABLE";
28        case LUA_TFUNCTION              : return "FUNCTION";
29        case LUA_TUSERDATA              : return nv::to_string( uint64( lua_touserdata( L, idx ) ) );
30        case LUA_TTHREAD                : return "THREAD";
31        default : return "UNKNOWN!";
32        }
33}
34
35// -----
36
37lua::stack_guard::stack_guard( lua::state* L )
38        : L(L), m_level( lua_gettop(L->L) )
39{
40
41}
42
43lua::stack_guard::~stack_guard()
44{
45        lua_settop( L->L, m_level );
46}
47
48lua::state::state( bool is_main /*= false*/ )
49{
50        m_owner = true;
51        L = luaL_newstate( );
52
53        lua_pushcfunction(L, luaopen_base);
54        lua_pushliteral(L, LUA_TABLIBNAME);
55        lua_call(L, 1, 0);
56
57        if (is_main)
58        {
59                NV_ASSERT( this == get(), "lua_state : another main state created!" );
60                stack_guard guard( this );
61                luaopen_base( L );
62                luaopen_string( L );
63                luaopen_table( L );
64                luaopen_math( L );
65        }
66
67        NV_LOG( nv::LOG_TRACE, is_main ? "Main Lua state created" : "Secondary Lua state created");
68}
69
70int lua::state::load_string( const std::string& code, const std::string& name )
71{
72        NV_LOG( nv::LOG_TRACE, "Loading Lua string '" << name << "'");
73        return luaL_loadbuffer( L, code.c_str(), code.length(), name.c_str() );
74}
75
76int lua::state::load_stream( std::istream& stream, const std::string& name )
77{
78        NV_LOG( nv::LOG_NOTICE, "Loading Lua stream '" << name << "'");
79        return load_string( std::string(
80                (std::istreambuf_iterator<char>(stream)),
81                std::istreambuf_iterator<char>()), name );
82}
83
84int lua::state::load_file( const std::string& filename )
85{
86        NV_LOG( nv::LOG_NOTICE, "Loading Lua file '" << filename << "'");
87        return luaL_loadfile( L, filename.c_str() );
88}
89
90bool lua::state::do_string( const std::string& code, const std::string& name )
91{
92        lua::stack_guard( this );
93        int result = load_string(code,name);
94        if (result)
95        {
96                NV_LOG( nv::LOG_WARNING, "Failed to load string " << name << ": " << lua_tostring(L, -1));
97                return false;
98        }
99        return do_current( name ) == 0;
100}
101
102bool lua::state::do_stream( std::istream& stream, const std::string& name )
103{
104        lua::stack_guard( this );
105        int result = load_stream(stream,name);
106        if (result)
107        {
108                NV_LOG( nv::LOG_WARNING, "Failed to open stream " << name << ": " << lua_tostring(L, -1));
109                return false;
110        }
111        return do_current( name ) == 0;
112}
113
114bool lua::state::do_file( const std::string& filename )
115{
116        lua::stack_guard( this );
117        int result = load_file(filename);
118        if (result)
119        {
120                NV_LOG( nv::LOG_WARNING, "Failed to open file " << filename << ": " << lua_tostring(L, -1));
121                return false;
122        }
123        return do_current( filename ) == 0;
124}
125
126int lua::state::do_current( const std::string& name )
127{
128        int result = lua_pcall(L, 0, 0, 0);
129        if (result)
130        {
131                NV_LOG( nv::LOG_WARNING, "Failed to run script " << name << ": " << lua_tostring(L, -1));
132                lua_pop( L, 1 );
133        }
134        return result;
135}
136
137lua::state::~state()
138{
139        if (m_owner)
140        {
141                lua_close( L );
142        }
143}
144
145lua::state* lua::state::get()
146{
147        static lua::state main_state(true);
148        return &main_state;
149}
150
151bool lua::state::push( const std::string& path, bool global )
152{
153        size_t point = path.find('.');
154
155        if (point == std::string::npos)
156        {
157                if (global)
158                {
159                        lua_getglobal( L, path.c_str() );
160                }
161                else
162                {
163                        lua_getfield( L, -1, path.c_str() );
164                }
165                return !lua_isnil( L, -1 );
166        }
167
168        size_t idx = 0;
169        size_t start = 0;
170
171        while( point != std::string::npos )
172        {
173                if (idx == 0)
174                {
175                        if (global)
176                        {
177                                lua_getglobal( L, path.substr(start,point-start).c_str() );
178                        }
179                        else
180                        {
181                                lua_getfield( L, -1, path.substr(start,point-start).c_str() );
182                        }
183                }
184                else
185                {
186                        if ( lua_istable( L, -1 ) )
187                        {
188                                lua_pushstring( L, path.substr(start,point-start).c_str() );
189                                lua_gettable( L, -2 );
190                                lua_insert( L, -2 );
191                                lua_pop( L, 1 );
192                        }
193                        else
194                        {
195                                lua_pop(L, 1);
196                                lua_pushnil(L);
197                                return false;
198                        }
199                }
200                start = point+1;
201                point = path.find( '.', start );
202        }
203        return true;
204}
205
206
207int lua::state::get_stack_size()
208{
209        return lua_gettop( L );
210}
211
212lua::table_guard::table_guard( lua::state* lstate, const std::string& table, bool global )
213        : L(lstate), m_guard(lstate)
214{
215        L->push( table, global );
216}
217
218lua::table_guard::table_guard( lua::state* lstate, const std::string& table, int index, bool global )
219        : L(lstate), m_guard(lstate)
220{
221        L->push( table, global );
222        lua_rawgeti( L->L, -1, index );
223}
224
225lua::table_guard::table_guard( lua::state* lstate, const std::string& table, const std::string& index, bool global /*= true */ )
226        : L(lstate), m_guard(lstate)
227{
228        L->push( table, global );
229        lua_pushstring( L->L, index.c_str() );
230        lua_rawget( L->L, -2 );
231}
232
233lua::table_guard::table_guard( const table_guard& parent, const std::string& index )
234        : L( parent.L ), m_guard( parent.L )
235{
236        lua_getfield( L->L, -1, index.c_str() );
237}
238
239lua::table_guard::table_guard( const table_guard& parent, int index )
240        : L( parent.L ), m_guard( parent.L )
241{
242        lua_rawgeti( L->L, -1, index );
243}
244
245bool lua::table_guard::has_field( const string& element )
246{
247        lua_getfield( L->L, -1, element.c_str() );
248        bool result = lua_isnil( L->L, -1 );
249        lua_pop( L->L, 1 );
250        return result;
251}
252
253string lua::table_guard::get_string( const string& element, const string& defval /*= "" */ )
254{
255        lua_getfield( L->L, -1, element.c_str() );
256        string result( ( lua_type( L->L, -1 ) == LUA_TSTRING ) ? lua_tostring( L->L, -1 ) : defval );
257        lua_pop( L->L, 1 );
258        return result;
259}
260
261char lua::table_guard::get_char( const string& element, char defval /*= "" */ )
262{
263        lua_getfield( L->L, -1, element.c_str() );
264        char result = ( lua_type( L->L, -1 ) == LUA_TSTRING && lua_rawlen( L->L, -1 ) > 0 ) ? lua_tostring( L->L, -1 )[0] : defval;
265        lua_pop( L->L, 1 );
266        return result;
267}
268
269int lua::table_guard::get_integer( const string& element, int defval /*= "" */ )
270{
271        lua_getfield( L->L, -1, element.c_str() );
272        int result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tointeger( L->L, -1 ) : defval;
273        lua_pop( L->L, 1 );
274        return result;
275}
276
277double lua::table_guard::get_double( const string& element, double defval /*= "" */ )
278{
279        lua_getfield( L->L, -1, element.c_str() );
280        double result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tonumber( L->L, -1 ) : defval;
281        lua_pop( L->L, 1 );
282        return result;
283}
284
285bool lua::table_guard::get_boolean( const string& element, bool defval /*= "" */ )
286{
287        lua_getfield( L->L, -1, element.c_str() );
288        bool result = lua_type( L->L, -1 ) == LUA_TBOOLEAN ? lua_toboolean( L->L, -1 ) != 0 : defval;
289        lua_pop( L->L, 1 );
290        return result;
291}
292
293void lua::state::log_stack()
294{
295        int top = lua_gettop(L);
296        NV_LOG( LOG_DEBUG, "Stack dump (" << top << ")");
297        for ( int i = 0; i < top; ++i )
298        {
299                NV_LOG( LOG_DEBUG, "#" << i+1 << " - " << lua_typename(L, i+1) << " = " << lua_typecontent(L, i+1) );
300        }
301}
302
303lua_State* lua::state::get_raw()
304{
305        return L;
306}
307
308
Note: See TracBrowser for help on using the repository browser.