Skip to content

Commit 965b66c

Browse files
authored
Add support for generic istream in ZArchiveReader (#25)
1 parent b467f7a commit 965b66c

2 files changed

Lines changed: 33 additions & 23 deletions

File tree

include/zarchive/zarchivereader.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
#pragma once
22

33
#include <cstdint>
4+
#include <memory>
45
#include <vector>
56
#include <string_view>
67
#include <unordered_map>
78
#include <mutex>
89

910
#include <filesystem>
10-
#include <fstream>
11+
#include <istream>
1112

1213
#include "zarchivecommon.h"
1314

@@ -27,6 +28,7 @@ class ZArchiveReader
2728
};
2829

2930
static ZArchiveReader* OpenFromFile(const std::filesystem::path& path);
31+
static ZArchiveReader* OpenFromStream(std::unique_ptr<std::istream>&& stream);
3032

3133
~ZArchiveReader();
3234

@@ -60,7 +62,7 @@ class ZArchiveReader
6062
CacheBlock* m_lruChainLast;
6163
std::unordered_map<uint64_t, CacheBlock*> m_blockLookup;
6264

63-
ZArchiveReader(std::ifstream&& file, std::vector<_ZARCHIVE::CompressionOffsetRecord>&& offsetRecords, std::vector<uint8_t>&& nameTable, std::vector<_ZARCHIVE::FileDirectoryEntry>&& fileTree, uint64_t compressedDataOffset, uint64_t compressedDataSize);
65+
ZArchiveReader(std::unique_ptr<std::istream>&& stream, std::vector<_ZARCHIVE::CompressionOffsetRecord>&& offsetRecords, std::vector<uint8_t>&& nameTable, std::vector<_ZARCHIVE::FileDirectoryEntry>&& fileTree, uint64_t compressedDataOffset, uint64_t compressedDataSize);
6466

6567
CacheBlock* GetCachedBlock(uint64_t blockIndex);
6668
CacheBlock* RecycleLRUBlock(uint64_t newBlockIndex);
@@ -72,7 +74,7 @@ class ZArchiveReader
7274

7375
static std::string_view GetName(const std::vector<uint8_t>& nameTable, uint32_t nameOffset);
7476

75-
std::ifstream m_file;
77+
std::unique_ptr<std::istream> m_stream;
7678
std::vector<_ZARCHIVE::CompressionOffsetRecord> m_offsetRecords;
7779
std::vector<uint8_t> m_nameTable;
7880
std::vector<_ZARCHIVE::FileDirectoryEntry> m_fileTree;

src/zarchivereader.cpp

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@
66
#include <zstd.h>
77
#include <cassert>
88

9-
static uint64_t _ifstream_getFileSize(std::ifstream& file)
9+
static uint64_t _istream_getFileSize(std::istream& stream)
1010
{
11-
file.seekg(0, std::ios_base::end);
12-
return (uint64_t)file.tellg();
11+
stream.seekg(0, std::ios_base::end);
12+
return (uint64_t)stream.tellg();
1313
}
1414

15-
static bool _ifstream_readBytes(std::ifstream& file, uint64_t offset, void* buffer, uint32_t size)
15+
static bool _istream_readBytes(std::istream& stream, uint64_t offset, void* buffer, uint32_t size)
1616
{
17-
file.seekg(offset, std::ios_base::beg);
18-
file.read((char*)buffer, size);
19-
return file.gcount() == size;
17+
stream.seekg(offset, std::ios_base::beg);
18+
stream.read((char*)buffer, size);
19+
return stream.gcount() == size;
2020
}
2121

2222
static uint64_t _getValidElementCount(uint64_t size, uint64_t elementSize)
@@ -28,16 +28,24 @@ static uint64_t _getValidElementCount(uint64_t size, uint64_t elementSize)
2828

