Merge branch 'dfapi' of https://github.com/warmist/dfhack
commit
761d0de74a
@ -0,0 +1,15 @@
|
|||||||
|
find_package(Lua51 QUIET)
|
||||||
|
|
||||||
|
if(LUA51_FOUND)
|
||||||
|
include_directories(${LUA_INCLUDE_DIR} include)
|
||||||
|
FILE(GLOB DFUSION_CPPS src/*.c*)
|
||||||
|
set(
|
||||||
|
DFUSION_CPPS_ALL
|
||||||
|
dfusion.cpp
|
||||||
|
${DFUSION_CPPS}
|
||||||
|
)
|
||||||
|
DFHACK_PLUGIN(dfusion ${DFUSION_CPPS_ALL})
|
||||||
|
target_link_libraries(dfusion ${LUA_LIBRARIES})
|
||||||
|
else(LUA51_FOUND)
|
||||||
|
MESSAGE(STATUS "Required libraries (lua51) not found - dfusion plugin can't be built.")
|
||||||
|
endif(LUA51_FOUND)
|
@ -0,0 +1,124 @@
|
|||||||
|
#include <dfhack/Core.h>
|
||||||
|
#include <dfhack/Console.h>
|
||||||
|
#include <dfhack/Export.h>
|
||||||
|
#include <dfhack/PluginManager.h>
|
||||||
|
#include <dfhack/Process.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "luamain.h"
|
||||||
|
#include "lua_Console.h"
|
||||||
|
#include "functioncall.h"
|
||||||
|
|
||||||
|
using std::vector;
|
||||||
|
using std::string;
|
||||||
|
using namespace DFHack;
|
||||||
|
|
||||||
|
static SDL::Mutex* mymutex=0;
|
||||||
|
|
||||||
|
DFhackCExport command_result dfusion (Core * c, vector <string> & parameters);
|
||||||
|
DFhackCExport command_result lua_run (Core * c, vector <string> & parameters);
|
||||||
|
|
||||||
|
typedef
|
||||||
|
int (__thiscall *dfprint)(const char*, char, char,void *) ;
|
||||||
|
|
||||||
|
DFhackCExport const char * plugin_name ( void )
|
||||||
|
{
|
||||||
|
return "dfusion";
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
|
||||||
|
{
|
||||||
|
commands.clear();
|
||||||
|
//maybe remake it to run automaticaly
|
||||||
|
lua::RegisterConsole(lua::glua::Get(),&c->con);
|
||||||
|
|
||||||
|
commands.push_back(PluginCommand("dfusion","Init dfusion system.",dfusion));
|
||||||
|
commands.push_back(PluginCommand("lua", "Run interactive interpreter.\
|
||||||
|
\n Options: <filename> = run <filename> instead",lua_run));
|
||||||
|
|
||||||
|
mymutex=SDL_CreateMutex();
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_shutdown ( Core * c )
|
||||||
|
{
|
||||||
|
|
||||||
|
// shutdown stuff
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_onupdate ( Core * c )
|
||||||
|
{
|
||||||
|
/*if(timering == true) //TODO maybe reuse this to make it run less often.
|
||||||
|
{
|
||||||
|
uint64_t time2 = GetTimeMs64();
|
||||||
|
uint64_t delta = time2-timeLast;
|
||||||
|
timeLast = time2;
|
||||||
|
c->con.print("Time delta = %d ms\n", delta);
|
||||||
|
}
|
||||||
|
return CR_OK;*/
|
||||||
|
SDL_mutexP(mymutex);
|
||||||
|
lua::state s=lua::glua::Get();
|
||||||
|
s.getglobal("OnTick");
|
||||||
|
if(s.is<lua::function>())
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
s.pcall();
|
||||||
|
}
|
||||||
|
catch(lua::exception &e)
|
||||||
|
{
|
||||||
|
c->con.printerr("Error OnTick:%s\n",e.what());
|
||||||
|
c->con.msleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.settop(0);
|
||||||
|
SDL_mutexV(mymutex);
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DFhackCExport command_result lua_run (Core * c, vector <string> & parameters)
|
||||||
|
{
|
||||||
|
Console &con=c->con;
|
||||||
|
SDL_mutexP(mymutex);
|
||||||
|
lua::state s=lua::glua::Get();
|
||||||
|
if(parameters.size()>0)
|
||||||
|
{
|
||||||
|
try{
|
||||||
|
s.loadfile(parameters[0]); //load file
|
||||||
|
s.pcall(0,0);// run it
|
||||||
|
}
|
||||||
|
catch(lua::exception &e)
|
||||||
|
{
|
||||||
|
con.printerr("Error:%s\n",e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//TODO interpreter...
|
||||||
|
}
|
||||||
|
s.settop(0);// clean up
|
||||||
|
SDL_mutexV(mymutex);
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
DFhackCExport command_result dfusion (Core * c, vector <string> & parameters)
|
||||||
|
{
|
||||||
|
|
||||||
|
Console &con=c->con;
|
||||||
|
con.print("%x\n",c->p->getBase());
|
||||||
|
SDL_mutexP(mymutex);
|
||||||
|
lua::state s=lua::glua::Get();
|
||||||
|
|
||||||
|
try{
|
||||||
|
s.loadfile("dfusion/init.lua"); //load script
|
||||||
|
s.pcall(0,0);// run it
|
||||||
|
}
|
||||||
|
catch(lua::exception &e)
|
||||||
|
{
|
||||||
|
con.printerr("Error:%s\n",e.what());
|
||||||
|
}
|
||||||
|
s.settop(0);// clean up
|
||||||
|
SDL_mutexV(mymutex);
|
||||||
|
return CR_OK;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef FUNCTIONCALL__H
|
||||||
|
#define FUNCTIONCALL__H
|
||||||
|
#include <vector>
|
||||||
|
using std::vector;
|
||||||
|
class FunctionCaller
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum callconv
|
||||||
|
{
|
||||||
|
STD_CALL, //__stdcall - all in stack
|
||||||
|
FAST_CALL, //__fastcall - as much in registers as fits
|
||||||
|
THIS_CALL, //__thiscall - eax ptr to this, rest in stack
|
||||||
|
CDECL_CALL //__cdecl - same as stdcall but no stack realign
|
||||||
|
};
|
||||||
|
|
||||||
|
FunctionCaller(size_t base):base_(base){};
|
||||||
|
|
||||||
|
int CallFunction(size_t func_ptr,callconv conv,const vector<int> &arguments);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int CallF(size_t count,callconv conv,void* f,const vector<int> &arguments);
|
||||||
|
size_t base_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //FUNCTIONCALL__H
|
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef LUA_CONSOLE_H
|
||||||
|
#define LUA_CONSOLE_H
|
||||||
|
#include <dfhack/Console.h>
|
||||||
|
#include "luamain.h"
|
||||||
|
|
||||||
|
namespace lua
|
||||||
|
{
|
||||||
|
|
||||||
|
void RegisterConsole(lua::state &st, DFHack::Console *c);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef LUAMAIN_H
|
||||||
|
#define LUAMAIN_H
|
||||||
|
#include <string>
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "lua.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
//#include "lune.h"
|
||||||
|
#include "luaxx.hpp"
|
||||||
|
|
||||||
|
namespace lua
|
||||||
|
{
|
||||||
|
//global lua state singleton
|
||||||
|
class glua
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static state &Get();
|
||||||
|
private:
|
||||||
|
glua();
|
||||||
|
static glua *ptr;
|
||||||
|
state mystate;
|
||||||
|
};
|
||||||
|
//registers basic lua commands
|
||||||
|
void RegBasics(lua::state &L);
|
||||||
|
//dumps lua function trace, useless unless called from lua.
|
||||||
|
string DebugDump(lua::state &L);
|
||||||
|
//register functions, first registers into global scope, second into current table
|
||||||
|
void RegFunctions(lua::state &L,luaL_reg const *arr);
|
||||||
|
void RegFunctionsLocal(lua::state &L,luaL_reg const *arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // LUAMAIN_H
|
@ -0,0 +1,525 @@
|
|||||||
|
/* vim: set et sw=3 tw=0 fo=croqlaw cino=t0:
|
||||||
|
*
|
||||||
|
* Luaxx, the C++ Lua wrapper library.
|
||||||
|
* Copyright (c) 2006-2008 Matthew Nicholson
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LUAXX_H
|
||||||
|
#define LUAXX_H
|
||||||
|
|
||||||
|
#define lua_Integer_long 1
|
||||||
|
#define lua_Integer_int 1
|
||||||
|
|
||||||
|
#include <lua.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <new>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
* Luaxx header file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @mainpage Luaxx
|
||||||
|
*
|
||||||
|
* Luaxx is a thin wrapper around the Lua C API. The wrapper adds some
|
||||||
|
* convenience functions and integrates well with modern C++.
|
||||||
|
*
|
||||||
|
* Luaxx is not designed like toLua, instead Luaxx is more of a 1 to 1
|
||||||
|
* logical mapping of the lua API in C++. For example: in C you would write
|
||||||
|
* 'lua_pushnumber(L, 3)', in C++ with Luaxx you would write
|
||||||
|
* 'L.push(3)'.
|
||||||
|
*
|
||||||
|
* Every thing is contained in the 'lua' namespace and exceptions are thrown
|
||||||
|
* when a lua API function returns an error. Most of the functionality is
|
||||||
|
* contained in the lua::state class, which can be passed directly to lua C API
|
||||||
|
* functions (the compiler will automatically use the internal lua_State
|
||||||
|
* pointer). See the documentation for that class for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace lua
|
||||||
|
{
|
||||||
|
void StackDump(lua_State *L);
|
||||||
|
/** A generic lua exception.
|
||||||
|
*/
|
||||||
|
class exception : public std::exception {
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
exception() : std::exception() { }
|
||||||
|
/// Constructor.
|
||||||
|
explicit exception(const char* desc) : std::exception(), description(desc) { }
|
||||||
|
virtual ~exception() throw() { }
|
||||||
|
/** Get a description of the error.
|
||||||
|
* @returns a C-string describing the error
|
||||||
|
*/
|
||||||
|
virtual const char* what() const throw() {
|
||||||
|
return description.c_str();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::string description;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A lua runtime error.
|
||||||
|
* This is thrown when there was an error executing some lua code.
|
||||||
|
* @note This is not an std::runtime error.
|
||||||
|
*/
|
||||||
|
class runtime_error : public exception {
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
runtime_error() : exception() { }
|
||||||
|
/// Constructor.
|
||||||
|
explicit runtime_error(const char* desc) : exception(desc) { }
|
||||||
|
virtual ~runtime_error() throw() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A syntax error.
|
||||||
|
*/
|
||||||
|
class syntax_error : public exception {
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
syntax_error() : exception() { }
|
||||||
|
/// Constructor.
|
||||||
|
explicit syntax_error(const char* desc) : exception(desc) { }
|
||||||
|
virtual ~syntax_error() throw() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** An error loading a lua file.
|
||||||
|
* This is thrown when a call to lua::loadfile failed because the file could
|
||||||
|
* not be opened or read.
|
||||||
|
*/
|
||||||
|
class file_error : public exception {
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
file_error() : exception() { }
|
||||||
|
/// Constructor.
|
||||||
|
explicit file_error(const char* desc) : exception(desc) { }
|
||||||
|
virtual ~file_error() throw() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A memory allocation error.
|
||||||
|
*/
|
||||||
|
class bad_alloc : public exception, std::bad_alloc {
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
bad_alloc() : lua::exception(), std::bad_alloc() { }
|
||||||
|
/// Constructor.
|
||||||
|
explicit bad_alloc(const char* desc) : lua::exception(desc), std::bad_alloc() { }
|
||||||
|
virtual ~bad_alloc() throw() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** An error converting a lua type.
|
||||||
|
*/
|
||||||
|
class bad_conversion : public exception {
|
||||||
|
public:
|
||||||
|
/// Constructor.
|
||||||
|
bad_conversion() : exception() { }
|
||||||
|
/// Constructor.
|
||||||
|
explicit bad_conversion(const char* desc) : exception(desc) { }
|
||||||
|
virtual ~bad_conversion() throw() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A Lua table (this class does not have any data).
|
||||||
|
class table { };
|
||||||
|
/// A Lua nil (this class does not have any data).
|
||||||
|
class nil { };
|
||||||
|
/// A lua function (not a cfunction).
|
||||||
|
class function { };
|
||||||
|
/// A lua userdatum
|
||||||
|
class userdata { };
|
||||||
|
/// A lua light userdatum
|
||||||
|
class lightuserdata { };
|
||||||
|
|
||||||
|
typedef lua_CFunction cfunction; ///< A cfunction on the lua statck
|
||||||
|
typedef lua_Integer integer; ///< The default lua integer type
|
||||||
|
typedef lua_Number number; ///< The default lua number type
|
||||||
|
typedef lua_Reader reader; ///< The type of function used by lua_load
|
||||||
|
const int multiret = LUA_MULTRET; ///< LUA_MULTIRET
|
||||||
|
|
||||||
|
/** This is the Luaxx equivalent of lua_State.
|
||||||
|
* The functions provided by this class, closely resemble those of the Lua C
|
||||||
|
* API.
|
||||||
|
*/
|
||||||
|
void StackDump(lua_State *L);
|
||||||
|
class state {
|
||||||
|
public:
|
||||||
|
state();
|
||||||
|
state(lua_State* L);
|
||||||
|
state(const state& t)
|
||||||
|
{
|
||||||
|
managed=false;
|
||||||
|
L=t.L;
|
||||||
|
}
|
||||||
|
state& operator = (const state& t);
|
||||||
|
~state();
|
||||||
|
|
||||||
|
operator lua_State*();
|
||||||
|
|
||||||
|
state& push();
|
||||||
|
state& push(nil);
|
||||||
|
state& push(bool boolean);
|
||||||
|
template<typename T> state& push(T number);
|
||||||
|
state& push(const char* s, size_t length);
|
||||||
|
state& push(const char* s);
|
||||||
|
state& push(const std::string& s);
|
||||||
|
state& push(cfunction f);
|
||||||
|
state& push(table);
|
||||||
|
state& push(void* p);
|
||||||
|
template<typename T> state& pushlightuserdata(T p);
|
||||||
|
|
||||||
|
template<typename T> state& to(T& number, int index = -1);
|
||||||
|
template<typename T> state& touserdata(T& p, int index = -1);
|
||||||
|
|
||||||
|
template<typename T> T as(T default_value, int index = -1);
|
||||||
|
template<typename T> T as(int index = -1);
|
||||||
|
template<typename T> T vpop()
|
||||||
|
{
|
||||||
|
T ret;
|
||||||
|
ret=as<T>();
|
||||||
|
pop();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template<typename T> bool is(int index = -1);
|
||||||
|
|
||||||
|
state& check(int narg);
|
||||||
|
#ifndef lua_Integer_int
|
||||||
|
state& check(int& i, int narg);
|
||||||
|
#endif
|
||||||
|
state& check(integer& i, int narg);
|
||||||
|
#ifndef lua_Integer_long
|
||||||
|
state& check(long& l, int narg);
|
||||||
|
#endif
|
||||||
|
state& check(std::string& s, int narg);
|
||||||
|
state& check(number& n, int narg);
|
||||||
|
|
||||||
|
template<typename msg_t> void error(msg_t message);
|
||||||
|
#if 0
|
||||||
|
template<> void error(const std::string& message);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
state& pcall(int nargs = 0, int nresults = 0, int on_error = 0);
|
||||||
|
state& call(int nargs = 0, int nresults = 0);
|
||||||
|
|
||||||
|
state& checkstack(int size);
|
||||||
|
state& settop(int index);
|
||||||
|
int gettop();
|
||||||
|
int size();
|
||||||
|
bool empty();
|
||||||
|
|
||||||
|
state& insert(int index);
|
||||||
|
state& replace(int index);
|
||||||
|
state& remove(int index);
|
||||||
|
state& pop(int elements = 1);
|
||||||
|
|
||||||
|
state& pushvalue(int index);
|
||||||
|
|
||||||
|
state& newtable();
|
||||||
|
bool newmetatable(const std::string& tname);
|
||||||
|
template<typename userdata_t> userdata_t* newuserdata();
|
||||||
|
void* newuserdata(size_t nbytes);
|
||||||
|
|
||||||
|
state& gettable(int index = -2);
|
||||||
|
state& getfield(const std::string& k, int index = -1);
|
||||||
|
state& settable(int index = -3);
|
||||||
|
state& setfield(const std::string& k, int index = -2);
|
||||||
|
state& getmetatable(const std::string& tname);
|
||||||
|
bool getmetatable(int index);
|
||||||
|
|
||||||
|
bool next(int index = -2);
|
||||||
|
|
||||||
|
state& getglobal(const std::string& name);
|
||||||
|
state& setglobal(const std::string& name);
|
||||||
|
|
||||||
|
state& loadfile(const std::string& filename);
|
||||||
|
state& loadstring(const std::string& s);
|
||||||
|
|
||||||
|
template<typename iterator_t> state& load(iterator_t begin, iterator_t end);
|
||||||
|
|
||||||
|
size_t objlen(int index = -1);
|
||||||
|
|
||||||
|
private:
|
||||||
|
lua_State* L;
|
||||||
|
bool managed;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int throw_error(int code);
|
||||||
|
};
|
||||||
|
|
||||||
|
// template functions
|
||||||
|
|
||||||
|
/** Push a number onto the stack.
|
||||||
|
* @tparam T the numeric type to push (should be automatically determined,
|
||||||
|
* if there is no specialization for the desired type, lua_pushnumber() will
|
||||||
|
* be used, and may fail)
|
||||||
|
* @param number the number to push
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
state& state::push(T number) {
|
||||||
|
lua_pushnumber(L, number);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push a light userdatum on to the stack.
|
||||||
|
* @tparam T the type of data to push (should be automatically determined)
|
||||||
|
* @param p the pointer to push
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
state& state::pushlightuserdata(T p) {
|
||||||
|
lua_pushlightuserdata(L, p);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if the given index is of the given type (defaults to using
|
||||||
|
* lua_isnumber()).
|
||||||
|
* @tparam T the type to check for (the default, if no specializations
|
||||||
|
* match, does lua_isnumber())
|
||||||
|
* @param index the index to check
|
||||||
|
* @note the default version (used if no specialization is matched) will
|
||||||
|
* check if the given value is a number
|
||||||
|
* @returns whether the value at the given index is a nil
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
bool state::is(int index) {
|
||||||
|
return lua_isnumber(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the value at index as the given numeric type.
|
||||||
|
* @tparam T they numeric type to static_cast<T>() the numeric value on the
|
||||||
|
* stack to
|
||||||
|
* @param number where to store the value
|
||||||
|
* @param index the index to get
|
||||||
|
* @note This function does \em not pop the value from the stack.
|
||||||
|
* @todo Instead of throwing an exception here, we may just return an
|
||||||
|
* error code.
|
||||||
|
* @throws lua::bad_conversion if the value on the stack could not be
|
||||||
|
* converted to the indicated type
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
state& state::to(T& number, int index) {
|
||||||
|
if (lua_isnumber(L, index))
|
||||||
|
number = static_cast<T>(lua_tonumber(L, index));
|
||||||
|
else
|
||||||
|
throw bad_conversion("Cannot convert non 'number' value to number");
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the value at index as (light) userdata.
|
||||||
|
* @tparam T the type of data pointed to (pointer is returned as
|
||||||
|
* reinterpret_cast<T>())
|
||||||
|
* @param p the pointer to store the value in
|
||||||
|
* @param index the index to get
|
||||||
|
* @note This function does \em not pop the value from the stack.
|
||||||
|
* @todo Instead of throwing an exception here, we may just return an
|
||||||
|
* error code.
|
||||||
|
* @throws lua::bad_conversion if the value on the stack could not be
|
||||||
|
* converted to the indicated type
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
state& state::touserdata(T& p, int index) {
|
||||||
|
if (lua_isuserdata(L, index))
|
||||||
|
p = reinterpret_cast<T>(lua_touserdata(L, index));
|
||||||
|
else
|
||||||
|
throw bad_conversion("Cannot convert non 'userdata' or 'lightuserdata' value to userdata");
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the value at index as the given type.
|
||||||
|
* @tparam T the type to retrieve the value on the stack as (the default
|
||||||
|
* template function uses lua_tonumber(), specializations may cause
|
||||||
|
* different behavior)
|
||||||
|
* @param default_value this value is returned if the conversion fails
|
||||||
|
* @param index the index to get
|
||||||
|
* @note This function does \em not pop the value from the stack.
|
||||||
|
* @returns the indicated value from the stack or the default value if
|
||||||
|
* the conversion fails
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
T state::as(T default_value, int index) {
|
||||||
|
if (lua_isnumber(L, index))
|
||||||
|
return static_cast<T>(lua_tonumber(L, index));
|
||||||
|
else
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the value at index as the given type.
|
||||||
|
* @tparam T the expected type of the value
|
||||||
|
* @param index the index to get
|
||||||
|
*
|
||||||
|
* @note This function does \em not pop the value from the stack.
|
||||||
|
* @note The default version of this function uses lua_tonumber() but
|
||||||
|
* specializations may cause different behavior.
|
||||||
|
*
|
||||||
|
* @todo Instead of throwing an exception here, we may just return an
|
||||||
|
* error code.
|
||||||
|
*
|
||||||
|
* @throws lua::bad_conversion if the value on the stack could not be
|
||||||
|
* converted to the indicated type
|
||||||
|
*
|
||||||
|
* This function will return the value on the stack as the given type. If
|
||||||
|
* the value is not of the given type <em>no conversion will be
|
||||||
|
* performed</em> and lua::bad_conversion will be thrown. There are some
|
||||||
|
* exceptions to this rule, for example, numbers will be converted to
|
||||||
|
* strings and vice-versa (conversion is only performed if the matching
|
||||||
|
* lua_is*() function returns true). The state::to() function should be
|
||||||
|
* used to perform automatic conversion.
|
||||||
|
*
|
||||||
|
* @returns the indicated value as the given type if possible
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
T state::as(int index) {
|
||||||
|
if (lua_isnumber(L, index))
|
||||||
|
return static_cast<T>(lua_tonumber(L, index));
|
||||||
|
else
|
||||||
|
throw bad_conversion("Cannot convert non 'number' value to number");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a new userdatum on the stack.
|
||||||
|
* @tparam userdata_t the type of the userdata (will be passed to sizeof())
|
||||||
|
*
|
||||||
|
* This function creates a new userdatum on the stack the size of
|
||||||
|
* userdata_t and return a pointer to it.
|
||||||
|
* @returns a pointer to the new userdatum
|
||||||
|
*/
|
||||||
|
template<typename userdata_t>
|
||||||
|
userdata_t* state::newuserdata() {
|
||||||
|
return reinterpret_cast<userdata_t*>(lua_newuserdata(L, sizeof(userdata_t)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Generate a Lua error.
|
||||||
|
* @tparam msg_t the type of error message data (should be automatically
|
||||||
|
* determined)
|
||||||
|
* @param message the error message/value
|
||||||
|
* @note This function is used to raise errors from lua::cfunctions.
|
||||||
|
* @note This function never returns, instead it throws an exception
|
||||||
|
* caught by the intepreter.
|
||||||
|
*/
|
||||||
|
template<typename msg_t>
|
||||||
|
void state::error(msg_t message) {
|
||||||
|
push(message);
|
||||||
|
lua_error(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load a sequence of data as a Lua chunk.
|
||||||
|
* @tparam iterator_t the type of iterator to use (should be automatically
|
||||||
|
* determined)
|
||||||
|
* @param begin an iterator to the start of the sequence
|
||||||
|
* @param end an iterator to the end of the sequence (one past the
|
||||||
|
* end)
|
||||||
|
*
|
||||||
|
* This function takes a sequence of data and attempts to convert it
|
||||||
|
* into a Lua chunk. The type of data passed must be able to be
|
||||||
|
* converted into an 8-bit char.
|
||||||
|
*
|
||||||
|
* @note This function should automatically detect if the data is text
|
||||||
|
* or binary.
|
||||||
|
*
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
template<typename iterator_t>
|
||||||
|
state& state::load(iterator_t begin, iterator_t end) {
|
||||||
|
// convert the data to characters
|
||||||
|
std::vector<char> chunk(begin, end);
|
||||||
|
|
||||||
|
// Here we use the address of the first element of our vector.
|
||||||
|
// This works because the data in std::vectors is contiguous.
|
||||||
|
throw_error(luaL_loadbuffer(L, &(*chunk.begin()), chunk.size(), NULL));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// template specializations
|
||||||
|
template<> state& state::to(bool& boolean, int index);
|
||||||
|
template<> state& state::to(std::string& string, int index);
|
||||||
|
|
||||||
|
template<> bool state::as(bool default_value, int index);
|
||||||
|
template<> std::string state::as(std::string default_value, int index);
|
||||||
|
template<> bool state::as(int index);
|
||||||
|
template<> std::string state::as(int index);
|
||||||
|
|
||||||
|
template<> bool state::is<nil>(int index);
|
||||||
|
template<> bool state::is<bool>(int index);
|
||||||
|
template<> bool state::is<std::string>(int index);
|
||||||
|
template<> bool state::is<table>(int index);
|
||||||
|
template<> bool state::is<cfunction>(int index);
|
||||||
|
template<> bool state::is<function>(int index);
|
||||||
|
template<> bool state::is<userdata>(int index);
|
||||||
|
template<> bool state::is<lightuserdata>(int index);
|
||||||
|
|
||||||
|
|
||||||
|
// inline functions
|
||||||
|
|
||||||
|
/** Convert a lua::state to a lua_State*.
|
||||||
|
* This operator allows lua::state to behave like a lua_State
|
||||||
|
* pointer.
|
||||||
|
*
|
||||||
|
* @note This should be used as a last result to interoperate with C
|
||||||
|
* code. This may be removed in future versions of Luaxx.
|
||||||
|
*/
|
||||||
|
inline state::operator lua_State*() {
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Throws exceptions for error return codes.
|
||||||
|
* @param code the return code
|
||||||
|
*
|
||||||
|
* This function throws an exception based on the error it was passed.
|
||||||
|
* If it is passed a 0 it will not throw anything.
|
||||||
|
*
|
||||||
|
* @todo In the future this function may check an exception mask
|
||||||
|
* before throwing an error.
|
||||||
|
*
|
||||||
|
* @returns the code it was passed
|
||||||
|
*/
|
||||||
|
inline int state::throw_error(int code) {
|
||||||
|
std::string error;
|
||||||
|
|
||||||
|
// below, we package lua errors into exceptions
|
||||||
|
switch (code) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case LUA_ERRSYNTAX:
|
||||||
|
to(error).pop();
|
||||||
|
throw syntax_error(error.c_str());
|
||||||
|
case LUA_ERRMEM:
|
||||||
|
to(error).pop();
|
||||||
|
throw bad_alloc(error.c_str());
|
||||||
|
case LUA_ERRRUN:
|
||||||
|
to(error).pop();
|
||||||
|
throw runtime_error(error.c_str());
|
||||||
|
case LUA_ERRFILE:
|
||||||
|
to(error).pop();
|
||||||
|
throw file_error(error.c_str());
|
||||||
|
default:
|
||||||
|
to(error).pop();
|
||||||
|
throw exception(error.c_str());
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,112 @@
|
|||||||
|
#include "functioncall.h"
|
||||||
|
#define __F_TDEF(CONV,CONV_,tag) typedef int(CONV_ *F_TYPE##CONV##tag)
|
||||||
|
#define __F_T(CONV,tag) F_TYPE##CONV##tag
|
||||||
|
#define __F_TYPEDEFS(CONV,CONV_) __F_TDEF(CONV,CONV_,1)(int);\
|
||||||
|
__F_TDEF(CONV,CONV_,2)(int,int);\
|
||||||
|
__F_TDEF(CONV,CONV_,3)(int,int,int);\
|
||||||
|
__F_TDEF(CONV,CONV_,4)(int,int,int,int);\
|
||||||
|
__F_TDEF(CONV,CONV_,5)(int,int,int,int,int);\
|
||||||
|
__F_TDEF(CONV,CONV_,6)(int,int,int,int,int,int);\
|
||||||
|
__F_TDEF(CONV,CONV_,7)(int,int,int,int,int,int,int)
|
||||||
|
|
||||||
|
|
||||||
|
#define __FCALL(CONV,CONV_) if(conv==CONV)\
|
||||||
|
{ \
|
||||||
|
if(count==1)\
|
||||||
|
ret= (reinterpret_cast<__F_T(CONV,1)>(f))\
|
||||||
|
(arguments[0]);\
|
||||||
|
else if(count==2)\
|
||||||
|
ret= (reinterpret_cast<__F_T(CONV,2)>(f))\
|
||||||
|
(arguments[0],arguments[1]);\
|
||||||
|
else if(count==3)\
|
||||||
|
ret= (reinterpret_cast<__F_T(CONV,3)>(f))\
|
||||||
|
(arguments[0],arguments[1],arguments[2]);\
|
||||||
|
else if(count==4)\
|
||||||
|
ret= (reinterpret_cast<__F_T(CONV,4)>(f))\
|
||||||
|
(arguments[0],arguments[1],arguments[2],arguments[3]);\
|
||||||
|
else if(count==5)\
|
||||||
|
ret= (reinterpret_cast<__F_T(CONV,5)>(f))\
|
||||||
|
(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]);\
|
||||||
|
else if(count==6)\
|
||||||
|
ret= (reinterpret_cast<__F_T(CONV,6)>(f))\
|
||||||
|
(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);\
|
||||||
|
else if(count==7)\
|
||||||
|
ret= (reinterpret_cast<__F_T(CONV,7)>(f))\
|
||||||
|
(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6]);\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __FCALLEX(CONV,CONV_) if(conv==CONV)\
|
||||||
|
{ if(count==1) {__F_T(CONV,1) tmp_F=reinterpret_cast<__F_T(CONV,1)>(f); return tmp_F(arguments[0]);}\
|
||||||
|
else if(count==2){__F_T(CONV,2) tmp_F=reinterpret_cast<__F_T(CONV,2)>(f); return tmp_F(arguments[0],arguments[1]);}\
|
||||||
|
else if(count==3){__F_T(CONV,3) tmp_F=reinterpret_cast<__F_T(CONV,3)>(f); return tmp_F(arguments[0],arguments[1],arguments[2]);}\
|
||||||
|
else if(count==4){__F_T(CONV,4) tmp_F=reinterpret_cast<__F_T(CONV,4)>(f); return tmp_F(arguments[0],arguments[1],arguments[2],arguments[3]);}\
|
||||||
|
else if(count==5){__F_T(CONV,5) tmp_F=reinterpret_cast<__F_T(CONV,5)>(f); return tmp_F(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]);}\
|
||||||
|
else if(count==6){__F_T(CONV,6) tmp_F=reinterpret_cast<__F_T(CONV,6)>(f); return tmp_F(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);}\
|
||||||
|
else if(count==7){__F_T(CONV,7) tmp_F=reinterpret_cast<__F_T(CONV,7)>(f); return tmp_F(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6]);}\
|
||||||
|
}
|
||||||
|
/*else if(count==8)\
|
||||||
|
ret= (reinterpret_cast<__F_T(CONV,8)>(f))\
|
||||||
|
(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7]);\
|
||||||
|
else if(count==9)\
|
||||||
|
ret= (reinterpret_cast<int (CONV_*)(int,int,int,int,int\
|
||||||
|
,int,int,int,int)>(f))\
|
||||||
|
(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8]);\
|
||||||
|
else if(count==10)\
|
||||||
|
ret= (reinterpret_cast<int (CONV_*)(int,int,int,int,int\
|
||||||
|
,int,int,int,int,int)>(f))\
|
||||||
|
(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9]);}*/
|
||||||
|
|
||||||
|
|
||||||
|
int FunctionCaller::CallF(size_t count,callconv conv,void* f,const vector<int> &arguments)//more complex but not more error safe
|
||||||
|
{
|
||||||
|
__F_TYPEDEFS(STD_CALL,__stdcall);
|
||||||
|
__F_TYPEDEFS(FAST_CALL,__fastcall);
|
||||||
|
__F_TYPEDEFS(THIS_CALL,__thiscall);
|
||||||
|
__F_TYPEDEFS(CDECL_CALL,__cdecl);
|
||||||
|
{
|
||||||
|
__FCALLEX(STD_CALL,__stdcall);
|
||||||
|
__FCALLEX(FAST_CALL,__fastcall);
|
||||||
|
__FCALLEX(THIS_CALL,__thiscall);
|
||||||
|
__FCALLEX(CDECL_CALL,__cdecl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int FunctionCaller::CallFunction(size_t func_ptr,callconv conv,const vector<int> &arguments)
|
||||||
|
{
|
||||||
|
//nasty nasty code...
|
||||||
|
|
||||||
|
void* f= reinterpret_cast<void*>(func_ptr+base_);
|
||||||
|
size_t count=arguments.size();
|
||||||
|
if(count==0)
|
||||||
|
return (reinterpret_cast<int (*)()>(f))(); //does not matter how we call it...
|
||||||
|
int ret=0;
|
||||||
|
//typedefs
|
||||||
|
__F_TYPEDEFS(STD_CALL,__stdcall);
|
||||||
|
__F_TYPEDEFS(FAST_CALL,__fastcall);
|
||||||
|
__F_TYPEDEFS(THIS_CALL,__thiscall);
|
||||||
|
__F_TYPEDEFS(CDECL_CALL,__cdecl);
|
||||||
|
//calls
|
||||||
|
__FCALL(STD_CALL,__stdcall);
|
||||||
|
__FCALL(FAST_CALL,__fastcall);
|
||||||
|
__FCALL(THIS_CALL,__thiscall);
|
||||||
|
__FCALL(CDECL_CALL,__cdecl);
|
||||||
|
return -1; //incorect type. Should probably throw...
|
||||||
|
//return CallF(count,conv,f,arguments);
|
||||||
|
/*//testing part{ worked some time ago..., put where DFHack::Core is accesible
|
||||||
|
c->Suspend();
|
||||||
|
FunctionCaller caller(c->p->getBase());
|
||||||
|
std::vector <int> args;
|
||||||
|
args.push_back((size_t)"Hello world");
|
||||||
|
args.push_back(4);
|
||||||
|
args.push_back(4);
|
||||||
|
args.push_back(0);
|
||||||
|
dfprint mprint=(dfprint)(0x27F030+c->p->getBase());
|
||||||
|
mprint("Hello world",4,4,0);
|
||||||
|
//caller.CallFunction((0x27F030),FunctionCaller::THIS_CALL,args);
|
||||||
|
c->Resume();
|
||||||
|
return CR_OK;
|
||||||
|
//}end testing*/
|
||||||
|
}
|
||||||
|
#undef __FCALL
|
||||||
|
#undef __FCALLEX
|
||||||
|
#undef __F_TYPEDEFS
|
||||||
|
#undef __F_T
|
@ -0,0 +1,137 @@
|
|||||||
|
#include "lua_Console.h"
|
||||||
|
//TODO error management. Using lua error? or something other?
|
||||||
|
static DFHack::Console* GetConsolePtr(lua::state &st)
|
||||||
|
{
|
||||||
|
int t=st.gettop();
|
||||||
|
st.getglobal("Console");
|
||||||
|
st.getfield("__pointer");
|
||||||
|
DFHack::Console* c=static_cast<DFHack::Console*>(lua_touserdata(st,-1));
|
||||||
|
st.settop(t);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
static int lua_Console_print(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
int t=st.gettop();
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->print("%s",st.as<string>(t).c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lua_Console_printerr(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
int t=st.gettop();
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->printerr("%s",st.as<string>(t).c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lua_Console_clear(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->clear();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int lua_Console_gotoxy(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->gotoxy(st.as<int>(1,1),st.as<int>(1,2));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int lua_Console_color(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->color( static_cast<DFHack::Console::color_value>(st.as<int>(-1,1)) );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int lua_Console_reset_color(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->reset_color();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int lua_Console_cursor(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->cursor(st.as<bool>(1));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int lua_Console_msleep(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->msleep(st.as<unsigned>(1));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int lua_Console_get_columns(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
st.push(c->get_columns());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int lua_Console_get_rows(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
st.push(c->get_rows());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
static int lua_Console_lineedit(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
string ret;
|
||||||
|
int i=c->lineedit(st.as<string>(1),ret);
|
||||||
|
st.push(ret);
|
||||||
|
st.push(i);
|
||||||
|
return 2;// dunno if len is needed...
|
||||||
|
}
|
||||||
|
static int lua_Console_history_add(lua_State *S)
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->history_add(st.as<string>(1));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*static int lua_Console_history_clear(lua_State *S) //TODO someday add this
|
||||||
|
{
|
||||||
|
lua::state st(S);
|
||||||
|
DFHack::Console* c=GetConsolePtr(st);
|
||||||
|
c->history_clear();
|
||||||
|
return 0;
|
||||||
|
}*/
|
||||||
|
const luaL_Reg lua_console_func[]=
|
||||||
|
{
|
||||||
|
{"print",lua_Console_print},
|
||||||
|
{"printerr",lua_Console_printerr},
|
||||||
|
{"clear",lua_Console_clear},
|
||||||
|
{"gotoxy",lua_Console_gotoxy},
|
||||||
|
{"color",lua_Console_color},
|
||||||
|
{"reset_color",lua_Console_reset_color},
|
||||||
|
{"cursor",lua_Console_cursor},
|
||||||
|
{"msleep",lua_Console_msleep},
|
||||||
|
{"get_columns",lua_Console_get_columns},
|
||||||
|
{"get_rows",lua_Console_get_rows},
|
||||||
|
{"lineedit",lua_Console_lineedit},
|
||||||
|
{"history_add",lua_Console_history_add},
|
||||||
|
//{"history_clear",lua_Console_history_clear},
|
||||||
|
{NULL,NULL}
|
||||||
|
};
|
||||||
|
void lua::RegisterConsole(lua::state &st, DFHack::Console *c)
|
||||||
|
{
|
||||||
|
st.newtable();
|
||||||
|
|
||||||
|
st.pushlightuserdata(c);
|
||||||
|
st.setfield("__pointer");
|
||||||
|
|
||||||
|
lua::RegFunctionsLocal(st, lua_console_func);
|
||||||
|
//TODO add color consts
|
||||||
|
st.setglobal("Console");
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
#include "luamain.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
lua::glua* lua::glua::ptr=0;
|
||||||
|
lua::glua::glua()
|
||||||
|
{
|
||||||
|
RegBasics(mystate);
|
||||||
|
}
|
||||||
|
lua::state &lua::glua::Get()
|
||||||
|
{
|
||||||
|
if(!glua::ptr)
|
||||||
|
glua::ptr=new glua();
|
||||||
|
return glua::ptr->mystate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int lua_Ver_Lua(lua_State *L)
|
||||||
|
{
|
||||||
|
lua::state st(L);
|
||||||
|
st.push(LUA_RELEASE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct luaL_reg lua_basic_lib [] =
|
||||||
|
{
|
||||||
|
{"getluaver", lua_Ver_Lua},
|
||||||
|
{NULL, NULL} /* sentinel */
|
||||||
|
};
|
||||||
|
void lua::RegBasics(lua::state &L)
|
||||||
|
{
|
||||||
|
luaL_openlibs(L);
|
||||||
|
RegFunctions(L,lua_basic_lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lua::RegFunctions(lua::state &L,luaL_reg const*arr)
|
||||||
|
{
|
||||||
|
luaL_reg const *cur=arr;
|
||||||
|
while(cur->name!=NULL)
|
||||||
|
{
|
||||||
|
lua_pushcfunction(L, cur->func);
|
||||||
|
lua_setglobal(L, cur->name);
|
||||||
|
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void lua::RegFunctionsLocal(lua::state &L,luaL_reg const*arr)
|
||||||
|
{
|
||||||
|
luaL_reg const *cur=arr;
|
||||||
|
while(cur->name!=NULL)
|
||||||
|
{
|
||||||
|
lua_pushcfunction(L, cur->func);
|
||||||
|
//lua_setglobal(L, cur->name);
|
||||||
|
L.setfield(cur->name);
|
||||||
|
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string lua::DebugDump(lua::state &L)
|
||||||
|
{
|
||||||
|
L.getglobal("debug");
|
||||||
|
L.getfield("traceback");
|
||||||
|
L.call(0,1);
|
||||||
|
string ret=L.as<string>();
|
||||||
|
//cout<<"StackTrace:"<<ret<<endl;
|
||||||
|
L.settop(0);
|
||||||
|
return ret;
|
||||||
|
}
|
@ -0,0 +1,824 @@
|
|||||||
|
/* vim: set et sw=3 tw=0 fo=croqlaw cino=t0:
|
||||||
|
*
|
||||||
|
* Luaxx, the C++ Lua wrapper library.
|
||||||
|
* Copyright (c) 2006-2008 Matthew Nicholson
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <luaxx.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#define LOG std::cout
|
||||||
|
/** @file
|
||||||
|
* Luaxx implementation file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace lua
|
||||||
|
{
|
||||||
|
void StackDump(lua_State *L)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
for (i = 1; i <= top; i++) /* repeat for each level */
|
||||||
|
{
|
||||||
|
int t = lua_type(L, i);
|
||||||
|
LOG<<i<<":";
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
|
||||||
|
case LUA_TSTRING: /* strings */
|
||||||
|
LOG<<"str ="<<lua_tostring(L, i)<<"\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LUA_TBOOLEAN: /* booleans */
|
||||||
|
LOG<<"bool="<<(lua_toboolean(L, i) ? "true" : "false")<<"\n";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LUA_TNUMBER: /* numbers */
|
||||||
|
LOG<<"num ="<<lua_tonumber(L, i)<<"\n";
|
||||||
|
break;
|
||||||
|
case LUA_TTABLE:
|
||||||
|
|
||||||
|
LOG<<lua_typename(L, t);
|
||||||
|
{
|
||||||
|
//LOG<<"PRE TOP:"<< lua_gettop(L)<<"\n";
|
||||||
|
lua_getglobal(L,"PrintTable");
|
||||||
|
//lua_insert(L,-2);
|
||||||
|
lua_pushvalue(L,i);
|
||||||
|
lua_pcall(L,1,0,0);
|
||||||
|
//LOG<<"POST TOP:"<< lua_gettop(L)<<"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default: /* other values */
|
||||||
|
LOG<<lua_typename(L, t);
|
||||||
|
{
|
||||||
|
//LOG<<"PRE TOP:"<< lua_gettop(L)<<"\n";
|
||||||
|
lua_getglobal(L,"tostring");
|
||||||
|
//lua_insert(L,-2);
|
||||||
|
lua_pushvalue(L,i);
|
||||||
|
lua_pcall(L,1,1,0);
|
||||||
|
LOG<<"=";
|
||||||
|
LOG<<lua_tostring(L,-1)<<"\n";
|
||||||
|
lua_pop(L,1);
|
||||||
|
//LOG<<"POST TOP:"<< lua_gettop(L)<<"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
LOG<<"\n"; /* end the listing */
|
||||||
|
LOG<<"==============================\n";
|
||||||
|
}
|
||||||
|
#undef LOG
|
||||||
|
/// Construct our lua environment.
|
||||||
|
state::state() : L(luaL_newstate()), managed(true) {
|
||||||
|
if (L == NULL)
|
||||||
|
throw bad_alloc("Error creating lua state");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct our lua environment from an existing lua_State.
|
||||||
|
* @param L the existing state to use.
|
||||||
|
*
|
||||||
|
* This function differs from the normal constructor as it sets a flag
|
||||||
|
* that prevents lua_close() from being called when this class is
|
||||||
|
* destroyed.
|
||||||
|
*/
|
||||||
|
state::state(lua_State* L) :
|
||||||
|
L(L), managed(false) {
|
||||||
|
}
|
||||||
|
state& state::operator = (const state& t)
|
||||||
|
{
|
||||||
|
if(managed)
|
||||||
|
lua_close(L);
|
||||||
|
managed=false;
|
||||||
|
L=t.L;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
/// Destroy our lua environment.
|
||||||
|
state::~state() {
|
||||||
|
if (managed)
|
||||||
|
lua_close(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push a nil onto the stack.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::push() {
|
||||||
|
lua_pushnil(L);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push a nil onto the stack.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::push(nil) {
|
||||||
|
lua_pushnil(L);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push a boolean onto the stack.
|
||||||
|
* @param boolean the value to push
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::push(bool boolean) {
|
||||||
|
lua_pushboolean(L, boolean);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push a C-style string onto the stack.
|
||||||
|
* @param s the string to push
|
||||||
|
* @param length the length of the string
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::push(const char* s, size_t length) {
|
||||||
|
lua_pushlstring(L, s, length);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push a C-style string onto the stack.
|
||||||
|
* @param s the string to push
|
||||||
|
* @note This must be a '0' terminated string.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::push(const char* s) {
|
||||||
|
lua_pushstring(L, s);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push an std::string onto the stack.
|
||||||
|
* @param s the string to push
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::push(const std::string& s) {
|
||||||
|
lua_pushlstring(L, s.c_str(), s.size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push an C function onto the stack.
|
||||||
|
* @param f the function to push
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::push(cfunction f) {
|
||||||
|
lua_pushcfunction(L, f);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a new table on to the stack.
|
||||||
|
* @see state::newtable()
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::push(table) {
|
||||||
|
lua_newtable(L);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push a light userdatum on to the stack.
|
||||||
|
* @param p the pointer to push
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::push(void* p) {
|
||||||
|
lua_pushlightuserdata(L, p);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the value at index as a string.
|
||||||
|
* @param default_value this value is returned if the conversion fails
|
||||||
|
* @param index the index to get
|
||||||
|
* @note This function does \em not pop the value from the stack.
|
||||||
|
*
|
||||||
|
* @note lua::state::as(std::string()) will convert the value at the
|
||||||
|
* indicated index to a string <em>on the stack</em>. This can
|
||||||
|
* confuse lua::state::next();
|
||||||
|
*
|
||||||
|
* @returns the indicated value from the stack or the default value if the
|
||||||
|
* conversion fails
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
std::string state::as(std::string default_value, int index) {
|
||||||
|
if (lua_isstring(L, index))
|
||||||
|
return std::string(lua_tostring(L, index), lua_strlen(L, index));
|
||||||
|
else
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check an argument of the current function.
|
||||||
|
* @param narg the argument number to check
|
||||||
|
*
|
||||||
|
* This function will throw a lua error if there is no argument at the
|
||||||
|
* given position.
|
||||||
|
*
|
||||||
|
* @note This function is meant to be called from with in a lua::cfunction.
|
||||||
|
* The error throw is internal to the lua interpreter. When compiled as
|
||||||
|
* C++, a C++ exception is thrown, so the stack is properly unwound. This
|
||||||
|
* exception is not meant to be caught.
|
||||||
|
*/
|
||||||
|
state& state::check(int narg) {
|
||||||
|
luaL_checkany(L, narg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef lua_Integer_int
|
||||||
|
/** Check an argument of the current function.
|
||||||
|
* @param i the int to hold the returned value
|
||||||
|
* @param narg the argument number to check
|
||||||
|
*
|
||||||
|
* This function checks if the given argument number is an int.
|
||||||
|
*
|
||||||
|
* @note This function is meant to be called from with in a
|
||||||
|
* lua::cfunction. The error throw is internal to the lua intrepeter.
|
||||||
|
* When compiled as C++, a C++ exception is thrown, so the stack is
|
||||||
|
* properly unwound. This exception is not meant to be caught.
|
||||||
|
*/
|
||||||
|
state& state::check(int& i, int narg) {
|
||||||
|
i = luaL_checkint(L, narg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Check an argument of the current function.
|
||||||
|
* @param i the lua::integer (lua_Integer) to hold the returned value
|
||||||
|
* @param narg the argument number to check
|
||||||
|
*
|
||||||
|
* This function checks if the given argument number is an integer.
|
||||||
|
*
|
||||||
|
* @note This is different from lua::check(int(), ...). It returns a
|
||||||
|
* lua::integer (lua_Integer), which may not be an int.
|
||||||
|
*
|
||||||
|
* @note This function is meant to be called from with in a
|
||||||
|
* lua::cfunction. The error throw is internal to the lua intrepeter.
|
||||||
|
* When compiled as C++, a C++ exception is thrown, so the stack is
|
||||||
|
* properly unwound. This exception is not meant to be caught.
|
||||||
|
*/
|
||||||
|
state& state::check(integer& i, int narg) {
|
||||||
|
i = luaL_checkinteger(L, narg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef lua_Integer_long
|
||||||
|
/** Check an argument of the current function.
|
||||||
|
* @param l the long to hold the returned value
|
||||||
|
* @param narg the argument number to check
|
||||||
|
*
|
||||||
|
* This function checks if the given argument number is a long.
|
||||||
|
*
|
||||||
|
* @note This function is meant to be called from with in a
|
||||||
|
* lua::cfunction. The error throw is internal to the lua intrepeter.
|
||||||
|
* When compiled as C++, a C++ exception is thrown, so the stack is
|
||||||
|
* properly unwound. This exception is not meant to be caught.
|
||||||
|
*/
|
||||||
|
state& state::check(long& l, int narg) {
|
||||||
|
l = luaL_checklong(L, narg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Check an argument of the current function.
|
||||||
|
* @param s the string to hold the returned value
|
||||||
|
* @param narg the argument number to check
|
||||||
|
*
|
||||||
|
* This function checks if the given argument number is a string.
|
||||||
|
*
|
||||||
|
* @note This function is meant to be called from with in a
|
||||||
|
* lua::cfunction. The error throw is internal to the lua intrepeter.
|
||||||
|
* When compiled as C++, a C++ exception is thrown, so the stack is
|
||||||
|
* properly unwound. This exception is not meant to be caught.
|
||||||
|
*/
|
||||||
|
state& state::check(std::string& s, int narg) {
|
||||||
|
const char* c;
|
||||||
|
size_t l;
|
||||||
|
c = luaL_checklstring(L, narg, &l);
|
||||||
|
|
||||||
|
s.assign(c, l);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check an argument of the current function.
|
||||||
|
* @param n the lua::number (lua_Number) to hold the returned value
|
||||||
|
* @param narg the argument number to check
|
||||||
|
*
|
||||||
|
* This function checks if the given argument number is a lua::number
|
||||||
|
* (lua_Number, a double by default).
|
||||||
|
*
|
||||||
|
* @note This function is meant to be called from with in a lua::cfunction.
|
||||||
|
* The error throw is internal to the lua interpreter. When compiled as
|
||||||
|
* C++, a C++ exception is thrown, so the stack is properly unwound. This
|
||||||
|
* exception is not meant to be caught.
|
||||||
|
*/
|
||||||
|
state& state::check(number& n, int narg) {
|
||||||
|
n = luaL_checknumber(L, narg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/** [specialization] Generate a Lua error (T = std::string).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
void state::error(const std::string& message) {
|
||||||
|
push(message);
|
||||||
|
lua_error(L);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Call a lua function.
|
||||||
|
* @param nargs the number of args to pass to the function
|
||||||
|
* @param nresults the number of values to return from the function
|
||||||
|
* @param on_error A stack index where the error handling function is
|
||||||
|
* stored.
|
||||||
|
* @note The error handling function must be pushed in the stack
|
||||||
|
* before the function to be called and its arguments.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::pcall(int nargs, int nresults, int on_error) {
|
||||||
|
throw_error(lua_pcall(L, nargs, nresults, on_error));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Call a lua function in unprotected mode.
|
||||||
|
* @param nargs the number of args to pass to the function
|
||||||
|
* @param nresults the number of values to return from the function
|
||||||
|
* stored.
|
||||||
|
* @note If there is an error in the call the program will terminate.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::call(int nargs, int nresults) {
|
||||||
|
lua_call(L, nargs, nresults);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Ensure the stack is at least the given size.
|
||||||
|
* @param size the size to use
|
||||||
|
*
|
||||||
|
* If the stack is smaller than the given size, it will grow to the
|
||||||
|
* specified size.
|
||||||
|
*
|
||||||
|
* @exception lua::exception Thrown if the operation fails.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::checkstack(int size) {
|
||||||
|
if (!lua_checkstack(L, size))
|
||||||
|
throw lua::exception("Error growing the stack");
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set a new index as the top of the stack.
|
||||||
|
* @param index the index to use as the new top
|
||||||
|
* @note If the previous top was higher than the new one, top values
|
||||||
|
* are discarded. Otherwise this function pushs nils on to the stack
|
||||||
|
* to get the proper size.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::settop(int index) {
|
||||||
|
lua_settop(L, index);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the number of elements in the stack.
|
||||||
|
* @note This value is also the index of the top element.
|
||||||
|
* @returns the number of elements in the stack
|
||||||
|
*/
|
||||||
|
int state::gettop() {
|
||||||
|
return lua_gettop(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the number of elements in the stack.
|
||||||
|
* @note This value is also the index of the top element.
|
||||||
|
* @returns the number of elements in the stack
|
||||||
|
*/
|
||||||
|
int state::size() {
|
||||||
|
return lua_gettop(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if the stack is empty.
|
||||||
|
* @returns true if the stack is empty, false otherwise
|
||||||
|
*/
|
||||||
|
bool state::empty() {
|
||||||
|
return !lua_gettop(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Move the top element to the given index.
|
||||||
|
* @param index the index to insert at
|
||||||
|
* @note All elements on top of the given index are shifted up to open
|
||||||
|
* space for this element.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::insert(int index) {
|
||||||
|
lua_insert(L, index);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Replace the given index with the top element.
|
||||||
|
* @param index the index to replae
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::replace(int index) {
|
||||||
|
lua_replace(L, index);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove the given index from the stack.
|
||||||
|
* @param index the index to remove
|
||||||
|
* @note Elements are shifted down to fill in the empty spot.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::remove(int index) {
|
||||||
|
lua_remove(L, index);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove the given number of elemens from the stack.
|
||||||
|
* @param elements the number of elements to remove
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::pop(int elements) {
|
||||||
|
lua_pop(L, elements);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Push a copy of the element at the given index to the top of the
|
||||||
|
* stack.
|
||||||
|
* @param index the index of the element to copy
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::pushvalue(int index) {
|
||||||
|
lua_pushvalue(L, index);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a new table on the stack.
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::newtable() {
|
||||||
|
lua_newtable(L);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a new metatable and add it to the registry.
|
||||||
|
* @param tname the name to use for the new metatable in the registry
|
||||||
|
*
|
||||||
|
* This function creates a new metatable and adds it to the registry
|
||||||
|
* with the given key. This function also pushes the new metatable
|
||||||
|
* onto the stack.
|
||||||
|
*
|
||||||
|
* @note Regardless of the return value, the new metatable is always pushed
|
||||||
|
* on to the stack.
|
||||||
|
*
|
||||||
|
* @return true if a new metatable was created, false if the registry
|
||||||
|
* alread has a key with the given name.
|
||||||
|
*/
|
||||||
|
bool state::newmetatable(const std::string& tname) {
|
||||||
|
return luaL_newmetatable(L, tname.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a new userdatum on the stack.
|
||||||
|
* @param nbytes the size of the new userdatum
|
||||||
|
* @return a pointer to the new userdatum
|
||||||
|
*/
|
||||||
|
void* state::newuserdata(size_t nbytes) {
|
||||||
|
return lua_newuserdata(L, nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a value from a table on the stack.
|
||||||
|
* @param index the index the table is stored at
|
||||||
|
*
|
||||||
|
* This function gets a value from the table at the given index and
|
||||||
|
* pushes it onto the stack.
|
||||||
|
*
|
||||||
|
* @note You should have already pushed the key used to reference this
|
||||||
|
* value onto the stack before calling this function.
|
||||||
|
*
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::gettable(int index) {
|
||||||
|
lua_gettable(L, index);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a value from a table on the stack.
|
||||||
|
* @param k the key
|
||||||
|
* @param index the index the table is stored at
|
||||||
|
*
|
||||||
|
* This function gets a value from the table at the given index and
|
||||||
|
* pushes it onto the stack.
|
||||||
|
*
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::getfield(const std::string& k, int index) {
|
||||||
|
lua_getfield(L, index, k.c_str());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set a value in a table.
|
||||||
|
* @param index the index the table is stored at
|
||||||
|
*
|
||||||
|
* This function sets a value in a table stored at the given index.
|
||||||
|
*
|
||||||
|
* @note The key and value to be used should have already been pushed
|
||||||
|
* on the stack in that order.
|
||||||
|
*
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::settable(int index) {
|
||||||
|
lua_settable(L, index);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set a field in a table.
|
||||||
|
* @param k the key
|
||||||
|
* @param index the index the table is stored at
|
||||||
|
*
|
||||||
|
* This function sets a value in a table stored at the given index.
|
||||||
|
*
|
||||||
|
* @note The value to be used should be on the top of the stack.
|
||||||
|
*
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::setfield(const std::string& k, int index) {
|
||||||
|
lua_setfield(L, index, k.c_str());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the metatable associated with the given registry entry.
|
||||||
|
* @param tname the name in the registry
|
||||||
|
*
|
||||||
|
* This function gets the metatable associated with the given key in
|
||||||
|
* the registry. The resulting metatable is pushed onto the stack.
|
||||||
|
*
|
||||||
|
* @note This function uses luaL_getmetatable() internally.
|
||||||
|
*
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::getmetatable(const std::string& tname) {
|
||||||
|
luaL_getmetatable(L, tname.c_str());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the metatable of the value at the given index.
|
||||||
|
* @param index the index the value is stored at
|
||||||
|
*
|
||||||
|
* This function pushes on to the stack the metatabe of the value at
|
||||||
|
* the given index.
|
||||||
|
*
|
||||||
|
* @note This function uses lua_getmetatable() internally.
|
||||||
|
*
|
||||||
|
* @returns false if the value at the given index does not have a
|
||||||
|
* metatable or if the index is not valid
|
||||||
|
*/
|
||||||
|
bool state::getmetatable(int index) {
|
||||||
|
return lua_getmetatable(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the next key value pair from a table on the stack.
|
||||||
|
* @param index the stack index the table is at
|
||||||
|
*
|
||||||
|
* This function pops a key from the stack and pushes the next key
|
||||||
|
* value pair to the stack. The key will be stored at index -2 and
|
||||||
|
* the value will be at index -1. The key is expected to be on the
|
||||||
|
* top of the stack.
|
||||||
|
*
|
||||||
|
* @note While traversing a table, do not call
|
||||||
|
* lua::state::to(std::string()) directly on a key, unless you know
|
||||||
|
* that the key is actually a string. lua::state::to(std::string())
|
||||||
|
* changes the value at the given index; this confuses the next call
|
||||||
|
* to lua::state::next().
|
||||||
|
*
|
||||||
|
* <strong>While Loop Example:</strong>
|
||||||
|
* @code
|
||||||
|
* while(L.next() != 0) {
|
||||||
|
* // do stuff
|
||||||
|
* L.pop();
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* <strong>For Loop Example:</strong>
|
||||||
|
* @code
|
||||||
|
* for(L.push(lua::nil()); L.next(); L.pop()) {
|
||||||
|
* // do stuff
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @returns true as long as there are remaining items in the table
|
||||||
|
*/
|
||||||
|
bool state::next(int index) {
|
||||||
|
return lua_next(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load a global symbol onto the stack.
|
||||||
|
* @param name the name of the global to load
|
||||||
|
*
|
||||||
|
* This function loads a global symbol onto the stack from the lua
|
||||||
|
* state.
|
||||||
|
*
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::getglobal(const std::string& name) {
|
||||||
|
lua_getglobal(L, name.c_str());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set a global symbol.
|
||||||
|
* @param name the name of the global to set
|
||||||
|
*
|
||||||
|
* This function sets/creates a global symbol from the value above it
|
||||||
|
* on the stack.
|
||||||
|
*
|
||||||
|
* @note You should have pushed the value of the symbol onto the stack
|
||||||
|
* before calling this function.
|
||||||
|
*
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::setglobal(const std::string& name) {
|
||||||
|
lua_setglobal(L, name.c_str());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load a file as a Lua chunk.
|
||||||
|
* @param filename the name of the file to load
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::loadfile(const std::string& filename) {
|
||||||
|
throw_error(luaL_loadfile(L, filename.c_str()));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load a string as a Lua chunk.
|
||||||
|
* @param s the string to load
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
state& state::loadstring(const std::string& s) {
|
||||||
|
throw_error(luaL_loadstring(L, s.c_str()));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the length of a value on the stack.
|
||||||
|
* @param index the index the value is stored at
|
||||||
|
* @returns the length of the indicated value
|
||||||
|
*/
|
||||||
|
size_t state::objlen(int index) {
|
||||||
|
return lua_objlen(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the value at index as a bool.
|
||||||
|
* @param boolean where to store the value
|
||||||
|
* @param index the index to get
|
||||||
|
* @note This function does \em not pop the value from the stack.
|
||||||
|
* @todo Instead of throwing an exception here, we may just return an
|
||||||
|
* error code.
|
||||||
|
* @throws lua::bad_conversion if the value on the stack could not be
|
||||||
|
* converted to the indicated type
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
state& state::to(bool& boolean, int index) {
|
||||||
|
if (lua_isboolean(L, index))
|
||||||
|
boolean = lua_toboolean(L, index);
|
||||||
|
else
|
||||||
|
throw bad_conversion("Cannot convert non 'boolean' value to bool");
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the value at index as a string.
|
||||||
|
* @param string where to store the value
|
||||||
|
* @param index the index to get
|
||||||
|
* @note This function does \em not pop the value from the stack.
|
||||||
|
* @todo Instead of throwing an exception here, we may just return an
|
||||||
|
* error code.
|
||||||
|
*
|
||||||
|
* @note lua::state::to(std::string()) will convert the value at the
|
||||||
|
* indicated index to a string <em>on the stack</em>. This can
|
||||||
|
* confuse lua::state::next();
|
||||||
|
*
|
||||||
|
* @throws lua::bad_conversion if the value on the stack could not be
|
||||||
|
* converted to the indicated type
|
||||||
|
* @returns a reference to this lua::state
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
state& state::to(std::string& string, int index) {
|
||||||
|
if (lua_isstring(L, index))
|
||||||
|
string.replace(0, std::string::npos, lua_tostring(L, index), lua_strlen(L, index));
|
||||||
|
else
|
||||||
|
throw bad_conversion("Cannot convert value to string");
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the value at index as a bool.
|
||||||
|
* @param default_value this value is returned if the conversion fails
|
||||||
|
* @param index the index to get
|
||||||
|
* @note This function does \em not pop the value from the stack.
|
||||||
|
* @returns the indicated value from the stack or the default value if the
|
||||||
|
* conversion fails
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::as(bool default_value, int index) {
|
||||||
|
if (lua_isboolean(L, index))
|
||||||
|
return lua_toboolean(L, index);
|
||||||
|
else
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Get the value at index as a bool (T = bool).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::as(int index) {
|
||||||
|
if (lua_isboolean(L, index))
|
||||||
|
return lua_toboolean(L, index);
|
||||||
|
else
|
||||||
|
throw bad_conversion("Cannot convert non 'boolean' value to bool");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Get the value at index as a string (T = std::string).
|
||||||
|
* @note lua::state::as(std::string()) will convert the value at the
|
||||||
|
* indicated index to a string <em>on the stack</em>. This can confuse
|
||||||
|
* lua::state::next();
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
std::string state::as(int index) {
|
||||||
|
if (lua_isstring(L, index))
|
||||||
|
return std::string(lua_tostring(L, index), lua_strlen(L, index));
|
||||||
|
else
|
||||||
|
throw bad_conversion("Cannot convert value to string");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Check if the given index is a nil (T = lua::nil).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::is<nil>(int index) {
|
||||||
|
return lua_isnil(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Check if the given index is a boolean (T = bool).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::is<bool>(int index) {
|
||||||
|
return lua_isboolean(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Check if the given index is a string (T = std::string).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::is<std::string>(int index) {
|
||||||
|
return lua_isstring(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Check if the given index is a table (T = lua::table).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::is<table>(int index) {
|
||||||
|
return lua_istable(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Check if the given index is a C function (T =
|
||||||
|
* lua::cfunction).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::is<cfunction>(int index) {
|
||||||
|
return lua_iscfunction(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Check if the given index is a function (T =
|
||||||
|
* lua::function).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::is<function>(int index) {
|
||||||
|
return lua_isfunction(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Check if the given index is userdata (T =
|
||||||
|
* lua::userdata).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::is<userdata>(int index) {
|
||||||
|
return lua_isuserdata(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [specialization] Check if the given index is light userdata (T =
|
||||||
|
* lua::lightuserdata).
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
bool state::is<lightuserdata>(int index) {
|
||||||
|
return lua_islightuserdata(L, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue