]> Dogcows Code - chaz/yoink/blobdiff - src/moof/script.hh
fixed documentation about where to find licenses
[chaz/yoink] / src / moof / script.hh
index 35e80d22eb6a8e57cec4d2b81fc148249888b863..0431f1afcebbe50e5942731074acef3ddf8e85f4 100644 (file)
@@ -1,27 +1,15 @@
 
-/*]  Copyright (c) 2009-2010, Charles McGarvey  [**************************
+/*]  Copyright (c) 2009-2011, Charles McGarvey  [*****************************
 **]  All rights reserved.
 *
-* vi:ts=4 sw=4 tw=75
-*
 * Distributable under the terms and conditions of the 2-clause BSD license;
 * see the file COPYING for a complete text of the license.
 *
-**************************************************************************/
+*****************************************************************************/
 
 #ifndef _MOOF_SCRIPT_HH_
 #define _MOOF_SCRIPT_HH_
 
-/**
- * \file script.hh
- * A thin wrapper over Lua 5.1.  This is not meant as a complicated binding
- * package between C++ and Lua.  It is not meant to obscure the division
- * between C++ and Lua but rather to clarify it and make it more
- * manageable.  It does not hide the concept of the Lua stack, but rather
- * provides that mechanism with a certain level of abstraction while also
- * providing a cleaner, more consistent API.
- */
-
 #include <cstring>
 #include <iostream>
 #include <map>
 #include <lua.hpp>
 
 
