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

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