From 4048de44a165ef22b55a63725ca80614de2e5ae2 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Tue, 6 Jan 2026 22:37:46 +0000 Subject: [PATCH] refactor: return ZoneOutputOffset when writing via ZoneOutputStream --- src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp | 33 +++++-- src/ZoneWriting/Game/IW3/ContentWriterIW3.h | 4 + src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp | 33 +++++-- src/ZoneWriting/Game/IW4/ContentWriterIW4.h | 4 + src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp | 33 +++++-- src/ZoneWriting/Game/IW5/ContentWriterIW5.h | 4 + src/ZoneWriting/Game/T5/ContentWriterT5.cpp | 33 +++++-- src/ZoneWriting/Game/T5/ContentWriterT5.h | 4 + src/ZoneWriting/Game/T6/ContentWriterT6.cpp | 41 ++++++--- src/ZoneWriting/Game/T6/ContentWriterT6.h | 4 + src/ZoneWriting/Writing/AssetWriter.cpp | 9 +- src/ZoneWriting/Writing/AssetWriter.h | 2 +- src/ZoneWriting/Writing/ContentWriterBase.cpp | 17 ++-- src/ZoneWriting/Writing/ContentWriterBase.h | 2 +- .../Zone/Stream/ZoneOutputStream.cpp | 86 +++++++++++++++---- .../Zone/Stream/ZoneOutputStream.h | 45 ++++++---- 16 files changed, 262 insertions(+), 92 deletions(-) diff --git a/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp b/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp index 72475a26..7acc1f11 100644 --- a/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp +++ b/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp @@ -60,15 +60,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); if (atStreamStart) - varScriptStringList = m_stream->Write(varScriptStringList); + varScriptStringListWritten = m_stream->Write(varScriptStringList); if (varScriptStringList->strings != nullptr) { - m_stream->Align(alignof(const char*)); + m_stream->Align(4); varXString = varScriptStringList->strings; WriteXStringArray(true, varScriptStringList->count); - m_stream->MarkFollowing(varScriptStringList->strings); +#ifdef ARCH_x86 + static_assert(offsetof(ScriptStringList, strings) == 4u); +#endif + m_stream->MarkFollowing(varScriptStringListWritten.WithInnerOffset(4)); } m_stream->PopBlock(); @@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart) assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset); + varXAssetWritten = m_stream->Write(varXAsset); switch (varXAsset->type) { @@ -137,12 +140,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset, count); + varXAssetWritten = m_stream->Write(varXAsset, count); for (size_t index = 0; index < count; index++) { WriteXAsset(false); varXAsset++; + +#ifdef ARCH_x86 + static_assert(sizeof(XAsset) == 8u); +#endif + varXAssetWritten.Inc(8u); } } @@ -157,17 +165,26 @@ void ContentWriter::WriteContent(ZoneOutputStream& stream) CreateXAssetList(assetList, memory); - varXAssetList = static_cast(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); + varXAssetList = &assetList; + varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList)); +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, stringList) == 0u); +#endif varScriptStringList = &varXAssetList->stringList; + varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0); WriteScriptStringList(false); if (varXAssetList->assets != nullptr) { - m_stream->Align(alignof(XAsset)); + m_stream->Align(4); varXAsset = varXAssetList->assets; WriteXAssetArray(true, varXAssetList->assetCount); - m_stream->MarkFollowing(varXAssetList->assets); + +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, assets) == 12u); +#endif + m_stream->MarkFollowing(varXAssetListWritten.WithInnerOffset(12)); } m_stream->PopBlock(); diff --git a/src/ZoneWriting/Game/IW3/ContentWriterIW3.h b/src/ZoneWriting/Game/IW3/ContentWriterIW3.h index 195df96c..b604fdf8 100644 --- a/src/ZoneWriting/Game/IW3/ContentWriterIW3.h +++ b/src/ZoneWriting/Game/IW3/ContentWriterIW3.h @@ -24,5 +24,9 @@ namespace IW3 XAssetList* varXAssetList; XAsset* varXAsset; ScriptStringList* varScriptStringList; + + ZoneOutputOffset varXAssetListWritten; + ZoneOutputOffset varXAssetWritten; + ZoneOutputOffset varScriptStringListWritten; }; } // namespace IW3 diff --git a/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp b/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp index 36592259..b6f12ad2 100644 --- a/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp +++ b/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp @@ -60,15 +60,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); if (atStreamStart) - varScriptStringList = m_stream->Write(varScriptStringList); + varScriptStringListWritten = m_stream->Write(varScriptStringList); if (varScriptStringList->strings != nullptr) { - m_stream->Align(alignof(const char*)); + m_stream->Align(4); varXString = varScriptStringList->strings; WriteXStringArray(true, varScriptStringList->count); - m_stream->MarkFollowing(varScriptStringList->strings); +#ifdef ARCH_x86 + static_assert(offsetof(ScriptStringList, strings) == 4u); +#endif + m_stream->MarkFollowing(varScriptStringListWritten.WithInnerOffset(4)); } m_stream->PopBlock(); @@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart) assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset); + varXAssetWritten = m_stream->Write(varXAsset); switch (varXAsset->type) { @@ -147,12 +150,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset, count); + varXAssetWritten = m_stream->Write(varXAsset, count); for (size_t index = 0; index < count; index++) { WriteXAsset(false); varXAsset++; + +#ifdef ARCH_x86 + static_assert(sizeof(XAsset) == 8u); +#endif + varXAssetWritten.Inc(8u); } } @@ -167,17 +175,26 @@ void ContentWriter::WriteContent(ZoneOutputStream& stream) CreateXAssetList(assetList, memory); - varXAssetList = static_cast(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); + varXAssetList = &assetList; + varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList)); +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, stringList) == 0u); +#endif varScriptStringList = &varXAssetList->stringList; + varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0); WriteScriptStringList(false); if (varXAssetList->assets != nullptr) { - m_stream->Align(alignof(XAsset)); + m_stream->Align(4); varXAsset = varXAssetList->assets; WriteXAssetArray(true, varXAssetList->assetCount); - m_stream->MarkFollowing(varXAssetList->assets); + +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, assets) == 12u); +#endif + m_stream->MarkFollowing(varXAssetListWritten.WithInnerOffset(12)); } m_stream->PopBlock(); diff --git a/src/ZoneWriting/Game/IW4/ContentWriterIW4.h b/src/ZoneWriting/Game/IW4/ContentWriterIW4.h index e5212c60..101c8041 100644 --- a/src/ZoneWriting/Game/IW4/ContentWriterIW4.h +++ b/src/ZoneWriting/Game/IW4/ContentWriterIW4.h @@ -24,5 +24,9 @@ namespace IW4 XAssetList* varXAssetList; XAsset* varXAsset; ScriptStringList* varScriptStringList; + + ZoneOutputOffset varXAssetListWritten; + ZoneOutputOffset varXAssetWritten; + ZoneOutputOffset varScriptStringListWritten; }; } // namespace IW4 diff --git a/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp b/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp index b5ecf4b2..554ad4c0 100644 --- a/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp +++ b/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp @@ -60,15 +60,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); if (atStreamStart) - varScriptStringList = m_stream->Write(varScriptStringList); + varScriptStringListWritten = m_stream->Write(varScriptStringList); if (varScriptStringList->strings != nullptr) { - m_stream->Align(alignof(const char*)); + m_stream->Align(4); varXString = varScriptStringList->strings; WriteXStringArray(true, varScriptStringList->count); - m_stream->MarkFollowing(varScriptStringList->strings); +#ifdef ARCH_x86 + static_assert(offsetof(ScriptStringList, strings) == 4u); +#endif + m_stream->MarkFollowing(varScriptStringListWritten.WithInnerOffset(4)); } m_stream->PopBlock(); @@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart) assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset); + varXAssetWritten = m_stream->Write(varXAsset); switch (varXAsset->type) { @@ -150,12 +153,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset, count); + varXAssetWritten = m_stream->Write(varXAsset, count); for (size_t index = 0; index < count; index++) { WriteXAsset(false); varXAsset++; + +#ifdef ARCH_x86 + static_assert(sizeof(XAsset) == 8u); +#endif + varXAssetWritten.Inc(8u); } } @@ -170,17 +178,26 @@ void ContentWriter::WriteContent(ZoneOutputStream& stream) CreateXAssetList(assetList, memory); - varXAssetList = static_cast(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); + varXAssetList = &assetList; + varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList)); +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, stringList) == 0u); +#endif varScriptStringList = &varXAssetList->stringList; + varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0); WriteScriptStringList(false); if (varXAssetList->assets != nullptr) { - m_stream->Align(alignof(XAsset)); + m_stream->Align(4); varXAsset = varXAssetList->assets; WriteXAssetArray(true, varXAssetList->assetCount); - m_stream->MarkFollowing(varXAssetList->assets); + +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, assets) == 12u); +#endif + m_stream->MarkFollowing(varXAssetListWritten.WithInnerOffset(12)); } m_stream->PopBlock(); diff --git a/src/ZoneWriting/Game/IW5/ContentWriterIW5.h b/src/ZoneWriting/Game/IW5/ContentWriterIW5.h index 6bf2ace2..82830b08 100644 --- a/src/ZoneWriting/Game/IW5/ContentWriterIW5.h +++ b/src/ZoneWriting/Game/IW5/ContentWriterIW5.h @@ -24,5 +24,9 @@ namespace IW5 XAssetList* varXAssetList; XAsset* varXAsset; ScriptStringList* varScriptStringList; + + ZoneOutputOffset varXAssetListWritten; + ZoneOutputOffset varXAssetWritten; + ZoneOutputOffset varScriptStringListWritten; }; } // namespace IW5 diff --git a/src/ZoneWriting/Game/T5/ContentWriterT5.cpp b/src/ZoneWriting/Game/T5/ContentWriterT5.cpp index 8c0c2ce6..ae2c40ce 100644 --- a/src/ZoneWriting/Game/T5/ContentWriterT5.cpp +++ b/src/ZoneWriting/Game/T5/ContentWriterT5.cpp @@ -60,15 +60,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); if (atStreamStart) - varScriptStringList = m_stream->Write(varScriptStringList); + varScriptStringListWritten = m_stream->Write(varScriptStringList); if (varScriptStringList->strings != nullptr) { - m_stream->Align(alignof(const char*)); + m_stream->Align(4); varXString = varScriptStringList->strings; WriteXStringArray(true, varScriptStringList->count); - m_stream->MarkFollowing(varScriptStringList->strings); +#ifdef ARCH_x86 + static_assert(offsetof(ScriptStringList, strings) == 4u); +#endif + m_stream->MarkFollowing(varScriptStringListWritten.WithInnerOffset(4)); } m_stream->PopBlock(); @@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart) assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset); + varXAssetWritten = m_stream->Write(varXAsset); switch (varXAsset->type) { @@ -143,12 +146,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset, count); + varXAssetWritten = m_stream->Write(varXAsset, count); for (size_t index = 0; index < count; index++) { WriteXAsset(false); varXAsset++; + +#ifdef ARCH_x86 + static_assert(sizeof(XAsset) == 8u); +#endif + varXAssetWritten.Inc(8u); } } @@ -163,17 +171,26 @@ void ContentWriter::WriteContent(ZoneOutputStream& stream) CreateXAssetList(assetList, memory); - varXAssetList = static_cast(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); + varXAssetList = &assetList; + varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList)); +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, stringList) == 0u); +#endif varScriptStringList = &varXAssetList->stringList; + varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0); WriteScriptStringList(false); if (varXAssetList->assets != nullptr) { - m_stream->Align(alignof(XAsset)); + m_stream->Align(4); varXAsset = varXAssetList->assets; WriteXAssetArray(true, varXAssetList->assetCount); - m_stream->MarkFollowing(varXAssetList->assets); + +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, assets) == 12u); +#endif + m_stream->MarkFollowing(varXAssetListWritten.WithInnerOffset(12)); } m_stream->PopBlock(); diff --git a/src/ZoneWriting/Game/T5/ContentWriterT5.h b/src/ZoneWriting/Game/T5/ContentWriterT5.h index 1c0cc137..094c5e62 100644 --- a/src/ZoneWriting/Game/T5/ContentWriterT5.h +++ b/src/ZoneWriting/Game/T5/ContentWriterT5.h @@ -24,5 +24,9 @@ namespace T5 XAssetList* varXAssetList; XAsset* varXAsset; ScriptStringList* varScriptStringList; + + ZoneOutputOffset varXAssetListWritten; + ZoneOutputOffset varXAssetWritten; + ZoneOutputOffset varScriptStringListWritten; }; } // namespace T5 diff --git a/src/ZoneWriting/Game/T6/ContentWriterT6.cpp b/src/ZoneWriting/Game/T6/ContentWriterT6.cpp index 234f80f5..c9544b45 100644 --- a/src/ZoneWriting/Game/T6/ContentWriterT6.cpp +++ b/src/ZoneWriting/Game/T6/ContentWriterT6.cpp @@ -63,15 +63,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); if (atStreamStart) - varScriptStringList = m_stream->Write(varScriptStringList); + varScriptStringListWritten = m_stream->Write(varScriptStringList); if (varScriptStringList->strings != nullptr) { - m_stream->Align(alignof(const char*)); + m_stream->Align(4); varXString = varScriptStringList->strings; WriteXStringArray(true, varScriptStringList->count); - m_stream->MarkFollowing(varScriptStringList->strings); +#ifdef ARCH_x86 + static_assert(offsetof(ScriptStringList, strings) == 4u); +#endif + m_stream->MarkFollowing(varScriptStringListWritten.WithInnerOffset(4)); } m_stream->PopBlock(); @@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart) assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset); + varXAssetWritten = m_stream->Write(varXAsset); switch (varXAsset->type) { @@ -158,12 +161,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun assert(varXAsset != nullptr); if (atStreamStart) - varXAsset = m_stream->Write(varXAsset, count); + varXAssetWritten = m_stream->Write(varXAsset, count); for (size_t index = 0; index < count; index++) { WriteXAsset(false); varXAsset++; + +#ifdef ARCH_x86 + static_assert(sizeof(XAsset) == 8u); +#endif + varXAssetWritten.Inc(8u); } } @@ -178,25 +186,38 @@ void ContentWriter::WriteContent(ZoneOutputStream& stream) CreateXAssetList(assetList, memory); - varXAssetList = static_cast(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); + varXAssetList = &assetList; + varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList)); +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, stringList) == 0u); +#endif varScriptStringList = &varXAssetList->stringList; + varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0); WriteScriptStringList(false); if (varXAssetList->depends != nullptr) { - m_stream->Align(alignof(const char*)); + m_stream->Align(4); varXString = varXAssetList->depends; WriteXStringArray(true, varXAssetList->dependCount); - m_stream->MarkFollowing(varXAssetList->depends); + +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, depends) == 12u); +#endif + m_stream->MarkFollowing(varXAssetListWritten.WithInnerOffset(12)); } if (varXAssetList->assets != nullptr) { - m_stream->Align(alignof(XAsset)); + m_stream->Align(4); varXAsset = varXAssetList->assets; WriteXAssetArray(true, varXAssetList->assetCount); - m_stream->MarkFollowing(varXAssetList->assets); + +#ifdef ARCH_x86 + static_assert(offsetof(XAssetList, assets) == 20u); +#endif + m_stream->MarkFollowing(varXAssetListWritten.WithInnerOffset(20)); } m_stream->PopBlock(); diff --git a/src/ZoneWriting/Game/T6/ContentWriterT6.h b/src/ZoneWriting/Game/T6/ContentWriterT6.h index 4bb08580..7fb5ce20 100644 --- a/src/ZoneWriting/Game/T6/ContentWriterT6.h +++ b/src/ZoneWriting/Game/T6/ContentWriterT6.h @@ -24,5 +24,9 @@ namespace T6 XAssetList* varXAssetList; XAsset* varXAsset; ScriptStringList* varScriptStringList; + + ZoneOutputOffset varXAssetListWritten; + ZoneOutputOffset varXAssetWritten; + ZoneOutputOffset varScriptStringListWritten; }; } // namespace T6 diff --git a/src/ZoneWriting/Writing/AssetWriter.cpp b/src/ZoneWriting/Writing/AssetWriter.cpp index e052927e..ecd8d70c 100644 --- a/src/ZoneWriting/Writing/AssetWriter.cpp +++ b/src/ZoneWriting/Writing/AssetWriter.cpp @@ -38,12 +38,13 @@ void AssetWriter::WriteScriptStringArray(const bool atStreamStart, const size_t varScriptStringWritten = m_stream->Write(varScriptString, count); } - assert(varScriptStringWritten != nullptr); + assert(varScriptStringWritten.Offset() != nullptr); - auto* ptr = varScriptStringWritten; for (size_t index = 0; index < count; index++) { - *ptr = UseScriptString(*ptr); - ptr++; + *static_cast(varScriptStringWritten.Offset()) = UseScriptString(*varScriptString); + + varScriptString++; + varScriptStringWritten.Inc(sizeof(scr_string_t)); } } diff --git a/src/ZoneWriting/Writing/AssetWriter.h b/src/ZoneWriting/Writing/AssetWriter.h index b3357054..10220241 100644 --- a/src/ZoneWriting/Writing/AssetWriter.h +++ b/src/ZoneWriting/Writing/AssetWriter.h @@ -17,5 +17,5 @@ protected: XAssetInfoGeneric* m_asset; scr_string_t* varScriptString; - scr_string_t* varScriptStringWritten; + ZoneOutputOffset varScriptStringWritten; }; diff --git a/src/ZoneWriting/Writing/ContentWriterBase.cpp b/src/ZoneWriting/Writing/ContentWriterBase.cpp index 71f603d9..b4b52a42 100644 --- a/src/ZoneWriting/Writing/ContentWriterBase.cpp +++ b/src/ZoneWriting/Writing/ContentWriterBase.cpp @@ -26,15 +26,15 @@ void ContentWriterBase::WriteXString(const bool atStreamStart) varXStringWritten = m_stream->Write(varXString); } - assert(varXStringWritten != nullptr); + assert(varXStringWritten.Offset() != nullptr); - if (m_stream->ReusableShouldWrite(varXStringWritten)) + if (m_stream->ReusableShouldWrite(*varXString, varXStringWritten)) { - m_stream->Align(alignof(const char)); - m_stream->ReusableAddOffset(*varXStringWritten); - m_stream->WriteNullTerminated(*varXStringWritten); + m_stream->Align(1); + m_stream->ReusableAddOffset(*varXString); + m_stream->WriteNullTerminated(*varXString); - m_stream->MarkFollowing(*varXStringWritten); + m_stream->MarkFollowing(varXStringWritten); } } @@ -46,11 +46,12 @@ void ContentWriterBase::WriteXStringArray(const bool atStreamStart, const size_t varXStringWritten = m_stream->Write(varXString, count); } - assert(varXStringWritten != nullptr); + assert(varXStringWritten.Offset() != nullptr); for (size_t index = 0; index < count; index++) { WriteXString(false); - varXStringWritten++; + varXString++; + varXStringWritten.Inc(m_stream->GetPointerByteCount()); } } diff --git a/src/ZoneWriting/Writing/ContentWriterBase.h b/src/ZoneWriting/Writing/ContentWriterBase.h index 9a58959d..47da7b56 100644 --- a/src/ZoneWriting/Writing/ContentWriterBase.h +++ b/src/ZoneWriting/Writing/ContentWriterBase.h @@ -24,5 +24,5 @@ protected: ZoneOutputStream* m_stream; const char** varXString; - const char** varXStringWritten; + ZoneOutputOffset varXStringWritten; }; diff --git a/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp index 836a3d2e..d8a209be 100644 --- a/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp +++ b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp @@ -44,7 +44,13 @@ namespace : m_zone_data(zoneData), m_blocks(blocks), m_block_bit_count(blockBitCount), - m_pointer_byte_count(pointerBitCount / 8u) + m_pointer_byte_count(pointerBitCount / 8u), + + // -1 + m_zone_ptr_following(std::numeric_limits::max() >> ((sizeof(std::uintptr_t) * 8u) - pointerBitCount)), + + // -2 + m_zone_ptr_insert((std::numeric_limits::max() >> ((sizeof(std::uintptr_t) * 8u) - pointerBitCount)) - 1u) { assert(pointerBitCount % 8u == 0u); assert(insertBlock < static_cast(blocks.size())); @@ -52,9 +58,9 @@ namespace m_insert_block = blocks[insertBlock]; } - [[nodiscard]] unsigned GetPointerBitCount() const override + [[nodiscard]] unsigned GetPointerByteCount() const override { - return m_pointer_byte_count * 8u; + return m_pointer_byte_count; } void PushBlock(const block_t block) override @@ -113,19 +119,20 @@ namespace } } - void* WriteDataRaw(const void* src, const size_t size) override + ZoneOutputOffset WriteDataRaw(const void* src, const size_t size) override { auto* result = m_zone_data.GetBufferOfSize(size); memcpy(result, src, size); - return result; + + return ZoneOutputOffset(result); } - void* WriteDataInBlock(const void* src, const size_t size) override + ZoneOutputOffset WriteDataInBlock(const void* src, const size_t size) override { assert(!m_block_stack.empty()); if (m_block_stack.empty()) - return nullptr; + return ZoneOutputOffset(); const auto* block = m_block_stack.top(); @@ -147,7 +154,8 @@ namespace } IncBlockPos(size); - return result; + + return ZoneOutputOffset(result); } void IncBlockPos(const size_t size) override @@ -174,19 +182,30 @@ namespace WriteDataInBlock(src, len + 1); } - void MarkFollowing(void** pPtr) override + void MarkFollowing(const ZoneOutputOffset outputOffset) override { assert(!m_block_stack.empty()); - assert(pPtr != nullptr); - *pPtr = m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP ? PTR_INSERT : PTR_FOLLOWING; + + auto* ptr = static_cast(outputOffset.Offset()); + assert(ptr != nullptr); + + if (m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP) + { + for (auto i = 0u; i < m_pointer_byte_count; i++) + ptr[i] = reinterpret_cast(&m_zone_ptr_insert)[i]; + } + else + { + for (auto i = 0u; i < m_pointer_byte_count; i++) + ptr[i] = reinterpret_cast(&m_zone_ptr_following)[i]; + } } - bool ReusableShouldWrite(void** pPtr, const size_t entrySize, const std::type_index type) override + bool ReusableShouldWrite(void* ptr, const ZoneOutputOffset outputOffset, const size_t entrySize, const std::type_index type) override { assert(!m_block_stack.empty()); - assert(pPtr != nullptr); - if (*pPtr == nullptr) + if (ptr == nullptr) return false; const auto foundEntriesForType = m_reusable_entries.find(type); @@ -197,11 +216,14 @@ namespace for (const auto& entry : foundEntriesForType->second) { - if (*pPtr >= entry.m_start_ptr && *pPtr < entry.m_end_ptr) + if (ptr >= entry.m_start_ptr && ptr < 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))); + assert((reinterpret_cast(ptr) - reinterpret_cast(entry.m_start_ptr)) % entrySize == 0); + const auto finalZonePointer = entry.m_start_zone_ptr + (reinterpret_cast(ptr) - reinterpret_cast(entry.m_start_ptr)); + + for (auto i = 0u; i < m_pointer_byte_count; i++) + static_cast(ptr)[i] = reinterpret_cast(&finalZonePointer)[i]; + return false; } } @@ -265,10 +287,38 @@ namespace unsigned m_pointer_byte_count; XBlock* m_insert_block; + uintptr_t m_zone_ptr_following; + uintptr_t m_zone_ptr_insert; + std::unordered_map> m_reusable_entries; }; } // namespace +ZoneOutputOffset::ZoneOutputOffset() + : m_offset(nullptr) +{ +} + +ZoneOutputOffset::ZoneOutputOffset(void* offset) + : m_offset(offset) +{ +} + +void* ZoneOutputOffset::Offset() const +{ + return m_offset; +} + +void ZoneOutputOffset::Inc(const size_t size) +{ + m_offset = static_cast(static_cast(m_offset) + size); +} + +ZoneOutputOffset ZoneOutputOffset::WithInnerOffset(const size_t innerOffset) const +{ + return ZoneOutputOffset(static_cast(m_offset) + innerOffset); +} + std::unique_ptr ZoneOutputStream::Create(unsigned pointerBitCount, unsigned blockBitCount, std::vector& blocks, block_t insertBlock, InMemoryZoneData& zoneData) { diff --git a/src/ZoneWriting/Zone/Stream/ZoneOutputStream.h b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.h index 95981657..3b6aa2ff 100644 --- a/src/ZoneWriting/Zone/Stream/ZoneOutputStream.h +++ b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.h @@ -10,13 +10,27 @@ #include #include +class ZoneOutputOffset +{ +public: + ZoneOutputOffset(); + explicit ZoneOutputOffset(void* offset); + + [[nodiscard]] void* Offset() const; + void Inc(size_t size); + [[nodiscard]] ZoneOutputOffset WithInnerOffset(size_t innerOffset) const; + +private: + void* m_offset; +}; + class ZoneOutputStream : public IZoneStream { public: /** * \brief Returns the configured bits that make up a pointer. */ - [[nodiscard]] virtual unsigned GetPointerBitCount() const = 0; + [[nodiscard]] virtual unsigned GetPointerByteCount() const = 0; /** * \brief Aligns the write position in the current block with the specified value. @@ -31,7 +45,7 @@ public: * \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; + virtual ZoneOutputOffset WriteDataRaw(const void* dst, size_t size) = 0; /** * \brief Write data with the current blocks write operation into its block memory. @@ -41,17 +55,17 @@ public: * \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 ZoneOutputOffset WriteDataInBlock(const void* dst, size_t size) = 0; virtual void IncBlockPos(size_t size) = 0; virtual void WriteNullTerminated(const void* dst) = 0; - virtual bool ReusableShouldWrite(void** pPtr, size_t size, std::type_index type) = 0; + virtual bool ReusableShouldWrite(void* pPtr, ZoneOutputOffset outputOffset, size_t size, std::type_index type) = 0; virtual void ReusableAddOffset(void* ptr, size_t size, size_t count, std::type_index type) = 0; - virtual void MarkFollowing(void** pPtr) = 0; + virtual void MarkFollowing(ZoneOutputOffset offset) = 0; - template bool ReusableShouldWrite(T** pPtr) + template bool ReusableShouldWrite(T* pPtr, const ZoneOutputOffset outputOffset) { - return ReusableShouldWrite(reinterpret_cast(reinterpret_cast(pPtr)), sizeof(T), std::type_index(typeid(T))); + return ReusableShouldWrite(const_cast(reinterpret_cast(pPtr)), outputOffset, sizeof(T), std::type_index(typeid(T))); } template void ReusableAddOffset(T* ptr) @@ -64,24 +78,19 @@ public: ReusableAddOffset(const_cast(reinterpret_cast(ptr)), sizeof(T), count, std::type_index(typeid(T))); } - template T* Write(T* dst) + template ZoneOutputOffset Write(T* dst) { - return static_cast(WriteDataInBlock(reinterpret_cast(dst), sizeof(T))); + return WriteDataInBlock(reinterpret_cast(dst), sizeof(T)); } - template T* Write(T* dst, const size_t count) + template ZoneOutputOffset Write(T* dst, const size_t count) { - return static_cast(WriteDataInBlock(reinterpret_cast(dst), count * sizeof(T))); + return WriteDataInBlock(reinterpret_cast(dst), count * sizeof(T)); } - template T* WritePartial(T* dst, const size_t size) + ZoneOutputOffset WritePartial(const void* dst, const size_t size) { - return static_cast(WriteDataInBlock(reinterpret_cast(dst), size)); - } - - template void MarkFollowing(T*& ptr) - { - MarkFollowing(reinterpret_cast(reinterpret_cast(&ptr))); + return WriteDataInBlock(dst, size); } static std::unique_ptr