diff options
| author | Alexander Gavrilov | 2012-06-13 22:40:39 +0400 |
|---|---|---|
| committer | Alexander Gavrilov | 2012-06-13 22:40:39 +0400 |
| commit | 149f1759096f1fa4117c0e7ac1e6172b669a801b (patch) | |
| tree | 2a432d4ae55a7b62d5ae8a43b166a66632869ddc | |
| parent | c50b605dfc2024bf5bca7d6dfb18fc266b358978 (diff) | |
| download | dfhack-149f1759096f1fa4117c0e7ac1e6172b669a801b.tar.gz dfhack-149f1759096f1fa4117c0e7ac1e6172b669a801b.tar.bz2 dfhack-149f1759096f1fa4117c0e7ac1e6172b669a801b.tar.xz | |
Make primitive refs (i.e. pointers to numbers, etc) behave as arrays.
| -rw-r--r-- | LUA_API.rst | 6 | ||||
| -rw-r--r-- | Lua API.html | 4 | ||||
| -rw-r--r-- | library/LuaTypes.cpp | 26 |
3 files changed, 34 insertions, 2 deletions
diff --git a/LUA_API.rst b/LUA_API.rst index 0b6ae863..f40b786d 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -121,6 +121,12 @@ or as a result of calling the ``_field()`` method. They behave as structs with one field ``value`` of the right type. +To make working with numeric buffers easier, they also allow +numeric indices. Note that other than excluding negative values +no bound checking is performed, since buffer length is not available. +Index 0 is equivalent to the ``value`` field. + + Struct references ----------------- diff --git a/Lua API.html b/Lua API.html index 2df8a7f2..3edcfd27 100644 --- a/Lua API.html +++ b/Lua API.html @@ -453,6 +453,10 @@ that don't fit any of the other reference types. Such references can only appear as a value of a pointer field, or as a result of calling the <tt class="docutils literal">_field()</tt> method.</p> <p>They behave as structs with one field <tt class="docutils literal">value</tt> of the right type.</p> +<p>To make working with numeric buffers easier, they also allow +numeric indices. Note that other than excluding negative values +no bound checking is performed, since buffer length is not available. +Index 0 is equivalent to the <tt class="docutils literal">value</tt> field.</p> </div> <div class="section" id="struct-references"> <h3><a class="toc-backref" href="#id4">Struct references</a></h3> diff --git a/library/LuaTypes.cpp b/library/LuaTypes.cpp index c58c25d1..8548c5d0 100644 --- a/library/LuaTypes.cpp +++ b/library/LuaTypes.cpp @@ -636,13 +636,35 @@ static int meta_struct_next(lua_State *state) } /** + * Field lookup for primitive refs: behave as a quasi-array with numeric indices. + */ +static type_identity *find_primitive_field(lua_State *state, int field, const char *mode, uint8_t **ptr) +{ + if (lua_type(state, field) == LUA_TNUMBER) + { + int idx = lua_tointeger(state, field); + if (idx < 0) + field_error(state, 2, "negative index", mode); + + lua_rawgetp(state, UPVAL_METATABLE, &DFHACK_IDENTITY_FIELD_TOKEN); + auto id = (type_identity *)lua_touserdata(state, -1); + lua_pop(state, 1); + + *ptr += int(id->byte_size()) * idx; + return id; + } + + return (type_identity*)find_field(state, field, mode); +} + +/** * Metamethod: __index for primitives, i.e. simple object references. * Fields point to identity, or NULL for metafields. */ static int meta_primitive_index(lua_State *state) { uint8_t *ptr = get_object_addr(state, 1, 2, "read"); - auto type = (type_identity*)find_field(state, 2, "read"); + auto type = find_primitive_field(state, 2, "read", &ptr); if (!type) return 1; type->lua_read(state, 2, ptr); @@ -655,7 +677,7 @@ static int meta_primitive_index(lua_State *state) static int meta_primitive_newindex(lua_State *state) { uint8_t *ptr = get_object_addr(state, 1, 2, "write"); - auto type = (type_identity*)find_field(state, 2, "write"); + auto type = find_primitive_field(state, 2, "write", &ptr); if (!type) field_error(state, 2, "builtin property or method", "write"); type->lua_write(state, 2, ptr, 3); |
