]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/Script.hh
converted tilemap scripts to lua
[chaz/yoink] / src / Moof / Script.hh
index b48f5f440ae04b49f3a6f778cf3e3e3eb4d3ccb1..2fe275e161aae3a7bd0e14bd15d94dd7907692cb 100644 (file)
@@ -39,7 +39,9 @@
  */
 
 #include <list>
+#include <map>
 #include <string>
+#include <vector>
 
 #include <boost/bind.hpp>
 #include <boost/function.hpp>
@@ -48,6 +50,7 @@
 #include <lua.hpp>
 
 #include <Moof/Exception.hh>
+#include <Moof/Log.hh>
 
 
 namespace Mf {
@@ -119,14 +122,22 @@ struct Script
                 * Value will be invalid even if index is manually changed to a valid
                 * index.  You have to index the script itself to get a valid Value.
                 */
-               Value() :
-                       index(0),
-                       state(0) {}
-
-               Value(lua_State* s, int i) :
+               Value(lua_State* s = 0, int i = 0) :
                        index(i),
                        state(s) {}
 
+               /**
+                * A copied value presently points to the same value, except the real
+                * index is used.  That means that if a value that refers to a frame
+                * referenced from the top of the stack will have its normalized index
+                * copied into the new value object.
+                */
+
+               Value(const Value& copy) :
+                       index(copy.getRealIndex()),
+                       state(copy.state) {}
+
+
                // check the type of the value
                bool isBoolean() const   { return (bool)lua_isboolean(state, index); }
                bool isFunction() const  { return (bool)lua_isfunction(state, index); }
@@ -141,6 +152,73 @@ struct Script
                bool isData() const      { return (bool)lua_isuserdata(state, index); }
                bool isLightData() const { return (bool)lua_islightuserdata(state, index); }
 
+               /**
+                * Check the value and throw and error if its the wrong type.  This
+                * method never returns because it does a long jump.  Consequently,
+                * constructed C++ objects  which exist on the stack between the current
+                * frame and some lua function will not be destructed.  That's not a
+                * problem for objects that only exist on the stack, but any objects
+                * that allocate memory on the heap (such as containers or strings) will
+                * leak.  Therefore, you should only call this method after cleaning up
+                * such objects.
+                */
+
+               void requireType(TYPE type) const
+               {
+                       if (type != getType())
+                       {
+                               luaL_typerror(state, index, lua_typename(state, type));
+                       }
+               }
+
+               void throwError(const char* error)
+               {
+                       luaL_argerror(state, index, error);
+               }
+
+
+               Value& requireBoolean()
+               {
+                       if (!isBoolean()) luaL_typerror(state, index, "boolean");
+                       return *this;
+               }
+               Value& requireNumber()
+               {
+                       if (!isNumber()) luaL_typerror(state, index, "number");
+                       return *this;
+               }
+               Value& requireString()
+               {
+                       if (!isString()) luaL_typerror(state, index, "string");
+                       return *this;
+               }
+               Value& requireTable()
+               {
+                       if (!isTable()) luaL_typerror(state, index, "table");
+                       return *this;
+               }
+               Value& requireFunction()
+               {
+                       if (!isFunction()) luaL_typerror(state, index, "function");
+                       return *this;
+               }
+               Value& requireData()
+               {
+                       if (!isData()) luaL_typerror(state, index, "data");
+                       return *this;
+               }
+               Value& requireNil()
+               {
+                       if (!isNil()) luaL_typerror(state, index, "nil");
+                       return *this;
+               }
+               Value& requireThread()
+               {
+                       if (!isThread()) luaL_typerror(state, index, "thread");
+                       return *this;
+               }
+
+
                /**
                 * Get the type of the value.
                 */
@@ -156,9 +234,26 @@ struct Script
 
                std::string getTypeName() const
                {
-                       return std::string(lua_typename(state, (int)getType()));
+                       return std::string(luaL_typename(state, index));
                }
 
+
+               /**
+                * Get the length of the value according to the definition given by Lua.
+                */
+
+               size_t getLength() const
+               {
+                       return lua_objlen(state, index);
+               }
+
+               int getRealIndex() const
+               {
+                       if (index < 0) return lua_gettop(state) + 1 + index;
+                       else           return index;
+               }
+
+
                /**
                 * Get a pointer value (for userdata, tables, threads, and functions).
                 */
@@ -206,61 +301,115 @@ struct Script
                }
 
 
