From df07ebe083e91a0d78b13ff8a3c42c79c50e4e66 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Tue, 6 Jan 2026 13:29:32 +0000 Subject: [PATCH] refactor: combined ZoneOutputStream interface with impl --- .../Templates/ZoneWriteTemplate.cpp | 4 +- src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp | 2 +- src/ZoneWriting/Game/IW3/ContentWriterIW3.h | 3 +- .../Game/IW3/ZoneWriterFactoryIW3.cpp | 2 +- src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp | 2 +- src/ZoneWriting/Game/IW4/ContentWriterIW4.h | 3 +- .../Game/IW4/ZoneWriterFactoryIW4.cpp | 2 +- src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp | 2 +- src/ZoneWriting/Game/IW5/ContentWriterIW5.h | 3 +- .../Game/IW5/ZoneWriterFactoryIW5.cpp | 2 +- src/ZoneWriting/Game/T5/ContentWriterT5.cpp | 2 +- src/ZoneWriting/Game/T5/ContentWriterT5.h | 5 +- .../Game/T5/ZoneWriterFactoryT5.cpp | 2 +- src/ZoneWriting/Game/T6/ContentWriterT6.cpp | 2 +- src/ZoneWriting/Game/T6/ContentWriterT6.h | 3 +- .../Game/T6/ZoneWriterFactoryT6.cpp | 3 +- src/ZoneWriting/Writing/AssetWriter.cpp | 2 +- src/ZoneWriting/Writing/AssetWriter.h | 3 +- src/ZoneWriting/Writing/ContentWriterBase.cpp | 2 +- src/ZoneWriting/Writing/ContentWriterBase.h | 6 +- .../Writing/IContentWritingEntryPoint.h | 4 +- .../Steps/StepWriteZoneContentToMemory.cpp | 13 +- .../Steps/StepWriteZoneContentToMemory.h | 10 +- .../Stream/Impl/InMemoryZoneOutputStream.cpp | 218 -------------- .../Stream/Impl/InMemoryZoneOutputStream.h | 51 ---- .../Stream}/InMemoryZoneData.cpp | 0 .../Stream}/InMemoryZoneData.h | 0 .../Zone/Stream/ZoneOutputStream.cpp | 276 ++++++++++++++++++ ...IZoneOutputStream.h => ZoneOutputStream.h} | 37 ++- 29 files changed, 354 insertions(+), 310 deletions(-) delete mode 100644 src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp delete mode 100644 src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.h rename src/ZoneWriting/{Writing => Zone/Stream}/InMemoryZoneData.cpp (100%) rename src/ZoneWriting/{Writing => Zone/Stream}/InMemoryZoneData.h (100%) create mode 100644 src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp rename src/ZoneWriting/Zone/Stream/{IZoneOutputStream.h => ZoneOutputStream.h} (53%) diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp index 921a3388..6952c402 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp @@ -253,7 +253,7 @@ namespace void PrintHeaderConstructor() const { - LINEF("{0}({1}* asset, const Zone& zone, IZoneOutputStream& stream);", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) + LINEF("{0}({1}* asset, const Zone& zone, ZoneOutputStream& stream);", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) } void PrintVariableInitialization(const DataDefinition* def) const @@ -279,7 +279,7 @@ namespace void PrintConstructorMethod() { LINEF( - "{0}::{0}({1}* asset, const Zone& zone, IZoneOutputStream& stream)", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) + "{0}::{0}({1}* asset, const Zone& zone, ZoneOutputStream& stream)", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) m_intendation++; LINEF(": AssetWriter(zone.m_pools->GetAssetOrAssetReference({0}::EnumEntry, NonReferenceAssetName(AssetName<{0}>(*asset))), zone, stream)", diff --git a/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp b/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp index 9e07914c..72475a26 100644 --- a/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp +++ b/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp @@ -146,7 +146,7 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun } } -void ContentWriter::WriteContent(IZoneOutputStream& stream) +void ContentWriter::WriteContent(ZoneOutputStream& stream) { m_stream = &stream; diff --git a/src/ZoneWriting/Game/IW3/ContentWriterIW3.h b/src/ZoneWriting/Game/IW3/ContentWriterIW3.h index 3421a923..195df96c 100644 --- a/src/ZoneWriting/Game/IW3/ContentWriterIW3.h +++ b/src/ZoneWriting/Game/IW3/ContentWriterIW3.h @@ -1,4 +1,5 @@ #pragma once + #include "Game/IW3/IW3.h" #include "Writing/ContentWriterBase.h" #include "Writing/IContentWritingEntryPoint.h" @@ -10,7 +11,7 @@ namespace IW3 public: explicit ContentWriter(const Zone& zone); - void WriteContent(IZoneOutputStream& stream) override; + void WriteContent(ZoneOutputStream& stream) override; private: void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; diff --git a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp index c9f47bb2..350e4971 100644 --- a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp +++ b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp @@ -52,7 +52,7 @@ std::unique_ptr ZoneWriterFactory::CreateWriter(const Zone& zone) co SetupBlocks(*writer); auto contentInMemory = std::make_unique( - std::make_unique(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); + std::make_unique(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); auto* contentInMemoryPtr = contentInMemory.get(); writer->AddWritingStep(std::move(contentInMemory)); diff --git a/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp b/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp index 0d3e0d06..36592259 100644 --- a/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp +++ b/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp @@ -156,7 +156,7 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun } } -void ContentWriter::WriteContent(IZoneOutputStream& stream) +void ContentWriter::WriteContent(ZoneOutputStream& stream) { m_stream = &stream; diff --git a/src/ZoneWriting/Game/IW4/ContentWriterIW4.h b/src/ZoneWriting/Game/IW4/ContentWriterIW4.h index 0217af78..e5212c60 100644 --- a/src/ZoneWriting/Game/IW4/ContentWriterIW4.h +++ b/src/ZoneWriting/Game/IW4/ContentWriterIW4.h @@ -1,4 +1,5 @@ #pragma once + #include "Game/IW4/IW4.h" #include "Writing/ContentWriterBase.h" #include "Writing/IContentWritingEntryPoint.h" @@ -10,7 +11,7 @@ namespace IW4 public: explicit ContentWriter(const Zone& zone); - void WriteContent(IZoneOutputStream& stream) override; + void WriteContent(ZoneOutputStream& stream) override; private: void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; diff --git a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp index 0f9f1daa..941f76e6 100644 --- a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp +++ b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp @@ -67,7 +67,7 @@ std::unique_ptr ZoneWriterFactory::CreateWriter(const Zone& zone) co SetupBlocks(*writer); auto contentInMemory = std::make_unique( - std::make_unique(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); + std::make_unique(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); auto* contentInMemoryPtr = contentInMemory.get(); writer->AddWritingStep(std::move(contentInMemory)); diff --git a/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp b/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp index ee0af8d3..b5ecf4b2 100644 --- a/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp +++ b/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp @@ -159,7 +159,7 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun } } -void ContentWriter::WriteContent(IZoneOutputStream& stream) +void ContentWriter::WriteContent(ZoneOutputStream& stream) { m_stream = &stream; diff --git a/src/ZoneWriting/Game/IW5/ContentWriterIW5.h b/src/ZoneWriting/Game/IW5/ContentWriterIW5.h index 1e8d64a1..6bf2ace2 100644 --- a/src/ZoneWriting/Game/IW5/ContentWriterIW5.h +++ b/src/ZoneWriting/Game/IW5/ContentWriterIW5.h @@ -1,4 +1,5 @@ #pragma once + #include "Game/IW5/IW5.h" #include "Writing/ContentWriterBase.h" #include "Writing/IContentWritingEntryPoint.h" @@ -10,7 +11,7 @@ namespace IW5 public: explicit ContentWriter(const Zone& zone); - void WriteContent(IZoneOutputStream& stream) override; + void WriteContent(ZoneOutputStream& stream) override; private: void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; diff --git a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp index 00338ed7..90ed3208 100644 --- a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp +++ b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp @@ -68,7 +68,7 @@ std::unique_ptr ZoneWriterFactory::CreateWriter(const Zone& zone) co SetupBlocks(*writer); auto contentInMemory = std::make_unique( - std::make_unique(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); + std::make_unique(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); auto* contentInMemoryPtr = contentInMemory.get(); writer->AddWritingStep(std::move(contentInMemory)); diff --git a/src/ZoneWriting/Game/T5/ContentWriterT5.cpp b/src/ZoneWriting/Game/T5/ContentWriterT5.cpp index e57067d5..8c0c2ce6 100644 --- a/src/ZoneWriting/Game/T5/ContentWriterT5.cpp +++ b/src/ZoneWriting/Game/T5/ContentWriterT5.cpp @@ -152,7 +152,7 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun } } -void ContentWriter::WriteContent(IZoneOutputStream& stream) +void ContentWriter::WriteContent(ZoneOutputStream& stream) { m_stream = &stream; diff --git a/src/ZoneWriting/Game/T5/ContentWriterT5.h b/src/ZoneWriting/Game/T5/ContentWriterT5.h index 50c78edb..1c0cc137 100644 --- a/src/ZoneWriting/Game/T5/ContentWriterT5.h +++ b/src/ZoneWriting/Game/T5/ContentWriterT5.h @@ -1,4 +1,5 @@ #pragma once + #include "Game/T5/T5.h" #include "Writing/ContentWriterBase.h" #include "Writing/IContentWritingEntryPoint.h" @@ -8,9 +9,9 @@ namespace T5 class ContentWriter final : public ContentWriterBase, public IContentWritingEntryPoint { public: - ContentWriter(const Zone& zone); + explicit ContentWriter(const Zone& zone); - void WriteContent(IZoneOutputStream& stream) override; + void WriteContent(ZoneOutputStream& stream) override; private: void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; diff --git a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp index cd5ca5bf..4cb65a9b 100644 --- a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp +++ b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp @@ -50,7 +50,7 @@ std::unique_ptr ZoneWriterFactory::CreateWriter(const Zone& zone) co SetupBlocks(*writer); auto contentInMemory = std::make_unique( - std::make_unique(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); + std::make_unique(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); auto* contentInMemoryPtr = contentInMemory.get(); writer->AddWritingStep(std::move(contentInMemory)); diff --git a/src/ZoneWriting/Game/T6/ContentWriterT6.cpp b/src/ZoneWriting/Game/T6/ContentWriterT6.cpp index d929bfa5..234f80f5 100644 --- a/src/ZoneWriting/Game/T6/ContentWriterT6.cpp +++ b/src/ZoneWriting/Game/T6/ContentWriterT6.cpp @@ -167,7 +167,7 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun } } -void ContentWriter::WriteContent(IZoneOutputStream& stream) +void ContentWriter::WriteContent(ZoneOutputStream& stream) { m_stream = &stream; diff --git a/src/ZoneWriting/Game/T6/ContentWriterT6.h b/src/ZoneWriting/Game/T6/ContentWriterT6.h index 3f78b034..4bb08580 100644 --- a/src/ZoneWriting/Game/T6/ContentWriterT6.h +++ b/src/ZoneWriting/Game/T6/ContentWriterT6.h @@ -1,4 +1,5 @@ #pragma once + #include "Game/T6/T6.h" #include "Writing/ContentWriterBase.h" #include "Writing/IContentWritingEntryPoint.h" @@ -10,7 +11,7 @@ namespace T6 public: explicit ContentWriter(const Zone& zone); - void WriteContent(IZoneOutputStream& stream) override; + void WriteContent(ZoneOutputStream& stream) override; private: void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; diff --git a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp index 536e08b6..fb3796f8 100644 --- a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp +++ b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp @@ -106,7 +106,7 @@ std::unique_ptr ZoneWriterFactory::CreateWriter(const Zone& zone) co SetupBlocks(*writer); auto contentInMemory = std::make_unique( - std::make_unique(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); + std::make_unique(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); auto* contentInMemoryPtr = contentInMemory.get(); writer->AddWritingStep(std::move(contentInMemory)); @@ -119,7 +119,6 @@ std::unique_ptr ZoneWriterFactory::CreateWriter(const Zone& zone) co AddXChunkProcessor(*writer, zone, isEncrypted, &dataToSignProvider, &xChunksProcessor); // Start of the XFile struct - // m_writer->AddWritingStep(std::make_unique(8)); // Skip size and externalSize fields since they are not interesting for us writer->AddWritingStep(std::make_unique(contentInMemoryPtr)); writer->AddWritingStep(std::make_unique(zone)); diff --git a/src/ZoneWriting/Writing/AssetWriter.cpp b/src/ZoneWriting/Writing/AssetWriter.cpp index 4dc9752c..e052927e 100644 --- a/src/ZoneWriting/Writing/AssetWriter.cpp +++ b/src/ZoneWriting/Writing/AssetWriter.cpp @@ -2,7 +2,7 @@ #include -AssetWriter::AssetWriter(XAssetInfoGeneric* asset, const Zone& zone, IZoneOutputStream& stream) +AssetWriter::AssetWriter(XAssetInfoGeneric* asset, const Zone& zone, ZoneOutputStream& stream) : ContentWriterBase(zone, stream), m_asset(asset), varScriptString(nullptr), diff --git a/src/ZoneWriting/Writing/AssetWriter.h b/src/ZoneWriting/Writing/AssetWriter.h index 188828c1..b3357054 100644 --- a/src/ZoneWriting/Writing/AssetWriter.h +++ b/src/ZoneWriting/Writing/AssetWriter.h @@ -2,14 +2,13 @@ #include "ContentWriterBase.h" #include "Pool/XAssetInfo.h" -#include "Utils/ClassUtils.h" #include "Zone/Zone.h" #include "Zone/ZoneTypes.h" class AssetWriter : public ContentWriterBase { protected: - AssetWriter(XAssetInfoGeneric* asset, const Zone& zone, IZoneOutputStream& stream); + AssetWriter(XAssetInfoGeneric* asset, const Zone& zone, ZoneOutputStream& stream); [[nodiscard]] static const char* NonReferenceAssetName(const char* assetName); [[nodiscard]] scr_string_t UseScriptString(scr_string_t scrString) const; diff --git a/src/ZoneWriting/Writing/ContentWriterBase.cpp b/src/ZoneWriting/Writing/ContentWriterBase.cpp index b4d775a1..71f603d9 100644 --- a/src/ZoneWriting/Writing/ContentWriterBase.cpp +++ b/src/ZoneWriting/Writing/ContentWriterBase.cpp @@ -10,7 +10,7 @@ ContentWriterBase::ContentWriterBase(const Zone& zone) { } -ContentWriterBase::ContentWriterBase(const Zone& zone, IZoneOutputStream& stream) +ContentWriterBase::ContentWriterBase(const Zone& zone, ZoneOutputStream& stream) : m_zone(zone), m_stream(&stream), varXString(nullptr), diff --git a/src/ZoneWriting/Writing/ContentWriterBase.h b/src/ZoneWriting/Writing/ContentWriterBase.h index 06dd121c..9a58959d 100644 --- a/src/ZoneWriting/Writing/ContentWriterBase.h +++ b/src/ZoneWriting/Writing/ContentWriterBase.h @@ -1,13 +1,13 @@ #pragma once -#include "Zone/Stream/IZoneOutputStream.h" +#include "Zone/Stream/ZoneOutputStream.h" #include "Zone/Zone.h" class ContentWriterBase { protected: explicit ContentWriterBase(const Zone& zone); - ContentWriterBase(const Zone& zone, IZoneOutputStream& stream); + ContentWriterBase(const Zone& zone, ZoneOutputStream& stream); public: virtual ~ContentWriterBase() = default; @@ -21,7 +21,7 @@ protected: void WriteXStringArray(bool atStreamStart, size_t count); const Zone& m_zone; - IZoneOutputStream* m_stream; + ZoneOutputStream* m_stream; const char** varXString; const char** varXStringWritten; diff --git a/src/ZoneWriting/Writing/IContentWritingEntryPoint.h b/src/ZoneWriting/Writing/IContentWritingEntryPoint.h index af0d5672..3cd3d140 100644 --- a/src/ZoneWriting/Writing/IContentWritingEntryPoint.h +++ b/src/ZoneWriting/Writing/IContentWritingEntryPoint.h @@ -1,6 +1,6 @@ #pragma once -#include "Zone/Stream/IZoneOutputStream.h" +#include "Zone/Stream/ZoneOutputStream.h" class IContentWritingEntryPoint { @@ -12,5 +12,5 @@ public: IContentWritingEntryPoint& operator=(const IContentWritingEntryPoint& other) = default; IContentWritingEntryPoint& operator=(IContentWritingEntryPoint&& other) noexcept = default; - virtual void WriteContent(IZoneOutputStream& stream) = 0; + virtual void WriteContent(ZoneOutputStream& stream) = 0; }; diff --git a/src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.cpp b/src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.cpp index 76d5f1ee..01cbc332 100644 --- a/src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.cpp +++ b/src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.cpp @@ -1,14 +1,16 @@ #include "StepWriteZoneContentToMemory.h" -#include "Zone/Stream/Impl/InMemoryZoneOutputStream.h" +#include "Zone/Stream/ZoneOutputStream.h" StepWriteZoneContentToMemory::StepWriteZoneContentToMemory(std::unique_ptr entryPoint, const Zone& zone, - const int offsetBlockBitCount, + const unsigned pointerBitCount, + const unsigned offsetBlockBitCount, const block_t insertBlock) : m_content_loader(std::move(entryPoint)), m_zone_data(std::make_unique()), m_zone(zone), + m_pointer_bit_count(pointerBitCount), m_offset_block_bit_count(offsetBlockBitCount), m_insert_block(insertBlock) { @@ -16,12 +18,11 @@ StepWriteZoneContentToMemory::StepWriteZoneContentToMemory(std::unique_ptr blocks; - blocks.reserve(zoneWriter->m_blocks.size()); + m_blocks.reserve(zoneWriter->m_blocks.size()); for (const auto& block : zoneWriter->m_blocks) - blocks.emplace_back(block.get()); + m_blocks.emplace_back(block.get()); - const auto zoneOutputStream = std::make_unique(m_zone_data.get(), std::move(blocks), m_offset_block_bit_count, m_insert_block); + const auto zoneOutputStream = ZoneOutputStream::Create(m_pointer_bit_count, m_offset_block_bit_count, m_blocks, m_insert_block, *m_zone_data); m_content_loader->WriteContent(*zoneOutputStream); } diff --git a/src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.h b/src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.h index 8bc43c48..89f38ba7 100644 --- a/src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.h +++ b/src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.h @@ -2,14 +2,15 @@ #include "Writing/IContentWritingEntryPoint.h" #include "Writing/IWritingStep.h" -#include "Writing/InMemoryZoneData.h" +#include "Zone/Stream/InMemoryZoneData.h" #include class StepWriteZoneContentToMemory final : public IWritingStep { public: - StepWriteZoneContentToMemory(std::unique_ptr entryPoint, const Zone& zone, int offsetBlockBitCount, block_t insertBlock); + StepWriteZoneContentToMemory( + std::unique_ptr entryPoint, const Zone& zone, unsigned pointerBitCount, unsigned offsetBlockBitCount, block_t insertBlock); void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override; [[nodiscard]] InMemoryZoneData* GetData() const; @@ -18,6 +19,9 @@ private: std::unique_ptr m_content_loader; std::unique_ptr m_zone_data; const Zone& m_zone; - int m_offset_block_bit_count; + std::vector m_blocks; + + unsigned m_pointer_bit_count; + unsigned m_offset_block_bit_count; block_t m_insert_block; }; diff --git a/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp b/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp deleted file mode 100644 index 6eff9d3f..00000000 --- a/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "InMemoryZoneOutputStream.h" - -#include -#include - -InMemoryZoneOutputStream::InMemoryZoneOutputStream(InMemoryZoneData* zoneData, std::vector blocks, const int blockBitCount, const block_t insertBlock) - : m_zone_data(zoneData), - m_blocks(std::move(blocks)), - m_block_bit_count(blockBitCount), - m_insert_block(m_blocks[insertBlock]) -{ -} - -InMemoryZoneOutputStream::ReusableEntry::ReusableEntry(void* startPtr, const size_t entrySize, const size_t entryCount, const uintptr_t startZonePtr) - : m_start_ptr(startPtr), - m_end_ptr(reinterpret_cast(reinterpret_cast(startPtr) + entrySize * entryCount)), - m_start_zone_ptr(startZonePtr), - m_entry_size(entrySize), - m_entry_count(entryCount) -{ -} - -void InMemoryZoneOutputStream::PushBlock(const block_t block) -{ - assert(block >= 0 && block < static_cast(m_blocks.size())); - - auto* newBlock = m_blocks[block]; - - assert(newBlock->m_index == block); - - m_block_stack.push(newBlock); - - if (newBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) - { - if (m_temp_sizes.empty()) - m_temp_sizes.push(0); - else - m_temp_sizes.push(m_temp_sizes.top()); - } -} - -block_t InMemoryZoneOutputStream::PopBlock() -{ - assert(!m_block_stack.empty()); - - if (m_block_stack.empty()) - return -1; - - auto* poppedBlock = m_block_stack.top(); - m_block_stack.pop(); - - // If temp block is popped, see if its size is bigger than the current maximum temp size - if (poppedBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) - { - const auto tempSize = m_temp_sizes.top(); - m_temp_sizes.pop(); - - if (tempSize > poppedBlock->m_buffer_size) - poppedBlock->m_buffer_size = tempSize; - } - - return poppedBlock->m_index; -} - -void InMemoryZoneOutputStream::Align(const int align) -{ - assert(!m_block_stack.empty()); - - if (align > 1) - { - auto* block = m_block_stack.top(); - - if (block->m_type == XBlockType::BLOCK_TYPE_TEMP) - m_temp_sizes.top() = (m_temp_sizes.top() + align - 1) / align * align; - else - block->m_buffer_size = (block->m_buffer_size + align - 1) / align * align; - } -} - -void* InMemoryZoneOutputStream::WriteDataRaw(const void* src, const size_t size) -{ - auto* result = m_zone_data->GetBufferOfSize(size); - memcpy(result, src, size); - return result; -} - -void* InMemoryZoneOutputStream::WriteDataInBlock(const void* src, const size_t size) -{ - assert(!m_block_stack.empty()); - - if (m_block_stack.empty()) - return nullptr; - - auto* block = m_block_stack.top(); - - void* result = nullptr; - switch (block->m_type) - { - case XBlockType::BLOCK_TYPE_TEMP: - case XBlockType::BLOCK_TYPE_NORMAL: - result = m_zone_data->GetBufferOfSize(size); - memcpy(result, src, size); - break; - - case XBlockType::BLOCK_TYPE_RUNTIME: - break; - - case XBlockType::BLOCK_TYPE_DELAY: - assert(false); - break; - } - - IncBlockPos(size); - return result; -} - -void InMemoryZoneOutputStream::IncBlockPos(const size_t size) -{ - assert(!m_block_stack.empty()); - - if (m_block_stack.empty()) - return; - - auto* block = m_block_stack.top(); - if (block->m_type == XBlockType::BLOCK_TYPE_TEMP) - { - m_temp_sizes.top() += size; - } - else - { - block->m_buffer_size += size; - } -} - -void InMemoryZoneOutputStream::WriteNullTerminated(const void* src) -{ - const auto len = strlen(static_cast(src)); - WriteDataInBlock(src, len + 1); -} - -uintptr_t InMemoryZoneOutputStream::GetCurrentZonePointer() -{ - assert(!m_block_stack.empty()); - assert(m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_NORMAL); - - uintptr_t ptr = 0; - ptr |= static_cast(m_block_stack.top()->m_index) << (sizeof(uintptr_t) * 8 - m_block_bit_count); - ptr |= m_block_stack.top()->m_buffer_size & (UINTPTR_MAX >> m_block_bit_count); - ptr++; - - return ptr; -} - -uintptr_t InMemoryZoneOutputStream::InsertPointer() -{ - PushBlock(m_insert_block->m_index); - - Align(sizeof(uintptr_t)); - const auto result = GetCurrentZonePointer(); - IncBlockPos(sizeof(uintptr_t)); - - PopBlock(); - - return result; -} - -void InMemoryZoneOutputStream::MarkFollowing(void** pPtr) -{ - assert(!m_block_stack.empty()); - assert(pPtr != nullptr); - *pPtr = m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP ? PTR_INSERT : PTR_FOLLOWING; -} - -bool InMemoryZoneOutputStream::ReusableShouldWrite(void** pPtr, const size_t entrySize, const std::type_index type) -{ - assert(!m_block_stack.empty()); - assert(pPtr != nullptr); - - if (*pPtr == nullptr) - return false; - - const auto foundEntriesForType = m_reusable_entries.find(type); - if (foundEntriesForType == m_reusable_entries.end()) - { - return true; - } - - for (const auto& entry : foundEntriesForType->second) - { - if (*pPtr >= entry.m_start_ptr && *pPtr < entry.m_end_ptr) - { - assert((reinterpret_cast(*pPtr) - reinterpret_cast(entry.m_start_ptr)) % entrySize == 0); - *pPtr = reinterpret_cast(entry.m_start_zone_ptr + (reinterpret_cast(*pPtr) - reinterpret_cast(entry.m_start_ptr))); - return false; - } - } - - return true; -} - -void InMemoryZoneOutputStream::ReusableAddOffset(void* ptr, size_t size, size_t count, std::type_index type) -{ - assert(!m_block_stack.empty()); - - const auto inTemp = m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP; - auto zoneOffset = inTemp ? InsertPointer() : GetCurrentZonePointer(); - const auto foundEntriesForType = m_reusable_entries.find(type); - if (foundEntriesForType == m_reusable_entries.end()) - { - std::vector entries; - entries.emplace_back(ptr, size, count, zoneOffset); - m_reusable_entries.emplace(std::make_pair(type, std::move(entries))); - } - else - { - foundEntriesForType->second.emplace_back(ptr, size, count, zoneOffset); - } -} diff --git a/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.h b/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.h deleted file mode 100644 index 3f2f8947..00000000 --- a/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once -#include "Writing/InMemoryZoneData.h" -#include "Zone/Stream/IZoneOutputStream.h" -#include "Zone/XBlock.h" - -#include -#include -#include - -class InMemoryZoneOutputStream final : public IZoneOutputStream -{ - class ReusableEntry - { - public: - void* m_start_ptr; - void* m_end_ptr; - uintptr_t m_start_zone_ptr; - size_t m_entry_size; - size_t m_entry_count; - - ReusableEntry(void* startPtr, size_t entrySize, size_t entryCount, uintptr_t startZonePtr); - }; - - InMemoryZoneData* m_zone_data; - std::vector m_blocks; - - std::stack m_block_stack; - std::stack m_temp_sizes; - - int m_block_bit_count; - XBlock* m_insert_block; - - std::unordered_map> m_reusable_entries; - - uintptr_t GetCurrentZonePointer(); - uintptr_t InsertPointer(); - -public: - InMemoryZoneOutputStream(InMemoryZoneData* zoneData, std::vector blocks, int blockBitCount, block_t insertBlock); - - void PushBlock(block_t block) override; - block_t PopBlock() override; - void Align(int align) override; - void* WriteDataRaw(const void* src, size_t size) override; - void* WriteDataInBlock(const void* src, size_t size) override; - void IncBlockPos(size_t size) override; - void WriteNullTerminated(const void* src) override; - void MarkFollowing(void** pPtr) override; - bool ReusableShouldWrite(void** pPtr, size_t entrySize, std::type_index type) override; - void ReusableAddOffset(void* ptr, size_t size, size_t count, std::type_index type) override; -}; diff --git a/src/ZoneWriting/Writing/InMemoryZoneData.cpp b/src/ZoneWriting/Zone/Stream/InMemoryZoneData.cpp similarity index 100% rename from src/ZoneWriting/Writing/InMemoryZoneData.cpp rename to src/ZoneWriting/Zone/Stream/InMemoryZoneData.cpp diff --git a/src/ZoneWriting/Writing/InMemoryZoneData.h b/src/ZoneWriting/Zone/Stream/InMemoryZoneData.h similarity index 100% rename from src/ZoneWriting/Writing/InMemoryZoneData.h rename to src/ZoneWriting/Zone/Stream/InMemoryZoneData.h diff --git a/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp new file mode 100644 index 00000000..836a3d2e --- /dev/null +++ b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp @@ -0,0 +1,276 @@ +#include "ZoneOutputStream.h" + +#include "InMemoryZoneData.h" +#include "Utils/Alignment.h" +#include "Zone/XBlock.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + inline const auto PTR_FOLLOWING = reinterpret_cast(-1); + inline const auto PTR_INSERT = reinterpret_cast(-2); + + class ReusableEntry + { + public: + ReusableEntry(void* startPtr, const size_t entrySize, const size_t entryCount, const uintptr_t startZonePtr) + : m_start_ptr(startPtr), + m_end_ptr(reinterpret_cast(reinterpret_cast(startPtr) + entrySize * entryCount)), + m_start_zone_ptr(startZonePtr), + m_entry_size(entrySize), + m_entry_count(entryCount) + { + } + + void* m_start_ptr; + void* m_end_ptr; + uintptr_t m_start_zone_ptr; + size_t m_entry_size; + size_t m_entry_count; + }; + + class InMemoryZoneOutputStream final : public ZoneOutputStream + { + public: + InMemoryZoneOutputStream( + const unsigned pointerBitCount, const unsigned blockBitCount, std::vector& blocks, const block_t insertBlock, InMemoryZoneData& zoneData) + : m_zone_data(zoneData), + m_blocks(blocks), + m_block_bit_count(blockBitCount), + m_pointer_byte_count(pointerBitCount / 8u) + { + assert(pointerBitCount % 8u == 0u); + assert(insertBlock < static_cast(blocks.size())); + + m_insert_block = blocks[insertBlock]; + } + + [[nodiscard]] unsigned GetPointerBitCount() const override + { + return m_pointer_byte_count * 8u; + } + + void PushBlock(const block_t block) override + { + assert(block < static_cast(m_blocks.size())); + + auto* newBlock = m_blocks[block]; + + assert(newBlock->m_index == block); + + m_block_stack.push(newBlock); + + if (newBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) + { + if (m_temp_sizes.empty()) + m_temp_sizes.push(0); + else + m_temp_sizes.push(m_temp_sizes.top()); + } + } + + block_t PopBlock() override + { + assert(!m_block_stack.empty()); + + if (m_block_stack.empty()) + return -1; + + auto* poppedBlock = m_block_stack.top(); + m_block_stack.pop(); + + // If temp block is popped, see if its size is bigger than the current maximum temp size + if (poppedBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) + { + const auto tempSize = m_temp_sizes.top(); + m_temp_sizes.pop(); + + poppedBlock->m_buffer_size = std::max(tempSize, poppedBlock->m_buffer_size); + } + + return poppedBlock->m_index; + } + + void Align(const unsigned align) override + { + assert(!m_block_stack.empty()); + + if (align > 1) + { + auto* block = m_block_stack.top(); + + if (block->m_type == XBlockType::BLOCK_TYPE_TEMP) + m_temp_sizes.top() = utils::Align(m_temp_sizes.top(), static_cast(align)); + else + block->m_buffer_size = utils::Align(block->m_buffer_size, static_cast(align)); + } + } + + void* WriteDataRaw(const void* src, const size_t size) override + { + auto* result = m_zone_data.GetBufferOfSize(size); + memcpy(result, src, size); + return result; + } + + void* WriteDataInBlock(const void* src, const size_t size) override + { + assert(!m_block_stack.empty()); + + if (m_block_stack.empty()) + return nullptr; + + const auto* block = m_block_stack.top(); + + void* result = nullptr; + switch (block->m_type) + { + case XBlockType::BLOCK_TYPE_TEMP: + case XBlockType::BLOCK_TYPE_NORMAL: + result = m_zone_data.GetBufferOfSize(size); + memcpy(result, src, size); + break; + + case XBlockType::BLOCK_TYPE_RUNTIME: + break; + + case XBlockType::BLOCK_TYPE_DELAY: + assert(false); + break; + } + + IncBlockPos(size); + return result; + } + + void IncBlockPos(const size_t size) override + { + assert(!m_block_stack.empty()); + + if (m_block_stack.empty()) + return; + + auto* block = m_block_stack.top(); + if (block->m_type == XBlockType::BLOCK_TYPE_TEMP) + { + m_temp_sizes.top() += size; + } + else + { + block->m_buffer_size += size; + } + } + + void WriteNullTerminated(const void* src) override + { + const auto len = strlen(static_cast(src)); + WriteDataInBlock(src, len + 1); + } + + void MarkFollowing(void** pPtr) override + { + assert(!m_block_stack.empty()); + assert(pPtr != nullptr); + *pPtr = m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP ? PTR_INSERT : PTR_FOLLOWING; + } + + bool ReusableShouldWrite(void** pPtr, const size_t entrySize, const std::type_index type) override + { + assert(!m_block_stack.empty()); + assert(pPtr != nullptr); + + if (*pPtr == nullptr) + return false; + + const auto foundEntriesForType = m_reusable_entries.find(type); + if (foundEntriesForType == m_reusable_entries.end()) + { + return true; + } + + for (const auto& entry : foundEntriesForType->second) + { + if (*pPtr >= entry.m_start_ptr && *pPtr < entry.m_end_ptr) + { + assert((reinterpret_cast(*pPtr) - reinterpret_cast(entry.m_start_ptr)) % entrySize == 0); + *pPtr = + reinterpret_cast(entry.m_start_zone_ptr + (reinterpret_cast(*pPtr) - reinterpret_cast(entry.m_start_ptr))); + return false; + } + } + + return true; + } + + void ReusableAddOffset(void* ptr, size_t size, size_t count, std::type_index type) override + { + assert(!m_block_stack.empty()); + + const auto inTemp = m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP; + auto zoneOffset = inTemp ? InsertPointer() : GetCurrentZonePointer(); + const auto foundEntriesForType = m_reusable_entries.find(type); + if (foundEntriesForType == m_reusable_entries.end()) + { + std::vector entries; + entries.emplace_back(ptr, size, count, zoneOffset); + m_reusable_entries.emplace(std::make_pair(type, std::move(entries))); + } + else + { + foundEntriesForType->second.emplace_back(ptr, size, count, zoneOffset); + } + } + + private: + uintptr_t GetCurrentZonePointer() + { + assert(!m_block_stack.empty()); + assert(m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_NORMAL); + + uintptr_t ptr = 0; + ptr |= static_cast(m_block_stack.top()->m_index) << (sizeof(uintptr_t) * 8 - m_block_bit_count); + ptr |= m_block_stack.top()->m_buffer_size & (UINTPTR_MAX >> m_block_bit_count); + ptr++; + + return ptr; + } + + uintptr_t InsertPointer() + { + PushBlock(m_insert_block->m_index); + + Align(sizeof(uintptr_t)); + const auto result = GetCurrentZonePointer(); + IncBlockPos(sizeof(uintptr_t)); + + PopBlock(); + + return result; + } + + InMemoryZoneData& m_zone_data; + std::vector& m_blocks; + + std::stack m_block_stack; + std::stack m_temp_sizes; + + unsigned m_block_bit_count; + unsigned m_pointer_byte_count; + XBlock* m_insert_block; + + std::unordered_map> m_reusable_entries; + }; +} // namespace + +std::unique_ptr + ZoneOutputStream::Create(unsigned pointerBitCount, unsigned blockBitCount, std::vector& blocks, block_t insertBlock, InMemoryZoneData& zoneData) +{ + return std::make_unique(pointerBitCount, blockBitCount, blocks, insertBlock, zoneData); +} diff --git a/src/ZoneWriting/Zone/Stream/IZoneOutputStream.h b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.h similarity index 53% rename from src/ZoneWriting/Zone/Stream/IZoneOutputStream.h rename to src/ZoneWriting/Zone/Stream/ZoneOutputStream.h index 43b795bd..95981657 100644 --- a/src/ZoneWriting/Zone/Stream/IZoneOutputStream.h +++ b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.h @@ -1,20 +1,46 @@ #pragma once +#include "InMemoryZoneData.h" #include "Zone/Stream/IZoneStream.h" +#include "Zone/XBlock.h" #include +#include #include #include +#include -class IZoneOutputStream : public IZoneStream +class ZoneOutputStream : public IZoneStream { public: - inline static void* const PTR_FOLLOWING = reinterpret_cast(-1); - inline static void* const PTR_INSERT = reinterpret_cast(-2); + /** + * \brief Returns the configured bits that make up a pointer. + */ + [[nodiscard]] virtual unsigned GetPointerBitCount() const = 0; - virtual void Align(int alignTo) = 0; + /** + * \brief Aligns the write position in the current block with the specified value. + * \param align The alignment value that the write position is aligned with. This should typically be the alignment of the struct that + * should be written afterward. + */ + virtual void Align(unsigned align) = 0; + /** + * \brief Write data to the zone data without considering the current block or advancing the block position. + * The data is written directly to the specified location instead of block memory. + * \param dst The memory location to write data to. + * \param size The amount of data to write. + */ virtual void* WriteDataRaw(const void* dst, size_t size) = 0; + + /** + * \brief Write data with the current blocks write operation into its block memory. + * Depending on the block type, the underlying stream might be written to or not. + * The current block position is advanced by the number of bytes written. + * The destination must be inside the current block's memory space, otherwise an exception is thrown. + * \param dst The destination where the data is written to. Must be inside the current block's memory bounds. + * \param size The amount of data to write. + */ virtual void* WriteDataInBlock(const void* dst, size_t size) = 0; virtual void IncBlockPos(size_t size) = 0; virtual void WriteNullTerminated(const void* dst) = 0; @@ -57,4 +83,7 @@ public: { MarkFollowing(reinterpret_cast(reinterpret_cast(&ptr))); } + + static std::unique_ptr + Create(unsigned pointerBitCount, unsigned blockBitCount, std::vector& blocks, block_t insertBlock, InMemoryZoneData& zoneData); };