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

Last change on this file since 78 was 78, checked in by epyon, 12 years ago
  • types.hh - basing totally on typeid now
  • types.hh - removed hash_string and name registration defines (get_type_name template)
  • types.hh - name is defined at registration via create_type
  • types.hh - overall the code is much cleaner now
File size: 8.4 KB
RevLine 
[9]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
[51]9#include "nv/lua/lua_raw.hh"
[9]10#include "nv/logging.hh"
11#include "nv/string.hh"
[77]12#include "nv/root.hh"
13#include "nv/types.hh"
[9]14
15using namespace nv;
16
17lua::stack_guard::stack_guard( lua::state* L )
18        : L(L), m_level( lua_gettop(L->L) )
19{
20
21}
22
23lua::stack_guard::~stack_guard()
24{
25        lua_settop( L->L, m_level );
26}
27
[74]28lua::state::state( bool load_libs /*= false*/ )
[9]29{
[74]30        load_lua_library();
[9]31        m_owner = true;
32        L = luaL_newstate( );
33
34        lua_pushcfunction(L, luaopen_base);
35        lua_pushliteral(L, LUA_TABLIBNAME);
36        lua_call(L, 1, 0);
37
[74]38        if ( load_libs )
[9]39        {
40                stack_guard guard( this );
[74]41                static const luaL_Reg lualibs[] =
42                {
43                        { "string", luaopen_string },
44                        { "table",  luaopen_table },
45                        { "math",   luaopen_math },
46                        { NULL, NULL}
47                };
48                const luaL_Reg *lib = lualibs;
49                for(; lib->func != NULL; lib++)
50                {
51                        lib->func( L );
52                }
[9]53        }
54
[74]55        NV_LOG( nv::LOG_TRACE, "Lua state created" );
[9]56}
57
58int lua::state::load_string( const std::string& code, const std::string& name )
59{
60        NV_LOG( nv::LOG_TRACE, "Loading Lua string '" << name << "'");
61        return luaL_loadbuffer( L, code.c_str(), code.length(), name.c_str() );
62}
63
64int lua::state::load_stream( std::istream& stream, const std::string& name )
65{
66        NV_LOG( nv::LOG_NOTICE, "Loading Lua stream '" << name << "'");
67        return load_string( std::string(
68                (std::istreambuf_iterator<char>(stream)),
69                std::istreambuf_iterator<char>()), name );
70}
71
72int lua::state::load_file( const std::string& filename )
73{
74        NV_LOG( nv::LOG_NOTICE, "Loading Lua file '" << filename << "'");
75        return luaL_loadfile( L, filename.c_str() );
76}
77
78bool lua::state::do_string( const std::string& code, const std::string& name )
79{
80        lua::stack_guard( this );
81        int result = load_string(code,name);
82        if (result)
83        {
84                NV_LOG( nv::LOG_WARNING, "Failed to load string " << name << ": " << lua_tostring(L, -1));
85                return false;
86        }
87        return do_current( name ) == 0;
88}
89
90bool lua::state::do_stream( std::istream& stream, const std::string& name )
91{
92        lua::stack_guard( this );
93        int result = load_stream(stream,name);
94        if (result)
95        {
96                NV_LOG( nv::LOG_WARNING, "Failed to open stream " << name << ": " << lua_tostring(L, -1));
97                return false;
98        }
99        return do_current( name ) == 0;
100}
101
102bool lua::state::do_file( const std::string& filename )
103{
104        lua::stack_guard( this );
105        int result = load_file(filename);
106        if (result)
107        {
108                NV_LOG( nv::LOG_WARNING, "Failed to open file " << filename << ": " << lua_tostring(L, -1));
109                return false;
110        }
111        return do_current( filename ) == 0;
112}
113
114int lua::state::do_current( const std::string& name )
115{
116        int result = lua_pcall(L, 0, 0, 0);
117        if (result)
118        {
119                NV_LOG( nv::LOG_WARNING, "Failed to run script " << name << ": " << lua_tostring(L, -1));
120                lua_pop( L, 1 );
121        }
122        return result;
123}
124
125lua::state::~state()
126{
127        if (m_owner)
128        {
129                lua_close( L );
130        }
131}
132
133bool lua::state::push( const std::string& path, bool global )
134{
135        size_t point = path.find('.');
136
137        if (point == std::string::npos)
138        {
139                if (global)
140                {
141                        lua_getglobal( L, path.c_str() );
142                }
143                else
144                {
145                        lua_getfield( L, -1, path.c_str() );
146                }
147                return !lua_isnil( L, -1 );
148        }
149
150        size_t idx = 0;
151        size_t start = 0;
152
153        while( point != std::string::npos )
154        {
155                if (idx == 0)
156                {
157                        if (global)
158                        {
159                                lua_getglobal( L, path.substr(start,point-start).c_str() );
160                        }
161                        else
162                        {
163                                lua_getfield( L, -1, path.substr(start,point-start).c_str() );
164                        }
165                }
166                else
167                {
168                        if ( lua_istable( L, -1 ) )
169                        {
170                                lua_pushstring( L, path.substr(start,point-start).c_str() );
171                                lua_gettable( L, -2 );
172                                lua_insert( L, -2 );
173                                lua_pop( L, 1 );
174                        }
175                        else
176                        {
177                                lua_pop(L, 1);
178                                lua_pushnil(L);
179                                return false;
180                        }
181                }
182                start = point+1;
183                point = path.find( '.', start );
184        }
185        return true;
186}
187
188
189int lua::state::get_stack_size()
190{
191        return lua_gettop( L );
192}
193
194lua::table_guard::table_guard( lua::state* lstate, const std::string& table, bool global )
195        : L(lstate), m_guard(lstate)
196{
197        L->push( table, global );
198}
199
200lua::table_guard::table_guard( lua::state* lstate, const std::string& table, int index, bool global )
201        : L(lstate), m_guard(lstate)
202{
203        L->push( table, global );
204        lua_rawgeti( L->L, -1, index );
205}
206
207lua::table_guard::table_guard( lua::state* lstate, const std::string& table, const std::string& index, bool global /*= true */ )
208        : L(lstate), m_guard(lstate)
209{
210        L->push( table, global );
211        lua_pushstring( L->L, index.c_str() );
212        lua_rawget( L->L, -2 );
213}
214
215lua::table_guard::table_guard( const table_guard& parent, const std::string& index )
216        : L( parent.L ), m_guard( parent.L )
217{
218        lua_getfield( L->L, -1, index.c_str() );
219}
220
221lua::table_guard::table_guard( const table_guard& parent, int index )
222        : L( parent.L ), m_guard( parent.L )
223{
224        lua_rawgeti( L->L, -1, index );
225}
226
227bool lua::table_guard::has_field( const string& element )
228{
229        lua_getfield( L->L, -1, element.c_str() );
230        bool result = lua_isnil( L->L, -1 );
231        lua_pop( L->L, 1 );
232        return result;
233}
234
235string lua::table_guard::get_string( const string& element, const string& defval /*= "" */ )
236{
237        lua_getfield( L->L, -1, element.c_str() );
238        string result( ( lua_type( L->L, -1 ) == LUA_TSTRING ) ? lua_tostring( L->L, -1 ) : defval );
239        lua_pop( L->L, 1 );
240        return result;
241}
242
243char lua::table_guard::get_char( const string& element, char defval /*= "" */ )
244{
245        lua_getfield( L->L, -1, element.c_str() );
246        char result = ( lua_type( L->L, -1 ) == LUA_TSTRING && lua_rawlen( L->L, -1 ) > 0 ) ? lua_tostring( L->L, -1 )[0] : defval;
247        lua_pop( L->L, 1 );
248        return result;
249}
250
251int lua::table_guard::get_integer( const string& element, int defval /*= "" */ )
252{
253        lua_getfield( L->L, -1, element.c_str() );
254        int result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tointeger( L->L, -1 ) : defval;
255        lua_pop( L->L, 1 );
256        return result;
257}
258
259double lua::table_guard::get_double( const string& element, double defval /*= "" */ )
260{
261        lua_getfield( L->L, -1, element.c_str() );
262        double result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tonumber( L->L, -1 ) : defval;
263        lua_pop( L->L, 1 );
264        return result;
265}
266
267bool lua::table_guard::get_boolean( const string& element, bool defval /*= "" */ )
268{
269        lua_getfield( L->L, -1, element.c_str() );
270        bool result = lua_type( L->L, -1 ) == LUA_TBOOLEAN ? lua_toboolean( L->L, -1 ) != 0 : defval;
271        lua_pop( L->L, 1 );
272        return result;
273}
274
275void lua::state::log_stack()
276{
277        int top = lua_gettop(L);
278        NV_LOG( LOG_DEBUG, "Stack dump (" << top << ")");
279        for ( int i = 0; i < top; ++i )
280        {
[74]281                NV_LOG( LOG_DEBUG, "#" << i+1 << " - " << lua_typename(L, lua_type(L, i+1) ) << " = " << nlua_typecontent(L, i+1) );
[9]282        }
283}
284
285lua_State* lua::state::get_raw()
286{
287        return L;
288}
289
[77]290lua::reference lua::state::register_object( object * o )
291{
292        if (!o) return ref_none;
293        type_database *db = o->get_root()->get_type_database();
294        if (!db) return ref_none;
295        type_entry* t = db->get_type(typeid(o));
296        if (!t) return ref_none;
297        stack_guard guard( this );
[78]298        lua_getglobal( L, t->name.c_str() );
[77]299        if ( lua_isnil( L, -1 ) )
300        {
[78]301                NV_THROW( runtime_error, std::string( t->name ) + " type not registered!" );
[77]302        }
303        deep_pointer_copy( -1, o );
304    return luaL_ref( L, LUA_REGISTRYINDEX );
305}
[9]306
[77]307void lua::state::unregister_object( object * o )
308{
309        if (!o) return;
310        stack_guard guard( this );
311        lua_rawgeti( L, LUA_REGISTRYINDEX, o->get_lua_index() );
312        lua_pushstring( L, "__ptr" );
313        lua_pushboolean( L, false );
314        lua_rawset( L, -3 );
315        lua_pop( L, 1 );
316        luaL_unref( L, LUA_REGISTRYINDEX, o->get_lua_index() );
317}
318
319void lua::state::deep_pointer_copy( int index, void* obj )
320{
321        index = lua_absindex( L, index );
322        lua_newtable( L );
323        lua_pushnil( L );
324        bool has_functions = false;
325        bool has_metatable = false;
326
327        while ( lua_next( L, index ) != 0 )
328        {
329                if ( lua_isfunction( L, -1 ) )
330                        has_functions = true;
331                else if ( lua_istable( L, -1 ) )
332                {
333                        deep_pointer_copy( -1, obj );
334                        lua_insert( L, -2 );
335                        lua_pop( L, 1 );
336                }
337                lua_pushvalue( L, -2 );
338                lua_insert( L, -2 );
339                lua_settable( L, -4 );
340        }
341
342        if ( lua_getmetatable( L, -2 ) )
343        {
344                lua_setmetatable( L, -2 );
345                has_metatable = true;
346        }
347
348        if ( has_functions || has_metatable )
349        {
350                lua_pushstring( L, "__ptr" );
351                lua_pushlightuserdata( L, obj );
352                lua_rawset( L, -3 );
353        }
354}
Note: See TracBrowser for help on using the repository browser.