diff options
| author | Alexander Gavrilov | 2012-03-28 01:47:52 +0800 |
|---|---|---|
| committer | Petr Mrázek | 2012-03-28 16:58:51 +0800 |
| commit | b76bdad50f03e5083b7dae99c5e1d2d8f80fc72d (patch) | |
| tree | 30e5c18e16a760a452788e48e5c38be2d7f401b6 /library/LuaTypes.cpp | |
| parent | d2d16271f052cbf01a8c6e9fab5574739b3dd185 (diff) | |
| download | dfhack-b76bdad50f03e5083b7dae99c5e1d2d8f80fc72d.tar.gz dfhack-b76bdad50f03e5083b7dae99c5e1d2d8f80fc72d.tar.bz2 dfhack-b76bdad50f03e5083b7dae99c5e1d2d8f80fc72d.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.cpp | 70 |
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; |
