mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-26 04:35:41 +03:00
LibArchive: Extract logic for calculating ZIP statistics
This commit is contained in:
parent
60e35f2a97
commit
8d53442187
Notes:
sideshowbarker
2024-07-17 05:00:08 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/8d53442187 Pull-request: https://github.com/SerenityOS/serenity/pull/20206 Reviewed-by: https://github.com/LucasChollet Reviewed-by: https://github.com/trflynn89 Reviewed-by: https://github.com/vkoskiv
33
Userland/Libraries/LibArchive/Statistics.h
Normal file
33
Userland/Libraries/LibArchive/Statistics.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Types.h>
|
||||||
|
|
||||||
|
namespace Archive {
|
||||||
|
|
||||||
|
class Statistics {
|
||||||
|
public:
|
||||||
|
Statistics(size_t file_count, size_t directory_count, size_t total_uncompressed_bytes)
|
||||||
|
: m_file_count(file_count)
|
||||||
|
, m_directory_count(directory_count)
|
||||||
|
, m_total_uncompressed_bytes(total_uncompressed_bytes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t file_count() const { return m_file_count; }
|
||||||
|
size_t directory_count() const { return m_directory_count; }
|
||||||
|
size_t member_count() const { return file_count() + directory_count(); }
|
||||||
|
size_t total_uncompressed_bytes() const { return m_total_uncompressed_bytes; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_file_count { 0 };
|
||||||
|
size_t m_directory_count { 0 };
|
||||||
|
size_t m_total_uncompressed_bytes { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -77,7 +77,7 @@ Optional<Zip> Zip::try_create(ReadonlyBytes buffer)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<bool> Zip::for_each_member(Function<ErrorOr<IterationDecision>(ZipMember const&)> callback)
|
ErrorOr<bool> Zip::for_each_member(Function<ErrorOr<IterationDecision>(ZipMember const&)> callback) const
|
||||||
{
|
{
|
||||||
size_t member_offset = m_members_start_offset;
|
size_t member_offset = m_members_start_offset;
|
||||||
for (size_t i = 0; i < m_member_count; i++) {
|
for (size_t i = 0; i < m_member_count; i++) {
|
||||||
@ -104,6 +104,24 @@ ErrorOr<bool> Zip::for_each_member(Function<ErrorOr<IterationDecision>(ZipMember
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<Statistics> Zip::calculate_statistics() const
|
||||||
|
{
|
||||||
|
size_t file_count = 0;
|
||||||
|
size_t directory_count = 0;
|
||||||
|
size_t uncompressed_bytes = 0;
|
||||||
|
|
||||||
|
TRY(for_each_member([&](auto zip_member) -> ErrorOr<IterationDecision> {
|
||||||
|
if (zip_member.is_directory)
|
||||||
|
directory_count++;
|
||||||
|
else
|
||||||
|
file_count++;
|
||||||
|
uncompressed_bytes += zip_member.uncompressed_size;
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return Statistics(file_count, directory_count, uncompressed_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
ZipOutputStream::ZipOutputStream(NonnullOwnPtr<Stream> stream)
|
ZipOutputStream::ZipOutputStream(NonnullOwnPtr<Stream> stream)
|
||||||
: m_stream(move(stream))
|
: m_stream(move(stream))
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <AK/Stream.h>
|
#include <AK/Stream.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
#include <LibArchive/Statistics.h>
|
||||||
#include <LibCore/DateTime.h>
|
#include <LibCore/DateTime.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -254,7 +255,8 @@ struct ZipMember {
|
|||||||
class Zip {
|
class Zip {
|
||||||
public:
|
public:
|
||||||
static Optional<Zip> try_create(ReadonlyBytes buffer);
|
static Optional<Zip> try_create(ReadonlyBytes buffer);
|
||||||
ErrorOr<bool> for_each_member(Function<ErrorOr<IterationDecision>(ZipMember const&)>);
|
ErrorOr<bool> for_each_member(Function<ErrorOr<IterationDecision>(ZipMember const&)>) const;
|
||||||
|
ErrorOr<Statistics> calculate_statistics() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool find_end_of_central_directory_offset(ReadonlyBytes, size_t& offset);
|
static bool find_end_of_central_directory_offset(ReadonlyBytes, size_t& offset);
|
||||||
|
@ -110,24 +110,14 @@ static ErrorOr<Optional<String>> zip_details(StringView description, StringView
|
|||||||
{
|
{
|
||||||
auto mapped_file = TRY(Core::MappedFile::map(path));
|
auto mapped_file = TRY(Core::MappedFile::map(path));
|
||||||
auto zip_file = Archive::Zip::try_create(mapped_file->bytes());
|
auto zip_file = Archive::Zip::try_create(mapped_file->bytes());
|
||||||
u32 files = 0;
|
auto statistics = TRY(zip_file->calculate_statistics());
|
||||||
u32 directories = 0;
|
|
||||||
u64 total_bytes = 0;
|
|
||||||
TRY(zip_file->for_each_member([&](auto zip_member) -> ErrorOr<IterationDecision> {
|
|
||||||
if (zip_member.is_directory)
|
|
||||||
directories++;
|
|
||||||
else
|
|
||||||
files++;
|
|
||||||
total_bytes += zip_member.uncompressed_size;
|
|
||||||
return IterationDecision::Continue;
|
|
||||||
}));
|
|
||||||
return TRY(String::formatted("{}, {} {}, {} {} totaling {} uncompressed",
|
return TRY(String::formatted("{}, {} {}, {} {} totaling {} uncompressed",
|
||||||
description,
|
description,
|
||||||
directories,
|
statistics.directory_count(),
|
||||||
directories == 1 ? "directory" : "directories",
|
statistics.directory_count() == 1 ? "directory" : "directories",
|
||||||
files,
|
statistics.file_count(),
|
||||||
files == 1 ? "file" : "files",
|
statistics.file_count() == 1 ? "file" : "files",
|
||||||
AK::human_readable_size(total_bytes)));
|
AK::human_readable_size(statistics.total_uncompressed_bytes())));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ErrorOr<Optional<String>> elf_details(StringView description, StringView path)
|
static ErrorOr<Optional<String>> elf_details(StringView description, StringView path)
|
||||||
|
@ -146,22 +146,17 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||||||
if (list_files) {
|
if (list_files) {
|
||||||
outln(" Length Date Time Name");
|
outln(" Length Date Time Name");
|
||||||
outln("--------- ---------- -------- ----");
|
outln("--------- ---------- -------- ----");
|
||||||
u32 members_count = 0;
|
|
||||||
u64 total_size = 0;
|
|
||||||
TRY(zip_file->for_each_member([&](auto zip_member) -> ErrorOr<IterationDecision> {
|
TRY(zip_file->for_each_member([&](auto zip_member) -> ErrorOr<IterationDecision> {
|
||||||
members_count++;
|
|
||||||
|
|
||||||
auto time = time_from_packed_dos(zip_member.modification_date, zip_member.modification_time);
|
auto time = time_from_packed_dos(zip_member.modification_date, zip_member.modification_time);
|
||||||
auto time_str = TRY(Core::DateTime::from_timestamp(time.seconds_since_epoch()).to_string());
|
auto time_str = TRY(Core::DateTime::from_timestamp(time.seconds_since_epoch()).to_string());
|
||||||
|
|
||||||
total_size += zip_member.uncompressed_size;
|
|
||||||
|
|
||||||
outln("{:>9} {} {}", zip_member.uncompressed_size, time_str, zip_member.name);
|
outln("{:>9} {} {}", zip_member.uncompressed_size, time_str, zip_member.name);
|
||||||
|
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
}));
|
}));
|
||||||
|
auto statistics = TRY(zip_file->calculate_statistics());
|
||||||
outln("--------- ----");
|
outln("--------- ----");
|
||||||
outln("{:>9} {} files", total_size, members_count);
|
outln("{:>9} {} files", statistics.total_uncompressed_bytes(), statistics.member_count());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user