+/**
+ * \file script.hh
+ * A thin wrapper over Lua 5.1.  This is not meant as a complicated binding
+ * package between C++ and Lua.  It is not meant to obscure the division
+ * between C++ and Lua but rather to clarify it and make it more manageable.
+ * It does not hide the concept of the Lua stack, but rather provides that
+ * mechanism with a certain level of abstraction while also providing a
+ * cleaner, more consistent API.
+ */
+
 namespace moof {
 
 
 class script;
 typedef boost::shared_ptr<script> script_ptr;
 
-
 class script
 {
 public:
@@ -53,13 +50,13 @@ public:
 
        enum status
        {
-               success                 = 0,
-               yielding                = LUA_YIELD,
+               success         = 0,
+               yielding        = LUA_YIELD,
                runtime_error   = LUA_ERRRUN,
                syntax_error    = LUA_ERRSYNTAX,
                memory_error    = LUA_ERRMEM,
                handler_error   = LUA_ERRERR,
-               file_error              = LUA_ERRFILE
+               file_error      = LUA_ERRFILE
        };
 
        enum pseudoindex
@@ -69,7 +66,6 @@ public:
                globals_index           = LUA_GLOBALSINDEX
        };
 
-
        template <class T>
        static int object_finalizer(script& script)
        {
@@ -77,88 +73,78 @@ public:
                return 0;
        }
 
-
        /**
         * This is the most prominent abstraction on top of the standard Lua
         * API.  A slot object represents a value on the stack.  More
         * specifically, it represents a position on the stack.  The
         * distinction is only important when objects are moved around on the
         * stack or if the slot represents a negative index on the stack (the
-        * value of which will change as things are pushed onto and popped from
-        * the stack).
+        * value of which will change as things are pushed onto and popped
+        * from the stack).
         */
        struct slot
        {
                /**
-                * You have direct access to the index of the value on the stack
-                * being represented.
+                * You have direct access to the index of the value on the
+                * stack being represented.
                 */
                int index;
 
-
                enum type
                {
-                       none                    = LUA_TNONE,
-                       nil                             = LUA_TNIL,
-                       boolean                 = LUA_TBOOLEAN,
-                       light_data              = LUA_TLIGHTUSERDATA,
-                       number                  = LUA_TNUMBER,
-                       string                  = LUA_TSTRING,
-                       table                   = LUA_TTABLE,
-                       function                = LUA_TFUNCTION,
-                       data                    = LUA_TUSERDATA,
-                       thread                  = LUA_TTHREAD
+                       none            = LUA_TNONE,
+                       nil             = LUA_TNIL,
+                       boolean         = LUA_TBOOLEAN,
+                       light_data      = LUA_TLIGHTUSERDATA,
+                       number          = LUA_TNUMBER,
+                       string          = LUA_TSTRING,
+                       table           = LUA_TTABLE,
+                       function        = LUA_TFUNCTION,
+                       data            = LUA_TUSERDATA,
+                       thread          = LUA_TTHREAD
                };
 
                static std::string type_name(type type)
                {
                        switch (type)
                        {
-                               case none:                      return "none";
-                               case nil:                       return "nil";
-                               case boolean:           return "boolean";
+                               case none:      return "none";
+                               case nil:       return "nil";
+                               case boolean:   return "boolean";
                                case light_data:
-                               case data:                      return "userdata";
-                               case number:            return "number";
-                               case string:            return "string";
-                               case table:                     return "table";
-                               case function:          return "function";
-                               case thread:            return "thread";
+                               case data:      return "userdata";
+                               case number:    return "number";
+                               case string:    return "string";
+                               case table:     return "table";
+                               case function:  return "function";
+                               case thread:    return "thread";
                        }
                        return "?";
                }
 
-
                slot(const class script& s, int i = 0) :
                        index(i),
                        script_(const_cast<class script*>(&s)) {}
 
-
                // check the type of the value
-               bool is_boolean() const
-               { return (bool)lua_isboolean(script_->state_, index); }
-               bool is_imported_function() const
-               { return (bool)lua_iscfunction(script_->state_, index); }
-               bool is_function() const
-               { return (bool)lua_isfunction(script_->state_, index); }
-               bool is_nil() const
-               { return (bool)lua_isnil(script_->state_, index); }
-               bool is_none() const
-               { return (bool)lua_isnone(script_->state_, index); }
-               bool is_none_or_nil() const
-               { return (bool)lua_isnoneornil(script_->state_, index); }
-               bool is_number() const
-               { return (bool)lua_isnumber(script_->state_, index); }
-               bool is_string() const
-               { return (bool)lua_isstring(script_->state_, index); }
-               bool is_table() const
-               { return (bool)lua_istable(script_->state_, index); }
-               bool is_thread() const
-               { return (bool)lua_isthread(script_->state_, index); }
-               bool is_data() const
-               { return (bool)lua_isuserdata(script_->state_, index); }
-               bool is_light_data() const
-               { return (bool)lua_islightuserdata(script_->state_, index); }
+#define IS_TYPE(T, N) \
+               bool is_##N() const \
+               { \
+                       return (bool)lua_is##T(script_->state_, index); \
+               }//
+               IS_TYPE(boolean, boolean);
+               IS_TYPE(cfunction, imported_function);
+               IS_TYPE(function, function);
+               IS_TYPE(lightuserdata, light_data);
+               IS_TYPE(nil, nil);
+               IS_TYPE(none, none);
+               IS_TYPE(noneornil, none_or_nil);
+               IS_TYPE(number, number);
+               IS_TYPE(string, string);
+               IS_TYPE(table, table);
+               IS_TYPE(thread, thread);
+               IS_TYPE(userdata, data);
+#undef IS_TYPE
 
                /**
                 * Check the value and throw an error if its the wrong type.
@@ -169,49 +155,25 @@ public:
                        return *this;
                }
 
-               const slot& require_boolean(const std::string& what = "boolean") const
-               {
-                       if (!is_boolean()) raise_type_error(what);
-                       return *this;
-               }
-               const slot& require_number(const std::string& what = "number") const
-               {
-                       if (!is_number()) raise_type_error(what);
-                       return *this;
-               }
-               const slot& require_string(const std::string& what = "string") const
-               {
-                       if (!is_string()) raise_type_error(what);
-                       return *this;
-               }
-               const slot& require_table(const std::string& what = "table") const
-               {
-                       if (!is_table()) raise_type_error(what);
-                       return *this;
-               }
-               const slot& require_function(const std::string& what = "function") const
-               {
-                       if (!is_function()) raise_type_error(what);
-                       return *this;
-               }
-               const slot& require_data(const std::string& what = "userdata") const
-               {
-                       if (!is_data()) raise_type_error(what);
-                       return *this;
-               }
-               const slot& require_nil(const std::string& what = "nil") const
-               {
-                       if (!is_nil()) raise_type_error(what);
-                       return *this;
-               }
-               const slot& require_thread(const std::string& what = "thread") const
-               {
-                       if (!is_thread()) raise_type_error(what);
-                       return *this;
-               }
+#define REQUIRE_TYPE(T) \
+               const slot& require_##T(const std::string& what = #T) const \
+               { \
+                       if (!is_##T()) raise_type_error(what); \
+                       return *this; \
+               }//
+               REQUIRE_TYPE(boolean);
+               REQUIRE_TYPE(number);
+               REQUIRE_TYPE(string);
+               REQUIRE_TYPE(table);
+               REQUIRE_TYPE(function);
+               REQUIRE_TYPE(data);
+               REQUIRE_TYPE(nil);
+               REQUIRE_TYPE(thread);
+#undef REQUIRE_TYPE
 
                template <class T>
-               const slot& require_object(const std::string& what = typeid(T).name()) const
+               const slot&
+               require_object(const std::string& what = typeid(T).name()) const
                {
                        if (!is_data()) raise_type_error(what);
 
@@ -235,7 +197,6 @@ public:
                        return *this;
                }
 
-
                /**
                 * Get the type of the value.
                 */
@@ -249,7 +210,10 @@ public:
                 */
                std::string type_name() const
                {
-                       if (is_none()) return "none";
+                       if (is_none())
+                       {
+                               return "none";
+                       }
                        else if (is_data() && !is_light_data())
                        {
                                slot metatable = push_metatable();
@@ -273,16 +237,14 @@ public:
                        return luaL_typename(script_->state_, index);
                }
 
-
                /**
-                * Get the length of the value according to the definition given by
-                * Lua.
+                * Get the length of the value according to the definition
+                * given by Lua.
                 */
                size_t size() const
                {
                        return lua_objlen(script_->state_, index);
                }
-
                size_t length() const
                {
                        return size();
@@ -290,11 +252,12 @@ public:
 
                int positive_index() const
                {
-                       if (index < 0) return index + lua_gettop(script_->state_) + 1;
-                       else           return index;
+                       if (index < 0)
+                               return index + lua_gettop(script_->state_) + 1;
+                       else
+                               return index;
                }
 
-
                /**
                 * Get a pointer value (for userdata, tables, threads, and
                 * functions).
@@ -314,31 +277,43 @@ public:
                        return !is_none();
                }
 
-
                bool operator == (const slot& rhs) const
                {
-                       return (bool)lua_equal(script_->state_, index, rhs.index);
+                       return (bool)lua_equal(script_->state_,
+                                       index, rhs.index);
                }
 
                bool operator < (const slot& rhs) const
                {
-                       return (bool)lua_lessthan(script_->state_, index, rhs.index);
+                       return (bool)lua_lessthan(script_->state_,
+                                       index, rhs.index);
                }
 
-
                /**
                 * Convert the underlying value to a C++ type.
                 */
-               template <class T>
-               bool get(T& value) const
-               {
-                       if (is_number())
-                       {
-                               value = (T)lua_tointeger(script_->state_, index);
-                               return true;
-                       }
-                       return false;
-               }
+
+#define GET_INT_OF_TYPE(T) \
+               bool get(T& value) const \
+               { \
+                       if (is_number()) \
+                       { \
+                               value = static_cast<T>(lua_tointeger(script_->state_, index)); \
+                               return true; \
+                       } \
+                       return false; \
+               }//
+               GET_INT_OF_TYPE(char);
+               GET_INT_OF_TYPE(unsigned char);
+               GET_INT_OF_TYPE(short);
+               GET_INT_OF_TYPE(unsigned short);
+               GET_INT_OF_TYPE(int);
+               GET_INT_OF_TYPE(unsigned int);
+               GET_INT_OF_TYPE(long);
+               GET_INT_OF_TYPE(unsigned long);
+               GET_INT_OF_TYPE(long long);
+               GET_INT_OF_TYPE(unsigned long long);
+#undef GET_INT_OF_TYPE
 
                bool get(float& value) const
                {
@@ -378,7 +353,6 @@ public:
                        }
                        return false;
                }
-
                bool get(std::string& value) const
                {
                        const char*     str;
@@ -401,6 +375,16 @@ public:
                        }
                        return false;
                }
+               template <class T>
+               bool get(T& value) const
+               {
+                       if (is_data())
+                       {
+                               value = *reinterpret_cast<T*>(lua_touserdata(script_->state_, index));
+                               return true;
+                       }
+                       return false;
+               }
                void* get_data() const
                {
                        return lua_touserdata(script_->state_, index);
@@ -414,7 +398,7 @@ public:
                        array.clear();
 
                        slot    value = (*script_)[-1];
-                       int             realIndex = positive_index();
+                       int     realIndex = positive_index();
 
                        bool done = false;
                        for (int i = 1; !done; ++i)
@@ -422,8 +406,10 @@ public:
                                lua_rawgeti(script_->state_, realIndex, i);
 
                                T v;
-                               if (value.get(v)) array.push_back(v);
-                               else              done = true;
+                               if (value.get(v))
+                                       array.push_back(v);
+                               else
+                                       done = true;
 
                                script_->pop();
                        }
@@ -440,7 +426,7 @@ public:
 
                        slot    key = (*script_)[-2];
                        slot    value = (*script_)[-1];
-                       int             realIndex = positive_index();
+                       int     realIndex = positive_index();
 
                        script_->push_nil();
                        while (lua_next(script_->state_, realIndex) != 0)
@@ -469,7 +455,6 @@ public:
                        return ret;
                }
 
-
                template <class T, class V>
                void set_field(const T& field, const V& value)
                {
@@ -483,7 +468,6 @@ public:
                        lua_settable(script_->state_, index);
                }
 
-
                void set_field(const std::string& field)
                {
                        set_field(field.c_str());
@@ -493,7 +477,6 @@ public:
                        lua_setfield(script_->state_, index, field);
                }
 
-
                template <class T>
                void set_field(const std::string& field, const T& value)
                {
@@ -539,7 +522,6 @@ public:
                        set();
                }
 
-
                void remove()
                {
                        lua_remove(script_->state_, index);
@@ -563,7 +545,6 @@ public:
                        lua_insert(script_->state_, index);
                }
 
-
                /**
                 * Copy the value and push the copy to the stack.
                 */
@@ -585,7 +566,6 @@ public:
                        return script_->top();
                }
 
-
                slot push_field() const
                {
                        lua_gettable(script_->state_, index);
@@ -609,7 +589,6 @@ public:
                        return script_->top();
                }
 
-
                class script& script()
                {
                        return *script_;
@@ -620,10 +599,9 @@ public:
                        return *script_;
                }
 
-
                /**
-                * Throw an exception with a message formatted to communicate a
-                * type mismatch with the argument represented by this slot.
+                * Throw an exception with a message formatted to communicate
+                * type mismatch with the argument represented by this slot.
                 */
                int raise_type_error(const std::string& expected) const
                {
@@ -653,13 +631,12 @@ public:
 
                        std::ostringstream stream;
                        stream << "bad argument " << index << " to '" << func
-                                  << "' (" << message << ")";
+                              << "' (" << message << ")";
 
                        throw std::invalid_argument(stream.str());
                        return 0;
                }
 
-
        private:
 
                mutable class script* script_;
@@ -677,7 +654,6 @@ public:
                destroy();
        }
 
-
        static script_ptr alloc()
        {
                return script_ptr(new script);
@@ -689,7 +665,6 @@ public:
                state_ = luaL_newstate();
        }
 
-
        void import_standard_libraries()
        {
                luaL_openlibs(state_);
@@ -721,64 +696,25 @@ public:
                pop();
        }
 
