Replace FileAPI with c++ streams and std::filesystem

This commit is contained in:
Jan
2021-03-03 14:04:35 +01:00
parent b6b0a57232
commit 1cd06668e0
96 changed files with 1355 additions and 1061 deletions

View File

@ -1,27 +1,33 @@
#include "IPak.h"
#include "zlib.h"
#include "Exception/IPakLoadException.h"
#include "ObjContainer/IPak/IPakTypes.h"
#include "Utils/PathUtils.h"
#include "IPakStreamManager.h"
#include <sstream>
#include <vector>
#include <memory>
#include <filesystem>
#include "zlib.h"
#include "Utils/FileUtils.h"
#include "Exception/IPakLoadException.h"
#include "ObjContainer/IPak/IPakTypes.h"
#include "IPakStreamManager.h"
namespace fs = std::filesystem;
ObjContainerRepository<IPak, Zone> IPak::Repository;
class IPak::Impl : public ObjContainerReferenceable
{
static const uint32_t MAGIC = 'IPAK';
static const uint32_t MAGIC = MakeMagic32('K', 'A', 'P', 'I');
static const uint32_t VERSION = 0x50000;
std::string m_path;
FileAPI::IFile* m_file;
std::unique_ptr<std::istream> m_stream;
bool m_initialized;
IPakSection* m_index_section;
IPakSection* m_data_section;
std::unique_ptr<IPakSection> m_index_section;
std::unique_ptr<IPakSection> m_data_section;
std::vector<IPakIndexEntry> m_index_entries;
@ -29,7 +35,7 @@ class IPak::Impl : public ObjContainerReferenceable
static uint32_t R_HashString(const char* str, uint32_t hash)
{
for (const char* pos = str; *pos; pos++)
for (const auto* pos = str; *pos; pos++)
{
hash = 33 * hash ^ (*pos | 0x20);
}
@ -39,12 +45,13 @@ class IPak::Impl : public ObjContainerReferenceable
bool ReadIndexSection()
{
m_file->Goto(m_index_section->offset);
m_stream->seekg(m_index_section->offset);
IPakIndexEntry indexEntry{};
for (unsigned itemIndex = 0; itemIndex < m_index_section->itemCount; itemIndex++)
{
if (m_file->Read(&indexEntry, sizeof indexEntry, 1) != 1)
m_stream->read(reinterpret_cast<char*>(&indexEntry), sizeof indexEntry);
if (m_stream->gcount() != sizeof indexEntry)
{
printf("Unexpected eof when trying to load index entry %u.\n", itemIndex);
return false;
@ -66,7 +73,8 @@ class IPak::Impl : public ObjContainerReferenceable
{
IPakSection section{};
if (m_file->Read(&section, sizeof section, 1) != 1)
m_stream->read(reinterpret_cast<char*>(&section), sizeof section);
if (m_stream->gcount() != sizeof section)
{
printf("Unexpected eof when trying to load section.\n");
return false;
@ -75,11 +83,11 @@ class IPak::Impl : public ObjContainerReferenceable
switch (section.type)
{
case 1:
m_index_section = new IPakSection(section);
m_index_section = std::make_unique<IPakSection>(section);
break;
case 2:
m_data_section = new IPakSection(section);
m_data_section = std::make_unique<IPakSection>(section);
break;
default:
@ -93,7 +101,8 @@ class IPak::Impl : public ObjContainerReferenceable
{
IPakHeader header{};
if (m_file->Read(&header, sizeof header, 1) != 1)
m_stream->read(reinterpret_cast<char*>(&header), sizeof header);
if (m_stream->gcount() != sizeof header)
{
printf("Unexpected eof when trying to load header.\n");
return false;
@ -136,28 +145,22 @@ class IPak::Impl : public ObjContainerReferenceable
}
public:
Impl(std::string path, FileAPI::IFile* file)
: m_stream_manager(file)
Impl(std::string path, std::unique_ptr<std::istream> stream)
: m_path(std::move(path)),
m_stream(std::move(stream)),
m_initialized(false),
m_index_section(nullptr),
m_data_section(nullptr),
m_stream_manager(*m_stream)
{
m_path = std::move(path);
m_file = file;
m_initialized = false;
m_index_section = nullptr;
m_data_section = nullptr;
}
~Impl()
{
delete m_index_section;
m_index_section = nullptr;
delete m_data_section;
m_data_section = nullptr;
}
~Impl() override
= default;
std::string GetName() override
{
return utils::Path::GetFilenameWithoutExtension(m_path);
return fs::path(m_path).filename().replace_extension("").string();
}
bool Initialize()
@ -172,7 +175,7 @@ public:
return true;
}
FileAPI::IFile* GetEntryData(const Hash nameHash, const Hash dataHash)
std::unique_ptr<iobjstream> GetEntryData(const Hash nameHash, const Hash dataHash)
{
IPakIndexEntryKey wantedKey{};
wantedKey.nameHash = nameHash;
@ -182,7 +185,7 @@ public:
{
if (entry.key.combinedKey == wantedKey.combinedKey)
{
return m_stream_manager.OpenStream(m_data_section->offset + entry.offset, entry.size);
return m_stream_manager.OpenStream(static_cast<int64_t>(m_data_section->offset) + entry.offset, entry.size);
}
else if (entry.key.combinedKey > wantedKey.combinedKey)
{
@ -205,9 +208,9 @@ public:
}
};
IPak::IPak(std::string path, FileAPI::IFile* file)
IPak::IPak(std::string path, std::unique_ptr<std::istream> stream)
{
m_impl = new Impl(std::move(path), file);
m_impl = new Impl(std::move(path), std::move(stream));
}
IPak::~IPak()
@ -221,12 +224,12 @@ std::string IPak::GetName()
return m_impl->GetName();
}
bool IPak::Initialize() const
bool IPak::Initialize()
{
return m_impl->Initialize();
}
FileAPI::IFile* IPak::GetEntryStream(const Hash nameHash, const Hash dataHash) const
std::unique_ptr<iobjstream> IPak::GetEntryStream(const Hash nameHash, const Hash dataHash) const
{
return m_impl->GetEntryData(nameHash, dataHash);
}

View File

@ -1,8 +1,11 @@
#pragma once
#include "Utils/FileAPI.h"
#include <istream>
#include "Utils/ClassUtils.h"
#include "ObjContainer/ObjContainerReferenceable.h"
#include "ObjContainer/ObjContainerRepository.h"
#include "Utils/ObjStream.h"
#include "Zone/Zone.h"
class IPak final : public ObjContainerReferenceable
@ -15,13 +18,13 @@ public:
static ObjContainerRepository<IPak, Zone> Repository;
IPak(std::string path, FileAPI::IFile* file);
~IPak();
IPak(std::string path, std::unique_ptr<std::istream> stream);
~IPak() override;
std::string GetName() override;
bool Initialize() const;
FileAPI::IFile* GetEntryStream(Hash nameHash, Hash dataHash) const;
bool Initialize();
_NODISCARD std::unique_ptr<iobjstream> GetEntryStream(Hash nameHash, Hash dataHash) const;
static Hash HashString(const std::string& str);
static Hash HashData(const void* data, size_t dataSize);

View File

@ -1,48 +1,47 @@
#include "IPakEntryReadStream.h"
#include "ObjContainer/IPak/IPakTypes.h"
#include <cassert>
#include <stdexcept>
#include <minilzo.h>
#include "ObjContainer/IPak/IPakTypes.h"
using namespace ipak_consts;
IPakEntryReadStream::IPakEntryReadStream(IFile* file, IPakStreamManagerActions* streamManagerActions,
IPakEntryReadStream::IPakEntryReadStream(std::istream& stream, IPakStreamManagerActions* streamManagerActions,
uint8_t* chunkBuffer, const int64_t startOffset, const size_t entrySize)
: m_decompress_buffer{}
: m_chunk_buffer(chunkBuffer),
m_stream(stream),
m_stream_manager_actions(streamManagerActions),
m_file_offset(0),
m_file_head(0),
m_entry_size(entrySize),
m_decompress_buffer{},
m_current_block(nullptr),
m_next_command(0),
m_current_command_buffer(nullptr),
m_current_command_length(0),
m_current_command_offset(0),
m_pos(startOffset),
m_base_pos(startOffset),
m_end_pos(startOffset + entrySize),
m_buffer_start_pos(0),
m_buffer_end_pos(0)
{
m_file = file;
m_stream_manager_actions = streamManagerActions;
m_chunk_buffer = chunkBuffer;
m_file_offset = 0;
m_file_head = 0;
m_entry_size = entrySize;
m_base_pos = startOffset;
m_end_pos = startOffset + entrySize;
m_pos = m_base_pos;
m_buffer_start_pos = 0;
m_buffer_end_pos = 0;
m_current_block = nullptr;
m_next_command = 0;
m_current_command_buffer = nullptr;
m_current_command_length = 0;
m_current_command_offset = 0;
lzo_init();
}
IPakEntryReadStream::~IPakEntryReadStream()
{
Close();
close();
}
size_t IPakEntryReadStream::ReadChunks(uint8_t* buffer, const int64_t startPos, const size_t chunkCount) const
{
m_stream_manager_actions->StartReading();
m_file->Goto(startPos);
const auto readSize = m_file->Read(buffer, 1, chunkCount * IPAK_CHUNK_SIZE);
m_stream.seekg(startPos);
m_stream.read(reinterpret_cast<char*>(buffer), static_cast<std::streamsize>(chunkCount) * IPAK_CHUNK_SIZE);
const auto readSize = static_cast<size_t>(m_stream.gcount());
m_stream_manager_actions->StopReading();
return readSize / IPAK_CHUNK_SIZE;
@ -66,47 +65,42 @@ bool IPakEntryReadStream::SetChunkBufferWindow(const int64_t startPos, size_t ch
return true;
}
const int64_t endPos = startPos + static_cast<int64_t>(chunkCount) * IPAK_CHUNK_SIZE;
const auto endPos = startPos + static_cast<int64_t>(chunkCount) * IPAK_CHUNK_SIZE;
if (startPos >= m_buffer_start_pos && startPos < m_buffer_end_pos)
{
if (m_buffer_start_pos != startPos)
{
const int64_t moveEnd = endPos < m_buffer_end_pos ? endPos : m_buffer_end_pos;
memmove_s(m_chunk_buffer,
IPAK_CHUNK_SIZE * IPAK_CHUNK_COUNT_PER_READ,
&m_chunk_buffer[startPos - m_buffer_start_pos],
const auto moveEnd = endPos < m_buffer_end_pos ? endPos : m_buffer_end_pos;
memmove_s(m_chunk_buffer, IPAK_CHUNK_SIZE * IPAK_CHUNK_COUNT_PER_READ, &m_chunk_buffer[startPos - m_buffer_start_pos],
static_cast<size_t>(moveEnd - startPos));
m_buffer_start_pos = startPos;
}
if (endPos > m_buffer_end_pos)
{
const size_t readChunkCount = ReadChunks(&m_chunk_buffer[m_buffer_end_pos - startPos],
m_buffer_end_pos,
static_cast<size_t>(endPos - m_buffer_end_pos) / IPAK_CHUNK_SIZE);
const auto readChunkCount = ReadChunks(&m_chunk_buffer[m_buffer_end_pos - startPos], m_buffer_end_pos,
static_cast<size_t>(endPos - m_buffer_end_pos) / IPAK_CHUNK_SIZE);
m_buffer_end_pos += static_cast<int64_t>(readChunkCount) * IPAK_CHUNK_SIZE;
return m_buffer_end_pos == endPos;
}
else
{
m_buffer_end_pos = endPos;
return true;
}
m_buffer_end_pos = endPos;
return true;
}
else if (endPos > m_buffer_start_pos && endPos <= m_buffer_end_pos)
if (endPos > m_buffer_start_pos && endPos <= m_buffer_end_pos)
{
memmove_s(&m_chunk_buffer[m_buffer_start_pos - startPos],
IPAK_CHUNK_SIZE * IPAK_CHUNK_COUNT_PER_READ - static_cast<size_t>(m_buffer_start_pos - startPos),
m_chunk_buffer,
static_cast<size_t>(endPos - m_buffer_start_pos));
const size_t readChunkCount = ReadChunks(m_chunk_buffer,
startPos,
static_cast<size_t>(m_buffer_start_pos - startPos) / IPAK_CHUNK_SIZE);
const auto readChunkCount = ReadChunks(m_chunk_buffer,
startPos,
static_cast<size_t>(m_buffer_start_pos - startPos) / IPAK_CHUNK_SIZE);
m_buffer_start_pos = startPos;
m_buffer_end_pos = readChunkCount == (m_buffer_start_pos - startPos) / IPAK_CHUNK_SIZE
@ -116,9 +110,7 @@ bool IPakEntryReadStream::SetChunkBufferWindow(const int64_t startPos, size_t ch
return m_buffer_end_pos == endPos;
}
const size_t readChunkCount = ReadChunks(m_chunk_buffer,
startPos,
chunkCount);
const auto readChunkCount = ReadChunks(m_chunk_buffer, startPos, chunkCount);
m_buffer_start_pos = startPos;
m_buffer_end_pos = startPos + static_cast<int64_t>(readChunkCount) * IPAK_CHUNK_SIZE;
@ -136,12 +128,12 @@ bool IPakEntryReadStream::ValidateBlockHeader(IPakDataBlockHeader* blockHeader)
if (blockHeader->offset != m_file_head)
{
// A matching offset is only relevant if a command contains data.
for(unsigned currentCommand = 0; currentCommand < blockHeader->count; currentCommand++)
for (unsigned currentCommand = 0; currentCommand < blockHeader->count; currentCommand++)
{
if(blockHeader->_commands[currentCommand].compressed == 0
if (blockHeader->_commands[currentCommand].compressed == 0
|| blockHeader->_commands[currentCommand].compressed == 1)
{
printf("IPak block offset is not the file head: %u != %u -> Invalid\n", blockHeader->offset, m_file_head);
printf("IPak block offset is not the file head: %u != %lld -> Invalid\n", blockHeader->offset, m_file_head);
return false;
}
}
@ -190,8 +182,8 @@ bool IPakEntryReadStream::NextBlock()
const auto chunkStartPos = AlignBackwards<int64_t>(m_pos, IPAK_CHUNK_SIZE);
const auto blockOffsetInChunk = static_cast<size_t>(m_pos - chunkStartPos);
const size_t sizeLeftToRead = m_entry_size - m_file_head;
size_t estimatedChunksToRead = AlignForward(m_entry_size - static_cast<size_t>(m_pos - m_base_pos), IPAK_CHUNK_SIZE)
const auto sizeLeftToRead = m_entry_size - m_file_head;
auto estimatedChunksToRead = AlignForward(m_entry_size - static_cast<size_t>(m_pos - m_base_pos), IPAK_CHUNK_SIZE)
/ IPAK_CHUNK_SIZE;
if (estimatedChunksToRead > IPAK_CHUNK_COUNT_PER_READ)
@ -263,18 +255,29 @@ bool IPakEntryReadStream::AdvanceStream()
return true;
}
bool IPakEntryReadStream::IsOpen()
bool IPakEntryReadStream::is_open() const
{
return m_file != nullptr;
return !m_stream.eof();
}
size_t IPakEntryReadStream::Read(void* buffer, const size_t elementSize, const size_t elementCount)
bool IPakEntryReadStream::close()
{
auto* destBuffer = static_cast<uint8_t*>(buffer);
const size_t bufferSize = elementCount * elementSize;
size_t countRead = 0;
if (is_open())
{
m_stream_manager_actions->CloseStream(this);
}
while (countRead < bufferSize)
return true;
}
std::streamsize IPakEntryReadStream::showmanyc()
{
return m_end_pos - m_pos;
}
std::streambuf::int_type IPakEntryReadStream::underflow()
{
while (true)
{
if (m_current_command_offset >= m_current_command_length)
{
@ -282,68 +285,93 @@ size_t IPakEntryReadStream::Read(void* buffer, const size_t elementSize, const s
break;
}
size_t sizeToRead = bufferSize - countRead;
if (m_current_command_length - m_current_command_offset < 1)
continue;
return m_current_command_buffer[m_current_command_offset];
}
return EOF;
}
std::streambuf::int_type IPakEntryReadStream::uflow()
{
while (true)
{
if (m_current_command_offset >= m_current_command_length)
{
if (!AdvanceStream())
break;
}
if (m_current_command_length - m_current_command_offset < 1)
continue;
const auto result = m_current_command_buffer[m_current_command_offset];
m_current_command_offset++;
m_file_offset++;
return result;
}
return EOF;
}
std::streamsize IPakEntryReadStream::xsgetn(char* ptr, const std::streamsize count)
{
auto* destBuffer = reinterpret_cast<uint8_t*>(ptr);
int64_t countRead = 0;
while (countRead < count)
{
if (m_current_command_offset >= m_current_command_length)
{
if (!AdvanceStream())
break;
}
auto sizeToRead = count - countRead;
if (sizeToRead > m_current_command_length - m_current_command_offset)
sizeToRead = m_current_command_length - m_current_command_offset;
if (sizeToRead > 0)
{
memcpy_s(&destBuffer[countRead], bufferSize - countRead,
&m_current_command_buffer[m_current_command_offset], sizeToRead);
memcpy_s(&destBuffer[countRead], static_cast<rsize_t>(count - countRead),
&m_current_command_buffer[m_current_command_offset], static_cast<rsize_t>(sizeToRead));
countRead += sizeToRead;
m_current_command_offset += sizeToRead;
m_file_offset += sizeToRead;
}
}
return countRead / elementSize;
return countRead;
}
size_t IPakEntryReadStream::Write(const void* data, size_t elementSize, size_t elementCount)
std::streambuf::pos_type IPakEntryReadStream::seekoff(const off_type off, const std::ios_base::seekdir dir, const std::ios_base::openmode mode)
{
// This is not meant for writing.
assert(false);
throw std::runtime_error("This is not a stream for output!");
}
void IPakEntryReadStream::Skip(const int64_t amount)
{
if (amount > 0)
pos_type pos;
if (dir == std::ios_base::beg)
{
const size_t targetOffset = m_file_offset + static_cast<size_t>(amount);
while (m_file_head < targetOffset)
{
if (!AdvanceStream())
break;
}
if (targetOffset <= m_file_head)
{
m_current_command_offset = m_current_command_length - (m_file_head - targetOffset);
m_file_offset = targetOffset;
}
else
{
m_current_command_offset = m_current_command_length;
m_file_offset = m_file_head;
}
pos = off;
}
else if (dir == std::ios_base::cur)
{
pos = off + m_file_offset;
}
else
{
pos = -1;
}
if (pos == 0 || pos > m_file_offset)
{
return seekpos(pos, mode);
}
return std::streampos(-1);
}
size_t IPakEntryReadStream::Printf(const char* fmt, ...)
{
// This is not meant for writing.
assert(false);
throw std::runtime_error("This is not a stream for output!");
}
int64_t IPakEntryReadStream::Pos()
{
return m_file_offset;
}
void IPakEntryReadStream::Goto(const int64_t pos)
std::streambuf::pos_type IPakEntryReadStream::seekpos(const pos_type pos, std::ios_base::openmode mode)
{
if (pos == 0)
{
@ -357,34 +385,31 @@ void IPakEntryReadStream::Goto(const int64_t pos)
m_current_command_buffer = nullptr;
m_current_command_length = 0;
m_current_command_offset = 0;
}
else if (pos > m_file_offset)
{
Skip(pos - m_file_offset);
}
else
{
// Not implemented due to being too time consuming.
// Can be added if necessary.
assert(false);
throw std::runtime_error("Operation not supported!");
}
}
void IPakEntryReadStream::GotoEnd()
{
// Not implemented due to being too time consuming.
// Can be added if necessary.
assert(false);
throw std::runtime_error("Operation not supported!");
}
void IPakEntryReadStream::Close()
{
if (IsOpen())
{
m_file = nullptr;
m_stream_manager_actions->CloseStream(this);
return pos;
}
if (pos > m_file_offset)
{
while (m_file_head < pos)
{
if (!AdvanceStream())
break;
}
if (pos <= m_file_head)
{
m_current_command_offset = m_current_command_length - (m_file_head - pos);
m_file_offset = pos;
}
else
{
m_current_command_offset = m_current_command_length;
m_file_offset = m_file_head;
}
return pos;
}
return std::streampos(-1);
}

View File

@ -1,21 +1,22 @@
#pragma once
#include "IPakStreamManager.h"
#include "Utils/FileAPI.h"
#include "ObjContainer/IPak/IPakTypes.h"
#include <mutex>
#include <istream>
class IPakEntryReadStream final : public FileAPI::IFile
#include "Utils/ObjStream.h"
#include "IPakStreamManager.h"
#include "ObjContainer/IPak/IPakTypes.h"
class IPakEntryReadStream final : public objbuf
{
static constexpr size_t IPAK_DECOMPRESS_BUFFER_SIZE = 0x8000;
uint8_t* m_chunk_buffer;
IFile* m_file;
std::istream& m_stream;
IPakStreamManagerActions* m_stream_manager_actions;
size_t m_file_offset;
size_t m_file_head;
int64_t m_file_offset;
int64_t m_file_head;
size_t m_entry_size;
@ -53,16 +54,17 @@ class IPakEntryReadStream final : public FileAPI::IFile
bool AdvanceStream();
public:
IPakEntryReadStream(IFile* file, IPakStreamManagerActions* streamManagerActions, uint8_t* chunkBuffer, int64_t startOffset, size_t entrySize);
IPakEntryReadStream(std::istream& stream, IPakStreamManagerActions* streamManagerActions, uint8_t* chunkBuffer, int64_t startOffset, size_t entrySize);
~IPakEntryReadStream() override;
bool IsOpen() override;
size_t Read(void* buffer, size_t elementSize, size_t elementCount) override;
size_t Write(const void* data, size_t elementSize, size_t elementCount) override;
void Skip(int64_t amount) override;
size_t Printf(const char* fmt, ...) override;
int64_t Pos() override;
void Goto(int64_t pos) override;
void GotoEnd() override;
void Close() override;
_NODISCARD bool is_open() const override;
bool close() override;
protected:
std::streamsize showmanyc() override;
int_type underflow() override;
int_type uflow() override;
std::streamsize xsgetn(char* ptr, std::streamsize count) override;
pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode mode) override;
pos_type seekpos(pos_type pos, std::ios_base::openmode mode) override;
};

View File

@ -1,9 +1,11 @@
#include "IPakStreamManager.h"
#include "IPakEntryReadStream.h"
#include "ObjContainer/IPak/IPakTypes.h"
#include <vector>
#include <algorithm>
#include "IPakEntryReadStream.h"
#include "ObjContainer/IPak/IPakTypes.h"
using namespace ipak_consts;
class IPakStreamManager::Impl final : public IPakStreamManagerActions
@ -30,7 +32,7 @@ class IPakStreamManager::Impl final : public IPakStreamManagerActions
}
};
FileAPI::IFile* m_file;
std::istream& m_stream;
std::mutex m_read_mutex;
std::mutex m_stream_mutex;
@ -39,10 +41,9 @@ class IPakStreamManager::Impl final : public IPakStreamManagerActions
std::vector<ChunkBuffer*> m_chunk_buffers;
public:
explicit Impl(FileAPI::IFile* file)
explicit Impl(std::istream& stream)
: m_stream(stream)
{
m_file = file;
m_chunk_buffers.push_back(new ChunkBuffer());
}
@ -55,7 +56,7 @@ public:
for (const auto& openStream : m_open_streams)
{
openStream.m_stream->Close();
openStream.m_stream->close();
}
m_open_streams.clear();
@ -65,16 +66,15 @@ public:
Impl& operator=(const Impl& other) = delete;
Impl& operator=(Impl&& other) noexcept = delete;
FileAPI::IFile* OpenStream(const int64_t startPosition, const size_t length)
std::unique_ptr<iobjstream> OpenStream(const int64_t startPosition, const size_t length)
{
m_stream_mutex.lock();
ChunkBuffer* reservedChunkBuffer;
const auto freeChunkBuffer = std::find_if(m_chunk_buffers.begin(), m_chunk_buffers.end(),
[](ChunkBuffer* chunkBuffer)
{
return chunkBuffer->m_using_stream == nullptr;
});
const auto freeChunkBuffer = std::find_if(m_chunk_buffers.begin(), m_chunk_buffers.end(), [](ChunkBuffer* chunkBuffer)
{
return chunkBuffer->m_using_stream == nullptr;
});
if (freeChunkBuffer == m_chunk_buffers.end())
{
@ -84,15 +84,15 @@ public:
else
reservedChunkBuffer = *freeChunkBuffer;
auto* stream = new IPakEntryReadStream(m_file, this, reservedChunkBuffer->m_buffer, startPosition, length);
auto ipakEntryStream = std::make_unique<IPakEntryReadStream>(m_stream, this, reservedChunkBuffer->m_buffer, startPosition, length);
reservedChunkBuffer->m_using_stream = stream;
reservedChunkBuffer->m_using_stream = ipakEntryStream.get();
m_open_streams.emplace_back(stream, reservedChunkBuffer);
m_open_streams.emplace_back(ipakEntryStream.get(), reservedChunkBuffer);
m_stream_mutex.unlock();
return stream;
return std::make_unique<iobjstream>(std::move(ipakEntryStream));
}
void StartReading() override
@ -105,15 +105,14 @@ public:
m_read_mutex.unlock();
}
void CloseStream(FileAPI::IFile* stream) override
void CloseStream(objbuf* stream) override
{
m_stream_mutex.lock();
const auto openStreamEntry = std::find_if(m_open_streams.begin(), m_open_streams.end(),
[stream](const ManagedStream& managedStream)
{
return managedStream.m_stream == stream;
});
const auto openStreamEntry = std::find_if(m_open_streams.begin(), m_open_streams.end(), [stream](const ManagedStream& managedStream)
{
return managedStream.m_stream == stream;
});
if (openStreamEntry != m_open_streams.end())
{
@ -138,9 +137,9 @@ public:
}
};
IPakStreamManager::IPakStreamManager(FileAPI::IFile* file)
IPakStreamManager::IPakStreamManager(std::istream& stream)
: m_impl(new Impl(stream))
{
m_impl = new Impl(file);
}
IPakStreamManager::~IPakStreamManager()
@ -149,7 +148,7 @@ IPakStreamManager::~IPakStreamManager()
m_impl = nullptr;
}
FileAPI::IFile* IPakStreamManager::OpenStream(const int64_t startPosition, const size_t length) const
std::unique_ptr<iobjstream> IPakStreamManager::OpenStream(const int64_t startPosition, const size_t length) const
{
return m_impl->OpenStream(startPosition, length);
}

View File

@ -1,8 +1,11 @@
#pragma once
#include "Utils/FileAPI.h"
#include <cstdint>
#include <mutex>
#include <istream>
#include "Utils/ClassUtils.h"
#include "Utils/ObjStream.h"
class IPakStreamManagerActions
{
@ -10,7 +13,7 @@ public:
virtual void StartReading() = 0;
virtual void StopReading() = 0;
virtual void CloseStream(FileAPI::IFile* stream) = 0;
virtual void CloseStream(objbuf* stream) = 0;
};
class IPakStreamManager
@ -19,7 +22,7 @@ class IPakStreamManager
Impl* m_impl;
public:
explicit IPakStreamManager(FileAPI::IFile* file);
explicit IPakStreamManager(std::istream& stream);
IPakStreamManager(const IPakStreamManager& other) = delete;
IPakStreamManager(IPakStreamManager&& other) noexcept = delete;
~IPakStreamManager();
@ -27,5 +30,5 @@ public:
IPakStreamManager& operator=(const IPakStreamManager& other) = delete;
IPakStreamManager& operator=(IPakStreamManager&& other) noexcept = delete;
FileAPI::IFile* OpenStream(int64_t startPosition, size_t length) const;
_NODISCARD std::unique_ptr<iobjstream> OpenStream(int64_t startPosition, size_t length) const;
};