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

Last change on this file since 74 was 74, checked in by epyon, 12 years ago
  • lua::state - removed notion of global state
  • lua_glm - fixed stack pollution at registration
  • lualib_test - made use of lua::state
File size: 6.8 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"
12
13using namespace nv;
14
15lua::stack_guard::stack_guard( lua::state* L )
16        : L(L), m_level( lua_gettop(L->L) )
17{
18
19}
20
21lua::stack_guard::~stack_guard()
22{
23        lua_settop( L->L, m_level );
24}
25
[74]26lua::state::state( bool load_libs /*= false*/ )
[9]27{
[74]28        load_lua_library();
[9]29        m_owner = true;
30        L = luaL_newstate( );
31
32        lua_pushcfunction(L, luaopen_base);
33        lua_pushliteral(L, LUA_TABLIBNAME);
34        lua_call(L, 1, 0);
35
[74]36        if ( load_libs )
[9]37        {
38                stack_guard guard( this );
[74]39                static const luaL_Reg lualibs[] =
40                {
41                        { "string", luaopen_string },
42                        { "table",  luaopen_table },
43                        { "math",   luaopen_math },
44                        { NULL, NULL}
45                };
46                const luaL_Reg *lib = lualibs;
47                for(; lib->func != NULL; lib++)
48                {
49                        lib->func( L );
50                }
[9]51        }
52
[74]53        NV_LOG( nv::LOG_TRACE, "Lua state created" );
[9]54}
55
56int lua::state::load_string( const std::string& code, const std::string& name )
57{
58        NV_LOG( nv::LOG_TRACE, "Loading Lua string '" << name << "'");
59        return luaL_loadbuffer( L, code.c_str(), code.length(), name.c_str() );
60}
61
62int lua::state::load_stream( std::istream& stream, const std::string& name )
63{
64        NV_LOG( nv::LOG_NOTICE, "Loading Lua stream '" << name << "'");
65        return load_string( std::string(
66                (std::istreambuf_iterator<char>(stream)),
67                std::istreambuf_iterator<char>()), name );
68}
69
70int lua::state::load_file( const std::string& filename )
71{
72        NV_LOG( nv::LOG_NOTICE, "Loading Lua file '" << filename << "'");
73        return luaL_loadfile( L, filename.c_str() );
74}
75
76bool lua::state::do_string( const std::string& code, const std::string& name )
77{
78        lua::stack_guard( this );
79        int result = load_string(code,name);
80        if (result)
81        {
82                NV_LOG( nv::LOG_WARNING, "Failed to load string " << name << ": " << lua_tostring(L, -1));
83                return false;
84        }
85        return do_current( name ) == 0;
86}
87
88bool lua::state::do_stream( std::istream& stream, const std::string& name )
89{
90        lua::stack_guard( this );
91        int result = load_stream(stream,name);
92        if (result)
93        {
94                NV_LOG( nv::LOG_WARNING, "Failed to open stream " << name << ": " << lua_tostring(L, -1));
95                return false;
96        }
97        return do_current( name ) == 0;
98}
99
100bool lua::state::do_file( const std::string& filename )
101{
102        lua::stack_guard( this );
103        int result = load_file(filename);
104        if (result)
105        {
106                NV_LOG( nv::LOG_WARNING, "Failed to open file " << filename << ": " << lua_tostring(L, -1));
107                return false;
108        }
109        return do_current( filename ) == 0;
110}
111
112int lua::state::do_current( const std::string& name )
113{
114        int result = lua_pcall(L, 0, 0, 0);
115        if (result)
116        {
117                NV_LOG( nv::LOG_WARNING, "Failed to run script " << name << ": " << lua_tostring(L, -1));
118                lua_pop( L, 1 );
119        }
120        return result;
121}
122
123lua::state::~state()
124{
125        if (m_owner)
126        {
127                lua_close( L );
128        }
129}
130
131bool lua::state::push( const std::string& path, bool global )
132{
133        size_t point = path.find('.');
134
135        if (point == std::string::npos)
136        {
137                if (global)
138                {
139                        lua_getglobal( L, path.c_str() );
140                }
141                else
142                {
143                        lua_getfield( L, -1, path.c_str() );
144                }
145                return !lua_isnil( L, -1 );
146        }
147
148        size_t idx = 0;
149        size_t start = 0;
150
151        while( point != std::string::npos )
152        {
153                if (idx == 0)
154                {
155                        if (global)
156                        {
157                                lua_getglobal( L, path.substr(start,point-start).c_str() );
158                        }
159                        else
160                        {
161                                lua_getfield( L, -1, path.substr(start,point-start).c_str() );
162                        }
163                }
164                else
165                {
166                        if ( lua_istable( L, -1 ) )
167                        {
168                                lua_pushstring( L, path.substr(start,point-start).c_str() );
169                                lua_gettable( L, -2 );
170                                lua_insert( L, -2 );
171                                lua_pop( L, 1 );
172                        }
173                        else
174                        {
175                                lua_pop(L, 1);
176                                lua_pushnil(L);
177                                return false;
178                        }
179                }
180                start = point+1;
181                point = path.find( '.', start );
182        }
183        return true;
184}
185
186
187int lua::state::get_stack_size()
188{
189        return lua_gettop( L );
190}
191
192lua::table_guard::table_guard( lua::state* lstate, const std::string& table, bool global )
193        : L(lstate), m_guard(lstate)
194{
195        L->push( table, global );
196}
197
198lua::table_guard::table_guard( lua::state* lstate, const std::string& table, int index, bool global )
199        : L(lstate), m_guard(lstate)
200{
201        L->push( table, global );
202        lua_rawgeti( L->L, -1, index );
203}
204
205lua::table_guard::table_guard( lua::state* lstate, const std::string& table, const std::string& index, bool global /*= true */ )
206        : L(lstate), m_guard(lstate)
207{
208        L->push( table, global );
209        lua_pushstring( L->L, index.c_str() );
210        lua_rawget( L->L, -2 );
211}
212
213lua::table_guard::table_guard( const table_guard& parent, const std::string& index )
214        : L( parent.L ), m_guard( parent.L )
215{
216        lua_getfield( L->L, -1, index.c_str() );
217}
218
219lua::table_guard::table_guard( const table_guard& parent, int index )
220        : L( parent.L ), m_guard( parent.L )
221{
222        lua_rawgeti( L->L, -1, index );
223}
224
225bool lua::table_guard::has_field( const string& element )
226{
227        lua_getfield( L->L, -1, element.c_str() );
228        bool result = lua_isnil( L->L, -1 );
229        lua_pop( L->L, 1 );
230        return result;
231}
232
233string lua::table_guard::get_string( const string& element, const string& defval /*= "" */ )
234{
235        lua_getfield( L->L, -1, element.c_str() );
236        string result( ( lua_type( L->L, -1 ) == LUA_TSTRING ) ? lua_tostring( L->L, -1 ) : defval );
237        lua_pop( L->L, 1 );
238        return result;
239}
240
241char lua::table_guard::get_char( const string& element, char defval /*= "" */ )
242{
243        lua_getfield( L->L, -1, element.c_str() );
244        char result = ( lua_type( L->L, -1 ) == LUA_TSTRING && lua_rawlen( L->L, -1 ) > 0 ) ? lua_tostring( L->L, -1 )[0] : defval;
245        lua_pop( L->L, 1 );
246        return result;
247}
248
249int lua::table_guard::get_integer( const string& element, int defval /*= "" */ )
250{
251        lua_getfield( L->L, -1, element.c_str() );
252        int result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tointeger( L->L, -1 ) : defval;
253        lua_pop( L->L, 1 );
254        return result;
255}
256
257double lua::table_guard::get_double( const string& element, double defval /*= "" */ )
258{
259        lua_getfield( L->L, -1, element.c_str() );
260        double result = lua_type( L->L, -1 ) == LUA_TNUMBER ? lua_tonumber( L->L, -1 ) : defval;
261        lua_pop( L->L, 1 );
262        return result;
263}
264
265bool lua::table_guard::get_boolean( const string& element, bool defval /*= "" */ )
266{
267        lua_getfield( L->L, -1, element.c_str() );
268        bool result = lua_type( L->L, -1 ) == LUA_TBOOLEAN ? lua_toboolean( L->L, -1 ) != 0 : defval;
269        lua_pop( L->L, 1 );
270        return result;
271}
272
273void lua::state::log_stack()
274{
275        int top = lua_gettop(L);
276        NV_LOG( LOG_DEBUG, "Stack dump (" << top << ")");
277        for ( int i = 0; i < top; ++i )
278        {
[74]279                NV_LOG( LOG_DEBUG, "#" << i+1 << " - " << lua_typename(L, lua_type(L, i+1) ) << " = " << nlua_typecontent(L, i+1) );
[9]280        }
281}
282
283lua_State* lua::state::get_raw()
284{
285        return L;
286}
287
288
Note: See TracBrowser for help on using the repository browser.