luaxx.hpp

Go to the documentation of this file.
00001 /* vim: set et sw=3 tw=0 fo=croqlaw cino=t0:
00002  *
00003  * Luaxx, the C++ Lua wrapper library.
00004  * Copyright (c) 2006-2008 Matthew Nicholson
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a copy 
00007  * of this software and associated documentation files (the "Software"), to 
00008  * deal in the Software without restriction, including without limitation the 
00009  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
00010  * sell copies of the Software, and to permit persons to whom the Software is 
00011  * furnished to do so, subject to the following conditions:
00012  * 
00013  * The above copyright notice and this permission notice shall be included in 
00014  * all copies or substantial portions of the Software.
00015  * 
00016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
00017  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
00018  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
00019  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
00020  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
00021  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
00022  * IN THE SOFTWARE. 
00023  */
00024 
00025 #ifndef LUAXX_H
00026 #define LUAXX_H
00027 
00028 #include <lua.hpp>
00029 #include <string>
00030 #include <vector>
00031 #include <new>
00032 #include <exception>
00033 
00055 namespace lua
00056 {
00059    class exception : public std::exception {
00060       public:
00062          exception() : std::exception() { }
00064          explicit exception(const char* desc) : std::exception(), description(desc) { }
00065          virtual ~exception() throw() { }
00069          virtual const char* what() const throw() {
00070             return description.c_str();
00071          }
00072       private:
00073          std::string description;
00074    };
00075 
00080    class runtime_error : public exception {
00081       public:
00083          runtime_error() : exception() { }
00085          explicit runtime_error(const char* desc) : exception(desc) { }
00086          virtual ~runtime_error() throw() { }
00087    };
00088 
00091    class syntax_error : public exception {
00092       public:
00094          syntax_error() : exception() { }
00096          explicit syntax_error(const char* desc) : exception(desc) { }
00097          virtual ~syntax_error() throw() { }
00098    };
00099 
00104    class file_error : public exception {
00105       public:
00107          file_error() : exception() { }
00109          explicit file_error(const char* desc) : exception(desc) { }
00110          virtual ~file_error() throw() { }
00111    };
00112 
00115    class bad_alloc : public exception, std::bad_alloc {
00116       public:
00118          bad_alloc() : lua::exception(), std::bad_alloc() { }
00120          explicit bad_alloc(const char* desc) : lua::exception(desc), std::bad_alloc() { }
00121          virtual ~bad_alloc() throw() { }
00122    };
00123    
00126    class bad_conversion : public exception {
00127       public:
00129          bad_conversion() : exception() { }
00131          explicit bad_conversion(const char* desc) : exception(desc) { }
00132          virtual ~bad_conversion() throw() { }
00133    };
00134 
00136    class table { };
00138    class nil { };
00140    class function { };
00142    class userdata { };
00144    class lightuserdata { };
00145 
00146    typedef lua_CFunction cfunction;  
00147    typedef lua_Integer integer;      
00148    typedef lua_Number number;        
00149    typedef lua_Reader reader;        
00150    const int multiret = LUA_MULTRET; 
00151 
00156    class state {
00157       public:
00158          state();
00159          state(lua_State* L);
00160          ~state();
00161 
00162          operator lua_State*();
00163 
00164          state& push();
00165          state& push(nil);
00166          state& push(bool boolean);
00167          template<typename T> state& push(T number);
00168          state& push(const char* s, size_t length);
00169          state& push(const char* s);
00170          state& push(const std::string& s);
00171          state& push(cfunction f);
00172          state& push(table);
00173          state& push(void* p);
00174          template<typename T> state& pushlightuserdata(T p);
00175          
00176          template<typename T> state& to(T& number, int index = -1);
00177          template<typename T> state& touserdata(T& p, int index = -1);
00178 
00179          template<typename T> T as(T default_value, int index = -1);
00180          template<typename T> T as(int index = -1);
00181 
00182          template<typename T> bool is(int index = -1);
00183 
00184          state& check(int narg);
00185 #if lua_Integer != int
00186          state& check(int& i, int narg);
00187 #endif
00188          state& check(integer& i, int narg);
00189 #if lua_Integer != long
00190          state& check(long& l, int narg);
00191 #endif
00192          state& check(std::string& s, int narg);
00193          state& check(number& n, int narg);
00194 
00195          template<typename msg_t> void error(msg_t message);
00196 #if 0
00197          template<> void error(const std::string& message);
00198 #endif
00199 
00200          state& pcall(int nargs = 0, int nresults = 0, int on_error = 0);
00201          state& call(int nargs = 0, int nresults = 0);
00202          
00203          state& checkstack(int size);
00204          state& settop(int index);
00205          int gettop();
00206          int size();
00207          bool empty();
00208          
00209          state& insert(int index);
00210          state& replace(int index);
00211          state& remove(int index);
00212          state& pop(int elements = 1);
00213 
00214          state& pushvalue(int index);
00215 
00216          state& newtable();
00217          bool newmetatable(const std::string& tname);
00218          template<typename userdata_t> userdata_t* newuserdata();
00219          void* newuserdata(size_t nbytes);
00220 
00221          state& gettable(int index = -2);
00222          state& getfield(const std::string& k, int index = -1);
00223          state& settable(int index = -3);
00224          state& setfield(const std::string& k, int index = -2);
00225          state& getmetatable(const std::string& tname);
00226          bool getmetatable(int index);
00227 
00228          bool next(int index = -2);
00229 
00230          state& getglobal(const std::string& name);
00231          state& setglobal(const std::string& name);
00232 
00233          state& loadfile(const std::string& filename);
00234          state& loadstring(const std::string& s);
00235 
00236          template<typename iterator_t> state& load(iterator_t begin, iterator_t end);
00237 
00238          size_t objlen(int index = -1);
00239 
00240       private:
00241          lua_State* L;
00242          bool managed;
00243          
00244          // make lua::states non copyable
00245          state(const state&);              
00246          state& operator = (const state&); 
00247 
00248          int throw_error(int code);
00249    };
00250 
00251    // template functions
00252    
00260    template<typename T>
00261    state& state::push(T number) {
00262       lua_pushnumber(L, number);
00263       return *this;
00264    }
00265 
00271    template<typename T>
00272    state& state::pushlightuserdata(T p) {
00273       lua_pushlightuserdata(L, p);
00274       return *this;
00275    }
00276 
00286    template<typename T>
00287    bool state::is(int index) {
00288       return lua_isnumber(L, index);
00289    }
00290 
00303    template<typename T>
00304    state& state::to(T& number, int index) {
00305       if (lua_isnumber(L, index))
00306          number = static_cast<T>(lua_tonumber(L, index));
00307       else
00308          throw bad_conversion("Cannot convert non 'number' value to number");
00309 
00310       return *this;
00311    }
00312    
00325    template<typename T>
00326    state& state::touserdata(T& p, int index) {
00327       if (lua_isuserdata(L, index))
00328          p = reinterpret_cast<T>(lua_touserdata(L, index));
00329       else
00330          throw bad_conversion("Cannot convert non 'userdata' or 'lightuserdata' value to userdata");
00331 
00332       return *this;
00333    }
00334    
00345    template<typename T>
00346    T state::as(T default_value, int index) {
00347       if (lua_isnumber(L, index))
00348          return static_cast<T>(lua_tonumber(L, index));
00349       else
00350          return default_value;
00351    }
00352 
00377    template<typename T>
00378    T state::as(int index) {
00379       if (lua_isnumber(L, index))
00380          return static_cast<T>(lua_tonumber(L, index));
00381       else
00382          throw bad_conversion("Cannot convert non 'number' value to number");
00383    }
00384    
00392    template<typename userdata_t>
00393    userdata_t* state::newuserdata() {
00394       return reinterpret_cast<userdata_t*>(lua_newuserdata(L, sizeof(userdata_t)));
00395    }
00396 
00405    template<typename msg_t>
00406    void state::error(msg_t message) {
00407       push(message);
00408       lua_error(L);
00409    }
00410 
00427    template<typename iterator_t>
00428    state& state::load(iterator_t begin, iterator_t end) {
00429       // convert the data to characters
00430       std::vector<char> chunk(begin, end);
00431       
00432       // Here we use the address of the first element of our vector.  
00433       // This works because the data in std::vectors is contiguous.
00434       throw_error(luaL_loadbuffer(L, &(*chunk.begin()), chunk.size(), NULL));
00435       return *this;
00436    }
00437 
00438 
00439    // template specializations
00440    template<> state& state::to(bool& boolean, int index);
00441    template<> state& state::to(std::string& string, int index);
00442 
00443    template<> bool state::as(bool default_value, int index);
00444    template<> std::string state::as(std::string default_value, int index);
00445    template<> bool state::as(int index);
00446    template<> std::string state::as(int index);
00447 
00448    template<> bool state::is<nil>(int index);
00449    template<> bool state::is<bool>(int index);
00450    template<> bool state::is<std::string>(int index);
00451    template<> bool state::is<table>(int index);
00452    template<> bool state::is<cfunction>(int index);
00453    template<> bool state::is<function>(int index);
00454    template<> bool state::is<userdata>(int index);
00455    template<> bool state::is<lightuserdata>(int index);
00456   
00457 
00458    // inline functions
00459    
00467    inline state::operator lua_State*() {
00468       return L;
00469    }
00470 
00482    inline int state::throw_error(int code) {
00483       std::string error;
00484 
00485       // below, we package lua errors into exceptions
00486       switch (code) {
00487          case 0:
00488             break;
00489          case LUA_ERRSYNTAX:
00490             to(error).pop();
00491             throw syntax_error(error.c_str());
00492          case LUA_ERRMEM:
00493             to(error).pop();
00494             throw bad_alloc(error.c_str());
00495          case LUA_ERRRUN:
00496             to(error).pop();
00497             throw runtime_error(error.c_str());
00498          case LUA_ERRFILE:
00499             to(error).pop();
00500             throw file_error(error.c_str());
00501          default:
00502             to(error).pop();
00503             throw exception(error.c_str());
00504       }
00505       return code;
00506    }
00507    
00508 }
00509 
00510 #endif

Generated on Wed Apr 30 09:34:45 2008 for Luaxx by  doxygen 1.5.5