#include "ZoneWriteTemplate.h" #include "Domain/Computations/StructureComputations.h" #include "Internal/BaseTemplate.h" #include #include #include namespace { constexpr int TAG_HEADER = 1; constexpr int TAG_SOURCE = 2; class Template final : BaseTemplate { public: Template(std::ostream& stream, RenderingContext* context) : BaseTemplate(stream, context) { } void Header() { LINE("// ====================================================================") LINE("// This file has been generated by ZoneCodeGenerator.") LINE("// Do not modify.") LINE("// Any changes will be discarded when regenerating.") LINE("// ====================================================================") LINE("") LINE("#pragma once") LINE("") LINE("#include \"Writing/AssetWriter.h\"") LINEF("#include \"Game/{0}/{0}.h\"", m_env.m_game) LINE("#include ") LINE("") LINEF("namespace {0}", m_env.m_game) LINE("{") m_intendation++; LINEF("class {0} final : public AssetWriter", WriterClassName(m_env.m_asset)) LINE("{") m_intendation++; LINE(VariableDecl(m_env.m_asset->m_definition)) LINE(WrittenVariableDecl(m_env.m_asset->m_definition)) LINE(PointerVariableDecl(m_env.m_asset->m_definition)) LINE(WrittenPointerVariableDecl(m_env.m_asset->m_definition)) LINE("") // Variable Declarations: type varType; for (const auto* type : m_env.m_used_types) { if (type->m_info && !type->m_info->m_definition->m_anonymous && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) { LINE(VariableDecl(type->m_type)) LINE(WrittenVariableDecl(type->m_type)) } } for (const auto* type : m_env.m_used_types) { if (type->m_pointer_array_reference_exists && !type->m_is_context_asset) { LINE(PointerVariableDecl(type->m_type)) LINE(WrittenPointerVariableDecl(type->m_type)) } } LINE("") // Method Declarations for (const auto* type : m_env.m_used_types) { if (type->m_pointer_array_reference_exists) { PrintHeaderPtrArrayWriteMethodDeclaration(type->m_type); } } for (const auto* type : m_env.m_used_types) { if (type->m_array_reference_exists && type->m_info && !type->m_info->m_is_leaf && type->m_non_runtime_reference_exists) { PrintHeaderArrayWriteMethodDeclaration(type->m_type); } } for (const auto* type : m_env.m_used_structures) { if (type->m_non_runtime_reference_exists && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) { PrintHeaderWriteMethodDeclaration(type->m_info); } } PrintHeaderWriteMethodDeclaration(m_env.m_asset); PrintHeaderTempPtrWriteMethodDeclaration(m_env.m_asset); LINE("") m_intendation--; LINE("public:") m_intendation++; PrintHeaderConstructor(); PrintHeaderMainWriteMethodDeclaration(m_env.m_asset); m_intendation--; LINE("};") m_intendation--; LINE("}") } void Source() { LINE("// ====================================================================") LINE("// This file has been generated by ZoneCodeGenerator.") LINE("// Do not modify.") LINE("// Any changes will be discarded when regenerating.") LINE("// ====================================================================") LINE("") LINEF("#include \"{0}_write_db.h\"", Lower(m_env.m_asset->m_definition->m_name)) LINE("#include ") LINE("") if (!m_env.m_referenced_assets.empty()) { LINE("// Referenced Assets:") for (const auto* type : m_env.m_referenced_assets) { LINEF("#include \"../{0}/{0}_write_db.h\"", Lower(type->m_type->m_name)) } LINE("") } LINEF("using namespace {0};", m_env.m_game) LINE("") PrintConstructorMethod(); for (const auto* type : m_env.m_used_types) { if (type->m_pointer_array_reference_exists) { LINE("") PrintWritePtrArrayMethod(type->m_type, type->m_info, type->m_pointer_array_reference_is_reusable); } } for (const auto* type : m_env.m_used_types) { if (type->m_array_reference_exists && type->m_info && !type->m_info->m_is_leaf && type->m_non_runtime_reference_exists) { LINE("") PrintWriteArrayMethod(type->m_type, type->m_info); } } for (const auto* type : m_env.m_used_structures) { if (type->m_non_runtime_reference_exists && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) { LINE("") PrintWriteMethod(type->m_info); } } LINE("") PrintWriteMethod(m_env.m_asset); LINE("") PrintWritePtrMethod(m_env.m_asset); LINE("") PrintMainWriteMethod(); } private: enum class MemberWriteType : std::uint8_t { ARRAY_POINTER, DYNAMIC_ARRAY, EMBEDDED, EMBEDDED_ARRAY, POINTER_ARRAY, SINGLE_POINTER }; static std::string WriterClassName(const StructureInformation* asset) { return std::format("Writer_{0}", asset->m_definition->m_name); } static std::string VariableDecl(const DataDefinition* def) { return std::format("{0}* var{1};", def->GetFullName(), MakeSafeTypeName(def)); } static std::string WrittenVariableDecl(const DataDefinition* def) { return std::format("{0}* var{1}Written;", def->GetFullName(), MakeSafeTypeName(def)); } static std::string PointerVariableDecl(const DataDefinition* def) { return std::format("{0}** var{1}Ptr;", def->GetFullName(), MakeSafeTypeName(def)); } static std::string WrittenPointerVariableDecl(const DataDefinition* def) { return std::format("{0}** var{1}PtrWritten;", def->GetFullName(), MakeSafeTypeName(def)); } void PrintHeaderPtrArrayWriteMethodDeclaration(const DataDefinition* def) const { LINEF("void WritePtrArray_{0}(bool atStreamStart, size_t count);", MakeSafeTypeName(def)) } void PrintHeaderArrayWriteMethodDeclaration(const DataDefinition* def) const { LINEF("void WriteArray_{0}(bool atStreamStart, size_t count);", MakeSafeTypeName(def)) } void PrintHeaderWriteMethodDeclaration(const StructureInformation* info) const { LINEF("void Write_{0}(bool atStreamStart);", MakeSafeTypeName(info->m_definition)) } void PrintHeaderTempPtrWriteMethodDeclaration(const StructureInformation* info) const { LINEF("void WritePtr_{0}(bool atStreamStart);", MakeSafeTypeName(info->m_definition)) } void PrintHeaderMainWriteMethodDeclaration(const StructureInformation* info) const { LINEF("void Write({0}** pAsset);", info->m_definition->GetFullName()) } void PrintHeaderConstructor() const { LINEF("{0}({1}* asset, const Zone& zone, IZoneOutputStream& stream);", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) } void PrintVariableInitialization(const DataDefinition* def) const { LINEF("var{0} = nullptr;", def->m_name) } void PrintWrittenVariableInitialization(const DataDefinition* def) const { LINEF("var{0}Written = nullptr;", def->m_name) } void PrintPointerVariableInitialization(const DataDefinition* def) const { LINEF("var{0}Ptr = nullptr;", def->m_name) } void PrintWrittenPointerVariableInitialization(const DataDefinition* def) const { LINEF("var{0}PtrWritten = nullptr;", def->m_name) } void PrintConstructorMethod() { LINEF( "{0}::{0}({1}* asset, const Zone& zone, IZoneOutputStream& stream)", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) m_intendation++; LINEF(": AssetWriter(zone.m_pools->GetAssetOrAssetReference({0}::EnumEntry, AssetNameAccessor<{0}>()(*asset)), zone, stream)", m_env.m_asset->m_asset_name) m_intendation--; LINE("{") m_intendation++; PrintVariableInitialization(m_env.m_asset->m_definition); PrintWrittenVariableInitialization(m_env.m_asset->m_definition); PrintPointerVariableInitialization(m_env.m_asset->m_definition); PrintWrittenPointerVariableInitialization(m_env.m_asset->m_definition); LINE("") for (const auto* type : m_env.m_used_types) { if (type->m_info && !type->m_info->m_definition->m_anonymous && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) { PrintVariableInitialization(type->m_type); PrintWrittenVariableInitialization(type->m_type); } } for (const auto* type : m_env.m_used_types) { if (type->m_info && type->m_pointer_array_reference_exists && !type->m_is_context_asset) { PrintPointerVariableInitialization(type->m_type); PrintWrittenPointerVariableInitialization(type->m_type); } } m_intendation--; LINE("}") } void WriteMember_ScriptString(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) const { if (writeType == MemberWriteType::ARRAY_POINTER) { LINEF("varScriptString = {0};", MakeMemberAccess(info, member, modifier)) LINEF("m_stream->MarkFollowing({0});", MakeWrittenMemberAccess(info, member, modifier)) LINEF("WriteScriptStringArray(true, {0});", MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) } else if (writeType == MemberWriteType::EMBEDDED_ARRAY) { LINEF("varScriptStringWritten = {0};", MakeWrittenMemberAccess(info, member, modifier)) LINEF("WriteScriptStringArray(false, {0});", MakeArrayCount(dynamic_cast(modifier.GetDeclarationModifier()))) } else if (writeType == MemberWriteType::EMBEDDED) { LINEF("{0} = UseScriptString({1});", MakeWrittenMemberAccess(info, member, modifier), MakeMemberAccess(info, member, modifier)) } else { assert(false); LINEF("#error unsupported writeType {0} for script string", static_cast(writeType)) } } void WriteMember_Asset(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) const { if (writeType == MemberWriteType::SINGLE_POINTER) { LINEF("{0} writer({1}, m_zone, *m_stream);", WriterClassName(member->m_type), MakeMemberAccess(info, member, modifier)) LINEF("writer.Write(&{0});", MakeWrittenMemberAccess(info, member, modifier)) } else if (writeType == MemberWriteType::POINTER_ARRAY) { WriteMember_PointerArray(info, member, modifier); } else { assert(false); LINEF("#error unsupported writeType {0} for asset", static_cast(writeType)) } } void WriteMember_String(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) const { if (writeType == MemberWriteType::SINGLE_POINTER) { if (member->m_member->m_type_declaration->m_is_const) { LINEF("varXStringWritten = &{0};", MakeWrittenMemberAccess(info, member, modifier)) } else { LINEF("varXStringWritten = const_cast(&{0});", MakeWrittenMemberAccess(info, member, modifier)) } LINE("WriteXString(false);") } else if (writeType == MemberWriteType::POINTER_ARRAY) { if (modifier.IsArray()) { LINEF("varXStringWritten = {0};", MakeWrittenMemberAccess(info, member, modifier)) LINEF("WriteXStringArray(false, {0});", modifier.GetArraySize()) } else { LINEF("varXString = {0};", MakeMemberAccess(info, member, modifier)) LINEF("m_stream->MarkFollowing({0});", MakeWrittenMemberAccess(info, member, modifier)) LINEF("WriteXStringArray(true, {0});", MakeEvaluation(modifier.GetPointerArrayCountEvaluation())) } } else { assert(false); LINEF("#error unsupported writeType {0} for string", static_cast(writeType)) } } void WriteMember_ArrayPointer(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { const MemberComputations computations(member); LINEF("m_stream->MarkFollowing({0});", MakeWrittenMemberAccess(info, member, modifier)) if (member->m_type && !member->m_type->m_is_leaf && !computations.IsInRuntimeBlock()) { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("WriteArray_{0}(true, {1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) } else { LINEF("m_stream->Write<{0}{1}>({2}, {3});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier), MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) } } void WriteMember_PointerArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { LINEF("{0} = {1};", MakeTypePtrVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) if (modifier.IsArray()) { LINEF("{0} = {1};", MakeTypeWrittenPtrVarName(member->m_member->m_type_declaration->m_type), MakeWrittenMemberAccess(info, member, modifier)) LINEF("WritePtrArray_{0}(false, {1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), modifier.GetArraySize()) } else { LINEF("m_stream->MarkFollowing({0});", MakeWrittenMemberAccess(info, member, modifier)) LINEF("WritePtrArray_{0}(true, {1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), MakeEvaluation(modifier.GetPointerArrayCountEvaluation())) } } void WriteMember_EmbeddedArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { const MemberComputations computations(member); std::string arraySizeStr; if (modifier.HasDynamicArrayCount()) arraySizeStr = MakeEvaluation(modifier.GetDynamicArrayCountEvaluation()); else arraySizeStr = std::to_string(modifier.GetArraySize()); if (!member->m_is_leaf) { if (computations.IsAfterPartialLoad()) { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("WriteArray_{0}(true, {1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), arraySizeStr) } else { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("{0} = {1};", MakeTypeWrittenVarName(member->m_member->m_type_declaration->m_type), MakeWrittenMemberAccess(info, member, modifier)) LINEF("WriteArray_{0}(false, {1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), arraySizeStr) } } else if (computations.IsAfterPartialLoad()) { LINEF("m_stream->Write<{0}{1}>({2}, {3});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier), arraySizeStr) } } void WriteMember_DynamicArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { if (member->m_type && !member->m_type->m_is_leaf) { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("WriteArray_{0}(true, {1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), MakeEvaluation(modifier.GetDynamicArraySizeEvaluation())) } else { LINEF("m_stream->Write<{0}{1}>({2}, {3});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier), MakeEvaluation(modifier.GetDynamicArraySizeEvaluation())) } } void WriteMember_Embedded(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { const MemberComputations computations(member); if (!member->m_is_leaf) { if (computations.IsAfterPartialLoad()) { LINEF("{0} = &{1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("Write_{0}(true);", MakeSafeTypeName(member->m_member->m_type_declaration->m_type)) } else { LINEF("{0} = &{1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("{0} = &{1};", MakeTypeWrittenVarName(member->m_member->m_type_declaration->m_type), MakeWrittenMemberAccess(info, member, modifier)) LINEF("Write_{0}(false);", MakeSafeTypeName(member->m_member->m_type_declaration->m_type)) } } else if (computations.IsAfterPartialLoad()) { LINEF("m_stream->Write<{0}{1}>(&{2});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier)) } } void WriteMember_SinglePointer(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const { const MemberComputations computations(member); LINEF("m_stream->MarkFollowing({0});", MakeWrittenMemberAccess(info, member, modifier)) if (member->m_type && !member->m_type->m_is_leaf && !computations.IsInRuntimeBlock()) { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("Write_{0}(true);", MakeSafeTypeName(member->m_type->m_definition)) } else { LINEF("m_stream->Write<{0}{1}>({2});", MakeTypeDecl(member->m_member->m_type_declaration.get()), MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()), MakeMemberAccess(info, member, modifier)) } } void WriteMember_TypeCheck(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) const { if (member->m_is_string) { WriteMember_String(info, member, modifier, writeType); } else if (member->m_is_script_string) { WriteMember_ScriptString(info, member, modifier, writeType); } else if (member->m_type && StructureComputations(member->m_type).IsAsset()) { WriteMember_Asset(info, member, modifier, writeType); } else { switch (writeType) { case MemberWriteType::ARRAY_POINTER: WriteMember_ArrayPointer(info, member, modifier); break; case MemberWriteType::SINGLE_POINTER: WriteMember_SinglePointer(info, member, modifier); break; case MemberWriteType::EMBEDDED: WriteMember_Embedded(info, member, modifier); break; case MemberWriteType::POINTER_ARRAY: WriteMember_PointerArray(info, member, modifier); break; case MemberWriteType::DYNAMIC_ARRAY: WriteMember_DynamicArray(info, member, modifier); break; case MemberWriteType::EMBEDDED_ARRAY: WriteMember_EmbeddedArray(info, member, modifier); break; default: LINEF("// t={0}", static_cast(writeType)) break; } } } static bool WriteMember_ShouldMakeInsertReuse(const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) { if (writeType != MemberWriteType::ARRAY_POINTER && writeType != MemberWriteType::SINGLE_POINTER && writeType != MemberWriteType::POINTER_ARRAY) { return false; } if (writeType == MemberWriteType::POINTER_ARRAY && modifier.IsArray()) { return false; } if (member->m_is_string) { return false; } if (member->m_type && StructureComputations(member->m_type).IsAsset()) { return false; } if (member->m_is_reusable) return true; if (member->m_type == nullptr || !member->m_type->m_reusable_reference_exists) return false; return true; } void WriteMember_InsertReuse(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) const { if (!WriteMember_ShouldMakeInsertReuse(member, modifier, writeType)) { WriteMember_TypeCheck(info, member, modifier, writeType); return; } if (writeType == MemberWriteType::ARRAY_POINTER) { LINEF("m_stream->ReusableAddOffset({0}, {1});", MakeMemberAccess(info, member, modifier), MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) } else if (writeType == MemberWriteType::POINTER_ARRAY) { const auto* evaluation = modifier.GetPointerArrayCountEvaluation(); if (evaluation) { LINEF("m_stream->ReusableAddOffset({0}, {1});", MakeMemberAccess(info, member, modifier), MakeEvaluation(modifier.GetPointerArrayCountEvaluation())) } else { LINEF("m_stream->ReusableAddOffset({0}, {1});", MakeMemberAccess(info, member, modifier), modifier.GetArraySize()) } } else { LINEF("m_stream->ReusableAddOffset({0});", MakeMemberAccess(info, member, modifier)) } WriteMember_TypeCheck(info, member, modifier, writeType); } static bool WriteMember_ShouldMakeAlign(const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) { if (writeType != MemberWriteType::ARRAY_POINTER && writeType != MemberWriteType::POINTER_ARRAY && writeType != MemberWriteType::SINGLE_POINTER) { return false; } if (writeType == MemberWriteType::POINTER_ARRAY) { return !modifier.IsArray(); } if (member->m_is_string) { return false; } if (member->m_type && StructureComputations(member->m_type).IsAsset()) { return false; } return true; } void WriteMember_Align(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) const { if (!WriteMember_ShouldMakeAlign(member, modifier, writeType)) { WriteMember_InsertReuse(info, member, modifier, writeType); return; } const auto typeDecl = MakeTypeDecl(member->m_member->m_type_declaration.get()); const auto followingReferences = MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()); if (member->m_alloc_alignment) { LINEF("m_stream->Align({0});", MakeEvaluation(member->m_alloc_alignment.get())) } else { LINEF("m_stream->Align({0});", modifier.GetAlignment()) } WriteMember_InsertReuse(info, member, modifier, writeType); } static bool WriteMember_ShouldMakeReuse(const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) { if (writeType != MemberWriteType::ARRAY_POINTER && writeType != MemberWriteType::SINGLE_POINTER && writeType != MemberWriteType::POINTER_ARRAY) { return false; } if (writeType == MemberWriteType::POINTER_ARRAY && modifier.IsArray()) { return false; } return member->m_is_reusable; } void WriteMember_Reuse(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) { if (!WriteMember_ShouldMakeReuse(member, modifier, writeType)) { WriteMember_Align(info, member, modifier, writeType); return; } LINEF("if (m_stream->ReusableShouldWrite(&{0}))", MakeWrittenMemberAccess(info, member, modifier)) LINE("{") m_intendation++; WriteMember_Align(info, member, modifier, writeType); m_intendation--; LINE("}") } static bool WriteMember_ShouldMakePointerCheck(const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) { if (writeType != MemberWriteType::ARRAY_POINTER && writeType != MemberWriteType::POINTER_ARRAY && writeType != MemberWriteType::SINGLE_POINTER) { return false; } if (writeType == MemberWriteType::POINTER_ARRAY) { return !modifier.IsArray(); } if (member->m_is_string) { return false; } return true; } void WriteMember_PointerCheck(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) { if (WriteMember_ShouldMakePointerCheck(member, modifier, writeType)) { LINEF("if ({0})", MakeMemberAccess(info, member, modifier)) LINE("{") m_intendation++; WriteMember_Reuse(info, member, modifier, writeType); m_intendation--; LINE("}") } else { WriteMember_Reuse(info, member, modifier, writeType); } } void WriteMember_Block(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, const MemberWriteType writeType) { const MemberComputations computations(member); const auto notInDefaultNormalBlock = computations.IsNotInDefaultNormalBlock(); if (notInDefaultNormalBlock) { LINEF("m_stream->PushBlock({0});", member->m_fast_file_block->m_name) } WriteMember_PointerCheck(info, member, modifier, writeType); if (notInDefaultNormalBlock) { LINE("m_stream->PopBlock();") } } void WriteMember_ReferenceArray(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) { auto first = true; for (const auto& entry : modifier.GetArrayEntries()) { if (first) { first = false; } else { LINE("") } WriteMember_Reference(info, member, entry); } } void WriteMember_Reference(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) { if (modifier.IsDynamicArray()) { WriteMember_Block(info, member, modifier, MemberWriteType::DYNAMIC_ARRAY); } else if (modifier.IsSinglePointer()) { WriteMember_Block(info, member, modifier, MemberWriteType::SINGLE_POINTER); } else if (modifier.IsArrayPointer()) { WriteMember_Block(info, member, modifier, MemberWriteType::ARRAY_POINTER); } else if (modifier.IsPointerArray()) { WriteMember_Block(info, member, modifier, MemberWriteType::POINTER_ARRAY); } else if (modifier.IsArray() && modifier.GetNextDeclarationModifier() == nullptr) { WriteMember_Block(info, member, modifier, MemberWriteType::EMBEDDED_ARRAY); } else if (modifier.GetDeclarationModifier() == nullptr) { WriteMember_Block(info, member, modifier, MemberWriteType::EMBEDDED); } else if (modifier.IsArray()) { WriteMember_ReferenceArray(info, member, modifier); } else { assert(false); LINEF("#error WriteMemberReference failed @ {0}", member->m_member->m_name) } } void WriteMember_Condition_Struct(const StructureInformation* info, const MemberInformation* member) { LINE("") if (member->m_condition) { LINEF("if ({0})", MakeEvaluation(member->m_condition.get())) LINE("{") m_intendation++; WriteMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } else { WriteMember_Reference(info, member, DeclarationModifierComputations(member)); } } void WriteMember_Condition_Union(const StructureInformation* info, const MemberInformation* member) { const MemberComputations computations(member); if (computations.IsFirstMember()) { LINE("") if (member->m_condition) { LINEF("if ({0})", MakeEvaluation(member->m_condition.get())) LINE("{") m_intendation++; WriteMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } else { WriteMember_Reference(info, member, DeclarationModifierComputations(member)); } } else if (computations.IsLastMember()) { if (member->m_condition) { LINEF("else if ({0})", MakeEvaluation(member->m_condition.get())) LINE("{") m_intendation++; WriteMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } else { LINE("else") LINE("{") m_intendation++; WriteMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } } else { if (member->m_condition) { LINEF("else if ({0})", MakeEvaluation(member->m_condition.get())) LINE("{") m_intendation++; WriteMember_Reference(info, member, DeclarationModifierComputations(member)); m_intendation--; LINE("}") } else { LINEF("#error Middle member of union must have condition ({0})", member->m_member->m_name) } } } void PrintWriteMemberIfNeedsTreatment(const StructureInformation* info, const MemberInformation* member) { const MemberComputations computations(member); if (computations.ShouldIgnore()) return; if (member->m_is_string || member->m_is_script_string || computations.ContainsNonEmbeddedReference() || member->m_type && !member->m_type->m_is_leaf || computations.IsAfterPartialLoad()) { if (info->m_definition->GetType() == DataDefinitionType::UNION) WriteMember_Condition_Union(info, member); else WriteMember_Condition_Struct(info, member); } } void PrintWriteMethod(const StructureInformation* info) { const StructureComputations computations(info); LINEF("void {0}::Write_{1}(const bool atStreamStart)", WriterClassName(m_env.m_asset), info->m_definition->m_name) LINE("{") m_intendation++; LINEF("assert({0} != nullptr);", MakeTypeVarName(info->m_definition)) LINE("") const auto* dynamicMember = computations.GetDynamicMember(); if (!(info->m_definition->GetType() == DataDefinitionType::UNION && dynamicMember)) { LINE("if (atStreamStart)") m_intendation++; if (dynamicMember == nullptr) { LINEF("{0} = m_stream->Write<{1}>({2}); // Size: {3}", MakeTypeWrittenVarName(info->m_definition), info->m_definition->GetFullName(), MakeTypeVarName(info->m_definition), info->m_definition->GetSize()) } else { LINEF("{0} = m_stream->WritePartial<{1}>({2}, offsetof({1}, {3}));", MakeTypeWrittenVarName(info->m_definition), info->m_definition->GetFullName(), MakeTypeVarName(info->m_definition), dynamicMember->m_member->m_name) } m_intendation--; LINE("") LINEF("assert({0} != nullptr);", MakeTypeWrittenVarName(info->m_definition)) } else { LINE("assert(atStreamStart);") } if (computations.IsAsset()) { LINE("") LINEF("m_stream->PushBlock({0});", m_env.m_default_normal_block->m_name) } else if (info->m_block) { LINE("") LINEF("m_stream->PushBlock({0});", info->m_block->m_name) } for (const auto& member : info->m_ordered_members) { PrintWriteMemberIfNeedsTreatment(info, member.get()); } if (info->m_block || computations.IsAsset()) { LINE("") LINE("m_stream->PopBlock();") } m_intendation--; LINE("}") } void PrintWritePtrMethod(const StructureInformation* info) { const bool inTemp = info->m_block && info->m_block->m_type == FastFileBlockType::TEMP; LINEF("void {0}::WritePtr_{1}(const bool atStreamStart)", WriterClassName(m_env.m_asset), MakeSafeTypeName(info->m_definition)) LINE("{") m_intendation++; LINEF("assert({0} != nullptr);", MakeTypePtrVarName(info->m_definition)) LINE("") LINE("if (atStreamStart)") m_intendation++; LINEF("{0} = m_stream->Write<{1}*>({2});", MakeTypeWrittenPtrVarName(info->m_definition), info->m_definition->GetFullName(), MakeTypePtrVarName(info->m_definition)) m_intendation--; LINE("") LINEF("assert({0} != nullptr);", MakeTypeWrittenPtrVarName(info->m_definition)) LINE("") if (inTemp) { LINEF("m_stream->PushBlock({0});", m_env.m_default_temp_block->m_name) LINE("") } LINEF("if (m_stream->ReusableShouldWrite({0}))", MakeTypeWrittenPtrVarName(info->m_definition)) LINE("{") m_intendation++; LINEF("m_stream->Align({0});", info->m_definition->GetAlignment()) LINEF("m_stream->ReusableAddOffset(*{0});", MakeTypePtrVarName(info->m_definition)) LINE("") if (!info->m_is_leaf) { LINEF("{0} = *{1};", MakeTypeVarName(info->m_definition), MakeTypePtrVarName(info->m_definition)) LINEF("Write_{0}(true);", MakeSafeTypeName(info->m_definition)) } else { LINE("#error Ptr method cannot have leaf type") } LINE("") LINEF("m_stream->MarkFollowing(*{0});", MakeTypeWrittenPtrVarName(info->m_definition)) m_intendation--; LINE("}") if (inTemp) { LINE("") LINE("m_stream->PopBlock();") } m_intendation--; LINE("}") } void PrintMainWriteMethod() { LINEF("void {0}::Write({1}** pAsset)", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) LINE("{") m_intendation++; LINE("assert(pAsset != nullptr);") LINE("assert(m_asset != nullptr);") LINE("assert(m_asset->m_ptr != nullptr);") LINE("") LINEF("auto* zoneAsset = static_cast<{0}*>(m_asset->m_ptr);", m_env.m_asset->m_definition->GetFullName()) LINEF("{0} = &zoneAsset;", MakeTypePtrVarName(m_env.m_asset->m_definition)) LINEF("{0} = &zoneAsset;", MakeTypeWrittenPtrVarName(m_env.m_asset->m_definition)) LINEF("WritePtr_{0}(false);", MakeSafeTypeName(m_env.m_asset->m_definition)) LINE("*pAsset = zoneAsset;") m_intendation--; LINE("}") } void PrintWritePtrArrayMethod_Loading(const DataDefinition* def, const StructureInformation* info, const bool reusable) const { LINEF("m_stream->Align({0});", def->GetAlignment()) if (reusable) { LINEF("m_stream->ReusableAddOffset(*{0});", MakeTypePtrVarName(def)) } if (info && !info->m_is_leaf) { LINEF("{0} = *{1};", MakeTypeVarName(info->m_definition), MakeTypePtrVarName(def)) LINEF("Write_{0}(true);", MakeSafeTypeName(def)) } else { LINEF("m_stream->Write<{0}>(*{1});", def->GetFullName(), MakeTypePtrVarName(def)) } LINEF("m_stream->MarkFollowing(*{0});", MakeTypeWrittenPtrVarName(def)) } void PrintWritePtrArrayMethod_PointerCheck(const DataDefinition* def, StructureInformation* info, const bool reusable) { LINEF("if (*{0})", MakeTypePtrVarName(def)) LINE("{") m_intendation++; if (info && StructureComputations(info).IsAsset()) { LINEF("{0} writer(*{1}, m_zone, *m_stream);", WriterClassName(info), MakeTypePtrVarName(def)) LINEF("writer.Write({0});", MakeTypeWrittenPtrVarName(def)) } else { if (reusable) { LINEF("if (m_stream->ReusableShouldWrite({0}))", MakeTypeWrittenPtrVarName(def)) LINE("{") m_intendation++; PrintWritePtrArrayMethod_Loading(def, info, reusable); m_intendation--; LINE("}") } else { PrintWritePtrArrayMethod_Loading(def, info, reusable); } } m_intendation--; LINE("}") } void PrintWritePtrArrayMethod(const DataDefinition* def, StructureInformation* info, const bool reusable) { LINEF("void {0}::WritePtrArray_{1}(const bool atStreamStart, const size_t count)", WriterClassName(m_env.m_asset), MakeSafeTypeName(def)) LINE("{") m_intendation++; LINEF("assert({0} != nullptr);", MakeTypePtrVarName(def)) LINE("") LINE("if (atStreamStart)") m_intendation++; LINEF("{0} = m_stream->Write<{1}*>({2}, count);", MakeTypeWrittenPtrVarName(def), def->GetFullName(), MakeTypePtrVarName(def)) m_intendation--; LINE("") LINEF("assert({0} != nullptr);", MakeTypeWrittenPtrVarName(def)) LINE("") LINEF("{0}** var = {1};", def->GetFullName(), MakeTypePtrVarName(def)) LINEF("{0}** varWritten = {1};", def->GetFullName(), MakeTypeWrittenPtrVarName(def)) LINE("for (size_t index = 0; index < count; index++)") LINE("{") m_intendation++; LINEF("{0} = var;", MakeTypePtrVarName(def)) LINEF("{0} = varWritten;", MakeTypeWrittenPtrVarName(def)) PrintWritePtrArrayMethod_PointerCheck(def, info, reusable); LINE("") LINE("var++;") LINE("varWritten++;") m_intendation--; LINE("}") m_intendation--; LINE("}") } void PrintWriteArrayMethod(const DataDefinition* def, const StructureInformation* info) { LINEF("void {0}::WriteArray_{1}(const bool atStreamStart, const size_t count)", WriterClassName(m_env.m_asset), MakeSafeTypeName(def)) LINE("{") m_intendation++; LINEF("assert({0} != nullptr);", MakeTypeVarName(def)) LINE("") LINE("if (atStreamStart)") m_intendation++; LINEF("{0} = m_stream->Write<{1}>({2}, count);", MakeTypeWrittenVarName(def), def->GetFullName(), MakeTypeVarName(def)) m_intendation--; LINE("") LINEF("assert({0} != nullptr);", MakeTypeWrittenVarName(def)) LINE("") LINEF("{0}* var = {1};", def->GetFullName(), MakeTypeVarName(def)) LINEF("{0}* varWritten = {1};", def->GetFullName(), MakeTypeWrittenVarName(def)) LINE("for (size_t index = 0; index < count; index++)") LINE("{") m_intendation++; LINEF("{0} = var;", MakeTypeVarName(info->m_definition)) LINEF("{0} = varWritten;", MakeTypeWrittenVarName(info->m_definition)) LINEF("Write_{0}(false);", info->m_definition->m_name) LINE("var++;") LINE("varWritten++;") m_intendation--; LINE("}") m_intendation--; LINE("}") } }; } // namespace std::vector ZoneWriteTemplate::GetFilesToRender(RenderingContext* context) { std::vector files; auto assetName = context->m_asset->m_definition->m_name; for (auto& c : assetName) c = static_cast(tolower(c)); files.emplace_back(std::format("{0}/{0}_write_db.h", assetName), TAG_HEADER); files.emplace_back(std::format("{0}/{0}_write_db.cpp", assetName), TAG_SOURCE); return files; } void ZoneWriteTemplate::RenderFile(std::ostream& stream, const int fileTag, RenderingContext* context) { Template t(stream, context); if (fileTag == TAG_HEADER) { t.Header(); } else { assert(fileTag == TAG_SOURCE); t.Source(); } }