From 28b5068382ebd406b269e6b4aeb073e7cd26503e Mon Sep 17 00:00:00 2001
From: Alexander Gavrilov
Date: Wed, 2 May 2012 12:50:05 +0400
Subject: [PATCH] Allow both coordinate object and (x,y,z) as arguments to
getTileBlock.
---
LUA_API.rst | 4 +-
Lua API.html | 6 +-
library/LuaApi.cpp | 24 ++++++-
library/LuaTools.cpp | 128 +++++++++++++++++++++++++++----------
library/include/LuaTools.h | 25 +++++++-
5 files changed, 143 insertions(+), 44 deletions(-)
diff --git a/LUA_API.rst b/LUA_API.rst
index e2d336f7e..3b2847a58 100644
--- a/LUA_API.rst
+++ b/LUA_API.rst
@@ -779,9 +779,9 @@ Maps module
Returns a map block object for given x,y,z in local block coordinates.
-* ``dfhack.maps.getTileBlock(coords)``
+* ``dfhack.maps.getTileBlock(coords)``, or ``getTileBlock(x,y,z)``
- Returns a map block object for given df::coord in local tile coordinates.
+ Returns a map block object for given df::coord or x,y,z in local tile coordinates.
* ``dfhack.maps.getRegionBiome(region_coord2d)``
diff --git a/Lua API.html b/Lua API.html
index ebfbe80ed..c7c2041db 100644
--- a/Lua API.html
+++ b/Lua API.html
@@ -1005,8 +1005,8 @@ Returns false in case of error.
dfhack.maps.getBlock(x,y,z)
Returns a map block object for given x,y,z in local block coordinates.
-dfhack.maps.getTileBlock(coords)
-Returns a map block object for given df::coord in local tile coordinates.
+dfhack.maps.getTileBlock(coords), or getTileBlock(x,y,z)
+Returns a map block object for given df::coord or x,y,z in local tile coordinates.
dfhack.maps.getRegionBiome(region_coord2d)
Returns the biome info struct for the given global map region.
@@ -1129,7 +1129,7 @@ from the size of the building.
dfhack.constructions.designateNew(pos,type,item_type,mat_index)
Designates a new construction at given position. If there already is
a planned but not completed construction there, changes its type.
-Returns true or false if obstructed.
+Returns true, or false if obstructed.
Note that designated constructions are technically buildings.
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index 0d0647183..05a71d610 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -520,8 +520,7 @@ static int dfhack_matinfo_matches(lua_State *state)
else if (lua_istable(state, 2))
{
df::dfhack_material_category tmp;
- if (!Lua::AssignDFObject(*Lua::GetOutput(state), state, &tmp, 2, false))
- lua_error(state);
+ Lua::CheckDFObject(state, &tmp, 2, false);
lua_pushboolean(state, info.matches(tmp));
}
else
@@ -714,7 +713,6 @@ static const luaL_Reg dfhack_items_funcs[] = {
static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock),
- WRAPN(getTileBlock, (df::map_block* (*)(df::coord))Maps::getTileBlock),
WRAPM(Maps, getRegionBiome),
WRAPM(Maps, getGlobalInitFeature),
WRAPM(Maps, getLocalInitFeature),
@@ -722,7 +720,27 @@ static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
{ NULL, NULL }
};
+static int maps_getTileBlock(lua_State *L)
+{
+ df::map_block *block;
+ if (lua_gettop(L) == 1)
+ {
+ df::coord pos;
+ Lua::CheckDFObject(L, &pos, 1);
+ block = Maps::getTileBlock(pos);
+ }
+ else
+ {
+ block = Maps::getTileBlock(
+ luaL_checkint(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3)
+ );
+ }
+ Lua::PushDFObject(L, block);
+ return 1;
+}
+
static const luaL_Reg dfhack_maps_funcs[] = {
+ { "getTileBlock", maps_getTileBlock },
{ NULL, NULL }
};
diff --git a/library/LuaTools.cpp b/library/LuaTools.cpp
index 253af099c..85e93fbba 100644
--- a/library/LuaTools.cpp
+++ b/library/LuaTools.cpp
@@ -84,7 +84,7 @@ void *DFHack::Lua::GetDFObject(lua_State *state, type_identity *type, int val_in
return get_object_internal(state, type, val_index, exact_type, false);
}
-void *DFHack::Lua::CheckDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type)
+static void check_valid_ptr_index(lua_State *state, int val_index)
{
if (lua_type(state, val_index) == LUA_TNONE)
{
@@ -93,23 +93,47 @@ void *DFHack::Lua::CheckDFObject(lua_State *state, type_identity *type, int val_
else
luaL_error(state, "at index %d: pointer expected", val_index);
}
+}
- if (lua_isnil(state, val_index))
- return NULL;
+static void dfhack_printerr(lua_State *S, const std::string &str);
- void *rv = get_object_internal(state, type, val_index, exact_type, false);
+static void signal_typeid_error(color_ostream *out, lua_State *state,
+ type_identity *type, const char *msg,
+ int val_index, bool perr, bool signal)
+{
+ std::string error = stl_sprintf(msg, type->getFullName().c_str());
- if (!rv)
+ if (signal)
{
- std::string error = "invalid pointer type";
- if (type)
- error += "; expected: " + type->getFullName();
-
if (val_index > 0)
luaL_argerror(state, val_index, error.c_str());
else
luaL_error(state, "at index %d: %s", val_index, error.c_str());
}
+ else if (perr)
+ {
+ if (out)
+ out->printerr("%s", error.c_str());
+ else
+ dfhack_printerr(state, error);
+ }
+ else
+ lua_pushstring(state, error.c_str());
+}
+
+
+void *DFHack::Lua::CheckDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type)
+{
+ check_valid_ptr_index(state, val_index);
+
+ if (lua_isnil(state, val_index))
+ return NULL;
+
+ void *rv = get_object_internal(state, type, val_index, exact_type, false);
+
+ if (!rv)
+ signal_typeid_error(NULL, state, type, "invalid pointer type; expected: %s",
+ val_index, false, true);
return rv;
}
@@ -343,7 +367,7 @@ static void error_tostring(lua_State *L, bool keep_old = false)
}
}
-static void report_error(lua_State *L, color_ostream *out = NULL)
+static void report_error(lua_State *L, color_ostream *out = NULL, bool pop = false)
{
error_tostring(L, true);
@@ -355,7 +379,7 @@ static void report_error(lua_State *L, color_ostream *out = NULL)
else
dfhack_printerr(L, msg);
- lua_pop(L, 1);
+ lua_pop(L, pop?2:1);
}
static bool convert_to_exception(lua_State *L, int slevel, lua_State *thread = NULL)
@@ -544,10 +568,7 @@ bool DFHack::Lua::SafeCall(color_ostream &out, lua_State *L, int nargs, int nres
bool ok = lua_pcall(L, nargs, nres, base) == LUA_OK;
if (!ok && perr)
- {
- report_error(L, &out);
- lua_pop(L, 1);
- }
+ report_error(L, &out, true);
lua_remove(L, base);
set_dfhack_output(L, cur_out);
@@ -658,10 +679,7 @@ int DFHack::Lua::SafeResume(color_ostream &out, lua_State *from, lua_State *thre
int rv = resume_helper(from, thread, nargs, nres);
if (!Lua::IsSuccess(rv) && perr)
- {
- report_error(from, &out);
- lua_pop(from, 1);
- }
+ report_error(from, &out, true);
set_dfhack_output(from, cur_out);
@@ -746,14 +764,64 @@ bool DFHack::Lua::Require(color_ostream &out, lua_State *state,
return true;
}
+static bool doAssignDFObject(color_ostream *out, lua_State *state,
+ type_identity *type, void *target, int val_index,
+ bool exact, bool perr, bool signal)
+{
+ if (signal)
+ check_valid_ptr_index(state, val_index);
+
+ if (lua_istable(state, val_index))
+ {
+ val_index = lua_absindex(state, val_index);
+ lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
+ Lua::PushDFObject(state, type, target);
+ lua_pushvalue(state, val_index);
+
+ if (signal)
+ {
+ lua_call(state, 2, 0);
+ return true;
+ }
+ else
+ return Lua::SafeCall(*out, state, 2, 0, perr);
+ }
+ else if (!lua_isuserdata(state, val_index))
+ {
+ signal_typeid_error(out, state, type, "pointer to %s expected",
+ val_index, perr, signal);
+ return false;
+ }
+ else
+ {
+ void *in_ptr = Lua::GetDFObject(state, type, val_index, exact);
+ if (!in_ptr)
+ {
+ signal_typeid_error(out, state, type, "incompatible pointer type: %s expected",
+ val_index, perr, signal);
+ return false;
+ }
+ if (!type->copy(target, in_ptr))
+ {
+ signal_typeid_error(out, state, type, "no copy support for %s",
+ val_index, perr, signal);
+ return false;
+ }
+ return true;
+ }
+}
+
bool DFHack::Lua::AssignDFObject(color_ostream &out, lua_State *state,
- type_identity *type, void *target, int val_index, bool perr)
+ type_identity *type, void *target, int val_index,
+ bool exact_type, bool perr)
{
- val_index = lua_absindex(state, val_index);
- lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
- PushDFObject(state, type, target);
- lua_pushvalue(state, val_index);
- return Lua::SafeCall(out, state, 2, 0, perr);
+ return doAssignDFObject(&out, state, type, target, val_index, exact_type, perr, false);
+}
+
+void DFHack::Lua::CheckDFObject(lua_State *state, type_identity *type,
+ void *target, int val_index, bool exact_type)
+{
+ doAssignDFObject(NULL, state, type, target, val_index, exact_type, false, true);
}
bool DFHack::Lua::SafeCallString(color_ostream &out, lua_State *state, const std::string &code,
@@ -773,10 +841,7 @@ bool DFHack::Lua::SafeCallString(color_ostream &out, lua_State *state, const std
if (luaL_loadbuffer(state, code.data(), code.size(), debug_tag) != LUA_OK)
{
if (perr)
- {
- report_error(state, &out);
- lua_pop(state, 1);
- }
+ report_error(state, &out, true);
return false;
}
@@ -1113,10 +1178,7 @@ static void do_invoke_event(lua_State *L, int argbase, int num_args, int errorfu
lua_pushvalue(L, argbase+i);
if (lua_pcall(L, num_args, 0, errorfun) != LUA_OK)
- {
- report_error(L);
- lua_pop(L, 1);
- }
+ report_error(L, NULL, true);
}
static void dfhack_event_invoke(lua_State *L, int base, bool from_c)
diff --git a/library/include/LuaTools.h b/library/include/LuaTools.h
index 1ca79d331..a6e538d2a 100644
--- a/library/include/LuaTools.h
+++ b/library/include/LuaTools.h
@@ -109,7 +109,15 @@ namespace DFHack {namespace Lua {
* Return behavior is of SafeCall below.
*/
DFHACK_EXPORT bool AssignDFObject(color_ostream &out, lua_State *state,
- type_identity *type, void *target, int val_index, bool perr = true);
+ type_identity *type, void *target, int val_index,
+ bool exact_type = false, bool perr = true);
+
+ /**
+ * Assign the value at val_index to the target of given identity using df.assign().
+ * Otherwise throws an error.
+ */
+ DFHACK_EXPORT void CheckDFObject(lua_State *state, type_identity *type,
+ void *target, int val_index, bool exact_type = false);
/**
* Push the pointer onto the stack as a wrapped DF object of a specific type.
@@ -139,8 +147,19 @@ namespace DFHack {namespace Lua {
* Assign the value at val_index to the target using df.assign().
*/
template
- bool AssignDFObject(color_ostream &out, lua_State *state, T *target, int val_index, bool perr = true) {
- return AssignDFObject(out, state, df::identity_traits::get(), target, val_index, perr);
+ bool AssignDFObject(color_ostream &out, lua_State *state, T *target,
+ int val_index, bool exact_type = false, bool perr = true) {
+ return AssignDFObject(out, state, df::identity_traits::get(),
+ target, val_index, exact_type, perr);
+ }
+
+ /**
+ * Assign the value at val_index to the target using df.assign().
+ * Throws in case of an error.
+ */
+ template
+ void CheckDFObject(lua_State *state, T *target, int val_index, bool exact_type = false) {
+ CheckDFObject(state, df::identity_traits::get(), target, val_index, exact_type);
}
/**