2929
ZArchiveReader* ZArchiveReader::OpenFromFile(const std::filesystem::path& path)
3030
{
31-
std::ifstream file;
32-
file.open(path, std::ios_base::in | std::ios_base::binary);
33-
if (!file.is_open())
31+
auto file = std::make_unique<std::ifstream>(path, std::ios_base::in | std::ios_base::binary);
32+
if (!file->is_open())
3433
return nullptr;
35-
uint64_t fileSize = _ifstream_getFileSize(file);
34+
35+
return ZArchiveReader::OpenFromStream(std::move(file));
36+
}
37+
38+
ZArchiveReader* ZArchiveReader::OpenFromStream(std::unique_ptr<std::istream>&& stream)
39+
{
40+
if(stream == nullptr)
41+
return nullptr;
42+
43+
uint64_t fileSize = _istream_getFileSize(*stream);
3644
if (fileSize <= sizeof(_ZARCHIVE::Footer))
3745
return nullptr;
3846
// read footer
3947
_ZARCHIVE::Footer footer;
40-
if (!_ifstream_readBytes(file, fileSize - sizeof(_ZARCHIVE::Footer), &footer, sizeof(_ZARCHIVE::Footer)))
48+
if (!_istream_readBytes(*stream, fileSize - sizeof(_ZARCHIVE::Footer), &footer, sizeof(_ZARCHIVE::Footer)))
4149
return nullptr;
4250
_ZARCHIVE::Footer::Deserialize(&footer, &footer);
4351
// validate footer
@@ -63,18 +71,18 @@ ZArchiveReader* ZArchiveReader::OpenFromFile(const std::filesystem::path& path)
6371
// read offset records
6472
std::vector<_ZARCHIVE::CompressionOffsetRecord> offsetRecords;
6573
offsetRecords.resize(_getValidElementCount(footer.sectionOffsetRecords.size, sizeof(_ZARCHIVE::CompressionOffsetRecord)));
66-
if (offsetRecords.empty() || !_ifstream_readBytes(file, footer.sectionOffsetRecords.offset, offsetRecords.data(), (uint32_t)(offsetRecords.size() * sizeof(_ZARCHIVE::CompressionOffsetRecord))))
74+
if (offsetRecords.empty() || !_istream_readBytes(*stream, footer.sectionOffsetRecords.offset, offsetRecords.data(), (uint32_t)(offsetRecords.size() * sizeof(_ZARCHIVE::CompressionOffsetRecord))))
6775
return nullptr;
6876
_ZARCHIVE::CompressionOffsetRecord::Deserialize(offsetRecords.data(), offsetRecords.size(), offsetRecords.data());
6977
// read name table
7078
std::vector<uint8_t> nameTable;
7179
nameTable.resize(footer.sectionNames.size);
72-
if (!_ifstream_readBytes(file, footer.sectionNames.offset, nameTable.data(), (uint32_t)(nameTable.size() * sizeof(uint8_t))))
80+
if (!_istream_readBytes(*stream, footer.sectionNames.offset, nameTable.data(), (uint32_t)(nameTable.size() * sizeof(uint8_t))))
7381
return nullptr;
7482
// read file tree
7583
std::vector<_ZARCHIVE::FileDirectoryEntry> fileTree;
7684
fileTree.resize(_getValidElementCount(footer.sectionFileTree.size, sizeof(_ZARCHIVE::FileDirectoryEntry)));
77-
if (fileTree.empty() || !_ifstream_readBytes(file, footer.sectionFileTree.offset, fileTree.data(), (uint32_t)(fileTree.size() * sizeof(_ZARCHIVE::FileDirectoryEntry))))
85+
if (fileTree.empty() || !_istream_readBytes(*stream, footer.sectionFileTree.offset, fileTree.data(), (uint32_t)(fileTree.size() * sizeof(_ZARCHIVE::FileDirectoryEntry))))
7886
return nullptr;
7987
_ZARCHIVE::FileDirectoryEntry::Deserialize(fileTree.data(), fileTree.size(), fileTree.data());
8088
// verify file tree
@@ -86,12 +94,12 @@ ZArchiveReader* ZArchiveReader::OpenFromFile(const std::filesystem::path& path)
8694
// read meta data
8795
// todo
8896

89-
ZArchiveReader* cfs = new ZArchiveReader(std::move(file), std::move(offsetRecords), std::move(nameTable), std::move(fileTree), footer.sectionCompressedData.offset, footer.sectionCompressedData.size);
97+
ZArchiveReader* cfs = new ZArchiveReader(std::move(stream), std::move(offsetRecords), std::move(nameTable), std::move(fileTree), footer.sectionCompressedData.offset, footer.sectionCompressedData.size);
9098
return cfs;
9199
}
92100

93-
ZArchiveReader::ZArchiveReader(std::ifstream&& file, std::vector<_ZARCHIVE::CompressionOffsetRecord>&& offsetRecords, std::vector<uint8_t>&& nameTable, std::vector<_ZARCHIVE::FileDirectoryEntry>&& fileTree, uint64_t compressedDataOffset, uint64_t compressedDataSize) :
94-
m_file(std::move(file)), m_offsetRecords(std::move(offsetRecords)), m_nameTable(std::move(nameTable)), m_fileTree(std::move(fileTree)),
101+
ZArchiveReader::ZArchiveReader(std::unique_ptr<std::istream>&& stream, std::vector<_ZARCHIVE::CompressionOffsetRecord>&& offsetRecords, std::vector<uint8_t>&& nameTable, std::vector<_ZARCHIVE::FileDirectoryEntry>&& fileTree, uint64_t compressedDataOffset, uint64_t compressedDataSize) :
102+
m_stream(std::move(stream)), m_offsetRecords(std::move(offsetRecords)), m_nameTable(std::move(nameTable)), m_fileTree(std::move(fileTree)),
95103
m_compressedDataOffset(compressedDataOffset), m_compressedDataSize(compressedDataSize)
96104
{
97105
m_blockCount = (uint64_t)m_offsetRecords.size() * _ZARCHIVE::ENTRIES_PER_OFFSETRECORD;
@@ -338,9 +346,9 @@ bool ZArchiveReader::LoadBlock(CacheBlock* block)
338346
if (compressedSize == _ZARCHIVE::COMPRESSED_BLOCK_SIZE)
339347
{
340348
// uncompressed block, read directly into cached block
341-
return _ifstream_readBytes(m_file, offset, block->data, compressedSize);
349+
return _istream_readBytes(*m_stream, offset, block->data, compressedSize);
342350
}
343-
if (!_ifstream_readBytes(m_file, offset, m_blockDecompressionBuffer.data(), compressedSize))
351+
if (!_istream_readBytes(*m_stream, offset, m_blockDecompressionBuffer.data(), compressedSize))
344352
return false;
345353
// decompress
346354
size_t outputSize = ZSTD_decompress(block->data, _ZARCHIVE::COMPRESSED_BLOCK_SIZE, m_blockDecompressionBuffer.data(), compressedSize);

0 commit comments

Comments
 (0)