mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-09-08 15:07:06 +00:00
fix: handle IWD entry end of stream (#976)
* fix: handle IWD entry end of stream Return EOF correctly for IWD entries and preserve peeked bytes during bulk reads. * chore: small code style adaption * chore: use minizip to write test zip file --------- Co-authored-by: Jan Laupetin <[email protected]>
This commit is contained in:
@@ -78,7 +78,8 @@ namespace
|
||||
|
||||
const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u);
|
||||
|
||||
if (result >= 0)
|
||||
// minizip returns zero at the end of the current archive entry.
|
||||
if (result > 0)
|
||||
{
|
||||
m_peeked = true;
|
||||
return m_peek_symbol;
|
||||
@@ -96,21 +97,30 @@ namespace
|
||||
}
|
||||
|
||||
const auto result = unzReadCurrentFile(m_container, &m_peek_symbol, 1u);
|
||||
return result >= 0 ? m_peek_symbol : EOF;
|
||||
return result > 0 ? m_peek_symbol : EOF;
|
||||
}
|
||||
|
||||
std::streamsize xsgetn(char* ptr, std::streamsize count) override
|
||||
{
|
||||
std::streamsize result{};
|
||||
|
||||
if (m_peeked && count >= 1)
|
||||
{
|
||||
*ptr = static_cast<char>(m_peek_symbol);
|
||||
m_peeked = false;
|
||||
ptr++;
|
||||
count--;
|
||||
result++;
|
||||
}
|
||||
|
||||
const auto result = unzReadCurrentFile(m_container, ptr, static_cast<unsigned>(count));
|
||||
if (count <= 0)
|
||||
return result;
|
||||
|
||||
return result >= 0 ? static_cast<std::streamsize>(result) : 0;
|
||||
const auto readResult = unzReadCurrentFile(m_container, ptr, static_cast<unsigned>(count));
|
||||
if (readResult > 0)
|
||||
result += static_cast<std::streamsize>(readResult);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pos_type seekoff(const off_type off, const std::ios_base::seekdir dir, const std::ios_base::openmode mode) override
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "OatTestPaths.h"
|
||||
#include "SearchPath/IWD.h"
|
||||
#include "Utils/FileToZlibWrapper.h"
|
||||
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string_view>
|
||||
#include <zip.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace
|
||||
{
|
||||
void WriteIwd(std::ostream& stream, const std::string& entryName, const std::string_view contents)
|
||||
{
|
||||
auto zlibFunctions = FileToZlibWrapper::CreateFunctions32ForFile(&stream);
|
||||
const auto zipHandle = zipOpen2("foo.zip", 0, nullptr, &zlibFunctions);
|
||||
zipOpenNewFileInZip2(zipHandle, entryName.c_str(), nullptr, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0);
|
||||
zipWriteInFileInZip(zipHandle, contents.data(), static_cast<unsigned>(contents.size()));
|
||||
zipCloseFileInZip(zipHandle);
|
||||
zipClose(zipHandle, nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("Iwd: Reads a peeked entry through end of stream", "[searchpath][iwd]")
|
||||
{
|
||||
constexpr auto ENTRY_NAME = "test.txt";
|
||||
constexpr auto CONTENTS = "IWD stream test";
|
||||
|
||||
const auto tempDirectory = oat::paths::GetTempDirectory("iwd");
|
||||
fs::create_directories(tempDirectory);
|
||||
const auto iwdPath = tempDirectory / "test.iwd";
|
||||
|
||||
{
|
||||
std::ofstream stream(iwdPath, std::ios::out | std::ios::binary);
|
||||
WriteIwd(stream, ENTRY_NAME, CONTENTS);
|
||||
stream.close();
|
||||
}
|
||||
|
||||
const auto searchPath = iwd::LoadFromFile(iwdPath.string());
|
||||
REQUIRE(searchPath);
|
||||
|
||||
const auto file = searchPath->Open(ENTRY_NAME);
|
||||
REQUIRE(file.IsOpen());
|
||||
|
||||
auto& stream = *file.m_stream;
|
||||
REQUIRE(stream.peek() == CONTENTS[0]);
|
||||
|
||||
std::array<char, std::string_view{CONTENTS}.size()> buffer{};
|
||||
stream.read(buffer.data(), buffer.size());
|
||||
REQUIRE(stream.gcount() == static_cast<std::streamsize>(buffer.size()));
|
||||
REQUIRE(std::string_view{buffer.data(), buffer.size()} == CONTENTS);
|
||||
REQUIRE(stream.get() == std::char_traits<char>::eof());
|
||||
}
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user