xref: /src/contrib/lutok/state.cpp (revision c697fb7f7cc9bedc5beee44d35b771c4e87b335a)
14b2c3eb9SBrooks Davis // Copyright 2011 Google Inc.
24b2c3eb9SBrooks Davis // All rights reserved.
34b2c3eb9SBrooks Davis //
44b2c3eb9SBrooks Davis // Redistribution and use in source and binary forms, with or without
54b2c3eb9SBrooks Davis // modification, are permitted provided that the following conditions are
64b2c3eb9SBrooks Davis // met:
74b2c3eb9SBrooks Davis //
84b2c3eb9SBrooks Davis // * Redistributions of source code must retain the above copyright
94b2c3eb9SBrooks Davis //   notice, this list of conditions and the following disclaimer.
104b2c3eb9SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
114b2c3eb9SBrooks Davis //   notice, this list of conditions and the following disclaimer in the
124b2c3eb9SBrooks Davis //   documentation and/or other materials provided with the distribution.
134b2c3eb9SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
144b2c3eb9SBrooks Davis //   may be used to endorse or promote products derived from this software
154b2c3eb9SBrooks Davis //   without specific prior written permission.
164b2c3eb9SBrooks Davis //
174b2c3eb9SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
184b2c3eb9SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
194b2c3eb9SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
204b2c3eb9SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
214b2c3eb9SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
224b2c3eb9SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
234b2c3eb9SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
244b2c3eb9SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
254b2c3eb9SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
264b2c3eb9SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
274b2c3eb9SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
284b2c3eb9SBrooks Davis 
294b2c3eb9SBrooks Davis extern "C" {
304b2c3eb9SBrooks Davis #include <unistd.h>
314b2c3eb9SBrooks Davis }
324b2c3eb9SBrooks Davis 
334b2c3eb9SBrooks Davis #include <cassert>
344b2c3eb9SBrooks Davis #include <cstring>
354b2c3eb9SBrooks Davis 
364b2c3eb9SBrooks Davis #include "c_gate.hpp"
374b2c3eb9SBrooks Davis #include "exceptions.hpp"
384b2c3eb9SBrooks Davis #include "state.ipp"
394b2c3eb9SBrooks Davis 
404b2c3eb9SBrooks Davis 
414b2c3eb9SBrooks Davis namespace {
424b2c3eb9SBrooks Davis 
434b2c3eb9SBrooks Davis 
444b2c3eb9SBrooks Davis /// Wrapper around lua_getglobal to run in a protected environment.
454b2c3eb9SBrooks Davis ///
464b2c3eb9SBrooks Davis /// \pre stack(-1) is the name of the global to get.
474b2c3eb9SBrooks Davis /// \post stack(-1) is the value of the global.
484b2c3eb9SBrooks Davis ///
494b2c3eb9SBrooks Davis /// \param state The Lua C API state.
504b2c3eb9SBrooks Davis ///
514b2c3eb9SBrooks Davis /// \return The number of return values pushed onto the stack.
524b2c3eb9SBrooks Davis static int
protected_getglobal(lua_State * state)534b2c3eb9SBrooks Davis protected_getglobal(lua_State* state)
544b2c3eb9SBrooks Davis {
554b2c3eb9SBrooks Davis     lua_getglobal(state, lua_tostring(state, -1));
564b2c3eb9SBrooks Davis     return 1;
574b2c3eb9SBrooks Davis }
584b2c3eb9SBrooks Davis 
594b2c3eb9SBrooks Davis 
604b2c3eb9SBrooks Davis /// Wrapper around lua_gettable to run in a protected environment.
614b2c3eb9SBrooks Davis ///
624b2c3eb9SBrooks Davis /// \pre stack(-2) is the table to get the element from.
634b2c3eb9SBrooks Davis /// \pre stack(-1) is the table index.
644b2c3eb9SBrooks Davis /// \post stack(-1) is the value of stack(-2)[stack(-1)].
654b2c3eb9SBrooks Davis ///
664b2c3eb9SBrooks Davis /// \param state The Lua C API state.
674b2c3eb9SBrooks Davis ///
684b2c3eb9SBrooks Davis /// \return The number of return values pushed onto the stack.
694b2c3eb9SBrooks Davis static int
protected_gettable(lua_State * state)704b2c3eb9SBrooks Davis protected_gettable(lua_State* state)
714b2c3eb9SBrooks Davis {
724b2c3eb9SBrooks Davis     lua_gettable(state, -2);
734b2c3eb9SBrooks Davis     return 1;
744b2c3eb9SBrooks Davis }
754b2c3eb9SBrooks Davis 
764b2c3eb9SBrooks Davis 
774b2c3eb9SBrooks Davis /// Wrapper around lua_next to run in a protected environment.
784b2c3eb9SBrooks Davis ///
794b2c3eb9SBrooks Davis /// \pre stack(-2) is the table to get the next element from.
804b2c3eb9SBrooks Davis /// \pre stack(-1) is the last processed key.
814b2c3eb9SBrooks Davis /// \post stack(-1) is the value of next(stack(-2), stack(-1)).
824b2c3eb9SBrooks Davis ///
834b2c3eb9SBrooks Davis /// \param state The Lua C API state.
844b2c3eb9SBrooks Davis ///
854b2c3eb9SBrooks Davis /// \return The number of return values pushed onto the stack.
864b2c3eb9SBrooks Davis static int
protected_next(lua_State * state)874b2c3eb9SBrooks Davis protected_next(lua_State* state)
884b2c3eb9SBrooks Davis {
894b2c3eb9SBrooks Davis     const int more = lua_next(state, -2) != 0;
904b2c3eb9SBrooks Davis     lua_pushboolean(state, more);
914b2c3eb9SBrooks Davis     return more ? 3 : 1;
924b2c3eb9SBrooks Davis }
934b2c3eb9SBrooks Davis 
944b2c3eb9SBrooks Davis 
954b2c3eb9SBrooks Davis /// Wrapper around lua_setglobal to run in a protected environment.
964b2c3eb9SBrooks Davis ///
974b2c3eb9SBrooks Davis /// \pre stack(-2) is the name of the global to set.
984b2c3eb9SBrooks Davis /// \pre stack(-1) is the value to set the global to.
994b2c3eb9SBrooks Davis ///
1004b2c3eb9SBrooks Davis /// \param state The Lua C API state.
1014b2c3eb9SBrooks Davis ///
1024b2c3eb9SBrooks Davis /// \return The number of return values pushed onto the stack.
1034b2c3eb9SBrooks Davis static int
protected_setglobal(lua_State * state)1044b2c3eb9SBrooks Davis protected_setglobal(lua_State* state)
1054b2c3eb9SBrooks Davis {
1064b2c3eb9SBrooks Davis     lua_setglobal(state, lua_tostring(state, -2));
1074b2c3eb9SBrooks Davis     return 0;
1084b2c3eb9SBrooks Davis }
1094b2c3eb9SBrooks Davis 
1104b2c3eb9SBrooks Davis 
1114b2c3eb9SBrooks Davis /// Wrapper around lua_settable to run in a protected environment.
1124b2c3eb9SBrooks Davis ///
1134b2c3eb9SBrooks Davis /// \pre stack(-3) is the table to set the element into.
1144b2c3eb9SBrooks Davis /// \pre stack(-2) is the table index.
1154b2c3eb9SBrooks Davis /// \pre stack(-1) is the value to set.
1164b2c3eb9SBrooks Davis ///
1174b2c3eb9SBrooks Davis /// \param state The Lua C API state.
1184b2c3eb9SBrooks Davis ///
1194b2c3eb9SBrooks Davis /// \return The number of return values pushed onto the stack.
1204b2c3eb9SBrooks Davis static int
protected_settable(lua_State * state)1214b2c3eb9SBrooks Davis protected_settable(lua_State* state)
1224b2c3eb9SBrooks Davis {
1234b2c3eb9SBrooks Davis     lua_settable(state, -3);
1244b2c3eb9SBrooks Davis     return 0;
1254b2c3eb9SBrooks Davis }
1264b2c3eb9SBrooks Davis 
1274b2c3eb9SBrooks Davis 
1284b2c3eb9SBrooks Davis /// Calls a C++ Lua function from a C calling environment.
1294b2c3eb9SBrooks Davis ///
1304b2c3eb9SBrooks Davis /// Any errors reported by the C++ function are caught and reported to the
1314b2c3eb9SBrooks Davis /// caller as Lua errors.
1324b2c3eb9SBrooks Davis ///
1334b2c3eb9SBrooks Davis /// \param function The C++ function to call.
1344b2c3eb9SBrooks Davis /// \param raw_state The raw Lua state.
1354b2c3eb9SBrooks Davis ///
1364b2c3eb9SBrooks Davis /// \return The number of return values pushed onto the Lua stack by the
1374b2c3eb9SBrooks Davis /// function.
1384b2c3eb9SBrooks Davis static int
call_cxx_function_from_c(lutok::cxx_function function,lua_State * raw_state)1394b2c3eb9SBrooks Davis call_cxx_function_from_c(lutok::cxx_function function,
1404b2c3eb9SBrooks Davis                          lua_State* raw_state) throw()
1414b2c3eb9SBrooks Davis {
1424b2c3eb9SBrooks Davis     char error_buf[1024];
1434b2c3eb9SBrooks Davis 
1444b2c3eb9SBrooks Davis     try {
1454b2c3eb9SBrooks Davis         lutok::state state = lutok::state_c_gate::connect(raw_state);
1464b2c3eb9SBrooks Davis         return function(state);
1474b2c3eb9SBrooks Davis     } catch (const std::exception& e) {
1484b2c3eb9SBrooks Davis         std::strncpy(error_buf, e.what(), sizeof(error_buf));
1494b2c3eb9SBrooks Davis     } catch (...) {
1504b2c3eb9SBrooks Davis         std::strncpy(error_buf, "Unhandled exception in Lua C++ hook",
1514b2c3eb9SBrooks Davis                      sizeof(error_buf));
1524b2c3eb9SBrooks Davis     }
1534b2c3eb9SBrooks Davis     error_buf[sizeof(error_buf) - 1] = '\0';
1544b2c3eb9SBrooks Davis     // We raise the Lua error from outside the try/catch context and we use
1554b2c3eb9SBrooks Davis     // a stack-based buffer to hold the message to ensure that we do not leak
1564b2c3eb9SBrooks Davis     // any C++ objects (and, as a likely result, memory) when Lua performs its
1574b2c3eb9SBrooks Davis     // longjmp.
1584b2c3eb9SBrooks Davis     return luaL_error(raw_state, "%s", error_buf);
1594b2c3eb9SBrooks Davis }
1604b2c3eb9SBrooks Davis 
1614b2c3eb9SBrooks Davis 
1624b2c3eb9SBrooks Davis /// Lua glue to call a C++ closure.
1634b2c3eb9SBrooks Davis ///
1644b2c3eb9SBrooks Davis /// This Lua binding is actually a closure that we have constructed from the
1654b2c3eb9SBrooks Davis /// state.push_cxx_closure() method.  The closure contains the same upvalues
1664b2c3eb9SBrooks Davis /// provided by the user plus an extra upvalue that contains the address of the
1674b2c3eb9SBrooks Davis /// C++ function we have to call.  All we do here is safely delegate the
1684b2c3eb9SBrooks Davis /// execution to the wrapped C++ closure.
1694b2c3eb9SBrooks Davis ///
1704b2c3eb9SBrooks Davis /// \param raw_state The Lua C API state.
1714b2c3eb9SBrooks Davis ///
1724b2c3eb9SBrooks Davis /// \return The number of return values of the called closure.
1734b2c3eb9SBrooks Davis static int
cxx_closure_trampoline(lua_State * raw_state)1744b2c3eb9SBrooks Davis cxx_closure_trampoline(lua_State* raw_state)
1754b2c3eb9SBrooks Davis {
1764b2c3eb9SBrooks Davis     lutok::state state = lutok::state_c_gate::connect(raw_state);
1774b2c3eb9SBrooks Davis 
1784b2c3eb9SBrooks Davis     int nupvalues;
1794b2c3eb9SBrooks Davis     {
1804b2c3eb9SBrooks Davis         lua_Debug debug;
1814b2c3eb9SBrooks Davis         lua_getstack(raw_state, 0, &debug);
1824b2c3eb9SBrooks Davis         lua_getinfo(raw_state, "u", &debug);
1834b2c3eb9SBrooks Davis         nupvalues = debug.nups;
1844b2c3eb9SBrooks Davis     }
1854b2c3eb9SBrooks Davis 
1864b2c3eb9SBrooks Davis     lutok::cxx_function* function = state.to_userdata< lutok::cxx_function >(
1874b2c3eb9SBrooks Davis         state.upvalue_index(nupvalues));
1884b2c3eb9SBrooks Davis     return call_cxx_function_from_c(*function, raw_state);
1894b2c3eb9SBrooks Davis }
1904b2c3eb9SBrooks Davis 
1914b2c3eb9SBrooks Davis 
1924b2c3eb9SBrooks Davis /// Lua glue to call a C++ function.
1934b2c3eb9SBrooks Davis ///
1944b2c3eb9SBrooks Davis /// This Lua binding is actually a closure that we have constructed from the
1954b2c3eb9SBrooks Davis /// state.push_cxx_function() method.  The closure has a single upvalue that
1964b2c3eb9SBrooks Davis /// contains the address of the C++ function we have to call.  All we do here is
1974b2c3eb9SBrooks Davis /// safely delegate the execution to the wrapped C++ function.
1984b2c3eb9SBrooks Davis ///
1994b2c3eb9SBrooks Davis /// \param raw_state The Lua C API state.
2004b2c3eb9SBrooks Davis ///
2014b2c3eb9SBrooks Davis /// \return The number of return values of the called function.
2024b2c3eb9SBrooks Davis static int
cxx_function_trampoline(lua_State * raw_state)2034b2c3eb9SBrooks Davis cxx_function_trampoline(lua_State* raw_state)
2044b2c3eb9SBrooks Davis {
2054b2c3eb9SBrooks Davis     lutok::state state = lutok::state_c_gate::connect(raw_state);
2064b2c3eb9SBrooks Davis     lutok::cxx_function* function = state.to_userdata< lutok::cxx_function >(
2074b2c3eb9SBrooks Davis         state.upvalue_index(1));
2084b2c3eb9SBrooks Davis     return call_cxx_function_from_c(*function, raw_state);
2094b2c3eb9SBrooks Davis }
2104b2c3eb9SBrooks Davis 
2114b2c3eb9SBrooks Davis 
2124b2c3eb9SBrooks Davis }  // anonymous namespace
2134b2c3eb9SBrooks Davis 
2144b2c3eb9SBrooks Davis 
2154b2c3eb9SBrooks Davis const int lutok::registry_index = LUA_REGISTRYINDEX;
2164b2c3eb9SBrooks Davis 
2174b2c3eb9SBrooks Davis 
2184b2c3eb9SBrooks Davis /// Internal implementation for lutok::state.
2194b2c3eb9SBrooks Davis struct lutok::state::impl {
2204b2c3eb9SBrooks Davis     /// The Lua internal state.
2214b2c3eb9SBrooks Davis     lua_State* lua_state;
2224b2c3eb9SBrooks Davis 
2234b2c3eb9SBrooks Davis     /// Whether we own the state or not (to decide if we close it).
2244b2c3eb9SBrooks Davis     bool owned;
2254b2c3eb9SBrooks Davis 
2264b2c3eb9SBrooks Davis     /// Constructor.
2274b2c3eb9SBrooks Davis     ///
2284b2c3eb9SBrooks Davis     /// \param lua_ The Lua internal state.
2294b2c3eb9SBrooks Davis     /// \param owned_ Whether we own the state or not.
impllutok::state::impl2304b2c3eb9SBrooks Davis     impl(lua_State* lua_, bool owned_) :
2314b2c3eb9SBrooks Davis         lua_state(lua_),
2324b2c3eb9SBrooks Davis         owned(owned_)
2334b2c3eb9SBrooks Davis     {
2344b2c3eb9SBrooks Davis     }
2354b2c3eb9SBrooks Davis };
2364b2c3eb9SBrooks Davis 
2374b2c3eb9SBrooks Davis 
2384b2c3eb9SBrooks Davis /// Initializes the Lua state.
2394b2c3eb9SBrooks Davis ///
2404b2c3eb9SBrooks Davis /// You must share the same state object alongside the lifetime of your Lua
2414b2c3eb9SBrooks Davis /// session.  As soon as the object is destroyed, the session is terminated.
state(void)2424b2c3eb9SBrooks Davis lutok::state::state(void)
2434b2c3eb9SBrooks Davis {
2444b2c3eb9SBrooks Davis     lua_State* lua = luaL_newstate();
2454b2c3eb9SBrooks Davis     if (lua == NULL)
2464b2c3eb9SBrooks Davis         throw lutok::error("lua open failed");
2474b2c3eb9SBrooks Davis     _pimpl.reset(new impl(lua, true));
2484b2c3eb9SBrooks Davis }
2494b2c3eb9SBrooks Davis 
2504b2c3eb9SBrooks Davis 
2514b2c3eb9SBrooks Davis /// Initializes the Lua state from an existing raw state.
2524b2c3eb9SBrooks Davis ///
2534b2c3eb9SBrooks Davis /// Instances constructed using this method do NOT own the raw state.  This
2544b2c3eb9SBrooks Davis /// means that, on exit, the state will not be destroyed.
2554b2c3eb9SBrooks Davis ///
2564b2c3eb9SBrooks Davis /// \param raw_state_ The raw Lua state to wrap.
state(void * raw_state_)2574b2c3eb9SBrooks Davis lutok::state::state(void* raw_state_) :
2584b2c3eb9SBrooks Davis     _pimpl(new impl(reinterpret_cast< lua_State* >(raw_state_), false))
2594b2c3eb9SBrooks Davis {
2604b2c3eb9SBrooks Davis }
2614b2c3eb9SBrooks Davis 
2624b2c3eb9SBrooks Davis 
2634b2c3eb9SBrooks Davis /// Destructor for the Lua state.
2644b2c3eb9SBrooks Davis ///
2654b2c3eb9SBrooks Davis /// Closes the session unless it has already been closed by calling the
2664b2c3eb9SBrooks Davis /// close() method.  It is recommended to explicitly close the session in the
2674b2c3eb9SBrooks Davis /// code.
~state(void)2684b2c3eb9SBrooks Davis lutok::state::~state(void)
2694b2c3eb9SBrooks Davis {
2704b2c3eb9SBrooks Davis     if (_pimpl->owned && _pimpl->lua_state != NULL)
2714b2c3eb9SBrooks Davis         close();
2724b2c3eb9SBrooks Davis }
2734b2c3eb9SBrooks Davis 
2744b2c3eb9SBrooks Davis 
2754b2c3eb9SBrooks Davis /// Terminates this Lua session.
2764b2c3eb9SBrooks Davis ///
2774b2c3eb9SBrooks Davis /// It is recommended to call this instead of relying on the destructor to do
2784b2c3eb9SBrooks Davis /// the cleanup, but it is not a requirement to use close().
2794b2c3eb9SBrooks Davis ///
2804b2c3eb9SBrooks Davis /// \pre close() has not yet been called.
2814b2c3eb9SBrooks Davis /// \pre The Lua stack is empty.  This is not truly necessary but ensures that
2824b2c3eb9SBrooks Davis ///     our code is consistent and clears the stack explicitly.
2834b2c3eb9SBrooks Davis void
close(void)2844b2c3eb9SBrooks Davis lutok::state::close(void)
2854b2c3eb9SBrooks Davis {
2864b2c3eb9SBrooks Davis     assert(_pimpl->lua_state != NULL);
2874b2c3eb9SBrooks Davis     assert(lua_gettop(_pimpl->lua_state) == 0);
2884b2c3eb9SBrooks Davis     lua_close(_pimpl->lua_state);
2894b2c3eb9SBrooks Davis     _pimpl->lua_state = NULL;
2904b2c3eb9SBrooks Davis }
2914b2c3eb9SBrooks Davis 
2924b2c3eb9SBrooks Davis 
2934b2c3eb9SBrooks Davis /// Wrapper around lua_getglobal.
2944b2c3eb9SBrooks Davis ///
2954b2c3eb9SBrooks Davis /// \param name The second parameter to lua_getglobal.
2964b2c3eb9SBrooks Davis ///
2974b2c3eb9SBrooks Davis /// \throw api_error If lua_getglobal fails.
2984b2c3eb9SBrooks Davis ///
2994b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory to manipulate
3004b2c3eb9SBrooks Davis /// the Lua stack.
3014b2c3eb9SBrooks Davis void
get_global(const std::string & name)3024b2c3eb9SBrooks Davis lutok::state::get_global(const std::string& name)
3034b2c3eb9SBrooks Davis {
3044b2c3eb9SBrooks Davis     lua_pushcfunction(_pimpl->lua_state, protected_getglobal);
3054b2c3eb9SBrooks Davis     lua_pushstring(_pimpl->lua_state, name.c_str());
3064b2c3eb9SBrooks Davis     if (lua_pcall(_pimpl->lua_state, 1, 1, 0) != 0)
3074b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "lua_getglobal");
3084b2c3eb9SBrooks Davis }
3094b2c3eb9SBrooks Davis 
3104b2c3eb9SBrooks Davis 
3114b2c3eb9SBrooks Davis /// Pushes a reference to the global table onto the stack.
3124b2c3eb9SBrooks Davis ///
3134b2c3eb9SBrooks Davis /// This is a wrapper around the incompatible differences between Lua 5.1 and
3144b2c3eb9SBrooks Davis /// 5.2 to access to the globals table.
3154b2c3eb9SBrooks Davis ///
3164b2c3eb9SBrooks Davis /// \post state(-1) Contains the reference to the globals table.
3174b2c3eb9SBrooks Davis void
get_global_table(void)3184b2c3eb9SBrooks Davis lutok::state::get_global_table(void)
3194b2c3eb9SBrooks Davis {
3204b2c3eb9SBrooks Davis #if LUA_VERSION_NUM >= 502
3214b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, registry_index);
3224b2c3eb9SBrooks Davis     lua_pushinteger(_pimpl->lua_state, LUA_RIDX_GLOBALS);
3234b2c3eb9SBrooks Davis     lua_gettable(_pimpl->lua_state, -2);
3244b2c3eb9SBrooks Davis     lua_remove(_pimpl->lua_state, -2);
3254b2c3eb9SBrooks Davis #else
3264b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, LUA_GLOBALSINDEX);
3274b2c3eb9SBrooks Davis #endif
3284b2c3eb9SBrooks Davis }
3294b2c3eb9SBrooks Davis 
3304b2c3eb9SBrooks Davis 
3314b2c3eb9SBrooks Davis /// Wrapper around luaL_getmetafield.
3324b2c3eb9SBrooks Davis ///
3334b2c3eb9SBrooks Davis /// \param index The second parameter to luaL_getmetafield.
3344b2c3eb9SBrooks Davis /// \param name The third parameter to luaL_getmetafield.
3354b2c3eb9SBrooks Davis ///
3364b2c3eb9SBrooks Davis /// \return The return value of luaL_getmetafield.
3374b2c3eb9SBrooks Davis ///
3384b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory to manipulate
3394b2c3eb9SBrooks Davis /// the Lua stack.
3404b2c3eb9SBrooks Davis bool
get_metafield(const int index,const std::string & name)3414b2c3eb9SBrooks Davis lutok::state::get_metafield(const int index, const std::string& name)
3424b2c3eb9SBrooks Davis {
3434b2c3eb9SBrooks Davis     return luaL_getmetafield(_pimpl->lua_state, index, name.c_str()) != 0;
3444b2c3eb9SBrooks Davis }
3454b2c3eb9SBrooks Davis 
3464b2c3eb9SBrooks Davis 
3474b2c3eb9SBrooks Davis /// Wrapper around lua_getmetatable.
3484b2c3eb9SBrooks Davis ///
3494b2c3eb9SBrooks Davis /// \param index The second parameter to lua_getmetatable.
3504b2c3eb9SBrooks Davis ///
3514b2c3eb9SBrooks Davis /// \return The return value of lua_getmetatable.
3524b2c3eb9SBrooks Davis bool
get_metatable(const int index)3534b2c3eb9SBrooks Davis lutok::state::get_metatable(const int index)
3544b2c3eb9SBrooks Davis {
3554b2c3eb9SBrooks Davis     return lua_getmetatable(_pimpl->lua_state, index) != 0;
3564b2c3eb9SBrooks Davis }
3574b2c3eb9SBrooks Davis 
3584b2c3eb9SBrooks Davis 
3594b2c3eb9SBrooks Davis /// Wrapper around lua_gettable.
3604b2c3eb9SBrooks Davis ///
3614b2c3eb9SBrooks Davis /// \param index The second parameter to lua_gettable.
3624b2c3eb9SBrooks Davis ///
3634b2c3eb9SBrooks Davis /// \throw api_error If lua_gettable fails.
3644b2c3eb9SBrooks Davis ///
3654b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory to manipulate
3664b2c3eb9SBrooks Davis /// the Lua stack.
3674b2c3eb9SBrooks Davis void
get_table(const int index)3684b2c3eb9SBrooks Davis lutok::state::get_table(const int index)
3694b2c3eb9SBrooks Davis {
3704b2c3eb9SBrooks Davis     assert(lua_gettop(_pimpl->lua_state) >= 2);
3714b2c3eb9SBrooks Davis     lua_pushcfunction(_pimpl->lua_state, protected_gettable);
3724b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index);
3734b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, -3);
3744b2c3eb9SBrooks Davis     if (lua_pcall(_pimpl->lua_state, 2, 1, 0) != 0)
3754b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "lua_gettable");
3764b2c3eb9SBrooks Davis     lua_remove(_pimpl->lua_state, -2);
3774b2c3eb9SBrooks Davis }
3784b2c3eb9SBrooks Davis 
3794b2c3eb9SBrooks Davis 
3804b2c3eb9SBrooks Davis /// Wrapper around lua_gettop.
3814b2c3eb9SBrooks Davis ///
3824b2c3eb9SBrooks Davis /// \return The return value of lua_gettop.
3834b2c3eb9SBrooks Davis int
get_top(void)3844b2c3eb9SBrooks Davis lutok::state::get_top(void)
3854b2c3eb9SBrooks Davis {
3864b2c3eb9SBrooks Davis     return lua_gettop(_pimpl->lua_state);
3874b2c3eb9SBrooks Davis }
3884b2c3eb9SBrooks Davis 
3894b2c3eb9SBrooks Davis 
3904b2c3eb9SBrooks Davis /// Wrapper around lua_insert.
3914b2c3eb9SBrooks Davis ///
3924b2c3eb9SBrooks Davis /// \param index The second parameter to lua_insert.
3934b2c3eb9SBrooks Davis void
insert(const int index)3944b2c3eb9SBrooks Davis lutok::state::insert(const int index)
3954b2c3eb9SBrooks Davis {
3964b2c3eb9SBrooks Davis     lua_insert(_pimpl->lua_state, index);
3974b2c3eb9SBrooks Davis }
3984b2c3eb9SBrooks Davis 
3994b2c3eb9SBrooks Davis 
4004b2c3eb9SBrooks Davis /// Wrapper around lua_isboolean.
4014b2c3eb9SBrooks Davis ///
4024b2c3eb9SBrooks Davis /// \param index The second parameter to lua_isboolean.
4034b2c3eb9SBrooks Davis ///
4044b2c3eb9SBrooks Davis /// \return The return value of lua_isboolean.
4054b2c3eb9SBrooks Davis bool
is_boolean(const int index)4064b2c3eb9SBrooks Davis lutok::state::is_boolean(const int index)
4074b2c3eb9SBrooks Davis {
4084b2c3eb9SBrooks Davis     return lua_isboolean(_pimpl->lua_state, index);
4094b2c3eb9SBrooks Davis }
4104b2c3eb9SBrooks Davis 
4114b2c3eb9SBrooks Davis 
4124b2c3eb9SBrooks Davis /// Wrapper around lua_isfunction.
4134b2c3eb9SBrooks Davis ///
4144b2c3eb9SBrooks Davis /// \param index The second parameter to lua_isfunction.
4154b2c3eb9SBrooks Davis ///
4164b2c3eb9SBrooks Davis /// \return The return value of lua_isfunction.
4174b2c3eb9SBrooks Davis bool
is_function(const int index)4184b2c3eb9SBrooks Davis lutok::state::is_function(const int index)
4194b2c3eb9SBrooks Davis {
4204b2c3eb9SBrooks Davis     return lua_isfunction(_pimpl->lua_state, index);
4214b2c3eb9SBrooks Davis }
4224b2c3eb9SBrooks Davis 
4234b2c3eb9SBrooks Davis 
4244b2c3eb9SBrooks Davis /// Wrapper around lua_isnil.
4254b2c3eb9SBrooks Davis ///
4264b2c3eb9SBrooks Davis /// \param index The second parameter to lua_isnil.
4274b2c3eb9SBrooks Davis ///
4284b2c3eb9SBrooks Davis /// \return The return value of lua_isnil.
4294b2c3eb9SBrooks Davis bool
is_nil(const int index)4304b2c3eb9SBrooks Davis lutok::state::is_nil(const int index)
4314b2c3eb9SBrooks Davis {
4324b2c3eb9SBrooks Davis     return lua_isnil(_pimpl->lua_state, index);
4334b2c3eb9SBrooks Davis }
4344b2c3eb9SBrooks Davis 
4354b2c3eb9SBrooks Davis 
4364b2c3eb9SBrooks Davis /// Wrapper around lua_isnumber.
4374b2c3eb9SBrooks Davis ///
4384b2c3eb9SBrooks Davis /// \param index The second parameter to lua_isnumber.
4394b2c3eb9SBrooks Davis ///
4404b2c3eb9SBrooks Davis /// \return The return value of lua_isnumber.
4414b2c3eb9SBrooks Davis bool
is_number(const int index)4424b2c3eb9SBrooks Davis lutok::state::is_number(const int index)
4434b2c3eb9SBrooks Davis {
4444b2c3eb9SBrooks Davis     return lua_isnumber(_pimpl->lua_state, index);
4454b2c3eb9SBrooks Davis }
4464b2c3eb9SBrooks Davis 
4474b2c3eb9SBrooks Davis 
4484b2c3eb9SBrooks Davis /// Wrapper around lua_isstring.
4494b2c3eb9SBrooks Davis ///
4504b2c3eb9SBrooks Davis /// \param index The second parameter to lua_isstring.
4514b2c3eb9SBrooks Davis ///
4524b2c3eb9SBrooks Davis /// \return The return value of lua_isstring.
4534b2c3eb9SBrooks Davis bool
is_string(const int index)4544b2c3eb9SBrooks Davis lutok::state::is_string(const int index)
4554b2c3eb9SBrooks Davis {
4564b2c3eb9SBrooks Davis     return lua_isstring(_pimpl->lua_state, index);
4574b2c3eb9SBrooks Davis }
4584b2c3eb9SBrooks Davis 
4594b2c3eb9SBrooks Davis 
4604b2c3eb9SBrooks Davis /// Wrapper around lua_istable.
4614b2c3eb9SBrooks Davis ///
4624b2c3eb9SBrooks Davis /// \param index The second parameter to lua_istable.
4634b2c3eb9SBrooks Davis ///
4644b2c3eb9SBrooks Davis /// \return The return value of lua_istable.
4654b2c3eb9SBrooks Davis bool
is_table(const int index)4664b2c3eb9SBrooks Davis lutok::state::is_table(const int index)
4674b2c3eb9SBrooks Davis {
4684b2c3eb9SBrooks Davis     return lua_istable(_pimpl->lua_state, index);
4694b2c3eb9SBrooks Davis }
4704b2c3eb9SBrooks Davis 
4714b2c3eb9SBrooks Davis 
4724b2c3eb9SBrooks Davis /// Wrapper around lua_isuserdata.
4734b2c3eb9SBrooks Davis ///
4744b2c3eb9SBrooks Davis /// \param index The second parameter to lua_isuserdata.
4754b2c3eb9SBrooks Davis ///
4764b2c3eb9SBrooks Davis /// \return The return value of lua_isuserdata.
4774b2c3eb9SBrooks Davis bool
is_userdata(const int index)4784b2c3eb9SBrooks Davis lutok::state::is_userdata(const int index)
4794b2c3eb9SBrooks Davis {
4804b2c3eb9SBrooks Davis     return lua_isuserdata(_pimpl->lua_state, index);
4814b2c3eb9SBrooks Davis }
4824b2c3eb9SBrooks Davis 
4834b2c3eb9SBrooks Davis 
4844b2c3eb9SBrooks Davis /// Wrapper around luaL_loadfile.
4854b2c3eb9SBrooks Davis ///
4864b2c3eb9SBrooks Davis /// \param file The second parameter to luaL_loadfile.
4874b2c3eb9SBrooks Davis ///
4884b2c3eb9SBrooks Davis /// \throw api_error If luaL_loadfile returns an error.
4894b2c3eb9SBrooks Davis /// \throw file_not_found_error If the file cannot be accessed.
4904b2c3eb9SBrooks Davis ///
4914b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
4924b2c3eb9SBrooks Davis void
load_file(const std::string & file)4934b2c3eb9SBrooks Davis lutok::state::load_file(const std::string& file)
4944b2c3eb9SBrooks Davis {
4954b2c3eb9SBrooks Davis     if (::access(file.c_str(), R_OK) == -1)
4964b2c3eb9SBrooks Davis         throw lutok::file_not_found_error(file);
4974b2c3eb9SBrooks Davis     if (luaL_loadfile(_pimpl->lua_state, file.c_str()) != 0)
4984b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "luaL_loadfile");
4994b2c3eb9SBrooks Davis }
5004b2c3eb9SBrooks Davis 
5014b2c3eb9SBrooks Davis 
5024b2c3eb9SBrooks Davis /// Wrapper around luaL_loadstring.
5034b2c3eb9SBrooks Davis ///
5044b2c3eb9SBrooks Davis /// \param str The second parameter to luaL_loadstring.
5054b2c3eb9SBrooks Davis ///
5064b2c3eb9SBrooks Davis /// \throw api_error If luaL_loadstring returns an error.
5074b2c3eb9SBrooks Davis ///
5084b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
5094b2c3eb9SBrooks Davis void
load_string(const std::string & str)5104b2c3eb9SBrooks Davis lutok::state::load_string(const std::string& str)
5114b2c3eb9SBrooks Davis {
5124b2c3eb9SBrooks Davis     if (luaL_loadstring(_pimpl->lua_state, str.c_str()) != 0)
5134b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "luaL_loadstring");
5144b2c3eb9SBrooks Davis }
5154b2c3eb9SBrooks Davis 
5164b2c3eb9SBrooks Davis 
5174b2c3eb9SBrooks Davis /// Wrapper around lua_newtable.
5184b2c3eb9SBrooks Davis ///
5194b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
5204b2c3eb9SBrooks Davis void
new_table(void)5214b2c3eb9SBrooks Davis lutok::state::new_table(void)
5224b2c3eb9SBrooks Davis {
5234b2c3eb9SBrooks Davis     lua_newtable(_pimpl->lua_state);
5244b2c3eb9SBrooks Davis }
5254b2c3eb9SBrooks Davis 
5264b2c3eb9SBrooks Davis 
5274b2c3eb9SBrooks Davis /// Wrapper around lua_newuserdata.
5284b2c3eb9SBrooks Davis ///
5294b2c3eb9SBrooks Davis /// This is internal.  The public type-safe interface of this method should be
5304b2c3eb9SBrooks Davis /// used instead.
5314b2c3eb9SBrooks Davis ///
5324b2c3eb9SBrooks Davis /// \param size The second parameter to lua_newuserdata.
5334b2c3eb9SBrooks Davis ///
5344b2c3eb9SBrooks Davis /// \return The return value of lua_newuserdata.
5354b2c3eb9SBrooks Davis ///
5364b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
5374b2c3eb9SBrooks Davis void*
new_userdata_voidp(const size_t size)5384b2c3eb9SBrooks Davis lutok::state::new_userdata_voidp(const size_t size)
5394b2c3eb9SBrooks Davis {
5404b2c3eb9SBrooks Davis     return lua_newuserdata(_pimpl->lua_state, size);
5414b2c3eb9SBrooks Davis }
5424b2c3eb9SBrooks Davis 
5434b2c3eb9SBrooks Davis 
5444b2c3eb9SBrooks Davis /// Wrapper around lua_next.
5454b2c3eb9SBrooks Davis ///
5464b2c3eb9SBrooks Davis /// \param index The second parameter to lua_next.
5474b2c3eb9SBrooks Davis ///
5484b2c3eb9SBrooks Davis /// \return True if there are more elements to process; false otherwise.
5494b2c3eb9SBrooks Davis ///
5504b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
5514b2c3eb9SBrooks Davis bool
next(const int index)5524b2c3eb9SBrooks Davis lutok::state::next(const int index)
5534b2c3eb9SBrooks Davis {
5544b2c3eb9SBrooks Davis     assert(lua_istable(_pimpl->lua_state, index));
5554b2c3eb9SBrooks Davis     assert(lua_gettop(_pimpl->lua_state) >= 1);
5564b2c3eb9SBrooks Davis     lua_pushcfunction(_pimpl->lua_state, protected_next);
5574b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index);
5584b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, -3);
5594b2c3eb9SBrooks Davis     if (lua_pcall(_pimpl->lua_state, 2, LUA_MULTRET, 0) != 0)
5604b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "lua_next");
5614b2c3eb9SBrooks Davis     const bool more = lua_toboolean(_pimpl->lua_state, -1);
5624b2c3eb9SBrooks Davis     lua_pop(_pimpl->lua_state, 1);
5634b2c3eb9SBrooks Davis     if (more)
5644b2c3eb9SBrooks Davis         lua_remove(_pimpl->lua_state, -3);
5654b2c3eb9SBrooks Davis     else
5664b2c3eb9SBrooks Davis         lua_pop(_pimpl->lua_state, 1);
5674b2c3eb9SBrooks Davis     return more;
5684b2c3eb9SBrooks Davis }
5694b2c3eb9SBrooks Davis 
5704b2c3eb9SBrooks Davis 
5714b2c3eb9SBrooks Davis /// Wrapper around luaL_openlibs.
5724b2c3eb9SBrooks Davis ///
5734b2c3eb9SBrooks Davis /// \throw api_error If luaL_openlibs fails.
5744b2c3eb9SBrooks Davis ///
5754b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
5764b2c3eb9SBrooks Davis void
open_all(void)5774b2c3eb9SBrooks Davis lutok::state::open_all(void)
5784b2c3eb9SBrooks Davis {
5794b2c3eb9SBrooks Davis     luaL_openlibs(_pimpl->lua_state);
5804b2c3eb9SBrooks Davis }
5814b2c3eb9SBrooks Davis 
5824b2c3eb9SBrooks Davis 
5834b2c3eb9SBrooks Davis /// Wrapper around luaopen_base.
5844b2c3eb9SBrooks Davis ///
5854b2c3eb9SBrooks Davis /// \throw api_error If luaopen_base fails.
5864b2c3eb9SBrooks Davis ///
5874b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
5884b2c3eb9SBrooks Davis void
open_base(void)5894b2c3eb9SBrooks Davis lutok::state::open_base(void)
5904b2c3eb9SBrooks Davis {
5914b2c3eb9SBrooks Davis     lua_pushcfunction(_pimpl->lua_state, luaopen_base);
5924b2c3eb9SBrooks Davis     if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0)
5934b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "luaopen_base");
5944b2c3eb9SBrooks Davis }
5954b2c3eb9SBrooks Davis 
5964b2c3eb9SBrooks Davis 
5974b2c3eb9SBrooks Davis /// Wrapper around luaopen_string.
5984b2c3eb9SBrooks Davis ///
5994b2c3eb9SBrooks Davis /// \throw api_error If luaopen_string fails.
6004b2c3eb9SBrooks Davis ///
6014b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
6024b2c3eb9SBrooks Davis void
open_string(void)6034b2c3eb9SBrooks Davis lutok::state::open_string(void)
6044b2c3eb9SBrooks Davis {
6054b2c3eb9SBrooks Davis #if LUA_VERSION_NUM >= 502
6064b2c3eb9SBrooks Davis     luaL_requiref(_pimpl->lua_state, LUA_STRLIBNAME, luaopen_string, 1);
6074b2c3eb9SBrooks Davis     lua_pop(_pimpl->lua_state, 1);
6084b2c3eb9SBrooks Davis #else
6094b2c3eb9SBrooks Davis     lua_pushcfunction(_pimpl->lua_state, luaopen_string);
6104b2c3eb9SBrooks Davis     if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0)
6114b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "luaopen_string");
6124b2c3eb9SBrooks Davis #endif
6134b2c3eb9SBrooks Davis }
6144b2c3eb9SBrooks Davis 
6154b2c3eb9SBrooks Davis 
6164b2c3eb9SBrooks Davis /// Wrapper around luaopen_table.
6174b2c3eb9SBrooks Davis ///
6184b2c3eb9SBrooks Davis /// \throw api_error If luaopen_table fails.
6194b2c3eb9SBrooks Davis ///
6204b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
6214b2c3eb9SBrooks Davis void
open_table(void)6224b2c3eb9SBrooks Davis lutok::state::open_table(void)
6234b2c3eb9SBrooks Davis {
6244b2c3eb9SBrooks Davis #if LUA_VERSION_NUM >= 502
6254b2c3eb9SBrooks Davis     luaL_requiref(_pimpl->lua_state, LUA_TABLIBNAME, luaopen_table, 1);
6264b2c3eb9SBrooks Davis     lua_pop(_pimpl->lua_state, 1);
6274b2c3eb9SBrooks Davis #else
6284b2c3eb9SBrooks Davis     lua_pushcfunction(_pimpl->lua_state, luaopen_table);
6294b2c3eb9SBrooks Davis     if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0)
6304b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "luaopen_table");
6314b2c3eb9SBrooks Davis #endif
6324b2c3eb9SBrooks Davis }
6334b2c3eb9SBrooks Davis 
6344b2c3eb9SBrooks Davis 
6354b2c3eb9SBrooks Davis /// Wrapper around lua_pcall.
6364b2c3eb9SBrooks Davis ///
6374b2c3eb9SBrooks Davis /// \param nargs The second parameter to lua_pcall.
6384b2c3eb9SBrooks Davis /// \param nresults The third parameter to lua_pcall.
6394b2c3eb9SBrooks Davis /// \param errfunc The fourth parameter to lua_pcall.
6404b2c3eb9SBrooks Davis ///
6414b2c3eb9SBrooks Davis /// \throw api_error If lua_pcall returns an error.
6424b2c3eb9SBrooks Davis void
pcall(const int nargs,const int nresults,const int errfunc)6434b2c3eb9SBrooks Davis lutok::state::pcall(const int nargs, const int nresults, const int errfunc)
6444b2c3eb9SBrooks Davis {
6454b2c3eb9SBrooks Davis     if (lua_pcall(_pimpl->lua_state, nargs, nresults, errfunc) != 0)
6464b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "lua_pcall");
6474b2c3eb9SBrooks Davis }
6484b2c3eb9SBrooks Davis 
6494b2c3eb9SBrooks Davis 
6504b2c3eb9SBrooks Davis /// Wrapper around lua_pop.
6514b2c3eb9SBrooks Davis ///
6524b2c3eb9SBrooks Davis /// \param count The second parameter to lua_pop.
6534b2c3eb9SBrooks Davis void
pop(const int count)6544b2c3eb9SBrooks Davis lutok::state::pop(const int count)
6554b2c3eb9SBrooks Davis {
6564b2c3eb9SBrooks Davis     assert(count <= lua_gettop(_pimpl->lua_state));
6574b2c3eb9SBrooks Davis     lua_pop(_pimpl->lua_state, count);
6584b2c3eb9SBrooks Davis     assert(lua_gettop(_pimpl->lua_state) >= 0);
6594b2c3eb9SBrooks Davis }
6604b2c3eb9SBrooks Davis 
6614b2c3eb9SBrooks Davis 
6624b2c3eb9SBrooks Davis /// Wrapper around lua_pushboolean.
6634b2c3eb9SBrooks Davis ///
6644b2c3eb9SBrooks Davis /// \param value The second parameter to lua_pushboolean.
6654b2c3eb9SBrooks Davis void
push_boolean(const bool value)6664b2c3eb9SBrooks Davis lutok::state::push_boolean(const bool value)
6674b2c3eb9SBrooks Davis {
6684b2c3eb9SBrooks Davis     lua_pushboolean(_pimpl->lua_state, value ? 1 : 0);
6694b2c3eb9SBrooks Davis }
6704b2c3eb9SBrooks Davis 
6714b2c3eb9SBrooks Davis 
6724b2c3eb9SBrooks Davis /// Wrapper around lua_pushcclosure.
6734b2c3eb9SBrooks Davis ///
6744b2c3eb9SBrooks Davis /// This is not a pure wrapper around lua_pushcclosure because this has to do
6754b2c3eb9SBrooks Davis /// extra magic to allow passing C++ functions instead of plain C functions.
6764b2c3eb9SBrooks Davis ///
6774b2c3eb9SBrooks Davis /// \param function The C++ function to be pushed as a closure.
6784b2c3eb9SBrooks Davis /// \param nvalues The number of upvalues that the function receives.
6794b2c3eb9SBrooks Davis void
push_cxx_closure(cxx_function function,const int nvalues)6804b2c3eb9SBrooks Davis lutok::state::push_cxx_closure(cxx_function function, const int nvalues)
6814b2c3eb9SBrooks Davis {
6824b2c3eb9SBrooks Davis     cxx_function *data = static_cast< cxx_function* >(
6834b2c3eb9SBrooks Davis         lua_newuserdata(_pimpl->lua_state, sizeof(cxx_function)));
6844b2c3eb9SBrooks Davis     *data = function;
6854b2c3eb9SBrooks Davis     lua_pushcclosure(_pimpl->lua_state, cxx_closure_trampoline, nvalues + 1);
6864b2c3eb9SBrooks Davis }
6874b2c3eb9SBrooks Davis 
6884b2c3eb9SBrooks Davis 
6894b2c3eb9SBrooks Davis /// Wrapper around lua_pushcfunction.
6904b2c3eb9SBrooks Davis ///
6914b2c3eb9SBrooks Davis /// This is not a pure wrapper around lua_pushcfunction because this has to do
6924b2c3eb9SBrooks Davis /// extra magic to allow passing C++ functions instead of plain C functions.
6934b2c3eb9SBrooks Davis ///
6944b2c3eb9SBrooks Davis /// \param function The C++ function to be pushed.
6954b2c3eb9SBrooks Davis void
push_cxx_function(cxx_function function)6964b2c3eb9SBrooks Davis lutok::state::push_cxx_function(cxx_function function)
6974b2c3eb9SBrooks Davis {
6984b2c3eb9SBrooks Davis     cxx_function *data = static_cast< cxx_function* >(
6994b2c3eb9SBrooks Davis         lua_newuserdata(_pimpl->lua_state, sizeof(cxx_function)));
7004b2c3eb9SBrooks Davis     *data = function;
7014b2c3eb9SBrooks Davis     lua_pushcclosure(_pimpl->lua_state, cxx_function_trampoline, 1);
7024b2c3eb9SBrooks Davis }
7034b2c3eb9SBrooks Davis 
7044b2c3eb9SBrooks Davis 
7054b2c3eb9SBrooks Davis /// Wrapper around lua_pushinteger.
7064b2c3eb9SBrooks Davis ///
7074b2c3eb9SBrooks Davis /// \param value The second parameter to lua_pushinteger.
7084b2c3eb9SBrooks Davis void
push_integer(const int value)7094b2c3eb9SBrooks Davis lutok::state::push_integer(const int value)
7104b2c3eb9SBrooks Davis {
7114b2c3eb9SBrooks Davis     lua_pushinteger(_pimpl->lua_state, value);
7124b2c3eb9SBrooks Davis }
7134b2c3eb9SBrooks Davis 
7144b2c3eb9SBrooks Davis 
7154b2c3eb9SBrooks Davis /// Wrapper around lua_pushnil.
7164b2c3eb9SBrooks Davis void
push_nil(void)7174b2c3eb9SBrooks Davis lutok::state::push_nil(void)
7184b2c3eb9SBrooks Davis {
7194b2c3eb9SBrooks Davis     lua_pushnil(_pimpl->lua_state);
7204b2c3eb9SBrooks Davis }
7214b2c3eb9SBrooks Davis 
7224b2c3eb9SBrooks Davis 
7234b2c3eb9SBrooks Davis /// Wrapper around lua_pushstring.
7244b2c3eb9SBrooks Davis ///
7254b2c3eb9SBrooks Davis /// \param str The second parameter to lua_pushstring.
7264b2c3eb9SBrooks Davis ///
7274b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
7284b2c3eb9SBrooks Davis void
push_string(const std::string & str)7294b2c3eb9SBrooks Davis lutok::state::push_string(const std::string& str)
7304b2c3eb9SBrooks Davis {
7314b2c3eb9SBrooks Davis     lua_pushstring(_pimpl->lua_state, str.c_str());
7324b2c3eb9SBrooks Davis }
7334b2c3eb9SBrooks Davis 
7344b2c3eb9SBrooks Davis 
7354b2c3eb9SBrooks Davis /// Wrapper around lua_pushvalue.
7364b2c3eb9SBrooks Davis ///
7374b2c3eb9SBrooks Davis /// \param index The second parameter to lua_pushvalue.
7384b2c3eb9SBrooks Davis void
push_value(const int index)7394b2c3eb9SBrooks Davis lutok::state::push_value(const int index)
7404b2c3eb9SBrooks Davis {
7414b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, index);
7424b2c3eb9SBrooks Davis }
7434b2c3eb9SBrooks Davis 
7444b2c3eb9SBrooks Davis 
7454b2c3eb9SBrooks Davis /// Wrapper around lua_rawget.
7464b2c3eb9SBrooks Davis ///
7474b2c3eb9SBrooks Davis /// \param index The second parameter to lua_rawget.
7484b2c3eb9SBrooks Davis void
raw_get(const int index)7494b2c3eb9SBrooks Davis lutok::state::raw_get(const int index)
7504b2c3eb9SBrooks Davis {
7514b2c3eb9SBrooks Davis     lua_rawget(_pimpl->lua_state, index);
7524b2c3eb9SBrooks Davis }
7534b2c3eb9SBrooks Davis 
7544b2c3eb9SBrooks Davis 
7554b2c3eb9SBrooks Davis /// Wrapper around lua_rawset.
7564b2c3eb9SBrooks Davis ///
7574b2c3eb9SBrooks Davis /// \param index The second parameter to lua_rawset.
7584b2c3eb9SBrooks Davis ///
7594b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory to manipulate
7604b2c3eb9SBrooks Davis /// the Lua stack.
7614b2c3eb9SBrooks Davis void
raw_set(const int index)7624b2c3eb9SBrooks Davis lutok::state::raw_set(const int index)
7634b2c3eb9SBrooks Davis {
7644b2c3eb9SBrooks Davis     lua_rawset(_pimpl->lua_state, index);
7654b2c3eb9SBrooks Davis }
7664b2c3eb9SBrooks Davis 
7674b2c3eb9SBrooks Davis 
7684b2c3eb9SBrooks Davis /// Wrapper around lua_setglobal.
7694b2c3eb9SBrooks Davis ///
7704b2c3eb9SBrooks Davis /// \param name The second parameter to lua_setglobal.
7714b2c3eb9SBrooks Davis ///
7724b2c3eb9SBrooks Davis /// \throw api_error If lua_setglobal fails.
7734b2c3eb9SBrooks Davis ///
7744b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory to manipulate
7754b2c3eb9SBrooks Davis /// the Lua stack.
7764b2c3eb9SBrooks Davis void
set_global(const std::string & name)7774b2c3eb9SBrooks Davis lutok::state::set_global(const std::string& name)
7784b2c3eb9SBrooks Davis {
7794b2c3eb9SBrooks Davis     lua_pushcfunction(_pimpl->lua_state, protected_setglobal);
7804b2c3eb9SBrooks Davis     lua_pushstring(_pimpl->lua_state, name.c_str());
7814b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, -3);
7824b2c3eb9SBrooks Davis     if (lua_pcall(_pimpl->lua_state, 2, 0, 0) != 0)
7834b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "lua_setglobal");
7844b2c3eb9SBrooks Davis     lua_pop(_pimpl->lua_state, 1);
7854b2c3eb9SBrooks Davis }
7864b2c3eb9SBrooks Davis 
7874b2c3eb9SBrooks Davis 
7884b2c3eb9SBrooks Davis /// Wrapper around lua_setmetatable.
7894b2c3eb9SBrooks Davis ///
7904b2c3eb9SBrooks Davis /// \param index The second parameter to lua_setmetatable.
7914b2c3eb9SBrooks Davis void
set_metatable(const int index)7924b2c3eb9SBrooks Davis lutok::state::set_metatable(const int index)
7934b2c3eb9SBrooks Davis {
7944b2c3eb9SBrooks Davis     lua_setmetatable(_pimpl->lua_state, index);
7954b2c3eb9SBrooks Davis }
7964b2c3eb9SBrooks Davis 
7974b2c3eb9SBrooks Davis 
7984b2c3eb9SBrooks Davis /// Wrapper around lua_settable.
7994b2c3eb9SBrooks Davis ///
8004b2c3eb9SBrooks Davis /// \param index The second parameter to lua_settable.
8014b2c3eb9SBrooks Davis ///
8024b2c3eb9SBrooks Davis /// \throw api_error If lua_settable fails.
8034b2c3eb9SBrooks Davis ///
8044b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory to manipulate
8054b2c3eb9SBrooks Davis /// the Lua stack.
8064b2c3eb9SBrooks Davis void
set_table(const int index)8074b2c3eb9SBrooks Davis lutok::state::set_table(const int index)
8084b2c3eb9SBrooks Davis {
8094b2c3eb9SBrooks Davis     lua_pushcfunction(_pimpl->lua_state, protected_settable);
8104b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index);
8114b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, -4);
8124b2c3eb9SBrooks Davis     lua_pushvalue(_pimpl->lua_state, -4);
8134b2c3eb9SBrooks Davis     if (lua_pcall(_pimpl->lua_state, 3, 0, 0) != 0)
8144b2c3eb9SBrooks Davis         throw lutok::api_error::from_stack(*this, "lua_settable");
8154b2c3eb9SBrooks Davis     lua_pop(_pimpl->lua_state, 2);
8164b2c3eb9SBrooks Davis }
8174b2c3eb9SBrooks Davis 
8184b2c3eb9SBrooks Davis 
8194b2c3eb9SBrooks Davis /// Wrapper around lua_toboolean.
8204b2c3eb9SBrooks Davis ///
8214b2c3eb9SBrooks Davis /// \param index The second parameter to lua_toboolean.
8224b2c3eb9SBrooks Davis ///
8234b2c3eb9SBrooks Davis /// \return The return value of lua_toboolean.
8244b2c3eb9SBrooks Davis bool
to_boolean(const int index)8254b2c3eb9SBrooks Davis lutok::state::to_boolean(const int index)
8264b2c3eb9SBrooks Davis {
8274b2c3eb9SBrooks Davis     assert(is_boolean(index));
8284b2c3eb9SBrooks Davis     return lua_toboolean(_pimpl->lua_state, index);
8294b2c3eb9SBrooks Davis }
8304b2c3eb9SBrooks Davis 
8314b2c3eb9SBrooks Davis 
8324b2c3eb9SBrooks Davis /// Wrapper around lua_tointeger.
8334b2c3eb9SBrooks Davis ///
8344b2c3eb9SBrooks Davis /// \param index The second parameter to lua_tointeger.
8354b2c3eb9SBrooks Davis ///
8364b2c3eb9SBrooks Davis /// \return The return value of lua_tointeger.
8374b2c3eb9SBrooks Davis long
to_integer(const int index)8384b2c3eb9SBrooks Davis lutok::state::to_integer(const int index)
8394b2c3eb9SBrooks Davis {
8404b2c3eb9SBrooks Davis     assert(is_number(index));
8414b2c3eb9SBrooks Davis     return lua_tointeger(_pimpl->lua_state, index);
8424b2c3eb9SBrooks Davis }
8434b2c3eb9SBrooks Davis 
8444b2c3eb9SBrooks Davis 
8454b2c3eb9SBrooks Davis /// Wrapper around lua_touserdata.
8464b2c3eb9SBrooks Davis ///
8474b2c3eb9SBrooks Davis /// This is internal.  The public type-safe interface of this method should be
8484b2c3eb9SBrooks Davis /// used instead.
8494b2c3eb9SBrooks Davis ///
8504b2c3eb9SBrooks Davis /// \param index The second parameter to lua_touserdata.
8514b2c3eb9SBrooks Davis ///
8524b2c3eb9SBrooks Davis /// \return The return value of lua_touserdata.
8534b2c3eb9SBrooks Davis ///
8544b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
8554b2c3eb9SBrooks Davis void*
to_userdata_voidp(const int index)8564b2c3eb9SBrooks Davis lutok::state::to_userdata_voidp(const int index)
8574b2c3eb9SBrooks Davis {
8584b2c3eb9SBrooks Davis     return lua_touserdata(_pimpl->lua_state, index);
8594b2c3eb9SBrooks Davis }
8604b2c3eb9SBrooks Davis 
8614b2c3eb9SBrooks Davis 
8624b2c3eb9SBrooks Davis 
8634b2c3eb9SBrooks Davis /// Wrapper around lua_tostring.
8644b2c3eb9SBrooks Davis ///
8654b2c3eb9SBrooks Davis /// \param index The second parameter to lua_tostring.
8664b2c3eb9SBrooks Davis ///
8674b2c3eb9SBrooks Davis /// \return The return value of lua_tostring.
8684b2c3eb9SBrooks Davis ///
8694b2c3eb9SBrooks Davis /// \warning Terminates execution if there is not enough memory.
8704b2c3eb9SBrooks Davis std::string
to_string(const int index)8714b2c3eb9SBrooks Davis lutok::state::to_string(const int index)
8724b2c3eb9SBrooks Davis {
8734b2c3eb9SBrooks Davis     assert(is_string(index));
8744b2c3eb9SBrooks Davis     const char *raw_string = lua_tostring(_pimpl->lua_state, index);
8754b2c3eb9SBrooks Davis     // Note that the creation of a string object below (explicit for clarity)
8764b2c3eb9SBrooks Davis     // implies that the raw string is duplicated and, henceforth, the string is
8774b2c3eb9SBrooks Davis     // safe even if the corresponding element is popped from the Lua stack.
8784b2c3eb9SBrooks Davis     return std::string(raw_string);
8794b2c3eb9SBrooks Davis }
8804b2c3eb9SBrooks Davis 
8814b2c3eb9SBrooks Davis 
8824b2c3eb9SBrooks Davis /// Wrapper around lua_upvalueindex.
8834b2c3eb9SBrooks Davis ///
8844b2c3eb9SBrooks Davis /// \param index The first parameter to lua_upvalueindex.
8854b2c3eb9SBrooks Davis ///
8864b2c3eb9SBrooks Davis /// \return The return value of lua_upvalueindex.
8874b2c3eb9SBrooks Davis int
upvalue_index(const int index)8884b2c3eb9SBrooks Davis lutok::state::upvalue_index(const int index)
8894b2c3eb9SBrooks Davis {
8904b2c3eb9SBrooks Davis     return lua_upvalueindex(index);
8914b2c3eb9SBrooks Davis }
8924b2c3eb9SBrooks Davis 
8934b2c3eb9SBrooks Davis 
8944b2c3eb9SBrooks Davis /// Gets the internal lua_State object.
8954b2c3eb9SBrooks Davis ///
8964b2c3eb9SBrooks Davis /// \return The raw Lua state.  This is returned as a void pointer to prevent
8974b2c3eb9SBrooks Davis /// including the lua.hpp header file from our public interface.  The only way
8984b2c3eb9SBrooks Davis /// to call this method is by using the c_gate module, and c_gate takes care of
8994b2c3eb9SBrooks Davis /// casting this object to the appropriate type.
9004b2c3eb9SBrooks Davis void*
raw_state(void)9014b2c3eb9SBrooks Davis lutok::state::raw_state(void)
9024b2c3eb9SBrooks Davis {
9034b2c3eb9SBrooks Davis     return _pimpl->lua_state;
9044b2c3eb9SBrooks Davis }
905