From 955df982799a01242820fa42f5edb69e5e534ea9 Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 2 May 2025 19:34:51 +0100 Subject: [PATCH] refactor: hide implementation details of zone loading processors --- .../Game/IW3/ZoneLoaderFactoryIW3.cpp | 2 +- .../Game/IW4/ZoneLoaderFactoryIW4.cpp | 16 +- .../Game/IW5/ZoneLoaderFactoryIW5.cpp | 14 +- .../Game/T5/ZoneLoaderFactoryT5.cpp | 2 +- .../Game/T6/ZoneLoaderFactoryT6.cpp | 2 +- .../Processor/ProcessorAuthedBlocks.cpp | 143 ++--- .../Loading/Processor/ProcessorAuthedBlocks.h | 26 +- .../Processor/ProcessorCaptureData.cpp | 102 ++-- .../Loading/Processor/ProcessorCaptureData.h | 19 +- .../Processor/ProcessorIW4xDecryption.cpp | 88 +-- .../Processor/ProcessorIW4xDecryption.h | 18 +- .../Loading/Processor/ProcessorInflate.cpp | 144 +++-- .../Loading/Processor/ProcessorInflate.h | 25 +- .../Processor/ProcessorStreamCipher.cpp | 51 +- .../Loading/Processor/ProcessorStreamCipher.h | 12 +- .../Loading/Processor/ProcessorXChunks.cpp | 568 +++++++++--------- .../Loading/Processor/ProcessorXChunks.h | 22 +- 17 files changed, 608 insertions(+), 646 deletions(-) diff --git a/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp b/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp index dc8c583c..199f65af 100644 --- a/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp +++ b/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp @@ -77,7 +77,7 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& SetupBlock(*zoneLoader); - zoneLoader->AddLoadingStep(std::make_unique(std::make_unique(ZoneConstants::AUTHED_CHUNK_SIZE))); + zoneLoader->AddLoadingStep(std::make_unique(processor::CreateProcessorInflate(ZoneConstants::AUTHED_CHUNK_SIZE))); // Start of the XFile struct zoneLoader->AddLoadingStep(std::make_unique(8)); diff --git a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp index 04621db5..47987241 100644 --- a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp +++ b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp @@ -136,7 +136,7 @@ namespace zoneLoader.AddLoadingStep(std::make_unique(std::move(rsa), subHeaderHashSignaturePtr, subHeaderHashPtr)); - auto subHeaderCapture = std::make_unique(sizeof(DB_AuthSubHeader)); + auto subHeaderCapture = processor::CreateProcessorCaptureData(sizeof(DB_AuthSubHeader)); auto* subHeaderCapturePtr = subHeaderCapture.get(); zoneLoader.AddLoadingStep(std::make_unique(std::move(subHeaderCapture))); @@ -155,11 +155,11 @@ namespace zoneLoader.AddLoadingStep(std::make_unique(ZoneConstants::AUTHED_CHUNK_SIZE - sizeof(DB_AuthHeader))); zoneLoader.AddLoadingStep(std::make_unique( - std::make_unique(ZoneConstants::AUTHED_CHUNK_COUNT_PER_GROUP, - ZoneConstants::AUTHED_CHUNK_SIZE, - static_cast(std::extent_v), - cryptography::CreateSha256(), - masterBlockHashesPtr))); + processor::CreateProcessorAuthedBlocks(ZoneConstants::AUTHED_CHUNK_COUNT_PER_GROUP, + ZoneConstants::AUTHED_CHUNK_SIZE, + static_cast(std::extent_v), + cryptography::CreateSha256(), + masterBlockHashesPtr))); } } // namespace @@ -193,11 +193,11 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& // Add steps for loading the auth header which also contain the signature of the zone if it is signed. AddAuthHeaderSteps(isSecure, isOfficial, *zoneLoader, fileName); - zoneLoader->AddLoadingStep(std::make_unique(std::make_unique(ZoneConstants::AUTHED_CHUNK_SIZE))); + zoneLoader->AddLoadingStep(std::make_unique(processor::CreateProcessorInflate(ZoneConstants::AUTHED_CHUNK_SIZE))); if (isIw4x) // IW4x has one extra byte of padding here for protection purposes { - zoneLoader->AddLoadingStep(std::make_unique(std::make_unique())); + zoneLoader->AddLoadingStep(std::make_unique(processor::CreateProcessorIW4xDecryption())); zoneLoader->AddLoadingStep(std::make_unique(1)); } diff --git a/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp b/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp index a2fe4cf3..d88e7610 100644 --- a/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp +++ b/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp @@ -120,7 +120,7 @@ namespace zoneLoader.AddLoadingStep(std::make_unique(std::move(rsa), subHeaderHashSignaturePtr, subHeaderHashPtr)); - auto subHeaderCapture = std::make_unique(sizeof(DB_AuthSubHeader)); + auto subHeaderCapture = processor::CreateProcessorCaptureData(sizeof(DB_AuthSubHeader)); auto* subHeaderCapturePtr = subHeaderCapture.get(); zoneLoader.AddLoadingStep(std::make_unique(std::move(subHeaderCapture))); @@ -139,11 +139,11 @@ namespace zoneLoader.AddLoadingStep(std::make_unique(ZoneConstants::AUTHED_CHUNK_SIZE - sizeof(DB_AuthHeader))); zoneLoader.AddLoadingStep(std::make_unique( - std::make_unique(ZoneConstants::AUTHED_CHUNK_COUNT_PER_GROUP, - ZoneConstants::AUTHED_CHUNK_SIZE, - static_cast(std::extent_v), - cryptography::CreateSha256(), - masterBlockHashesPtr))); + processor::CreateProcessorAuthedBlocks(ZoneConstants::AUTHED_CHUNK_COUNT_PER_GROUP, + ZoneConstants::AUTHED_CHUNK_SIZE, + static_cast(std::extent_v), + cryptography::CreateSha256(), + masterBlockHashesPtr))); } } // namespace @@ -176,7 +176,7 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& // Add steps for loading the auth header which also contain the signature of the zone if it is signed. AddAuthHeaderSteps(isSecure, isOfficial, *zoneLoader, fileName); - zoneLoader->AddLoadingStep(std::make_unique(std::make_unique(ZoneConstants::AUTHED_CHUNK_SIZE))); + zoneLoader->AddLoadingStep(std::make_unique(processor::CreateProcessorInflate(ZoneConstants::AUTHED_CHUNK_SIZE))); // Start of the XFile struct zoneLoader->AddLoadingStep(std::make_unique(8)); diff --git a/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp b/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp index 348b1e6f..4e516974 100644 --- a/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp +++ b/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp @@ -77,7 +77,7 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& SetupBlock(*zoneLoader); - zoneLoader->AddLoadingStep(std::make_unique(std::make_unique(ZoneConstants::AUTHED_CHUNK_SIZE))); + zoneLoader->AddLoadingStep(std::make_unique(processor::CreateProcessorInflate(ZoneConstants::AUTHED_CHUNK_SIZE))); // Start of the XFile struct zoneLoader->AddLoadingStep(std::make_unique(8)); diff --git a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp index 7cb8146d..413db7e3 100644 --- a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp +++ b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp @@ -148,7 +148,7 @@ namespace ICapturedDataProvider* AddXChunkProcessor(const bool isEncrypted, ZoneLoader& zoneLoader, std::string& fileName) { ICapturedDataProvider* result = nullptr; - auto xChunkProcessor = std::make_unique(ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE); + auto xChunkProcessor = processor::CreateProcessorXChunks(ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE); if (isEncrypted) { diff --git a/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.cpp b/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.cpp index cc5c8f39..acc6bae6 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.cpp +++ b/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.cpp @@ -5,39 +5,19 @@ #include "Loading/Exception/TooManyAuthedGroupsException.h" #include "Loading/Exception/UnexpectedEndOfFileException.h" +#include #include -#include #include -class ProcessorAuthedBlocks::Impl +class ProcessorAuthedBlocks final : public StreamProcessor { - ProcessorAuthedBlocks* const m_base; - - const unsigned m_authed_chunk_count; - const size_t m_chunk_size; - const unsigned m_max_master_block_count; - - const std::unique_ptr m_hash_function; - IHashProvider* const m_master_block_hash_provider; - const std::unique_ptr m_chunk_hashes_buffer; - const std::unique_ptr m_current_chunk_hash_buffer; - - const std::unique_ptr m_chunk_buffer; - unsigned m_current_group; - unsigned m_current_chunk_in_group; - - size_t m_current_chunk_offset; - size_t m_current_chunk_size; - public: - Impl(ProcessorAuthedBlocks* base, - const unsigned authedChunkCount, - const size_t chunkSize, - const unsigned maxMasterBlockCount, - std::unique_ptr hashFunction, - IHashProvider* masterBlockHashProvider) - : m_base(base), - m_authed_chunk_count(authedChunkCount), + ProcessorAuthedBlocks(const unsigned authedChunkCount, + const size_t chunkSize, + const unsigned maxMasterBlockCount, + std::unique_ptr hashFunction, + IHashProvider* masterBlockHashProvider) + : m_authed_chunk_count(authedChunkCount), m_chunk_size(chunkSize), m_max_master_block_count(maxMasterBlockCount), m_hash_function(std::move(hashFunction)), @@ -53,13 +33,43 @@ public: assert(m_authed_chunk_count * m_hash_function->GetHashSize() <= m_chunk_size); } + size_t Load(void* buffer, const size_t length) override + { + size_t loadedSize = 0; + + while (loadedSize < length) + { + if (m_current_chunk_offset >= m_current_chunk_size) + { + if (!NextChunk()) + return loadedSize; + } + + auto sizeToWrite = length - loadedSize; + sizeToWrite = std::min(sizeToWrite, m_current_chunk_size - m_current_chunk_offset); + + assert(length - loadedSize >= sizeToWrite); + memcpy(&static_cast(buffer)[loadedSize], &m_chunk_buffer[m_current_chunk_offset], sizeToWrite); + loadedSize += sizeToWrite; + m_current_chunk_offset += sizeToWrite; + } + + return loadedSize; + } + + int64_t Pos() override + { + return m_base_stream->Pos() - static_cast(m_current_chunk_size - m_current_chunk_offset); + } + +private: bool NextChunk() { m_current_chunk_offset = 0; while (true) { - m_current_chunk_size = m_base->m_base_stream->Load(m_chunk_buffer.get(), m_chunk_size); + m_current_chunk_size = m_base_stream->Load(m_chunk_buffer.get(), m_chunk_size); if (m_current_chunk_size == 0) return false; @@ -79,7 +89,9 @@ public: if (masterBlockHashSize != m_hash_function->GetHashSize() || std::memcmp(m_current_chunk_hash_buffer.get(), masterBlockHash, m_hash_function->GetHashSize()) != 0) + { throw InvalidHashException(); + } memcpy(m_chunk_hashes_buffer.get(), m_chunk_buffer.get(), m_authed_chunk_count * m_hash_function->GetHashSize()); @@ -91,7 +103,9 @@ public: &m_chunk_hashes_buffer[(m_current_chunk_in_group - 1) * m_hash_function->GetHashSize()], m_hash_function->GetHashSize()) != 0) + { throw InvalidHashException(); + } if (++m_current_chunk_in_group > m_authed_chunk_count) { @@ -107,58 +121,31 @@ public: } } - size_t Load(void* buffer, const size_t length) - { - size_t loadedSize = 0; + const unsigned m_authed_chunk_count; + const size_t m_chunk_size; + const unsigned m_max_master_block_count; - while (loadedSize < length) - { - if (m_current_chunk_offset >= m_current_chunk_size) - { - if (!NextChunk()) - return loadedSize; - } + const std::unique_ptr m_hash_function; + IHashProvider* const m_master_block_hash_provider; + const std::unique_ptr m_chunk_hashes_buffer; + const std::unique_ptr m_current_chunk_hash_buffer; - size_t sizeToWrite = length - loadedSize; - if (sizeToWrite > m_current_chunk_size - m_current_chunk_offset) - sizeToWrite = m_current_chunk_size - m_current_chunk_offset; + const std::unique_ptr m_chunk_buffer; + unsigned m_current_group; + unsigned m_current_chunk_in_group; - assert(length - loadedSize >= sizeToWrite); - memcpy(&static_cast(buffer)[loadedSize], &m_chunk_buffer[m_current_chunk_offset], sizeToWrite); - loadedSize += sizeToWrite; - m_current_chunk_offset += sizeToWrite; - } - - return loadedSize; - } - - int64_t Pos() - { - return m_base->m_base_stream->Pos() - (m_current_chunk_size - m_current_chunk_offset); - } + size_t m_current_chunk_offset; + size_t m_current_chunk_size; }; -ProcessorAuthedBlocks::ProcessorAuthedBlocks(const unsigned authedChunkCount, - const size_t chunkSize, - const unsigned maxMasterBlockCount, - std::unique_ptr hashFunction, - IHashProvider* masterBlockHashProvider) - : m_impl(new Impl(this, authedChunkCount, chunkSize, maxMasterBlockCount, std::move(hashFunction), masterBlockHashProvider)) +namespace processor { -} - -ProcessorAuthedBlocks::~ProcessorAuthedBlocks() -{ - delete m_impl; - m_impl = nullptr; -} - -size_t ProcessorAuthedBlocks::Load(void* buffer, const size_t length) -{ - return m_impl->Load(buffer, length); -} - -int64_t ProcessorAuthedBlocks::Pos() -{ - return m_impl->Pos(); -} + std::unique_ptr CreateProcessorAuthedBlocks(unsigned authedChunkCount, + size_t chunkSize, + unsigned maxMasterBlockCount, + std::unique_ptr hashFunction, + IHashProvider* masterBlockHashProvider) + { + return std::make_unique(authedChunkCount, chunkSize, maxMasterBlockCount, std::move(hashFunction), masterBlockHashProvider); + } +} // namespace processor diff --git a/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.h b/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.h index 5bcf4a19..f6cf4883 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.h +++ b/src/ZoneLoading/Loading/Processor/ProcessorAuthedBlocks.h @@ -6,23 +6,11 @@ #include -class ProcessorAuthedBlocks final : public StreamProcessor +namespace processor { - class Impl; - Impl* m_impl; - -public: - ProcessorAuthedBlocks(unsigned authedChunkCount, - size_t chunkSize, - unsigned maxMasterBlockCount, - std::unique_ptr hashFunction, - IHashProvider* masterBlockHashProvider); - ~ProcessorAuthedBlocks() override; - ProcessorAuthedBlocks(const ProcessorAuthedBlocks& other) = delete; - ProcessorAuthedBlocks(ProcessorAuthedBlocks&& other) noexcept = default; - ProcessorAuthedBlocks& operator=(const ProcessorAuthedBlocks& other) = delete; - ProcessorAuthedBlocks& operator=(ProcessorAuthedBlocks&& other) noexcept = default; - - size_t Load(void* buffer, size_t length) override; - int64_t Pos() override; -}; + std::unique_ptr CreateProcessorAuthedBlocks(unsigned authedChunkCount, + size_t chunkSize, + unsigned maxMasterBlockCount, + std::unique_ptr hashFunction, + IHashProvider* masterBlockHashProvider); +} diff --git a/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.cpp b/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.cpp index f0b1b3b5..1ae0a125 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.cpp +++ b/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.cpp @@ -1,51 +1,67 @@ #include "ProcessorCaptureData.h" +#include #include -#include -ProcessorCaptureData::ProcessorCaptureData(const size_t captureSize) - : m_data(std::make_unique(captureSize)), - m_capture_size(captureSize), - m_captured_data_size(0) +namespace { -} + class ProcessorCaptureData final : public processor::IProcessorCaptureData + { + public: + explicit ProcessorCaptureData(const size_t captureSize) + : m_data(std::make_unique(captureSize)), + m_capture_size(captureSize), + m_captured_data_size(0) + { + } -ProcessorCaptureData::~ProcessorCaptureData() = default; + size_t Load(void* buffer, const size_t length) override + { + if (m_captured_data_size >= m_capture_size) + return m_base_stream->Load(buffer, length); -size_t ProcessorCaptureData::Load(void* buffer, const size_t length) + auto dataToCapture = m_capture_size - m_captured_data_size; + dataToCapture = std::min(length, dataToCapture); + + auto loadedSize = m_base_stream->Load(&m_data[m_captured_data_size], dataToCapture); + assert(length >= loadedSize); + memcpy(buffer, &m_data[m_captured_data_size], loadedSize); + + m_captured_data_size += loadedSize; + + if (length > dataToCapture) + loadedSize += m_base_stream->Load(&static_cast(buffer)[dataToCapture], length - dataToCapture); + + return loadedSize; + } + + int64_t Pos() override + { + return m_base_stream->Pos(); + } + + void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) override + { + assert(pCapturedData != nullptr); + assert(pSize != nullptr); + + assert(m_captured_data_size == m_capture_size); + + *pCapturedData = m_data.get(); + *pSize = m_captured_data_size; + } + + private: + std::unique_ptr m_data; + size_t m_capture_size; + size_t m_captured_data_size; + }; +} // namespace + +namespace processor { - if (m_captured_data_size >= m_capture_size) - return m_base_stream->Load(buffer, length); - - size_t dataToCapture = m_capture_size - m_captured_data_size; - - if (length < dataToCapture) - dataToCapture = length; - - size_t loadedSize = m_base_stream->Load(&m_data[m_captured_data_size], dataToCapture); - assert(length >= loadedSize); - memcpy(buffer, &m_data[m_captured_data_size], loadedSize); - - m_captured_data_size += loadedSize; - - if (length > dataToCapture) - loadedSize += m_base_stream->Load(&static_cast(buffer)[dataToCapture], length - dataToCapture); - - return loadedSize; -} - -int64_t ProcessorCaptureData::Pos() -{ - return m_base_stream->Pos(); -} - -void ProcessorCaptureData::GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) -{ - assert(pCapturedData != nullptr); - assert(pSize != nullptr); - - assert(m_captured_data_size == m_capture_size); - - *pCapturedData = m_data.get(); - *pSize = m_captured_data_size; -} + std::unique_ptr CreateProcessorCaptureData(size_t captureSize) + { + return std::make_unique(captureSize); + } +} // namespace processor diff --git a/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.h b/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.h index 4d6fac57..810b9ad1 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.h +++ b/src/ZoneLoading/Loading/Processor/ProcessorCaptureData.h @@ -1,20 +1,15 @@ #pragma once + #include "Loading/StreamProcessor.h" #include "Utils/ICapturedDataProvider.h" #include -class ProcessorCaptureData final : public StreamProcessor, public ICapturedDataProvider +namespace processor { - std::unique_ptr m_data; - const size_t m_capture_size; - size_t m_captured_data_size; + class IProcessorCaptureData : public StreamProcessor, public ICapturedDataProvider + { + }; -public: - explicit ProcessorCaptureData(size_t captureSize); - ~ProcessorCaptureData() override; - - size_t Load(void* buffer, size_t length) override; - int64_t Pos() override; - void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) override; -}; + std::unique_ptr CreateProcessorCaptureData(size_t captureSize); +} // namespace processor diff --git a/src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.cpp b/src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.cpp index c26157f9..393a5f4d 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.cpp +++ b/src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.cpp @@ -2,44 +2,62 @@ #include -ProcessorIW4xDecryption::ProcessorIW4xDecryption() - : m_last_byte(0u) +namespace { -} - -uint8_t ProcessorIW4xDecryption::RotateLeft(const uint8_t value, const unsigned count) -{ - assert(count < sizeof(value) * 8); - return static_cast(value << count | (value >> ((sizeof(value) * 8) - count))); -} - -uint8_t ProcessorIW4xDecryption::RotateRight(uint8_t value, const unsigned count) -{ - assert(count < sizeof(value) * 8); - return static_cast(value >> count | (value << ((sizeof(value) * 8) - count))); -} - -size_t ProcessorIW4xDecryption::Load(void* buffer, const size_t length) -{ - const auto readLen = m_base_stream->Load(buffer, length); - - auto* charBuffer = static_cast(buffer); - for (auto i = 0u; i < readLen; i++) + uint8_t RotateLeft(const uint8_t value, const unsigned count) { - auto value = charBuffer[i]; - value ^= m_last_byte; - value = RotateLeft(value, 4); - value ^= -1; - value = RotateRight(value, 6); - - charBuffer[i] = value; - m_last_byte = value; + assert(count < sizeof(value) * 8); + return static_cast(value << count | (value >> ((sizeof(value) * 8) - count))); } - return readLen; -} + uint8_t RotateRight(const uint8_t value, const unsigned count) + { + assert(count < sizeof(value) * 8); + return static_cast(value >> count | (value << ((sizeof(value) * 8) - count))); + } -int64_t ProcessorIW4xDecryption::Pos() + class ProcessorIW4xDecryption final : public StreamProcessor + { + public: + ProcessorIW4xDecryption() + : m_last_byte(0u) + { + } + + size_t Load(void* buffer, const size_t length) override + { + const auto readLen = m_base_stream->Load(buffer, length); + + auto* charBuffer = static_cast(buffer); + for (auto i = 0u; i < readLen; i++) + { + auto value = charBuffer[i]; + value ^= m_last_byte; + value = RotateLeft(value, 4); + value ^= -1; + value = RotateRight(value, 6); + + charBuffer[i] = value; + m_last_byte = value; + } + + return readLen; + } + + int64_t Pos() override + { + return m_base_stream->Pos(); + } + + private: + uint8_t m_last_byte; + }; +} // namespace + +namespace processor { - return m_base_stream->Pos(); -} + std::unique_ptr CreateProcessorIW4xDecryption() + { + return std::make_unique(); + } +} // namespace processor diff --git a/src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.h b/src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.h index 6f9acc37..19946be9 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.h +++ b/src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.h @@ -1,16 +1,10 @@ #pragma once + #include "Loading/StreamProcessor.h" -class ProcessorIW4xDecryption final : public StreamProcessor +#include + +namespace processor { - uint8_t m_last_byte; - - static uint8_t RotateLeft(uint8_t value, unsigned count); - static uint8_t RotateRight(uint8_t value, unsigned count); - -public: - ProcessorIW4xDecryption(); - - size_t Load(void* buffer, size_t length) override; - int64_t Pos() override; -}; + std::unique_ptr CreateProcessorIW4xDecryption(); +} diff --git a/src/ZoneLoading/Loading/Processor/ProcessorInflate.cpp b/src/ZoneLoading/Loading/Processor/ProcessorInflate.cpp index e04de7db..3cca74f6 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorInflate.cpp +++ b/src/ZoneLoading/Loading/Processor/ProcessorInflate.cpp @@ -8,93 +8,85 @@ #include #include -class ProcessorInflate::Impl +namespace { - z_stream m_stream{}; - ProcessorInflate* m_base; + constexpr size_t DEFAULT_BUFFER_SIZE = 0x2000; - std::unique_ptr m_buffer; - size_t m_buffer_size; - -public: - Impl(ProcessorInflate* baseClass, const size_t bufferSize) - : m_buffer(std::make_unique(bufferSize)), - m_buffer_size(bufferSize) + class ProcessorInflate final : public StreamProcessor { - m_base = baseClass; - - m_stream.zalloc = Z_NULL; - m_stream.zfree = Z_NULL; - m_stream.opaque = Z_NULL; - m_stream.avail_in = 0; - m_stream.next_in = Z_NULL; - - const int ret = inflateInit(&m_stream); - - if (ret != Z_OK) + public: + explicit ProcessorInflate(const size_t bufferSize) + : m_buffer(std::make_unique(bufferSize)), + m_buffer_size(bufferSize) { - throw std::runtime_error("Initializing inflate failed"); + m_stream.zalloc = Z_NULL; + m_stream.zfree = Z_NULL; + m_stream.opaque = Z_NULL; + m_stream.avail_in = 0; + m_stream.next_in = Z_NULL; + + const int ret = inflateInit(&m_stream); + + if (ret != Z_OK) + throw std::runtime_error("Initializing inflate failed"); } - } - ~Impl() - { - inflateEnd(&m_stream); - } - - Impl(const Impl& other) = delete; - Impl(Impl&& other) noexcept = default; - Impl& operator=(const Impl& other) = delete; - Impl& operator=(Impl&& other) noexcept = default; - - size_t Load(void* buffer, const size_t length) - { - m_stream.next_out = static_cast(buffer); - m_stream.avail_out = static_cast(length); - - while (m_stream.avail_out > 0) + ~ProcessorInflate() override { - if (m_stream.avail_in == 0) - { - m_stream.avail_in = static_cast(m_base->m_base_stream->Load(m_buffer.get(), m_buffer_size)); - m_stream.next_in = m_buffer.get(); + inflateEnd(&m_stream); + } - if (m_stream.avail_in == 0) // EOF - return length - m_stream.avail_out; + ProcessorInflate(const ProcessorInflate& other) = delete; + ProcessorInflate(ProcessorInflate&& other) noexcept = default; + ProcessorInflate& operator=(const ProcessorInflate& other) = delete; + ProcessorInflate& operator=(ProcessorInflate&& other) noexcept = default; + + size_t Load(void* buffer, const size_t length) override + { + m_stream.next_out = static_cast(buffer); + m_stream.avail_out = static_cast(length); + + while (m_stream.avail_out > 0) + { + if (m_stream.avail_in == 0) + { + m_stream.avail_in = static_cast(m_base_stream->Load(m_buffer.get(), m_buffer_size)); + m_stream.next_in = m_buffer.get(); + + if (m_stream.avail_in == 0) // EOF + return length - m_stream.avail_out; + } + + const auto ret = inflate(&m_stream, Z_SYNC_FLUSH); + + if (ret < 0) + throw InvalidCompressionException(); } - const auto ret = inflate(&m_stream, Z_SYNC_FLUSH); - - if (ret < 0) - throw InvalidCompressionException(); + return length - m_stream.avail_out; } - return length - m_stream.avail_out; + int64_t Pos() override + { + return m_base_stream->Pos(); + } + + private: + z_stream m_stream{}; + std::unique_ptr m_buffer; + size_t m_buffer_size; + }; +} // namespace + +namespace processor +{ + std::unique_ptr CreateProcessorInflate() + { + return std::make_unique(DEFAULT_BUFFER_SIZE); } -}; -ProcessorInflate::ProcessorInflate() - : ProcessorInflate(DEFAULT_BUFFER_SIZE) -{ -} - -ProcessorInflate::ProcessorInflate(const size_t bufferSize) - : m_impl(new Impl(this, bufferSize)) -{ -} - -ProcessorInflate::~ProcessorInflate() -{ - delete m_impl; - m_impl = nullptr; -} - -size_t ProcessorInflate::Load(void* buffer, const size_t length) -{ - return m_impl->Load(buffer, length); -} - -int64_t ProcessorInflate::Pos() -{ - return m_base_stream->Pos(); -} + std::unique_ptr CreateProcessorInflate(size_t bufferSize) + { + return std::make_unique(bufferSize); + } +} // namespace processor diff --git a/src/ZoneLoading/Loading/Processor/ProcessorInflate.h b/src/ZoneLoading/Loading/Processor/ProcessorInflate.h index f1e17ed5..bf704ee0 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorInflate.h +++ b/src/ZoneLoading/Loading/Processor/ProcessorInflate.h @@ -1,22 +1,11 @@ #pragma once + #include "Loading/StreamProcessor.h" -class ProcessorInflate final : public StreamProcessor +#include + +namespace processor { - class Impl; - Impl* m_impl; - - static constexpr size_t DEFAULT_BUFFER_SIZE = 0x2000; - -public: - ProcessorInflate(); - ProcessorInflate(size_t bufferSize); - ~ProcessorInflate() override; - ProcessorInflate(const ProcessorInflate& other) = delete; - ProcessorInflate(ProcessorInflate&& other) noexcept = default; - ProcessorInflate& operator=(const ProcessorInflate& other) = delete; - ProcessorInflate& operator=(ProcessorInflate&& other) noexcept = default; - - size_t Load(void* buffer, size_t length) override; - int64_t Pos() override; -}; + std::unique_ptr CreateProcessorInflate(); + std::unique_ptr CreateProcessorInflate(size_t bufferSize); +} // namespace processor diff --git a/src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.cpp b/src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.cpp index 73279921..e74fc044 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.cpp +++ b/src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.cpp @@ -1,21 +1,44 @@ #include "ProcessorStreamCipher.h" -ProcessorStreamCipher::ProcessorStreamCipher(std::unique_ptr cipher) - : m_cipher(std::move(cipher)) +namespace { -} - -size_t ProcessorStreamCipher::Load(void* buffer, const size_t length) -{ - if (m_base_stream != nullptr) + class ProcessorStreamCipher final : public StreamProcessor { - const size_t readSize = m_base_stream->Load(buffer, length); + public: + explicit ProcessorStreamCipher(std::unique_ptr cipher) + : m_cipher(std::move(cipher)) + { + } - if (readSize > 0) - m_cipher->Process(buffer, buffer, readSize); + size_t Load(void* buffer, const size_t length) override + { + if (m_base_stream != nullptr) + { + const size_t readSize = m_base_stream->Load(buffer, length); - return readSize; + if (readSize > 0) + m_cipher->Process(buffer, buffer, readSize); + + return readSize; + } + + return 0; + } + + int64_t Pos() override + { + return m_base_stream->Pos(); + } + + private: + std::unique_ptr m_cipher; + }; +} // namespace + +namespace processor +{ + std::unique_ptr CreateProcessorStreamCipher(std::unique_ptr cipher) + { + return std::make_unique(std::move(cipher)); } - - return 0; -} +} // namespace processor diff --git a/src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.h b/src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.h index 3b40f4a5..d74908c0 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.h +++ b/src/ZoneLoading/Loading/Processor/ProcessorStreamCipher.h @@ -5,13 +5,7 @@ #include -class ProcessorStreamCipher final : public StreamProcessor +namespace processor { -public: - explicit ProcessorStreamCipher(std::unique_ptr cipher); - - size_t Load(void* buffer, size_t length) override; - -private: - std::unique_ptr m_cipher; -}; + std::unique_ptr CreateProcessorStreamCipher(std::unique_ptr cipher); +} diff --git a/src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp b/src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp index c0f727c8..8f4fc161 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp +++ b/src/ZoneLoading/Loading/Processor/ProcessorXChunks.cpp @@ -5,334 +5,304 @@ #include #include -#include #include #include +#include #include #include -class DBLoadStream +namespace { - int m_index; - - std::unique_ptr m_buffers[2]; - - uint8_t* m_input_buffer; - size_t m_input_size; - - uint8_t* m_output_buffer; - size_t m_output_size; - - size_t m_chunk_size; - - bool m_is_loading; - std::mutex m_load_mutex; - std::condition_variable m_loading_finished; - std::thread m_load_thread; - - std::vector>& m_processors; - - void Load() + class DbLoadStream { - std::lock_guard lock(m_load_mutex); - - bool firstProcessor = true; - - for (const auto& processor : m_processors) + public: + DbLoadStream(const int streamIndex, const size_t chunkSize, std::vector>& chunkProcessors) + : m_index(streamIndex), + m_input_size(0), + m_output_size(0), + m_chunk_size(chunkSize), + m_is_loading(false), + m_processors(chunkProcessors) { - if (!firstProcessor) - { - uint8_t* previousInputBuffer = m_input_buffer; - m_input_buffer = m_output_buffer; - m_output_buffer = previousInputBuffer; + for (auto& buffer : m_buffers) + buffer = std::make_unique(chunkSize); - m_input_size = m_output_size; - m_output_size = 0; - } - - m_output_size = processor->Process(m_index, m_input_buffer, m_input_size, m_output_buffer, m_chunk_size); - - firstProcessor = false; + m_input_buffer = m_buffers[0].get(); + m_output_buffer = m_buffers[1].get(); } - m_is_loading = false; - m_loading_finished.notify_all(); - } - -public: - DBLoadStream(const int streamIndex, const size_t chunkSize, std::vector>& chunkProcessors) - : m_processors(chunkProcessors) - { - m_index = streamIndex; - m_chunk_size = chunkSize; - - for (auto& buffer : m_buffers) - buffer = std::make_unique(chunkSize); - - m_input_buffer = m_buffers[0].get(); - m_output_buffer = m_buffers[1].get(); - - m_input_size = 0; - m_output_size = 0; - - m_is_loading = false; - } - - [[nodiscard]] uint8_t* GetInputBuffer() const - { - return m_input_buffer; - } - - void StartLoading(const size_t inputSize) - { - if (inputSize > 0) + [[nodiscard]] uint8_t* GetInputBuffer() const { - std::unique_lock lock(m_load_mutex); + return m_input_buffer; + } + void StartLoading(const size_t inputSize) + { + if (inputSize > 0) + { + std::unique_lock lock(m_load_mutex); + + if (m_is_loading) + { + m_loading_finished.wait(lock); + } + + m_input_size = inputSize; + m_is_loading = true; + m_load_thread = std::thread(&DbLoadStream::Load, this); + m_load_thread.detach(); + } + else + { + m_output_size = 0; + } + } + + void GetOutput(const uint8_t** pBuffer, size_t* pSize) + { + assert(pBuffer != nullptr); + assert(pSize != nullptr); + + std::unique_lock lock(m_load_mutex); if (m_is_loading) { m_loading_finished.wait(lock); } - m_input_size = inputSize; - m_is_loading = true; - m_load_thread = std::thread(&DBLoadStream::Load, this); - m_load_thread.detach(); - } - else - { - m_output_size = 0; - } - } - - void GetOutput(const uint8_t** pBuffer, size_t* pSize) - { - assert(pBuffer != nullptr); - assert(pSize != nullptr); - - std::unique_lock lock(m_load_mutex); - if (m_is_loading) - { - m_loading_finished.wait(lock); + *pBuffer = m_output_buffer; + *pSize = m_output_size; } - *pBuffer = m_output_buffer; - *pSize = m_output_size; - } -}; - -class ProcessorXChunks::ProcessorXChunksImpl -{ - ProcessorXChunks* m_base; - - std::vector> m_streams; - size_t m_chunk_size; - size_t m_vanilla_buffer_size; - std::vector> m_chunk_processors; - - bool m_initialized_streams; - unsigned int m_current_stream; - const uint8_t* m_current_chunk; - size_t m_current_chunk_size; - size_t m_current_chunk_offset; - size_t m_vanilla_buffer_offset; - - bool m_eof_reached; - unsigned int m_eof_stream; - - void AdvanceStream(const unsigned streamNum) - { - assert(streamNum < m_streams.size()); - - if (m_eof_reached) - return; - - xchunk_size_t chunkSize; - if (m_vanilla_buffer_size > 0) + private: + void Load() { - if (m_vanilla_buffer_offset + sizeof(chunkSize) > m_vanilla_buffer_size) + std::lock_guard lock(m_load_mutex); + + bool firstProcessor = true; + + for (const auto& processor : m_processors) { - m_base->m_base_stream->Load(&chunkSize, m_vanilla_buffer_size - m_vanilla_buffer_offset); - m_vanilla_buffer_offset = 0; - } - - m_vanilla_buffer_offset = (m_vanilla_buffer_offset + sizeof(chunkSize)) % m_vanilla_buffer_size; - } - - const size_t readSize = m_base->m_base_stream->Load(&chunkSize, sizeof(chunkSize)); - - if (readSize == 0) - { - m_eof_reached = true; - m_eof_stream = streamNum; - return; - } - - if (chunkSize > m_chunk_size) - { - throw InvalidChunkSizeException(chunkSize, m_chunk_size); - } - - const auto& stream = m_streams[streamNum]; - const size_t loadedChunkSize = m_base->m_base_stream->Load(stream->GetInputBuffer(), chunkSize); - - if (loadedChunkSize != chunkSize) - { - throw InvalidChunkSizeException(chunkSize); - } - - if (m_vanilla_buffer_size > 0) - { - m_vanilla_buffer_offset = (m_vanilla_buffer_offset + loadedChunkSize) % m_vanilla_buffer_size; - } - - stream->StartLoading(loadedChunkSize); - } - - void NextStream() - { - AdvanceStream(m_current_stream); - - m_current_stream = (m_current_stream + 1) % m_streams.size(); - m_current_chunk_offset = 0; - m_streams[m_current_stream]->GetOutput(&m_current_chunk, &m_current_chunk_size); - } - - void InitStreams() - { - m_initialized_streams = true; - m_vanilla_buffer_offset = static_cast(m_base->m_base_stream->Pos()); - - const auto streamCount = static_cast(m_streams.size()); - for (auto streamNum = 0u; streamNum < streamCount; streamNum++) - { - AdvanceStream(streamNum); - } - - m_current_stream = 0; - m_current_chunk_offset = 0; - m_streams[0]->GetOutput(&m_current_chunk, &m_current_chunk_size); - } - - [[nodiscard]] bool EndOfStream() const - { - return m_eof_reached && m_eof_stream == m_current_stream; - } - -public: - ProcessorXChunksImpl(ProcessorXChunks* base, const int numStreams, const size_t xChunkSize) - { - assert(base != nullptr); - assert(numStreams > 0); - assert(xChunkSize > 0); - - m_base = base; - - for (int streamIndex = 0; streamIndex < numStreams; streamIndex++) - { - m_streams.emplace_back(std::make_unique(streamIndex, xChunkSize, m_chunk_processors)); - } - - m_chunk_size = xChunkSize; - m_vanilla_buffer_size = 0; - - m_initialized_streams = false; - m_current_stream = 0; - m_current_chunk = nullptr; - m_current_chunk_size = 0; - m_current_chunk_offset = 0; - m_vanilla_buffer_offset = 0; - - m_eof_reached = false; - m_eof_stream = 0; - } - - ProcessorXChunksImpl(ProcessorXChunks* base, const int numStreams, const size_t xChunkSize, const size_t vanillaBufferSize) - : ProcessorXChunksImpl(base, numStreams, xChunkSize) - { - m_vanilla_buffer_size = vanillaBufferSize; - } - - void AddChunkProcessor(std::unique_ptr streamProcessor) - { - assert(streamProcessor != nullptr); - - m_chunk_processors.emplace_back(std::move(streamProcessor)); - } - - size_t Load(void* buffer, const size_t length) - { - assert(buffer != nullptr); - - if (!m_initialized_streams) - { - InitStreams(); - } - - size_t loadedSize = 0; - while (!EndOfStream() && loadedSize < length) - { - auto* bufferPos = static_cast(buffer) + loadedSize; - const size_t sizeToRead = length - loadedSize; - const size_t bytesLeftInCurrentChunk = m_current_chunk_size - m_current_chunk_offset; - - if (sizeToRead > bytesLeftInCurrentChunk) - { - assert(sizeToRead >= bytesLeftInCurrentChunk); - memcpy(bufferPos, &m_current_chunk[m_current_chunk_offset], bytesLeftInCurrentChunk); - loadedSize += bytesLeftInCurrentChunk; - - NextStream(); - } - else - { - memcpy(bufferPos, &m_current_chunk[m_current_chunk_offset], sizeToRead); - loadedSize += sizeToRead; - m_current_chunk_offset += sizeToRead; - - if (m_current_chunk_offset == m_current_chunk_size) + if (!firstProcessor) { + uint8_t* previousInputBuffer = m_input_buffer; + m_input_buffer = m_output_buffer; + m_output_buffer = previousInputBuffer; + + m_input_size = m_output_size; + m_output_size = 0; + } + + m_output_size = processor->Process(m_index, m_input_buffer, m_input_size, m_output_buffer, m_chunk_size); + + firstProcessor = false; + } + + m_is_loading = false; + m_loading_finished.notify_all(); + } + + int m_index; + + std::unique_ptr m_buffers[2]; + + uint8_t* m_input_buffer; + size_t m_input_size; + + uint8_t* m_output_buffer; + size_t m_output_size; + + size_t m_chunk_size; + + bool m_is_loading; + std::mutex m_load_mutex; + std::condition_variable m_loading_finished; + std::thread m_load_thread; + + std::vector>& m_processors; + }; + + class ProcessorXChunks final : public processor::IProcessorXChunks + { + public: + ProcessorXChunks(const int numStreams, const size_t xChunkSize, const std::optional vanillaBufferSize) + : m_chunk_size(xChunkSize), + m_vanilla_buffer_size(vanillaBufferSize), + m_initialized_streams(false), + m_current_stream(0), + m_current_chunk(nullptr), + m_current_chunk_size(0), + m_current_chunk_offset(0), + m_vanilla_buffer_offset(0), + m_eof_reached(false), + m_eof_stream(0) + { + assert(numStreams > 0); + assert(xChunkSize > 0); + + for (int streamIndex = 0; streamIndex < numStreams; streamIndex++) + { + m_streams.emplace_back(std::make_unique(streamIndex, xChunkSize, m_chunk_processors)); + } + } + + size_t Load(void* buffer, const size_t length) override + { + assert(buffer != nullptr); + + if (!m_initialized_streams) + { + InitStreams(); + } + + size_t loadedSize = 0; + while (!EndOfStream() && loadedSize < length) + { + auto* bufferPos = static_cast(buffer) + loadedSize; + const size_t sizeToRead = length - loadedSize; + const size_t bytesLeftInCurrentChunk = m_current_chunk_size - m_current_chunk_offset; + + if (sizeToRead > bytesLeftInCurrentChunk) + { + assert(sizeToRead >= bytesLeftInCurrentChunk); + memcpy(bufferPos, &m_current_chunk[m_current_chunk_offset], bytesLeftInCurrentChunk); + loadedSize += bytesLeftInCurrentChunk; + NextStream(); } + else + { + memcpy(bufferPos, &m_current_chunk[m_current_chunk_offset], sizeToRead); + loadedSize += sizeToRead; + m_current_chunk_offset += sizeToRead; + + if (m_current_chunk_offset == m_current_chunk_size) + { + NextStream(); + } + } } + + return loadedSize; } - return loadedSize; - } + int64_t Pos() override + { + return m_base_stream->Pos(); + } - int64_t Pos() const + void AddChunkProcessor(std::unique_ptr chunkProcessor) override + { + assert(chunkProcessor); + + m_chunk_processors.emplace_back(std::move(chunkProcessor)); + } + + private: + void AdvanceStream(const unsigned streamNum) + { + assert(streamNum < m_streams.size()); + + if (m_eof_reached) + return; + + xchunk_size_t chunkSize; + if (m_vanilla_buffer_size.has_value()) + { + if (m_vanilla_buffer_offset + sizeof(chunkSize) > *m_vanilla_buffer_size) + { + m_base_stream->Load(&chunkSize, *m_vanilla_buffer_size - m_vanilla_buffer_offset); + m_vanilla_buffer_offset = 0; + } + + m_vanilla_buffer_offset = (m_vanilla_buffer_offset + sizeof(chunkSize)) % *m_vanilla_buffer_size; + } + + const size_t readSize = m_base_stream->Load(&chunkSize, sizeof(chunkSize)); + + if (readSize == 0) + { + m_eof_reached = true; + m_eof_stream = streamNum; + return; + } + + if (chunkSize > m_chunk_size) + { + throw InvalidChunkSizeException(chunkSize, m_chunk_size); + } + + const auto& stream = m_streams[streamNum]; + const size_t loadedChunkSize = m_base_stream->Load(stream->GetInputBuffer(), chunkSize); + + if (loadedChunkSize != chunkSize) + { + throw InvalidChunkSizeException(chunkSize); + } + + if (m_vanilla_buffer_size.has_value()) + { + m_vanilla_buffer_offset = (m_vanilla_buffer_offset + loadedChunkSize) % *m_vanilla_buffer_size; + } + + stream->StartLoading(loadedChunkSize); + } + + void NextStream() + { + AdvanceStream(m_current_stream); + + m_current_stream = (m_current_stream + 1) % m_streams.size(); + m_current_chunk_offset = 0; + m_streams[m_current_stream]->GetOutput(&m_current_chunk, &m_current_chunk_size); + } + + void InitStreams() + { + m_initialized_streams = true; + m_vanilla_buffer_offset = static_cast(m_base_stream->Pos()); + + const auto streamCount = static_cast(m_streams.size()); + for (auto streamNum = 0u; streamNum < streamCount; streamNum++) + { + AdvanceStream(streamNum); + } + + m_current_stream = 0; + m_current_chunk_offset = 0; + m_streams[0]->GetOutput(&m_current_chunk, &m_current_chunk_size); + } + + [[nodiscard]] bool EndOfStream() const + { + return m_eof_reached && m_eof_stream == m_current_stream; + } + + std::vector> m_streams; + size_t m_chunk_size; + std::optional m_vanilla_buffer_size; + std::vector> m_chunk_processors; + + bool m_initialized_streams; + unsigned int m_current_stream; + const uint8_t* m_current_chunk; + size_t m_current_chunk_size; + size_t m_current_chunk_offset; + size_t m_vanilla_buffer_offset; + + bool m_eof_reached; + unsigned int m_eof_stream; + }; +} // namespace + +namespace processor +{ + std::unique_ptr CreateProcessorXChunks(int numStreams, const size_t xChunkSize) { - return m_base->m_base_stream->Pos(); + return std::make_unique(numStreams, xChunkSize, std::nullopt); } -}; -ProcessorXChunks::ProcessorXChunks(const int numStreams, const size_t xChunkSize) -{ - m_impl = new ProcessorXChunksImpl(this, numStreams, xChunkSize); -} - -ProcessorXChunks::ProcessorXChunks(const int numStreams, const size_t xChunkSize, const size_t vanillaBufferSize) -{ - m_impl = new ProcessorXChunksImpl(this, numStreams, xChunkSize, vanillaBufferSize); -} - -ProcessorXChunks::~ProcessorXChunks() -{ - delete m_impl; - m_impl = nullptr; -} - -void ProcessorXChunks::AddChunkProcessor(std::unique_ptr chunkProcessor) const -{ - m_impl->AddChunkProcessor(std::move(chunkProcessor)); -} - -size_t ProcessorXChunks::Load(void* buffer, const size_t length) -{ - return m_impl->Load(buffer, length); -} - -int64_t ProcessorXChunks::Pos() -{ - return m_impl->Pos(); -} + std::unique_ptr CreateProcessorXChunks(int numStreams, const size_t xChunkSize, const size_t vanillaBufferSize) + { + return std::make_unique(numStreams, xChunkSize, vanillaBufferSize); + } +} // namespace processor diff --git a/src/ZoneLoading/Loading/Processor/ProcessorXChunks.h b/src/ZoneLoading/Loading/Processor/ProcessorXChunks.h index 924f799b..dec161af 100644 --- a/src/ZoneLoading/Loading/Processor/ProcessorXChunks.h +++ b/src/ZoneLoading/Loading/Processor/ProcessorXChunks.h @@ -4,18 +4,14 @@ #include -class ProcessorXChunks : public StreamProcessor +namespace processor { - class ProcessorXChunksImpl; - ProcessorXChunksImpl* m_impl; + class IProcessorXChunks : public StreamProcessor + { + public: + virtual void AddChunkProcessor(std::unique_ptr chunkProcessor) = 0; + }; -public: - ProcessorXChunks(int numStreams, size_t xChunkSize); - ProcessorXChunks(int numStreams, size_t xChunkSize, size_t vanillaBufferSize); - ~ProcessorXChunks() override; - - size_t Load(void* buffer, size_t length) override; - int64_t Pos() override; - - void AddChunkProcessor(std::unique_ptr chunkProcessor) const; -}; + std::unique_ptr CreateProcessorXChunks(int numStreams, size_t xChunkSize); + std::unique_ptr CreateProcessorXChunks(int numStreams, size_t xChunkSize, size_t vanillaBufferSize); +} // namespace processor