2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-01-13 12:11:50 +00:00

refactor: return ZoneOutputOffset when writing via ZoneOutputStream

This commit is contained in:
Jan Laupetin
2026-01-06 22:37:46 +00:00
parent df07ebe083
commit 4048de44a1
16 changed files with 262 additions and 92 deletions

View File

@@ -60,15 +60,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart)
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
if (atStreamStart) if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList); varScriptStringListWritten = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); 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(); m_stream->PopBlock();
@@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -137,12 +140,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); varXAssetWritten = m_stream->Write(varXAsset, count);
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; 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); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(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; varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->assets != nullptr) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); 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(); m_stream->PopBlock();

View File

@@ -24,5 +24,9 @@ namespace IW3
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace IW3 } // namespace IW3

View File

@@ -60,15 +60,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart)
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
if (atStreamStart) if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList); varScriptStringListWritten = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); 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(); m_stream->PopBlock();
@@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -147,12 +150,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); varXAssetWritten = m_stream->Write(varXAsset, count);
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; 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); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(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; varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->assets != nullptr) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); 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(); m_stream->PopBlock();

View File

@@ -24,5 +24,9 @@ namespace IW4
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace IW4 } // namespace IW4

View File

@@ -60,15 +60,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart)
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
if (atStreamStart) if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList); varScriptStringListWritten = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); 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(); m_stream->PopBlock();
@@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -150,12 +153,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); varXAssetWritten = m_stream->Write(varXAsset, count);
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; 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); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(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; varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->assets != nullptr) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); 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(); m_stream->PopBlock();

View File

@@ -24,5 +24,9 @@ namespace IW5
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace IW5 } // namespace IW5

View File

@@ -60,15 +60,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart)
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
if (atStreamStart) if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList); varScriptStringListWritten = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); 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(); m_stream->PopBlock();
@@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -143,12 +146,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); varXAssetWritten = m_stream->Write(varXAsset, count);
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; 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); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(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; varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->assets != nullptr) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); 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(); m_stream->PopBlock();

View File

@@ -24,5 +24,9 @@ namespace T5
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace T5 } // namespace T5

View File

@@ -63,15 +63,18 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart)
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
if (atStreamStart) if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList); varScriptStringListWritten = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); 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(); m_stream->PopBlock();
@@ -90,7 +93,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -158,12 +161,17 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); varXAssetWritten = m_stream->Write(varXAsset, count);
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; 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); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(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; varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.WithInnerOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->depends != nullptr) if (varXAssetList->depends != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varXAssetList->depends; varXString = varXAssetList->depends;
WriteXStringArray(true, varXAssetList->dependCount); 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) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); 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(); m_stream->PopBlock();

View File

@@ -24,5 +24,9 @@ namespace T6
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace T6 } // namespace T6

View File

@@ -38,12 +38,13 @@ void AssetWriter::WriteScriptStringArray(const bool atStreamStart, const size_t
varScriptStringWritten = m_stream->Write<scr_string_t>(varScriptString, count); varScriptStringWritten = m_stream->Write<scr_string_t>(varScriptString, count);
} }
assert(varScriptStringWritten != nullptr); assert(varScriptStringWritten.Offset() != nullptr);
auto* ptr = varScriptStringWritten;
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
*ptr = UseScriptString(*ptr); *static_cast<scr_string_t*>(varScriptStringWritten.Offset()) = UseScriptString(*varScriptString);
ptr++;
varScriptString++;
varScriptStringWritten.Inc(sizeof(scr_string_t));
} }
} }

View File

@@ -17,5 +17,5 @@ protected:
XAssetInfoGeneric* m_asset; XAssetInfoGeneric* m_asset;
scr_string_t* varScriptString; scr_string_t* varScriptString;
scr_string_t* varScriptStringWritten; ZoneOutputOffset varScriptStringWritten;
}; };

View File