-       void import_base_library()
-       {
-               push(luaopen_base);
-               push(LUA_COLIBNAME);
-               call(1, 0);
-       }
-
-       void import_package_library()
-       {
-               push(luaopen_package);
-               push(LUA_LOADLIBNAME);
-               call(1, 0);
-       }
-
-       void import_string_library()
-       {
-               push(luaopen_string);
-               push(LUA_STRLIBNAME);
-               call(1, 0);
-       }
-
-       void import_table_library()
-       {
-               push(luaopen_table);
-               push(LUA_TABLIBNAME);
-               call(1, 0);
-       }
-
-       void import_math_library()
-       {
-               push(luaopen_math);
-               push(LUA_MATHLIBNAME);
-               call(1, 0);
-       }
-
-       void import_io_library()
-       {
-               push(luaopen_io);
-               push(LUA_IOLIBNAME);
-               call(1, 0);
-       }
-
-       void import_os_library()
-       {
-               push(luaopen_os);
-               push(LUA_OSLIBNAME);
-               call(1, 0);
-       }
-
-       void import_debug_library()
-       {
-               push(luaopen_debug);
-               push(LUA_DBLIBNAME);
-               call(1, 0);
-       }
-
-
-       void import_function(const std::string& name, const function& function)
+#define IMPORT_LIBRARY(L, K) \
+       void import_##L##_library() \
+       { \
+               push(luaopen_##L); \
+               push(LUA_##K##LIBNAME); \
+               call(1, 0); \
+       }//
+       IMPORT_LIBRARY(base, CO);
+       IMPORT_LIBRARY(debug, DB);
+       IMPORT_LIBRARY(io, IO);
+       IMPORT_LIBRARY(math, MATH);
+       IMPORT_LIBRARY(os, OS);
+       IMPORT_LIBRARY(package, LOAD);
+       IMPORT_LIBRARY(string, STR);
+       IMPORT_LIBRARY(table, TAB);
+#undef IMPORT_LIBRARY
+
+       void
+       import_function(const std::string& name, const function& function)
        {
                push(function);
                lua_setglobal(state_, name.c_str());
@@ -794,7 +730,6 @@ public:
                return status(luaL_dofile(state_, file.c_str()));
        }
 
-
        /*
         * Thread-handling methods.
         */
@@ -832,7 +767,6 @@ public:
                return is_main;
        }
 
-
        /**
         * Throw an error with the value at the top of the stack.  If this is
         * called from an imported function, the error will be caught and
@@ -855,7 +789,6 @@ public:
                return 0;
        }
 
-
        /*
         * Get significant values.
         */
@@ -864,23 +797,19 @@ public:
        {
                return slot(*this, globals_index);
        }
-
        slot registry() const
        {
                return slot(*this, registry_index);
        }
-
        slot environment() const
        {
                return slot(*this, environment_index);
        }
-
        slot top() const
        {
                return slot(*this, stack_size());
        }
 
-
        /**
         * Set the size of the stack.
         * \param size The stack size.
@@ -908,7 +837,6 @@ public:
                stack_size(0);
        }
 
-
        /**
         * Makes sure there is at least extra more places on the stack.
         * Returns false if space couldn't be created.  Just like with the
@@ -921,7 +849,6 @@ public:
                return (bool)lua_checkstack(state_, extra);
        }
 
-
        /**
         * Concatenates the top-most n slots on the stack.
         */
@@ -930,61 +857,27 @@ public:
                lua_concat(state_, n);
        }
 
