Allow uncompressed files in zip archives
This commit is contained in:
@@ -32,8 +32,6 @@ namespace OpenVulkano
|
||||
[[nodiscard]] int GetLibArchiveArchiveType() const;
|
||||
|
||||
[[nodiscard]] int GetLibArchiveCompressionType() const;
|
||||
|
||||
[[nodiscard]] constexpr bool AllowsUnknownFileSize() const { return type == ArchiveType::ZIP; }
|
||||
};
|
||||
|
||||
namespace ArchiveConfig
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace OpenVulkano
|
||||
[[nodiscard]] constexpr bool operator!=(ArchiveType rhs) const { return m_type != rhs.m_type; }
|
||||
|
||||
[[nodiscard]] constexpr explicit operator int() const { return m_type; }
|
||||
[[nodiscard]] constexpr operator Type() const { return m_type; }
|
||||
|
||||
[[nodiscard]] static constexpr std::optional<ArchiveType> FromExtension(std::string_view fName)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "ArchiveWriter.hpp"
|
||||
#include "LibArchiveHelper.hpp"
|
||||
#include "ArchiveStreamBufferWriter.hpp"
|
||||
#include "SimpleFileTypeShouldCompressChecker.hpp"
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
#include <iostream>
|
||||
@@ -16,6 +17,7 @@ namespace OpenVulkano
|
||||
ArchiveWriter::ArchiveWriter(const char* fileName, ArchiveConfiguration archiveConfiguration, const std::shared_ptr<spdlog::logger>& logger)
|
||||
: ArchiveBase(archive_write_new(), archive_entry_new(), logger)
|
||||
, m_archiveConfig(archiveConfiguration)
|
||||
, m_shouldCompress(&SimpleFileTypeShouldCompressChecker)
|
||||
{ //TODO error handling
|
||||
ChkErr(archive_write_set_format(m_archive, archiveConfiguration.GetLibArchiveArchiveType()));
|
||||
if (archiveConfiguration.type == ArchiveType::TAR)
|
||||
@@ -87,6 +89,11 @@ namespace OpenVulkano
|
||||
void ArchiveWriter::WriteHeader(const FileDescription& fileDescription)
|
||||
{
|
||||
if (m_asBuffer) { m_asBuffer->Close(); m_asBuffer = nullptr; }
|
||||
if (m_archiveConfig.type.AllowsMixedCompressionLevels())
|
||||
{
|
||||
if (m_shouldCompress(fileDescription)) SetCompressed();
|
||||
else SetUncompressed();
|
||||
}
|
||||
archive_entry_clear(m_archiveEntry);
|
||||
archive_entry_set_pathname_utf8(m_archiveEntry, fileDescription.path.c_str());
|
||||
if (fileDescription.size != FileDescription::UNKNOWN_SIZE)
|
||||
@@ -95,7 +102,7 @@ namespace OpenVulkano
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_archiveConfig.AllowsUnknownFileSize())
|
||||
if (!m_archiveConfig.type.AllowsUnknownFileSize())
|
||||
throw std::invalid_argument("Only ZIP files allow files of unknown size");
|
||||
archive_entry_unset_size(m_archiveEntry);
|
||||
}
|
||||
@@ -106,4 +113,26 @@ namespace OpenVulkano
|
||||
ChkErr(archive_write_header(m_archive, m_archiveEntry));
|
||||
m_bytesWritten += fileDescription.size;
|
||||
}
|
||||
|
||||
void ArchiveWriter::SetUncompressed()
|
||||
{
|
||||
if (!m_lastCompressed) return;
|
||||
m_lastCompressed = false;
|
||||
switch (m_archiveConfig.type)
|
||||
{
|
||||
case ArchiveType::ZIP: ChkErr(archive_write_zip_set_compression_store(m_archive));
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveWriter::SetCompressed()
|
||||
{
|
||||
if (m_lastCompressed) return;
|
||||
m_lastCompressed = true;
|
||||
switch (m_archiveConfig.type)
|
||||
{
|
||||
case ArchiveType::ZIP: ChkErr(archive_write_zip_set_compression_deflate(m_archive));
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace OpenVulkano
|
||||
ArchiveConfiguration m_archiveConfig;
|
||||
size_t m_bytesWritten = 0;
|
||||
ArchiveOStream::ASBufferPtr m_asBuffer = nullptr;
|
||||
bool m_lastCompressed = true;
|
||||
std::function<bool(const FileDescription&)> m_shouldCompress;
|
||||
|
||||
public:
|
||||
ArchiveWriter(const char* fileName, const std::shared_ptr<spdlog::logger>& logger = nullptr)
|
||||
@@ -39,7 +41,13 @@ namespace OpenVulkano
|
||||
bool AddFile(const char* fileName, const char* inArchiveName) override;
|
||||
[[nodiscard]] ArchiveOStream AddFileStream(const FileDescription& description) override;
|
||||
|
||||
void SetShouldCompressFunction(const std::function<bool(const FileDescription&)>& shouldComp) override { m_shouldCompress = shouldComp; }
|
||||
|
||||
private:
|
||||
void WriteHeader(const FileDescription& fileDescription);
|
||||
|
||||
void SetUncompressed();
|
||||
|
||||
void SetCompressed();
|
||||
};
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "ArchiveOStream.hpp"
|
||||
#include "IO/FileDescription.hpp"
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenVulkano
|
||||
@@ -20,6 +21,8 @@ namespace OpenVulkano
|
||||
public:
|
||||
virtual ~IArchiveWriter() = default;
|
||||
|
||||
virtual void SetShouldCompressFunction(const std::function<bool(const FileDescription&)>& shouldComp) = 0;
|
||||
|
||||
virtual bool AddFile(const FileDescription& description, const void* buffer) = 0;
|
||||
virtual bool AddFile(const FileDescription& description, const std::vector<std::pair<const void*, size_t>>& buffers) = 0;
|
||||
virtual bool AddFile(const char* fileName, const char* inArchiveName) = 0;
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace OpenVulkano
|
||||
#else
|
||||
m_writer = std::make_unique<ArchiveWriter>(m_archives.back().c_str(), m_archiveConfig, m_logger);
|
||||
#endif
|
||||
if (m_shouldCompress) m_writer->SetShouldCompressFunction(m_shouldCompress);
|
||||
}
|
||||
|
||||
void MultiPartArchiveWriter::CheckSize(size_t size)
|
||||
@@ -114,4 +115,10 @@ namespace OpenVulkano
|
||||
if (!m_writer || !m_writer->GetTotalWrittenBytes()) return; // Nothing has been written yet, no need to split file
|
||||
m_writer = nullptr;
|
||||
}
|
||||
|
||||
void MultiPartArchiveWriter::SetShouldCompressFunction(const std::function<bool(const FileDescription&)>& shouldComp)
|
||||
{
|
||||
if (m_writer) m_writer->SetShouldCompressFunction(shouldComp);
|
||||
m_shouldCompress = shouldComp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace OpenVulkano
|
||||
std::unique_ptr<ArchiveWriter> m_writer;
|
||||
std::shared_ptr<spdlog::logger> m_logger;
|
||||
std::vector<std::filesystem::path> m_archives;
|
||||
std::function<bool(const FileDescription&)> m_shouldCompress;
|
||||
bool m_lazyCreation;
|
||||
|
||||
void StartNewFile();
|
||||
@@ -39,6 +40,8 @@ namespace OpenVulkano
|
||||
using IArchiveWriter::AddFile;
|
||||
[[nodiscard]] virtual ArchiveOStream AddFileStream(const FileDescription& description) override;
|
||||
|
||||
void SetShouldCompressFunction(const std::function<bool(const FileDescription&)>& shouldComp) override;
|
||||
|
||||
void SetLogger(const std::shared_ptr<spdlog::logger>& logger) { m_logger = logger; }
|
||||
[[nodiscard]] std::shared_ptr<spdlog::logger> GetLogger() const { return m_logger; }
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "SimpleFileTypeShouldCompressChecker.hpp"
|
||||
#include "Base/Utils.hpp"
|
||||
#include <set>
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const std::set<std::string_view> INCOMPRESSIBLE_TYPES = {
|
||||
// Image formats
|
||||
"jpg", "jpeg", "png",
|
||||
// Video formats
|
||||
"mp4",
|
||||
// Audio formats
|
||||
"mp3", "aac", "ac3",
|
||||
// Other
|
||||
};
|
||||
}
|
||||
|
||||
bool SimpleFileTypeShouldCompressChecker(const FileDescription& fileDescription)
|
||||
{
|
||||
auto [fName, fType] = Utils::SplitAtLastOccurrence(fileDescription.path, '.');
|
||||
std::transform(fType.begin(), fType.end(), fType.begin(), ::tolower); // fType to lowercase
|
||||
return !INCOMPRESSIBLE_TYPES.count(fType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IO/FileDescription.hpp"
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
bool SimpleFileTypeShouldCompressChecker(const FileDescription& fileDescription);
|
||||
}
|
||||
Reference in New Issue
Block a user