@@ -26,15 +26,15 @@ void ContentWriterBase::WriteXString(const bool atStreamStart)
varXStringWritten = m_stream->Write<const char*>(varXString); varXStringWritten = m_stream->Write<const char*>(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->Align(1);
m_stream->ReusableAddOffset(*varXStringWritten); m_stream->ReusableAddOffset(*varXString);
m_stream->WriteNullTerminated(*varXStringWritten); 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<const char*>(varXString, count); varXStringWritten = m_stream->Write<const char*>(varXString, count);
} }
assert(varXStringWritten != nullptr); assert(varXStringWritten.Offset() != nullptr);
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXString(false); WriteXString(false);
varXStringWritten++; varXString++;
varXStringWritten.Inc(m_stream->GetPointerByteCount());
} }
} }

View File

@@ -24,5 +24,5 @@ protected:
ZoneOutputStream* m_stream; ZoneOutputStream* m_stream;
const char** varXString; const char** varXString;
const char** varXStringWritten; ZoneOutputOffset varXStringWritten;
}; };

View File

@@ -44,7 +44,13 @@ namespace
: m_zone_data(zoneData), : m_zone_data(zoneData),
m_blocks(blocks), m_blocks(blocks),
m_block_bit_count(blockBitCount), 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<std::uintptr_t>::max() >> ((sizeof(std::uintptr_t) * 8u) - pointerBitCount)),
// -2
m_zone_ptr_insert((std::numeric_limits<std::uintptr_t>::max() >> ((sizeof(std::uintptr_t) * 8u) - pointerBitCount)) - 1u)
{ {
assert(pointerBitCount % 8u == 0u); assert(pointerBitCount % 8u == 0u);
assert(insertBlock < static_cast<block_t>(blocks.size())); assert(insertBlock < static_cast<block_t>(blocks.size()));
@@ -52,9 +58,9 @@ namespace
m_insert_block = blocks[insertBlock]; 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 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); auto* result = m_zone_data.GetBufferOfSize(size);
memcpy(result, src, 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()); assert(!m_block_stack.empty());
if (m_block_stack.empty()) if (m_block_stack.empty())
return nullptr; return ZoneOutputOffset();
const auto* block = m_block_stack.top(); const auto* block = m_block_stack.top();
@@ -147,7 +154,8 @@ namespace
} }
IncBlockPos(size); IncBlockPos(size);
return result;
return ZoneOutputOffset(result);
} }
void IncBlockPos(const size_t size) override void IncBlockPos(const size_t size) override
@@ -174,19 +182,30 @@ namespace
WriteDataInBlock(src, len + 1); WriteDataInBlock(src, len + 1);
} }
void MarkFollowing(void** pPtr) override void MarkFollowing(const ZoneOutputOffset outputOffset) override
{ {
assert(!m_block_stack.empty()); 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<char*>(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<const char*>(&m_zone_ptr_insert)[i];
}
else
{
for (auto i = 0u; i < m_pointer_byte_count; i++)
ptr[i] = reinterpret_cast<const char*>(&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(!m_block_stack.empty());
assert(pPtr != nullptr);
if (*pPtr == nullptr) if (ptr == nullptr)
return false; return false;
const auto foundEntriesForType = m_reusable_entries.find(type); const auto foundEntriesForType = m_reusable_entries.find(type);
@@ -197,11 +216,14 @@ namespace
for (const auto& entry : foundEntriesForType->second) 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<uintptr_t>(*pPtr) - reinterpret_cast<uintptr_t>(entry.m_start_ptr)) % entrySize == 0); assert((reinterpret_cast<uintptr_t>(ptr) - reinterpret_cast<uintptr_t>(entry.m_start_ptr)) % entrySize == 0);
*pPtr = const auto finalZonePointer = entry.m_start_zone_ptr + (reinterpret_cast<uintptr_t>(ptr) - reinterpret_cast<uintptr_t>(entry.m_start_ptr));
reinterpret_cast<void*>(entry.m_start_zone_ptr + (reinterpret_cast<uintptr_t>(*pPtr) - reinterpret_cast<uintptr_t>(entry.m_start_ptr)));
for (auto i = 0u; i < m_pointer_byte_count; i++)
static_cast<char*>(ptr)[i] = reinterpret_cast<const char*>(&finalZonePointer)[i];
return false; return false;
} }
} }
@@ -265,10 +287,38 @@ namespace
unsigned m_pointer_byte_count; unsigned m_pointer_byte_count;
XBlock* m_insert_block; XBlock* m_insert_block;
uintptr_t m_zone_ptr_following;
uintptr_t m_zone_ptr_insert;
std::unordered_map<std::type_index, std::vector<ReusableEntry>> m_reusable_entries; std::unordered_map<std::type_index, std::vector<ReusableEntry>> m_reusable_entries;
}; };
} // namespace } // 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<void*>(static_cast<char*>(m_offset) + size);
}
ZoneOutputOffset ZoneOutputOffset::WithInnerOffset(const size_t innerOffset) const
{
return ZoneOutputOffset(static_cast<char*>(m_offset) + innerOffset);
}
std::unique_ptr<ZoneOutputStream> std::unique_ptr<ZoneOutputStream>
ZoneOutputStream::Create(unsigned pointerBitCount, unsigned blockBitCount, std::vector<XBlock*>& blocks, block_t insertBlock, InMemoryZoneData& zoneData) ZoneOutputStream::Create(unsigned pointerBitCount, unsigned blockBitCount, std::vector<XBlock*>& blocks, block_t insertBlock, InMemoryZoneData& zoneData)
{ {

View File

@@ -10,13 +10,27 @@
#include <typeinfo> #include <typeinfo>
#include <vector> #include <vector>
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 class ZoneOutputStream : public IZoneStream
{ {
public: public:
/** /**
* \brief Returns the configured bits that make up a pointer. * \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. * \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 dst The memory location to write data to.
* \param size The amount of data to write. * \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. * \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 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. * \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 IncBlockPos(size_t size) = 0;
virtual void WriteNullTerminated(const void* dst) = 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 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<typename T> bool ReusableShouldWrite(T** pPtr) template<typename T> bool ReusableShouldWrite(T* pPtr, const ZoneOutputOffset outputOffset)
{ {
return ReusableShouldWrite(reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(pPtr)), sizeof(T), std::type_index(typeid(T))); return ReusableShouldWrite(const_cast<void*>(reinterpret_cast<const void*>(pPtr)), outputOffset, sizeof(T), std::type_index(typeid(T)));
} }
template<typename T> void ReusableAddOffset(T* ptr) template<typename T> void ReusableAddOffset(T* ptr)
@@ -64,24 +78,19 @@ public:
ReusableAddOffset(const_cast<void*>(reinterpret_cast<const void*>(ptr)), sizeof(T), count, std::type_index(typeid(T))); ReusableAddOffset(const_cast<void*>(reinterpret_cast<const void*>(ptr)), sizeof(T), count, std::type_index(typeid(T)));
} }
template<typename T> T* Write(T* dst) template<typename T> ZoneOutputOffset Write(T* dst)
{ {
return static_cast<T*>(WriteDataInBlock(reinterpret_cast<const void*>(dst), sizeof(T))); return WriteDataInBlock(reinterpret_cast<const void*>(dst), sizeof(T));
} }
template<typename T> T* Write(T* dst, const size_t count) template<typename T> ZoneOutputOffset Write(T* dst, const size_t count)
{ {
return static_cast<T*>(WriteDataInBlock(reinterpret_cast<const void*>(dst), count * sizeof(T))); return WriteDataInBlock(reinterpret_cast<const void*>(dst), count * sizeof(T));
} }
template<typename T> T* WritePartial(T* dst, const size_t size) ZoneOutputOffset WritePartial(const void* dst, const size_t size)
{ {
return static_cast<T*>(WriteDataInBlock(reinterpret_cast<const void*>(dst), size)); return WriteDataInBlock(dst, size);
}
template<typename T> void MarkFollowing(T*& ptr)
{
MarkFollowing(reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(&ptr)));
} }
static std::unique_ptr<ZoneOutputStream> static std::unique_ptr<ZoneOutputStream>