Make enum attributes accessible through the lua wrapper.

TODO: make them completely read-only.
develop
Alexander Gavrilov 2012-03-25 19:12:59 +04:00
parent 0412aaebe4
commit 1d81cb56ba
7 changed files with 133 additions and 8 deletions

@ -149,10 +149,11 @@ enum_identity::enum_identity(size_t size,
compound_identity *scope_parent, const char *dfhack_name, compound_identity *scope_parent, const char *dfhack_name,
type_identity *base_type, type_identity *base_type,
int64_t first_item_value, int64_t last_item_value, int64_t first_item_value, int64_t last_item_value,
const char *const *keys) const char *const *keys,
const void *attrs, struct_identity *attr_type)
: compound_identity(size, NULL, scope_parent, dfhack_name), : compound_identity(size, NULL, scope_parent, dfhack_name),
first_item_value(first_item_value), last_item_value(last_item_value), first_item_value(first_item_value), last_item_value(last_item_value),
keys(keys), base_type(base_type) keys(keys), base_type(base_type), attrs(attrs), attr_type(attr_type)
{ {
} }

@ -31,6 +31,8 @@ namespace df {
bool_identity identity_traits<bool>::identity; bool_identity identity_traits<bool>::identity;
stl_string_identity identity_traits<std::string>::identity; stl_string_identity identity_traits<std::string>::identity;
ptr_string_identity identity_traits<char*>::identity;
ptr_string_identity identity_traits<const char*>::identity;
pointer_identity identity_traits<void*>::identity; pointer_identity identity_traits<void*>::identity;
stl_ptr_vector_identity identity_traits<std::vector<void*> >::identity; stl_ptr_vector_identity identity_traits<std::vector<void*> >::identity;
stl_bit_vector_identity identity_traits<std::vector<bool> >::identity; stl_bit_vector_identity identity_traits<std::vector<bool> >::identity;

@ -110,6 +110,20 @@ void df::bool_identity::lua_write(lua_State *state, int fname_idx, void *ptr, in
field_error(state, fname_idx, "boolean or number expected", "write"); field_error(state, fname_idx, "boolean or number expected", "write");
} }
void df::ptr_string_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{
auto pstr = (char**)ptr;
if (*pstr)
lua_pushstring(state, *pstr);
else
lua_pushnil(state);
}
void df::ptr_string_identity::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
field_error(state, fname_idx, "raw pointer string", "write");
}
void df::stl_string_identity::lua_read(lua_State *state, int fname_idx, void *ptr) void df::stl_string_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{ {
auto pstr = (std::string*)ptr; auto pstr = (std::string*)ptr;

@ -698,6 +698,30 @@ static int meta_ptr_tostring(lua_State *state)
return 1; return 1;
} }
/**
* Metamethod: __index for enum.attrs
*/
static int meta_enum_attr_index(lua_State *state)
{
if (!lua_isnumber(state, 2))
lua_rawget(state, UPVAL_FIELDTABLE);
if (!lua_isnumber(state, 2))
luaL_error(state, "Invalid index in enum.attrs[]");
auto id = (enum_identity*)lua_touserdata(state, lua_upvalueindex(2));
int64_t idx = lua_tonumber(state, 2);
if (idx < id->getFirstItem() || idx > id->getLastItem())
idx = id->getLastItem()+1;
idx -= id->getFirstItem();
uint8_t *ptr = (uint8_t*)id->getAttrs();
auto atype = id->getAttrType();
push_object_internal(state, atype, ptr + unsigned(atype->byte_size()*idx));
return 1;
}
/** /**
* Make a metatable with most common fields, and an empty table for UPVAL_FIELDTABLE. * Make a metatable with most common fields, and an empty table for UPVAL_FIELDTABLE.
*/ */
@ -864,23 +888,48 @@ static void FillEnumKeys(lua_State *state, int ftable, enum_identity *eid)
{ {
const char *const *keys = eid->getKeys(); const char *const *keys = eid->getKeys();
// Create a new table attached to ftable as __index
lua_newtable(state);
lua_dup(state);
lua_setmetatable(state, ftable);
int base = lua_gettop(state);
lua_newtable(state);
// For enums, set mapping between keys and values // For enums, set mapping between keys and values
for (int64_t i = eid->getFirstItem(), j = 0; i <= eid->getLastItem(); i++, j++) for (int64_t i = eid->getFirstItem(), j = 0; i <= eid->getLastItem(); i++, j++)
{ {
if (keys[j]) if (keys[j])
AssociateId(state, ftable, i, keys[j]); AssociateId(state, base+1, i, keys[j]);
} }
if (eid->getFirstItem() <= eid->getLastItem()) if (eid->getFirstItem() <= eid->getLastItem())
{ {
lua_pushinteger(state, eid->getFirstItem()); lua_pushinteger(state, eid->getFirstItem());
lua_setfield(state, ftable, "_first_item"); lua_setfield(state, base+1, "_first_item");
lua_pushinteger(state, eid->getLastItem()); lua_pushinteger(state, eid->getLastItem());
lua_setfield(state, ftable, "_last_item"); lua_setfield(state, base+1, "_last_item");
} }
SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME); SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME);
// Add an attribute table if any
if (eid->getAttrs())
{
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME);
lua_pushlightuserdata(state, eid);
lua_pushvalue(state, base+1);
lua_pushcclosure(state, meta_enum_attr_index, 3);
freeze_table(state, false, (eid->getFullName()+".attrs").c_str());
lua_setfield(state, ftable, "attrs");
}
lua_setfield(state, base, "__index");
lua_pop(state, 1);
} }
static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *eid) static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *eid)
@ -904,7 +953,6 @@ static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *ei
SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME); SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME);
} }
static void RenderType(lua_State *state, compound_identity *node) static void RenderType(lua_State *state, compound_identity *node)
{ {
assert(node->getName()); assert(node->getName());

@ -183,6 +183,8 @@ namespace DFHack
virtual void build_metatable(lua_State *state); virtual void build_metatable(lua_State *state);
}; };
class struct_identity;
class DFHACK_EXPORT enum_identity : public compound_identity { class DFHACK_EXPORT enum_identity : public compound_identity {
const char *const *keys; const char *const *keys;
int64_t first_item_value; int64_t first_item_value;
@ -190,6 +192,9 @@ namespace DFHack
type_identity *base_type; type_identity *base_type;
const void *attrs;
struct_identity *attr_type;
protected: protected:
virtual bool can_allocate() { return true; } virtual bool can_allocate() { return true; }
virtual void *do_allocate(); virtual void *do_allocate();
@ -201,7 +206,8 @@ namespace DFHack
compound_identity *scope_parent, const char *dfhack_name, compound_identity *scope_parent, const char *dfhack_name,
type_identity *base_type, type_identity *base_type,
int64_t first_item_value, int64_t last_item_value, int64_t first_item_value, int64_t last_item_value,
const char *const *keys); const char *const *keys,
const void *attrs, struct_identity *attr_type);
virtual identity_type type() { return IDTYPE_ENUM; } virtual identity_type type() { return IDTYPE_ENUM; }
@ -211,6 +217,8 @@ namespace DFHack
const char *const *getKeys() { return keys; } const char *const *getKeys() { return keys; }
type_identity *getBaseType() { return base_type; } type_identity *getBaseType() { return base_type; }
const void *getAttrs() { return attrs; }
struct_identity *getAttrType() { return attr_type; }
virtual bool isPrimitive() { return true; } virtual bool isPrimitive() { return true; }
virtual bool isConstructed() { return false; } virtual bool isConstructed() { return false; }

