summaryrefslogtreecommitdiff
path: root/library/LuaTypes.cpp
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-03-27 21:47:52 +0400
committerAlexander Gavrilov2012-03-27 21:47:52 +0400
commitbc74c5984e8ccfd1ed0d0ba4f1e058fce7acc46a (patch)
tree169b7b8fd555096dadafbf568be082972c3a5e63 /library/LuaTypes.cpp
parent2ac562d4d7f989d2a79aad88ca2a14602bb44bea (diff)
downloaddfhack-bc74c5984e8ccfd1ed0d0ba4f1e058fce7acc46a.tar.gz
dfhack-bc74c5984e8ccfd1ed0d0ba4f1e058fce7acc46a.tar.bz2
dfhack-bc74c5984e8ccfd1ed0d0ba4f1e058fce7acc46a.tar.xz
Implement recursive transfer of values from lua to c++ structures.
E.g. df.global.cursor = { x = 1, y = 2, z = 3 }. The lua data must be represented by raw lua tables. For structs, the entries in the table are assigned to matching fields. For containers, if a 'resize' field is missing or nil, the table is treated like 1-based lua array, and the container is resized to match its # length. Otherwise, the field must be either an explicit number, true or false. If it is true, the size is selected by the highest index in the table. After that, entries are copied using 0-based indices. For pointers, the table must match the target object. If the pointer is null, the object is auto-allocated; this can be controlled using the 'new' field, the value of which will be passed to df.new().
Diffstat (limited to 'library/LuaTypes.cpp')
-rw-r--r--library/LuaTypes.cpp70
1 files changed, 68 insertions, 2 deletions
diff --git a/library/LuaTypes.cpp b/library/LuaTypes.cpp
index 536bcd72..1e33ed71 100644
--- a/library/LuaTypes.cpp
+++ b/library/LuaTypes.cpp
@@ -65,9 +65,22 @@ void constructed_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
push_object_internal(state, this, ptr);
}
+static void invoke_assign(lua_State *state, type_identity *id, void *ptr, int val_index)
+{
+ lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
+ push_object_internal(state, id, ptr);
+ lua_pushvalue(state, val_index);
+ lua_call(state, 2, 0);
+}
+
void constructed_identity::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
- field_error(state, fname_idx, "complex object", "write");
+ if (lua_istable(state, val_index))
+ {
+ invoke_assign(state, this, ptr, val_index);
+ }
+ else
+ field_error(state, fname_idx, "complex object", "write");
}
void enum_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
@@ -150,6 +163,47 @@ void df::pointer_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
lua_read(state, fname_idx, ptr, target);
}
+static void autovivify_ptr(lua_State *state, int fname_idx, void **pptr,
+ type_identity *target, int val_index)
+{
+ lua_getfield(state, val_index, "new");
+
+ if (!lua_isnil(state, -1))
+ {
+ int top = lua_gettop(state);
+
+ type_identity *suggested = get_object_identity(state, top, "autovivify", true, true);
+
+ if (!is_type_compatible(state, target, 0, suggested, top+1, false))
+ field_error(state, fname_idx, "incompatible suggested autovivify type", "write");
+
+ lua_pop(state, 1);
+
+ lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME);
+ lua_swap(state);
+ lua_call(state, 1, 1);
+
+ void *nval = get_object_internal(state, target, top, false);
+
+ if (!nval)
+ field_error(state, fname_idx, "inconsistent autovivify type", "write");
+
+ *pptr = nval;
+ }
+ else
+ {
+ if (!target)
+ field_error(state, fname_idx, "trying to autovivify void*", "write");
+
+ *pptr = target->allocate();
+
+ if (!*pptr)
+ field_error(state, fname_idx, "could not allocate in autovivify", "write");
+ }
+
+ lua_pop(state, 1);
+}
+
void df::pointer_identity::lua_write(lua_State *state, int fname_idx, void *ptr,
type_identity *target, int val_index)
{
@@ -157,6 +211,13 @@ void df::pointer_identity::lua_write(lua_State *state, int fname_idx, void *ptr,
if (lua_isnil(state, val_index))
*pptr = NULL;
+ else if (lua_istable(state, val_index))
+ {
+ if (!*pptr)
+ autovivify_ptr(state, fname_idx, pptr, target, val_index);
+
+ invoke_assign(state, target, *pptr, val_index);
+ }
else
{
void *nval = get_object_internal(state, target, val_index, false);
@@ -435,10 +496,15 @@ static void write_field(lua_State *state, const struct_field_info *field, void *
case struct_field_info::POINTER:
df::pointer_identity::lua_write(state, 2, ptr, field->type, value_idx);
+ return;
case struct_field_info::STATIC_ARRAY:
case struct_field_info::STL_VECTOR_PTR:
- field_error(state, 2, "complex object", "write");
+ lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
+ read_field(state, field, ptr);
+ lua_pushvalue(state, value_idx);
+ lua_call(state, 2, 0);
+ return;
case struct_field_info::END:
return;