implement tagged union structures attributes

develop
Ben Lubar 2020-03-21 14:29:14 -05:00
parent b29d009b14
commit 97916fd55e
No known key found for this signature in database
GPG Key ID: 92939677AB59EDA4
5 changed files with 50 additions and 9 deletions

@ -457,6 +457,19 @@ void DFHack::flagarrayToString(std::vector<std::string> *pvec, const void *p,
static const struct_field_info *find_union_tag_candidate(const struct_field_info *fields, const struct_field_info *union_field)
{
if (union_field->extra && union_field->extra->union_tag_field)
{
auto defined_field_name = union_field->extra->union_tag_field;
for (auto field = fields; field->mode != struct_field_info::END; field++)
{
if (!strcmp(field->name, defined_field_name))
{
return field;
}
}
return nullptr;
}
std::string name(union_field->name);
if (name.length() >= 4 && name.substr(name.length() - 4) == "data")
{

@ -1 +1 @@
Subproject commit 6ad3e99e1ed26f1b0af210f941ace905a70b50e7
Subproject commit ab463895a32b47f3b4165b669e0e35994589caa7

@ -117,6 +117,7 @@ public:
const std::string *validate_stl_string_pointer(const void *const*);
#endif
static const char *const *get_enum_item_key(enum_identity *identity, int64_t value);
static const char *const *get_enum_item_attr_or_key(enum_identity *identity, int64_t value, const char *attr_name);
private:
color_ostream & fail(int, const QueueItem &, const CheckedStructure &);
@ -134,8 +135,8 @@ private:
void dispatch_class(const QueueItem &, const CheckedStructure &);
void dispatch_buffer(const QueueItem &, const CheckedStructure &);
void dispatch_stl_ptr_vector(const QueueItem &, const CheckedStructure &);
void dispatch_tagged_union(const QueueItem &, const QueueItem &, const CheckedStructure &, const CheckedStructure &);
void dispatch_tagged_union_vector(const QueueItem &, const QueueItem &, const CheckedStructure &, const CheckedStructure &);
void dispatch_tagged_union(const QueueItem &, const QueueItem &, const CheckedStructure &, const CheckedStructure &, const char *);
void dispatch_tagged_union_vector(const QueueItem &, const QueueItem &, const CheckedStructure &, const CheckedStructure &, const char *);
void dispatch_untagged_union(const QueueItem &, const CheckedStructure &);
void check_unknown_pointer(const QueueItem &);
void check_stl_vector(const QueueItem &, type_identity *, type_identity *);

@ -545,13 +545,14 @@ void Checker::dispatch_field(const QueueItem & item, const CheckedStructure & cs
auto tag_ptr = PTR_ADD(item.ptr, tag_field->offset);
QueueItem tag_item(item, tag_field->name, tag_ptr);
CheckedStructure tag_cs(tag_field);
auto attr_name = field->extra ? field->extra->union_tag_attr : nullptr;
if (tag_cs.identity->isContainer())
{
dispatch_tagged_union_vector(field_item, tag_item, field_cs, tag_cs);
dispatch_tagged_union_vector(field_item, tag_item, field_cs, tag_cs, attr_name);
}
else
{
dispatch_tagged_union(field_item, tag_item, field_cs, tag_cs);
dispatch_tagged_union(field_item, tag_item, field_cs, tag_cs, attr_name);
}
return;
}
@ -602,7 +603,7 @@ void Checker::dispatch_stl_ptr_vector(const QueueItem & item, const CheckedStruc
auto ptr_type = wrap_in_pointer(identity->getItemType());
check_stl_vector(item, ptr_type, identity->getIndexEnumType());
}
void Checker::dispatch_tagged_union(const QueueItem & item, const QueueItem & tag_item, const CheckedStructure & cs, const CheckedStructure & tag_cs)
void Checker::dispatch_tagged_union(const QueueItem & item, const QueueItem & tag_item, const CheckedStructure & cs, const CheckedStructure & tag_cs, const char *attr_name)
{
if (tag_cs.identity->type() != IDTYPE_ENUM || cs.identity->type() != IDTYPE_UNION)
{
@ -664,7 +665,7 @@ void Checker::dispatch_tagged_union(const QueueItem & item, const QueueItem & ta
}
}
auto tag_name = get_enum_item_key(tag_identity, tag_value);
auto tag_name = get_enum_item_attr_or_key(tag_identity, tag_value, attr_name);
if (!tag_name)
{
FAIL("tagged union tag (accessed as " << tag_item.path << ") value (" << tag_value << ") not defined in enum " << tag_cs.identity->getFullName());
@ -701,7 +702,7 @@ void Checker::dispatch_tagged_union(const QueueItem & item, const QueueItem & ta
FAIL("tagged union missing " << *tag_name << " field to match tag (accessed as " << tag_item.path << ") value (" << tag_value << ")");
}
void Checker::dispatch_tagged_union_vector(const QueueItem & item, const QueueItem & tag_item, const CheckedStructure & cs, const CheckedStructure & tag_cs)
void Checker::dispatch_tagged_union_vector(const QueueItem & item, const QueueItem & tag_item, const CheckedStructure & cs, const CheckedStructure & tag_cs, const char *attr_name)
{
auto union_container_identity = static_cast<container_identity *>(cs.identity);
CheckedStructure union_item_cs(union_container_identity->getItemType());
@ -735,7 +736,7 @@ void Checker::dispatch_tagged_union_vector(const QueueItem & item, const QueueIt
for (size_t i = 0; i < vec_union.second.count && i < vec_tag.second.count; i++)
{
dispatch_tagged_union(QueueItem(item, i, vec_union.first), QueueItem(tag_item, i, vec_tag.first), union_item_cs, tag_item_cs);
dispatch_tagged_union(QueueItem(item, i, vec_union.first), QueueItem(tag_item, i, vec_tag.first), union_item_cs, tag_item_cs, attr_name);
vec_union.first = PTR_ADD(vec_union.first, union_item_cs.identity->byte_size());
vec_tag.first = PTR_ADD(vec_tag.first, tag_item_cs.identity->byte_size());
}

@ -389,6 +389,11 @@ const std::string *Checker::validate_stl_string_pointer(const void *const* base)
#endif
const char *const *Checker::get_enum_item_key(enum_identity *identity, int64_t value)
{
return get_enum_item_attr_or_key(identity, value, nullptr);
}
const char *const *Checker::get_enum_item_attr_or_key(enum_identity *identity, int64_t value, const char *attr_name)
{
size_t index;
if (auto cplx = identity->getComplex())
@ -409,5 +414,26 @@ const char *const *Checker::get_enum_item_key(enum_identity *identity, int64_t v
index = value - identity->getFirstItem();
}
if (attr_name)
{
auto attrs = identity->getAttrs();
auto attr_type = identity->getAttrType();
if (!attrs || !attr_type)
{
return nullptr;
}
attrs = PTR_ADD(attrs, attr_type->byte_size() * index);
for (auto field = attr_type->getFields(); field->mode != struct_field_info::END; field++)
{
if (!strcmp(field->name, attr_name))
{
return reinterpret_cast<const char *const *>(PTR_ADD(attrs, field->offset));
}
}
return nullptr;
}
return &identity->getKeys()[index];
}