-               /**
-                * Get the length of the value according to the definition given by Lua.
-                */
-
-               size_t getLength() const
-               {
-                       return lua_objlen(state, index);
-               }
-
-
                /**
                 * Convert the underlying value to a C++ type.
                 */
 
                template <typename T>
-               void get(T& value) const
+               bool get(T& value) const
                {
-                       value = (T)lua_tointeger(state, index);
+                       if (isNumber())
+                       {
+                               value = (T)lua_tointeger(state, index);
+                               return true;
+                       }
+                       return false;
                }
 
-               void get(bool& value) const
+               bool get(float& value) const
                {
-                       value = (bool)lua_toboolean(state, index);
+                       if (isNumber())
+                       {
+                               value = (float)lua_tonumber(state, index);
+                               return true;
+                       }
+                       return false;
                }
-
-               void get(float& value) const
+               bool get(double& value) const
                {
-                       value = (float)lua_tonumber(state, index);
+                       if (isNumber())
+                       {
+                               value = (double)lua_tonumber(state, index);
+                               return true;
+                       }
+                       return false;
                }
-               void get(double& value) const
+
+               bool get(bool& value) const
                {
-                       value = (double)lua_tonumber(state, index);
+                       if (isBoolean())
+                       {
+                               value = (bool)lua_toboolean(state, index);
+                               return true;
+                       }
+                       return false;
                }
 
-               void get(std::string& value) const
+               bool get(std::string& value) const
                {
-                       size_t size;
-                       const char* str = lua_tolstring(state, index, &size);
-                       value.assign(str, size);
+                       if (isString())
+                       {
+                               size_t size;
+                               const char* str = lua_tolstring(state, index, &size);
+                               value.assign(str, size);
+                               return true;
+                       }
+                       return false;
                }
 
+               template <typename T>
+               bool get(std::vector<T>& array) const
+               {
+                       if (!isTable()) return false;
+
+                       array.clear();
+
+                       Value   value(state, -1);
+                       int             realIndex = getRealIndex();
+
+                       bool done = false;
+                       for (int i = 1; !done; ++i)
+                       {
+                               lua_rawgeti(state, realIndex, i);
 
-               void set(std::string& value)
+                               T v;
+                               if (value.get(v)) array.push_back(v);
+                               else              done = true;
+
+                               lua_pop(state, 1);
+                       }
+
+                       return true;
+               }
+
+               template <typename T>
+               bool get(std::map<std::string,T>& dictionary) const
                {
+                       if (!isTable()) return false;
+
+                       dictionary.clear();
+
+                       Value   key(state, -2);
+                       Value   value(state, -1);
+                       int             realIndex = getRealIndex();
+
+                       lua_pushnil(state);
+                       while (lua_next(state, realIndex) != 0)
+                       {
+                               std::string k;
+                               if (!key.isNumber() && key.get(k))
+                               {
+                                       T v;
+                                       if (value.get(v)) dictionary[k] = v;
+                               }
+                               lua_pop(state, 1);
+                       }
+                       lua_pop(state, 1);
+
+                       return true;
                }
 
-               //template <typename T>
-               //void get(const std::string& field, T& value) const
-               //{
-                       ////lua_getfield(state_, field.c_str());
-                       //pushField(field);
-                       //get(-1, value);
-                       //lua_pop(state_, 1);
-               //}
-               
+
 
                /**
                 * Copy the value and push the copy to the stack.
@@ -395,6 +544,22 @@ struct Script
        }
 
 
+       /**
+        * Throw an error with the value at the top of the stack.  This method never
+        * returns because it does a long jump.  Consequently, constructed C++
+        * objects  which exist on the stack between the current frame and some lua
+        * function will not be destructed.  That's not a problem for objects that
+        * only exist on the stack, but any objects that allocate memory on the heap
+        * (such as containers or strings) will leak.  Therefore, you should only
+        * call this method after cleaning up such objects.
+        */
+
+       void throwError()
+       {
+               lua_error(state_);
+       }
+
+
        /**
         * Get significant values.
         */
@@ -491,6 +656,10 @@ struct Script
        {
                lua_pushlstring(state_, value.c_str(), value.length());
        }
+       void push(const char* value)
+       {
+               lua_pushstring(state_, value);
+       }
        void push(const char* value, size_t length)
        {
                lua_pushlstring(state_, value, length);
@@ -557,7 +726,7 @@ struct Script
         * Pops n values from the top of the stack.
         */
 
-       void pop(int n)
+       void pop(int n = 1)
        {
                lua_pop(state_, n);
        }
This page took 0.024338 seconds and 4 git commands to generate.