-
        /*
         * Push some values onto the stack.
         */
 
-       slot push(char value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
-       slot push(unsigned char value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
-       slot push(short value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
-       slot push(unsigned short value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
-       slot push(int value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
-       slot push(unsigned int value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
-       slot push(long value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
-       slot push(unsigned long value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
-       slot push(long long value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
-       slot push(unsigned long long value)
-       {
-               lua_pushinteger(state_, lua_Integer(value));
-               return top();
-       }
+#define PUSH_INT_OF_TYPE(T) \
+       slot push(T value) \
+       { \
+               lua_pushinteger(state_, static_cast<lua_Integer>(value)); \
+               return top(); \
+       }//
+       PUSH_INT_OF_TYPE(char);
+       PUSH_INT_OF_TYPE(unsigned char);
+       PUSH_INT_OF_TYPE(short);
+       PUSH_INT_OF_TYPE(unsigned short);
+       PUSH_INT_OF_TYPE(int);
+       PUSH_INT_OF_TYPE(unsigned int);
+       PUSH_INT_OF_TYPE(long);
+       PUSH_INT_OF_TYPE(unsigned long);
+       PUSH_INT_OF_TYPE(long long);
+       PUSH_INT_OF_TYPE(unsigned long long);
+#undef PUSH_INT_OF_TYPE
 
        slot push(bool value)
        {
@@ -1090,12 +983,10 @@ public:
        }
 
        slot push_code(const std::string& name,
-                                  const char* buffer,
-                                  size_t size,
-                                  status& result)
+                       const char* buffer, size_t size, status& result)
        {
                result = status(luaL_loadbuffer(state_,
-                                                                               buffer, size, name.c_str()));
+                                       buffer, size, name.c_str()));
                return top();
        }
 
@@ -1108,7 +999,8 @@ public:
        template <class T>
        slot push_pointer(const T* ptr)
        {
-               lua_pushlightuserdata(state_, const_cast<void*>((const void*)ptr));
+               lua_pushlightuserdata(state_,
+                               const_cast<void*>((const void*)ptr));
                return top();
        }
        slot push_pointer(cfunction function)
@@ -1152,7 +1044,6 @@ public:
                return push_pointer(&typeid(T));
        }
 
-
        /**
         * Call a function on the stack.  The correct procedure is to push a
         * function onto the stack followed by nargs arguments.  This method
@@ -1164,7 +1055,6 @@ public:
                return status(lua_pcall(state_, nargs, nresults, 0));
        }
 
-
        /**
         * Pops n values from the top of the stack.
         */
@@ -1173,7 +1063,6 @@ public:
                lua_pop(state_, n);
        }
 
-
        /**
         * Index into the stack to get a slot.
         */
@@ -1182,7 +1071,6 @@ public:
                return slot(*this, index);
        }
 
-
        /*
         * Control over the garbage collection process.
         */
@@ -1218,7 +1106,6 @@ public:
                lua_gc(state_, LUA_GCSETSTEPMUL, step);
        }
 
-
 private:
 
        script(lua_State* state) :
@@ -1237,15 +1124,12 @@ private:
                slot metatable = push_metatable(typeid(T).name(), is_new);
                if (is_new)
                {
-                       metatable.push_copy();                          // class behavior
+                       metatable.push_copy();                  // class behavior
                        metatable.set_field("__index");
-
                        push_type<T>();
                        metatable.set_field("__cxxtype");       // type_info
-
                        push(object_finalizer_<T>);
                        metatable.set_field("__gc");            // finalizer
-
                        //push(object_tostring_<T>);
                        //metatable.set_field("__tostring");    // tostring
                }
@@ -1257,7 +1141,8 @@ private:
        {
                std::ostringstream stream;
                stream << *reinterpret_cast<T*>(lua_touserdata(state, 1));
-               lua_pushlstring(state, stream.str().c_str(), stream.str().length());
+               lua_pushlstring(state,
+                               stream.str().c_str(), stream.str().length());
                return 1;
        }
 
@@ -1303,7 +1188,6 @@ private:
                }
        }
 
-
        static int call_function(lua_State* state)
        {
                cfunction function = (cfunction)lua_touserdata(state,
@@ -1339,24 +1223,21 @@ private:
                }
        }
 
-
        void destroy()
        {
                if (is_main_thread()) lua_close(state_);
        }
 
-
        lua_State*                      state_;
 };
 
 using namespace std::rel_ops;
 
-
 /**
  * Output a script value to a stream.
  */
-inline std::ostream& operator << (std::ostream& stream,
-                                                                 const script::slot& slot)
+inline std::ostream&
+operator << (std::ostream& stream, const script::slot& slot)
 {
        std::string     str;
        bool            boolean;
@@ -1368,7 +1249,7 @@ inline std::ostream& operator << (std::ostream& stream,
        else if (slot.get(boolean))
        {
                if (boolean) stream << "true";
-               else         stream << "false";
+               else stream << "false";
        }
        else if (slot.is_nil())
        {
This page took 0.042334 seconds and 4 git commands to generate.