Dump StructuredDataDef struct member types

This commit is contained in:
Jan 2022-03-20 18:32:25 +01:00
parent 0a226652f2
commit d82e876558
6 changed files with 184 additions and 16 deletions

View File

@ -1,5 +1,9 @@
#include "CommonStructuredDataTypes.h"
#include <cassert>
#include "CommonStructuredDataDef.h"
CommonStructuredDataType::CommonStructuredDataType()
: m_category(CommonStructuredDataTypeCategory::UNKNOWN),
m_info({0})
@ -18,6 +22,62 @@ CommonStructuredDataType::CommonStructuredDataType(const CommonStructuredDataTyp
{
}
size_t CommonStructuredDataType::GetAlignmentInBits() const
{
return m_category == CommonStructuredDataTypeCategory::BOOL ? 0u : 8u;
}
size_t CommonStructuredDataType::GetSizeInBits(const CommonStructuredDataDef& def) const
{
switch (m_category)
{
case CommonStructuredDataTypeCategory::INT:
case CommonStructuredDataTypeCategory::FLOAT:
return 32u;
case CommonStructuredDataTypeCategory::BYTE:
return 8u;
case CommonStructuredDataTypeCategory::BOOL:
return 1u;
case CommonStructuredDataTypeCategory::ENUM:
case CommonStructuredDataTypeCategory::SHORT:
return 16u;
case CommonStructuredDataTypeCategory::STRING:
return m_info.string_length * 8;
case CommonStructuredDataTypeCategory::STRUCT:
if (m_info.type_index >= def.m_structs.size())
{
assert(false);
return 0u;
}
return def.m_structs[m_info.type_index]->m_size_in_byte * 8u;
case CommonStructuredDataTypeCategory::INDEXED_ARRAY:
{
if (m_info.type_index >= def.m_indexed_arrays.size())
{
assert(false);
return 0u;
}
const auto& indexedArray = def.m_indexed_arrays[m_info.type_index];
return indexedArray.m_element_size_in_bits * indexedArray.m_element_count;
}
case CommonStructuredDataTypeCategory::ENUM_ARRAY:
{
if (m_info.type_index >= def.m_enumed_arrays.size())
{
assert(false);
return 0u;
}
const auto& enumedArray = def.m_enumed_arrays[m_info.type_index];
return enumedArray.m_element_size_in_bits * enumedArray.m_element_count;
}
case CommonStructuredDataTypeCategory::UNKNOWN:
default:
assert(false);
return 0u;
}
}
bool operator<(const CommonStructuredDataType& lhs, const CommonStructuredDataType& rhs)
{
if (lhs.m_category < rhs.m_category)

View File

@ -2,6 +2,8 @@
#include <cstddef>
#include "Utils/ClassUtils.h"
enum class CommonStructuredDataTypeCategory
{
UNKNOWN,
@ -23,6 +25,7 @@ union CommonStructuredDataTypeExtraInfo
size_t type_index;
};
class CommonStructuredDataDef;
struct CommonStructuredDataType
{
CommonStructuredDataTypeCategory m_category;
@ -32,6 +35,9 @@ struct CommonStructuredDataType
explicit CommonStructuredDataType(CommonStructuredDataTypeCategory category);
CommonStructuredDataType(CommonStructuredDataTypeCategory category, size_t extraInfo);
_NODISCARD size_t GetAlignmentInBits() const;
_NODISCARD size_t GetSizeInBits(const CommonStructuredDataDef& def) const;
friend bool operator<(const CommonStructuredDataType& lhs, const CommonStructuredDataType& rhs);
friend bool operator<=(const CommonStructuredDataType& lhs, const CommonStructuredDataType& rhs);
friend bool operator>(const CommonStructuredDataType& lhs, const CommonStructuredDataType& rhs);

View File

@ -420,14 +420,19 @@ void AssetDumperStructuredDataDefSet::ConvertEnum(CommonStructuredDataEnum* out,
out->SortEntries();
}
void AssetDumperStructuredDataDefSet::ConvertStruct(const CommonStructuredDataDef* def, CommonStructuredDataStruct* out, const StructuredDataStruct* in, const size_t structIndex, const size_t rootIndex)
void AssetDumperStructuredDataDefSet::ConvertStruct(const CommonStructuredDataDef* def, const StructuredDataDef* gameDef, CommonStructuredDataStruct* out, const StructuredDataStruct* in, const size_t structIndex)
{
if (structIndex == rootIndex)
if (gameDef->rootType.type == DATA_STRUCT && structIndex == static_cast<size_t>(gameDef->rootType.u.structIndex))
{
out->m_name = "root";
out->m_size_in_byte = gameDef->size;
}
else
{
out->m_name = "STRUCT_" + std::to_string(structIndex);
out->m_size_in_byte = static_cast<size_t>(std::max(in->size, 0));
}
out->m_size_in_byte = static_cast<size_t>(std::max(in->size, 0));
out->m_bit_offset = in->bitOffset;
out->m_properties.resize(static_cast<size_t>(std::max(in->propertyCount, 0)));
@ -463,7 +468,10 @@ void AssetDumperStructuredDataDefSet::ConvertEnumedArray(const CommonStructuredD
out->m_enum_index = std::max(std::min(static_cast<size_t>(in->enumIndex), def->m_enums.size() - 1u), 0u);
if (def->m_enums.empty())
{
assert(false);
return;
}
out->m_element_count = def->m_enums[out->m_enum_index]->ElementCount();
}
@ -490,7 +498,7 @@ std::unique_ptr<CommonStructuredDataDef> AssetDumperStructuredDataDefSet::Conver
for (auto i = 0u; i < out->m_structs.size(); i++)
{
auto _struct = std::make_unique<CommonStructuredDataStruct>();
ConvertStruct(out.get(), _struct.get(), &in->structs[i], i, static_cast<size_t>(in->rootType.u.structIndex));
ConvertStruct(out.get(), in, _struct.get(), &in->structs[i], i);
out->m_structs[i] = std::move(_struct);
}
for (auto i = 0u; i < out->m_indexed_arrays.size(); i++)

View File

@ -23,7 +23,7 @@ namespace IW4
static CommonStructuredDataType ConvertType(const CommonStructuredDataDef* def, const StructuredDataType in);
static void ConvertEnum(CommonStructuredDataEnum* out, const StructuredDataEnum* in, size_t enumIndex);
static void ConvertStruct(const CommonStructuredDataDef* def, CommonStructuredDataStruct* out, const StructuredDataStruct* in, const size_t structIndex, const size_t rootIndex);
static void ConvertStruct(const CommonStructuredDataDef* def, const StructuredDataDef* gameDef, CommonStructuredDataStruct* out, const StructuredDataStruct* in, const size_t structIndex);
static void ConvertIndexedArray(const CommonStructuredDataDef* def, CommonStructuredDataIndexedArray* out, const StructuredDataIndexedArray* in);
static void ConvertEnumedArray(const CommonStructuredDataDef* def, CommonStructuredDataEnumedArray* out, const StructuredDataEnumedArray* in);
static std::unique_ptr<CommonStructuredDataDef> ConvertDef(const StructuredDataDef* in);

View File

@ -1,5 +1,8 @@
#include "StructuredDataDefDumper.h"
#include <cassert>
#include <sstream>
StructuredDataDefDumperNew::StructuredDataDefDumperNew(std::ostream& stream)
: AbstractTextDumper(stream),
m_flags{}
@ -44,32 +47,123 @@ void StructuredDataDefDumperNew::DumpEnum(const CommonStructuredDataEnum& _enum)
m_stream << "};\n"; // end enum
}
void StructuredDataDefDumperNew::DumpType(const CommonStructuredDataDef& def, CommonStructuredDataType type, std::string& typeName, std::vector<std::string>& arraySpecifiersInReverseOrder)
void StructuredDataDefDumperNew::DumpType(const CommonStructuredDataDef& def, CommonStructuredDataType type, std::string& typeName, std::vector<std::string>& arraySpecifiers) const
{
typeName = "unknown";
while (type.m_category != CommonStructuredDataTypeCategory::UNKNOWN)
{
switch (type.m_category)
{
case CommonStructuredDataTypeCategory::INT:
typeName = "int";
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
case CommonStructuredDataTypeCategory::BYTE:
typeName = "byte";
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
case CommonStructuredDataTypeCategory::BOOL:
typeName = "bool";
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
case CommonStructuredDataTypeCategory::FLOAT:
typeName = "float";
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
case CommonStructuredDataTypeCategory::SHORT:
typeName = "short";
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
case CommonStructuredDataTypeCategory::STRING:
{
std::ostringstream ss;
ss << "string(" << type.m_info.string_length << ')';
typeName = ss.str();
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
}
break;
case CommonStructuredDataTypeCategory::ENUM:
assert(type.m_info.type_index < def.m_enums.size());
if (type.m_info.type_index < def.m_enums.size())
typeName = def.m_enums[type.m_info.type_index]->m_name;
else
typeName = "unknown";
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
case CommonStructuredDataTypeCategory::STRUCT:
assert(type.m_info.type_index < def.m_structs.size());
if (type.m_info.type_index < def.m_structs.size())
typeName = def.m_structs[type.m_info.type_index]->m_name;
else
typeName = "unknown";
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
case CommonStructuredDataTypeCategory::INDEXED_ARRAY:
assert(type.m_info.type_index < def.m_indexed_arrays.size());
if (type.m_info.type_index < def.m_indexed_arrays.size())
{
const auto& indexArray = def.m_indexed_arrays[type.m_info.type_index];
arraySpecifiers.push_back(std::to_string(indexArray.m_element_count));
type = indexArray.m_array_type;
}
else
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
case CommonStructuredDataTypeCategory::ENUM_ARRAY:
assert(type.m_info.type_index < def.m_enumed_arrays.size());
if (type.m_info.type_index < def.m_enumed_arrays.size())
{
const auto& enumedArray = def.m_enumed_arrays[type.m_info.type_index];
assert(enumedArray.m_enum_index < def.m_enums.size());
if (enumedArray.m_enum_index < def.m_enums.size())
arraySpecifiers.push_back(def.m_enums[enumedArray.m_enum_index]->m_name);
type = enumedArray.m_array_type;
}
else
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
default:
type = CommonStructuredDataType(CommonStructuredDataTypeCategory::UNKNOWN);
break;
}
}
}
void StructuredDataDefDumperNew::DumpProperty(const CommonStructuredDataDef& def, const CommonStructuredDataStructProperty& property, unsigned& currentOffsetInBit)
void StructuredDataDefDumperNew::DumpProperty(const CommonStructuredDataDef& def, const CommonStructuredDataStructProperty& property, unsigned& currentOffsetInBit) const
{
std::string typeName;
std::vector<std::string> arraySpecifiersInReverseOrder;
std::vector<std::string> arraySpecifiers;
DumpType(def, property.m_type, typeName, arraySpecifiersInReverseOrder);
DumpType(def, property.m_type, typeName, arraySpecifiers);
Indent();
m_stream << typeName << ' ' << property.m_name;
for (auto ri = arraySpecifiersInReverseOrder.rbegin(); ri != arraySpecifiersInReverseOrder.rend(); ++ri)
for (auto ri = arraySpecifiers.begin(); ri != arraySpecifiers.end(); ++ri)
m_stream << '[' << *ri << ']';
#ifdef STRUCTUREDDATADEF_DEBUG
m_stream << " /* Offset: " << (property.m_offset_in_bits / 8) << " byte";
m_stream << "; // Offset: " << (property.m_offset_in_bits / 8) << " byte";
if (property.m_offset_in_bits % 8 > 0)
m_stream << " + " << (property.m_offset_in_bits % 8) << " bit";
m_stream << " */";
#endif
const auto sizeInBits = property.m_type.GetSizeInBits(def);
m_stream << " | Size: ";
if (sizeInBits % 8 == 0)
m_stream << (sizeInBits / 8) << " byte";
else if (sizeInBits > 8)
m_stream << (sizeInBits / 8) << " byte + " << (sizeInBits % 8) << " bit";
else
m_stream << sizeInBits << " bit";
m_stream << " | Alignment: " << property.m_type.GetAlignmentInBits() << " bit";
m_stream << '\n';
#else
m_stream << ";\n";
#endif
}
void StructuredDataDefDumperNew::DumpStruct(const CommonStructuredDataDef& def, const CommonStructuredDataStruct& _struct, const size_t structIndex)

View File

@ -16,8 +16,8 @@ class StructuredDataDefDumperNew : AbstractTextDumper
void WriteLineComment(const std::string& comment) const;
void DumpEnum(const CommonStructuredDataEnum& _enum);
void DumpType(const CommonStructuredDataDef& def, CommonStructuredDataType type, std::string& typeName, std::vector<std::string>& arraySpecifiersInReverseOrder);
void DumpProperty(const CommonStructuredDataDef& def, const CommonStructuredDataStructProperty& property, unsigned& currentOffsetInBit);
void DumpType(const CommonStructuredDataDef& def, CommonStructuredDataType type, std::string& typeName, std::vector<std::string>& arraySpecifiers) const;
void DumpProperty(const CommonStructuredDataDef& def, const CommonStructuredDataStructProperty& property, unsigned& currentOffsetInBit) const;
void DumpStruct(const CommonStructuredDataDef& def, const CommonStructuredDataStruct& _struct, size_t structIndex);
public: