]> git.lizzy.rs Git - minetest.git/blobdiff - src/script/common/c_converter.cpp
Lua->C getintfield() use lua_tointeger (#4408)
[minetest.git] / src / script / common / c_converter.cpp
index 66eeec68ebd0fc87fa072c48da5f8eb1610cc46a..857300fa5fcf3ea77034dc5f52f22778fef23b79 100644 (file)
@@ -23,9 +23,23 @@ extern "C" {
 }
 
 #include "util/numeric.h"
+#include "util/string.h"
 #include "common/c_converter.h"
 #include "constants.h"
 
+
+#define CHECK_TYPE(index, name, type) do { \
+               int t = lua_type(L, (index)); \
+               if (t != (type)) { \
+                       throw LuaError(std::string("Invalid ") + (name) + \
+                               " (expected " + lua_typename(L, (type)) + \
+                               " got " + lua_typename(L, t) + ")."); \
+               } \
+       } while(0)
+#define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER)
+#define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE)
+
+
 void push_v3f(lua_State *L, v3f p)
 {
        lua_newtable(L);
@@ -49,7 +63,7 @@ void push_v2f(lua_State *L, v2f p)
 v2s16 read_v2s16(lua_State *L, int index)
 {
        v2s16 p;
-       luaL_checktype(L, index, LUA_TTABLE);
+       CHECK_POS_TAB(index);
        lua_getfield(L, index, "x");
        p.X = lua_tonumber(L, -1);
        lua_pop(L, 1);
@@ -59,10 +73,43 @@ v2s16 read_v2s16(lua_State *L, int index)
        return p;
 }
 
+v2s16 check_v2s16(lua_State *L, int index)
+{
+       v2s16 p;
+       CHECK_POS_TAB(index);
+       lua_getfield(L, index, "x");
+       CHECK_POS_COORD("x");
+       p.X = lua_tonumber(L, -1);
+       lua_pop(L, 1);
+       lua_getfield(L, index, "y");
+       CHECK_POS_COORD("y");
+       p.Y = lua_tonumber(L, -1);
+       lua_pop(L, 1);
+       return p;
+}
+
+void push_v2s16(lua_State *L, v2s16 p)
+{
+       lua_newtable(L);
+       lua_pushnumber(L, p.X);
+       lua_setfield(L, -2, "x");
+       lua_pushnumber(L, p.Y);
+       lua_setfield(L, -2, "y");
+}
+
+void push_v2s32(lua_State *L, v2s32 p)
+{
+       lua_newtable(L);
+       lua_pushnumber(L, p.X);
+       lua_setfield(L, -2, "x");
+       lua_pushnumber(L, p.Y);
+       lua_setfield(L, -2, "y");
+}
+
 v2s32 read_v2s32(lua_State *L, int index)
 {
        v2s32 p;
-       luaL_checktype(L, index, LUA_TTABLE);
+       CHECK_POS_TAB(index);
        lua_getfield(L, index, "x");
        p.X = lua_tonumber(L, -1);
        lua_pop(L, 1);
@@ -75,11 +122,26 @@ v2s32 read_v2s32(lua_State *L, int index)
 v2f read_v2f(lua_State *L, int index)
 {
        v2f p;
-       luaL_checktype(L, index, LUA_TTABLE);
+       CHECK_POS_TAB(index);
+       lua_getfield(L, index, "x");
+       p.X = lua_tonumber(L, -1);
+       lua_pop(L, 1);
+       lua_getfield(L, index, "y");
+       p.Y = lua_tonumber(L, -1);
+       lua_pop(L, 1);
+       return p;
+}
+
+v2f check_v2f(lua_State *L, int index)
+{
+       v2f p;
+       CHECK_POS_TAB(index);
        lua_getfield(L, index, "x");
+       CHECK_POS_COORD("x");
        p.X = lua_tonumber(L, -1);
        lua_pop(L, 1);
        lua_getfield(L, index, "y");
+       CHECK_POS_COORD("y");
        p.Y = lua_tonumber(L, -1);
        lua_pop(L, 1);
        return p;
@@ -88,7 +150,7 @@ v2f read_v2f(lua_State *L, int index)
 v3f read_v3f(lua_State *L, int index)
 {
        v3f pos;
-       luaL_checktype(L, index, LUA_TTABLE);
+       CHECK_POS_TAB(index);
        lua_getfield(L, index, "x");
        pos.X = lua_tonumber(L, -1);
        lua_pop(L, 1);
@@ -104,19 +166,35 @@ v3f read_v3f(lua_State *L, int index)
 v3f check_v3f(lua_State *L, int index)
 {
        v3f pos;
-       luaL_checktype(L, index, LUA_TTABLE);
+       CHECK_POS_TAB(index);
        lua_getfield(L, index, "x");
-       pos.X = luaL_checknumber(L, -1);
+       CHECK_POS_COORD("x");
+       pos.X = lua_tonumber(L, -1);
        lua_pop(L, 1);
        lua_getfield(L, index, "y");
-       pos.Y = luaL_checknumber(L, -1);
+       CHECK_POS_COORD("y");
+       pos.Y = lua_tonumber(L, -1);
        lua_pop(L, 1);
        lua_getfield(L, index, "z");
-       pos.Z = luaL_checknumber(L, -1);
+       CHECK_POS_COORD("z");
+       pos.Z = lua_tonumber(L, -1);
        lua_pop(L, 1);
        return pos;
 }
 
+void push_ARGB8(lua_State *L, video::SColor color)
+{
+       lua_newtable(L);
+       lua_pushnumber(L, color.getAlpha());
+       lua_setfield(L, -2, "a");
+       lua_pushnumber(L, color.getRed());
+       lua_setfield(L, -2, "r");
+       lua_pushnumber(L, color.getGreen());
+       lua_setfield(L, -2, "g");
+       lua_pushnumber(L, color.getBlue());
+       lua_setfield(L, -2, "b");
+}
+
 void pushFloatPos(lua_State *L, v3f p)
 {
        p /= BS;
@@ -153,13 +231,31 @@ v3s16 check_v3s16(lua_State *L, int index)
        return floatToInt(pf, 1.0);
 }
 
-video::SColor readARGB8(lua_State *L, int index)
+bool read_color(lua_State *L, int index, video::SColor *color)
+{
+       if (lua_istable(L, index)) {
+               *color = read_ARGB8(L, index);
+       } else if (lua_isnumber(L, index)) {
+               color->set(lua_tonumber(L, index));
+       } else if (lua_isstring(L, index)) {
+               video::SColor parsed_color;
+               if (!parseColorString(lua_tostring(L, index), parsed_color, true))
+                       return false;
+
+               *color = parsed_color;
+       } else {
+               return false;
+       }
+
+       return true;
+}
+
+video::SColor read_ARGB8(lua_State *L, int index)
 {
        video::SColor color(0);
-       luaL_checktype(L, index, LUA_TTABLE);
+       CHECK_TYPE(index, "ARGB color", LUA_TTABLE);
        lua_getfield(L, index, "a");
-       if(lua_isnumber(L, -1))
-               color.setAlpha(lua_tonumber(L, -1));
+       color.setAlpha(lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 0xFF);
        lua_pop(L, 1);
        lua_getfield(L, index, "r");
        color.setRed(lua_tonumber(L, -1));
@@ -199,6 +295,23 @@ aabb3f read_aabb3f(lua_State *L, int index, f32 scale)
        return box;
 }
 
+void push_aabb3f(lua_State *L, aabb3f box)
+{
+       lua_newtable(L);
+       lua_pushnumber(L, box.MinEdge.X);
+       lua_rawseti(L, -2, 1);
+       lua_pushnumber(L, box.MinEdge.Y);
+       lua_rawseti(L, -2, 2);
+       lua_pushnumber(L, box.MinEdge.Z);
+       lua_rawseti(L, -2, 3);
+       lua_pushnumber(L, box.MaxEdge.X);
+       lua_rawseti(L, -2, 4);
+       lua_pushnumber(L, box.MaxEdge.Y);
+       lua_rawseti(L, -2, 5);
+       lua_pushnumber(L, box.MaxEdge.Z);
+       lua_rawseti(L, -2, 6);
+}
+
 std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale)
 {
        std::vector<aabb3f> boxes;
@@ -227,24 +340,28 @@ std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale)
        return boxes;
 }
 
-bool read_stringlist(lua_State *L, int index, std::vector<const char *> &result)
+size_t read_stringlist(lua_State *L, int index, std::vector<std::string> *result)
 {
        if (index < 0)
                index = lua_gettop(L) + 1 + index;
 
+       size_t num_strings = 0;
+
        if (lua_istable(L, index)) {
                lua_pushnil(L);
                while (lua_next(L, index)) {
-                       if (lua_isstring(L, -1))
-                               result.push_back(lua_tostring(L, -1));
+                       if (lua_isstring(L, -1)) {
+                               result->push_back(lua_tostring(L, -1));
+                               num_strings++;
+                       }
                        lua_pop(L, 1);
                }
        } else if (lua_isstring(L, index)) {
-               result.push_back(lua_tostring(L, index));
-       } else {
-               return false;
+               result->push_back(lua_tostring(L, index));
+               num_strings++;
        }
-       return true;
+
+       return num_strings;
 }
 
 /*
@@ -274,7 +391,46 @@ bool getintfield(lua_State *L, int table,
        lua_getfield(L, table, fieldname);
        bool got = false;
        if(lua_isnumber(L, -1)){
-               result = lua_tonumber(L, -1);
+               result = lua_tointeger(L, -1);
+               got = true;
+       }
+       lua_pop(L, 1);
+       return got;
+}
+
+bool getintfield(lua_State *L, int table,
+               const char *fieldname, u8 &result)
+{
+       lua_getfield(L, table, fieldname);
+       bool got = false;
+       if(lua_isnumber(L, -1)){
+               result = lua_tointeger(L, -1);
+               got = true;
+       }
+       lua_pop(L, 1);
+       return got;
+}
+
+bool getintfield(lua_State *L, int table,
+               const char *fieldname, u16 &result)
+{
+       lua_getfield(L, table, fieldname);
+       bool got = false;
+       if(lua_isnumber(L, -1)){
+               result = lua_tointeger(L, -1);
+               got = true;
+       }
+       lua_pop(L, 1);
+       return got;
+}
+
+bool getintfield(lua_State *L, int table,
+               const char *fieldname, u32 &result)
+{
+       lua_getfield(L, table, fieldname);
+       bool got = false;
+       if(lua_isnumber(L, -1)){
+               result = lua_tointeger(L, -1);
                got = true;
        }
        lua_pop(L, 1);
@@ -307,24 +463,26 @@ bool getboolfield(lua_State *L, int table,
        return got;
 }
 
-bool getstringlistfield(lua_State *L, int table, const char *fieldname,
-               std::vector<const char *> &result)
+size_t getstringlistfield(lua_State *L, int table, const char *fieldname,
+               std::vector<std::string> *result)
 {
        lua_getfield(L, table, fieldname);
 
-       bool got = read_stringlist(L, -1, result);
+       size_t num_strings_read = read_stringlist(L, -1, result);
 
        lua_pop(L, 1);
-       return got;
+       return num_strings_read;
 }
 
 std::string checkstringfield(lua_State *L, int table,
                const char *fieldname)
 {
        lua_getfield(L, table, fieldname);
-       std::string s = luaL_checkstring(L, -1);
+       CHECK_TYPE(-1, std::string("field \"") + fieldname + '"', LUA_TSTRING);
+       size_t len;
+       const char *s = lua_tolstring(L, -1, &len);
        lua_pop(L, 1);
-       return s;
+       return std::string(s, len);
 }
 
 std::string getstringfield_default(lua_State *L, int table,
@@ -359,6 +517,15 @@ bool getboolfield_default(lua_State *L, int table,
        return result;
 }
 
+void setstringfield(lua_State *L, int table,
+               const char *fieldname, const char *value)
+{
+       lua_pushstring(L, value);
+       if(table < 0)
+               table -= 1;
+       lua_setfield(L, table, fieldname);
+}
+
 void setintfield(lua_State *L, int table,
                const char *fieldname, int value)
 {
@@ -387,3 +554,95 @@ void setboolfield(lua_State *L, int table,
 }
 
 
+////
+//// Array table slices
+////
+
+size_t write_array_slice_float(
+       lua_State *L,
+       int table_index,
+       float *data,
+       v3u16 data_size,
+       v3u16 slice_offset,
+       v3u16 slice_size)
+{
+       v3u16 pmin, pmax(data_size);
+
+       if (slice_offset.X > 0) {
+               slice_offset.X--;
+               pmin.X = slice_offset.X;
+               pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
+       }
+
+       if (slice_offset.Y > 0) {
+               slice_offset.Y--;
+               pmin.Y = slice_offset.Y;
+               pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
+       }
+
+       if (slice_offset.Z > 0) {
+               slice_offset.Z--;
+               pmin.Z = slice_offset.Z;
+               pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
+       }
+
+       const u32 ystride = data_size.X;
+       const u32 zstride = data_size.X * data_size.Y;
+
+       u32 elem_index = 1;
+       for (u32 z = pmin.Z; z != pmax.Z; z++)
+       for (u32 y = pmin.Y; y != pmax.Y; y++)
+       for (u32 x = pmin.X; x != pmax.X; x++) {
+               u32 i = z * zstride + y * ystride + x;
+               lua_pushnumber(L, data[i]);
+               lua_rawseti(L, table_index, elem_index);
+               elem_index++;
+       }
+
+       return elem_index - 1;
+}
+
+
+size_t write_array_slice_u16(
+       lua_State *L,
+       int table_index,
+       u16 *data,
+       v3u16 data_size,
+       v3u16 slice_offset,
+       v3u16 slice_size)
+{
+       v3u16 pmin, pmax(data_size);
+
+       if (slice_offset.X > 0) {
+               slice_offset.X--;
+               pmin.X = slice_offset.X;
+               pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
+       }
+
+       if (slice_offset.Y > 0) {
+               slice_offset.Y--;
+               pmin.Y = slice_offset.Y;
+               pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
+       }
+
+       if (slice_offset.Z > 0) {
+               slice_offset.Z--;
+               pmin.Z = slice_offset.Z;
+               pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
+       }
+
+       const u32 ystride = data_size.X;
+       const u32 zstride = data_size.X * data_size.Y;
+
+       u32 elem_index = 1;
+       for (u32 z = pmin.Z; z != pmax.Z; z++)
+       for (u32 y = pmin.Y; y != pmax.Y; y++)
+       for (u32 x = pmin.X; x != pmax.X; x++) {
+               u32 i = z * zstride + y * ystride + x;
+               lua_pushinteger(L, data[i]);
+               lua_rawseti(L, table_index, elem_index);
+               elem_index++;
+       }
+
+       return elem_index - 1;
+}