@ -205,6 +205,16 @@ namespace df
virtual void lua_write(lua_State *state, int fname_idx, void *ptr, int val_index); virtual void lua_write(lua_State *state, int fname_idx, void *ptr, int val_index);
}; };
class ptr_string_identity : public primitive_identity {
public:
ptr_string_identity() : primitive_identity(sizeof(char*)) {};
std::string getFullName() { return "char*"; }
virtual void lua_read(lua_State *state, int fname_idx, void *ptr);
virtual void lua_write(lua_State *state, int fname_idx, void *ptr, int val_index);
};
class stl_string_identity : public DFHack::constructed_identity { class stl_string_identity : public DFHack::constructed_identity {
public: public:
stl_string_identity() stl_string_identity()
@ -388,6 +398,28 @@ namespace df
} }
}; };
template<class T>
class enum_list_attr_identity : public container_identity {
public:
typedef enum_list_attr<T> container;
enum_list_attr_identity(type_identity *item)
: container_identity(sizeof(container), NULL, item, NULL)
{}
std::string getFullName(type_identity *item) {
return "enum_list_attr" + container_identity::getFullName(item);
}
protected:
virtual int item_count(void *ptr, CountMode cm) {
return cm == COUNT_WRITE ? 0 : ((container*)ptr)->size;
}
virtual void *item_pointer(type_identity *item, void *ptr, int idx) {
return (void*)&((container*)ptr)->items[idx];
}
};
#define NUMBER_IDENTITY_TRAITS(type) \ #define NUMBER_IDENTITY_TRAITS(type) \
template<> struct identity_traits<type> { \ template<> struct identity_traits<type> { \
static number_identity<type> identity; \ static number_identity<type> identity; \
@ -415,6 +447,16 @@ namespace df
static stl_string_identity *get() { return &identity; } static stl_string_identity *get() { return &identity; }
}; };
template<> struct identity_traits<char*> {
static ptr_string_identity identity;
static ptr_string_identity *get() { return &identity; }
};
template<> struct identity_traits<const char*> {
static ptr_string_identity identity;
static ptr_string_identity *get() { return &identity; }
};
template<> struct identity_traits<void*> { template<> struct identity_traits<void*> {
static pointer_identity identity; static pointer_identity identity;
static pointer_identity *get() { return &identity; } static pointer_identity *get() { return &identity; }
@ -466,6 +508,10 @@ namespace df
static container_identity *get(); static container_identity *get();
}; };
template<class T> struct identity_traits<enum_list_attr<T> > {
static container_identity *get();
};
// Container definitions // Container definitions
template<class Enum, class FT> template<class Enum, class FT>
@ -519,5 +565,11 @@ namespace df
static stl_container_identity<container> identity("DfArray", identity_traits<T>::get()); static stl_container_identity<container> identity("DfArray", identity_traits<T>::get());
return &identity; return &identity;
} }
template<class T>
inline container_identity *identity_traits<enum_list_attr<T> >::get() {
static enum_list_attr_identity<T> identity(identity_traits<T>::get());
return &identity;
}
} }

@ -1 +1 @@
Subproject commit 2f3525af4c7a99564cbffd662e6d0a0b24bedbe6 Subproject commit b9c7b74e8a1bb64532fe58e40a4c23e1d4aca8e3