From a212bc3052a00528c9c570f6be21072c02e5e1e7 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Tue, 27 Dec 2022 11:40:23 +0100 Subject: [PATCH] LibCompress: Port `GzipCompressor` to `Core::Stream` --- Tests/LibCompress/TestGzip.cpp | 2 +- Userland/Libraries/LibCompress/Gzip.cpp | 51 +++++++++++++++---------- Userland/Libraries/LibCompress/Gzip.h | 16 ++++---- Userland/Utilities/gzip.cpp | 27 ++----------- Userland/Utilities/tar.cpp | 10 ++--- 5 files changed, 50 insertions(+), 56 deletions(-) diff --git a/Tests/LibCompress/TestGzip.cpp b/Tests/LibCompress/TestGzip.cpp index 90c0acf045..2f90725aea 100644 --- a/Tests/LibCompress/TestGzip.cpp +++ b/Tests/LibCompress/TestGzip.cpp @@ -90,7 +90,7 @@ TEST_CASE(gzip_round_trip) auto original = ByteBuffer::create_uninitialized(1024).release_value(); fill_with_random(original.data(), 1024); auto compressed = Compress::GzipCompressor::compress_all(original); - EXPECT(compressed.has_value()); + EXPECT(!compressed.is_error()); auto uncompressed = Compress::GzipDecompressor::decompress_all(compressed.value()); EXPECT(!uncompressed.is_error()); EXPECT(uncompressed.value() == original); diff --git a/Userland/Libraries/LibCompress/Gzip.cpp b/Userland/Libraries/LibCompress/Gzip.cpp index 2aeccf7757..4f2426d04c 100644 --- a/Userland/Libraries/LibCompress/Gzip.cpp +++ b/Userland/Libraries/LibCompress/Gzip.cpp @@ -173,12 +173,17 @@ ErrorOr GzipDecompressor::write(ReadonlyBytes) VERIFY_NOT_REACHED(); } -GzipCompressor::GzipCompressor(OutputStream& stream) - : m_output_stream(stream) +GzipCompressor::GzipCompressor(Core::Stream::Handle stream) + : m_output_stream(move(stream)) { } -size_t GzipCompressor::write(ReadonlyBytes bytes) +ErrorOr GzipCompressor::read(Bytes) +{ + return Error::from_errno(EBADF); +} + +ErrorOr GzipCompressor::write(ReadonlyBytes bytes) { BlockHeader header; header.identification_1 = 0x1f; @@ -188,39 +193,45 @@ size_t GzipCompressor::write(ReadonlyBytes bytes) header.modification_time = 0; header.extra_flags = 3; // DEFLATE sets 2 for maximum compression and 4 for minimum compression header.operating_system = 3; // unix - m_output_stream << Bytes { &header, sizeof(header) }; - DeflateCompressor compressed_stream { m_output_stream }; - VERIFY(compressed_stream.write_or_error(bytes)); + TRY(m_output_stream->write_entire_buffer({ &header, sizeof(header) })); + Core::Stream::WrapInAKOutputStream wrapped_stream { *m_output_stream }; + DeflateCompressor compressed_stream { wrapped_stream }; + if (!compressed_stream.write_or_error(bytes)) + return Error::from_string_literal("Underlying DeflateCompressor indicated an error"); compressed_stream.final_flush(); Crypto::Checksum::CRC32 crc32; crc32.update(bytes); LittleEndian digest = crc32.digest(); LittleEndian size = bytes.size(); - m_output_stream << digest << size; + TRY(m_output_stream->write_entire_buffer(digest.bytes())); + TRY(m_output_stream->write_entire_buffer(size.bytes())); return bytes.size(); } -bool GzipCompressor::write_or_error(ReadonlyBytes bytes) +bool GzipCompressor::is_eof() const { - if (write(bytes) < bytes.size()) { - set_fatal_error(); - return false; - } - return true; } -Optional GzipCompressor::compress_all(ReadonlyBytes bytes) +bool GzipCompressor::is_open() const { - DuplexMemoryStream output_stream; - GzipCompressor gzip_stream { output_stream }; + return m_output_stream->is_open(); +} - gzip_stream.write_or_error(bytes); +void GzipCompressor::close() +{ +} - if (gzip_stream.handle_any_error()) - return {}; +ErrorOr GzipCompressor::compress_all(ReadonlyBytes bytes) +{ + auto output_stream = TRY(try_make()); + GzipCompressor gzip_stream { Core::Stream::Handle(*output_stream) }; - return output_stream.copy_into_contiguous_buffer(); + TRY(gzip_stream.write_entire_buffer(bytes)); + + auto buffer = TRY(ByteBuffer::create_uninitialized(output_stream->used_buffer_size())); + TRY(output_stream->read_entire_buffer(buffer.bytes())); + return buffer; } } diff --git a/Userland/Libraries/LibCompress/Gzip.h b/Userland/Libraries/LibCompress/Gzip.h index 74ab4a7b6a..5a038515ab 100644 --- a/Userland/Libraries/LibCompress/Gzip.h +++ b/Userland/Libraries/LibCompress/Gzip.h @@ -79,18 +79,20 @@ private: bool m_eof { false }; }; -class GzipCompressor final : public OutputStream { +class GzipCompressor final : public Core::Stream::Stream { public: - GzipCompressor(OutputStream&); - ~GzipCompressor() = default; + GzipCompressor(Core::Stream::Handle); - size_t write(ReadonlyBytes) override; - bool write_or_error(ReadonlyBytes) override; + virtual ErrorOr read(Bytes) override; + virtual ErrorOr write(ReadonlyBytes) override; + virtual bool is_eof() const override; + virtual bool is_open() const override; + virtual void close() override; - static Optional compress_all(ReadonlyBytes bytes); + static ErrorOr compress_all(ReadonlyBytes bytes); private: - OutputStream& m_output_stream; + Core::Stream::Handle m_output_stream; }; } diff --git a/Userland/Utilities/gzip.cpp b/Userland/Utilities/gzip.cpp index 991ff21674..4271aa4f28 100644 --- a/Userland/Utilities/gzip.cpp +++ b/Userland/Utilities/gzip.cpp @@ -50,33 +50,14 @@ ErrorOr serenity_main(Main::Arguments arguments) input_bytes = file->bytes(); } - AK::Optional output_bytes; + ByteBuffer output_bytes; if (decompress) output_bytes = TRY(Compress::GzipDecompressor::decompress_all(input_bytes)); else - output_bytes = Compress::GzipCompressor::compress_all(input_bytes); + output_bytes = TRY(Compress::GzipCompressor::compress_all(input_bytes)); - if (!output_bytes.has_value()) { - warnln("Failed gzip {} input file", decompress ? "decompressing"sv : "compressing"sv); - return 1; - } - - auto success = false; - if (write_to_stdout) { - auto stdout = Core::OutputFileStream { Core::File::standard_output() }; - success = stdout.write_or_error(output_bytes.value()); - } else { - auto output_stream_result = Core::OutputFileStream::open(output_filename); - if (output_stream_result.is_error()) { - warnln("Failed opening output file for writing: {}", output_stream_result.error()); - return 1; - } - success = output_stream_result.value().write_or_error(output_bytes.value()); - } - if (!success) { - warnln("Failed writing to output"); - return 1; - } + auto output_stream = write_to_stdout ? TRY(Core::Stream::File::standard_output()) : TRY(Core::Stream::File::open(output_filename, Core::Stream::OpenMode::Write)); + TRY(output_stream->write_entire_buffer(output_bytes)); if (!keep_input_files) { TRY(Core::System::unlink(input_filename)); diff --git a/Userland/Utilities/tar.cpp b/Userland/Utilities/tar.cpp index 55355d07e9..58b3a50726 100644 --- a/Userland/Utilities/tar.cpp +++ b/Userland/Utilities/tar.cpp @@ -207,18 +207,18 @@ ErrorOr serenity_main(Main::Arguments arguments) return 1; } - auto file = Core::File::standard_output(); + NonnullOwnPtr output_stream = TRY(Core::Stream::File::standard_output()); if (!archive_file.is_empty()) - file = TRY(Core::File::open(archive_file, Core::OpenMode::WriteOnly)); + output_stream = TRY(Core::Stream::File::open(archive_file, Core::Stream::OpenMode::Write)); if (!directory.is_empty()) TRY(Core::System::chdir(directory)); - NonnullOwnPtr file_output_stream = make(file); - NonnullOwnPtr gzip_output_stream = make(*file_output_stream); + if (gzip) + output_stream = TRY(try_make(move(output_stream))); - Archive::TarOutputStream tar_stream(make(move((gzip) ? gzip_output_stream : file_output_stream))); + Archive::TarOutputStream tar_stream(move(output_stream)); auto add_file = [&](DeprecatedString path) -> ErrorOr { auto file = Core::File::construct(path);