LibArchive: Add helper functions for adding members to a ZipOutputStream
This commit is contained in:
parent
2f85faef0f
commit
b5124bd826
Notes:
sideshowbarker
2024-07-17 06:39:26 +09:00
Author: https://github.com/caoimhebyrne Commit: https://github.com/SerenityOS/serenity/commit/b5124bd826 Pull-request: https://github.com/SerenityOS/serenity/pull/19229 Reviewed-by: https://github.com/gmta Reviewed-by: https://github.com/linusg ✅
3 changed files with 71 additions and 1 deletions
|
@ -5,4 +5,4 @@ set(SOURCES
|
|||
)
|
||||
|
||||
serenity_lib(LibArchive archive)
|
||||
target_link_libraries(LibArchive PRIVATE LibCore)
|
||||
target_link_libraries(LibArchive PRIVATE LibCompress LibCore LibCrypto)
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
|
||||
#include <LibArchive/Zip.h>
|
||||
#include <LibCompress/Deflate.h>
|
||||
#include <LibCrypto/Checksum/CRC32.h>
|
||||
|
||||
namespace Archive {
|
||||
|
||||
|
@ -138,6 +140,62 @@ ErrorOr<void> ZipOutputStream::add_member(ZipMember const& member)
|
|||
return local_file_header.write(*m_stream);
|
||||
}
|
||||
|
||||
ErrorOr<ZipOutputStream::MemberInformation> ZipOutputStream::add_member_from_stream(StringView path, Stream& stream, Optional<Core::DateTime> const& modification_time)
|
||||
{
|
||||
auto buffer = TRY(stream.read_until_eof());
|
||||
|
||||
Archive::ZipMember member {};
|
||||
member.name = TRY(String::from_utf8(path));
|
||||
|
||||
if (modification_time.has_value()) {
|
||||
member.modification_date = to_packed_dos_date(modification_time->year(), modification_time->month(), modification_time->day());
|
||||
member.modification_time = to_packed_dos_time(modification_time->hour(), modification_time->minute(), modification_time->second());
|
||||
}
|
||||
|
||||
auto deflate_buffer = Compress::DeflateCompressor::compress_all(buffer);
|
||||
auto compression_ratio = 1.f;
|
||||
auto compressed_size = buffer.size();
|
||||
|
||||
if (!deflate_buffer.is_error() && deflate_buffer.value().size() < buffer.size()) {
|
||||
member.compressed_data = deflate_buffer.value().bytes();
|
||||
member.compression_method = Archive::ZipCompressionMethod::Deflate;
|
||||
|
||||
compression_ratio = static_cast<float>(deflate_buffer.value().size()) / static_cast<float>(buffer.size());
|
||||
compressed_size = member.compressed_data.size();
|
||||
} else {
|
||||
member.compressed_data = buffer.bytes();
|
||||
member.compression_method = Archive::ZipCompressionMethod::Store;
|
||||
}
|
||||
|
||||
member.uncompressed_size = buffer.size();
|
||||
|
||||
Crypto::Checksum::CRC32 checksum { buffer.bytes() };
|
||||
member.crc32 = checksum.digest();
|
||||
member.is_directory = false;
|
||||
|
||||
TRY(add_member(member));
|
||||
|
||||
return MemberInformation { compression_ratio, compressed_size };
|
||||
}
|
||||
|
||||
ErrorOr<void> ZipOutputStream::add_directory(StringView name, Optional<Core::DateTime> const& modification_time)
|
||||
{
|
||||
Archive::ZipMember member {};
|
||||
member.name = TRY(String::from_utf8(name));
|
||||
member.compressed_data = {};
|
||||
member.compression_method = Archive::ZipCompressionMethod::Store;
|
||||
member.uncompressed_size = 0;
|
||||
member.crc32 = 0;
|
||||
member.is_directory = true;
|
||||
|
||||
if (modification_time.has_value()) {
|
||||
member.modification_date = to_packed_dos_date(modification_time->year(), modification_time->month(), modification_time->day());
|
||||
member.modification_time = to_packed_dos_time(modification_time->hour(), modification_time->minute(), modification_time->second());
|
||||
}
|
||||
|
||||
return add_member(member);
|
||||
}
|
||||
|
||||
ErrorOr<void> ZipOutputStream::finish()
|
||||
{
|
||||
VERIFY(!m_finished);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <AK/Stream.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibCore/DateTime.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Archive {
|
||||
|
@ -271,9 +272,20 @@ private:
|
|||
|
||||
class ZipOutputStream {
|
||||
public:
|
||||
struct MemberInformation {
|
||||
float compression_ratio;
|
||||
size_t compressed_size;
|
||||
};
|
||||
|
||||
ZipOutputStream(NonnullOwnPtr<Stream>);
|
||||
|
||||
ErrorOr<void> add_member(ZipMember const&);
|
||||
ErrorOr<MemberInformation> add_member_from_stream(StringView, Stream&, Optional<Core::DateTime> const& = {});
|
||||
|
||||
// NOTE: This does not add any of the files within the directory,
|
||||
// it just adds an entry for it.
|
||||
ErrorOr<void> add_directory(StringView, Optional<Core::DateTime> const& = {});
|
||||
|
||||
ErrorOr<void> finish();
|
||||
|
||||
private:
|
||||
|
|
Loading…
Add table
Reference in a new issue