Gzip.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <LibCompress/Deflate.h>
  9. #include <LibCrypto/Checksum/CRC32.h>
  10. namespace Compress {
  11. constexpr u8 gzip_magic_1 = 0x1f;
  12. constexpr u8 gzip_magic_2 = 0x8b;
  13. struct [[gnu::packed]] BlockHeader {
  14. u8 identification_1;
  15. u8 identification_2;
  16. u8 compression_method;
  17. u8 flags;
  18. LittleEndian<u32> modification_time;
  19. u8 extra_flags;
  20. u8 operating_system;
  21. bool valid_magic_number() const;
  22. bool supported_by_implementation() const;
  23. };
  24. struct Flags {
  25. static constexpr u8 FTEXT = 1 << 0;
  26. static constexpr u8 FHCRC = 1 << 1;
  27. static constexpr u8 FEXTRA = 1 << 2;
  28. static constexpr u8 FNAME = 1 << 3;
  29. static constexpr u8 FCOMMENT = 1 << 4;
  30. static constexpr u8 MAX = FTEXT | FHCRC | FEXTRA | FNAME | FCOMMENT;
  31. };
  32. class GzipDecompressor final : public InputStream {
  33. public:
  34. GzipDecompressor(InputStream&);
  35. ~GzipDecompressor();
  36. size_t read(Bytes) override;
  37. bool read_or_error(Bytes) override;
  38. bool discard_or_error(size_t) override;
  39. bool unreliable_eof() const override;
  40. bool handle_any_error() override;
  41. static Optional<ByteBuffer> decompress_all(ReadonlyBytes);
  42. static Optional<String> describe_header(ReadonlyBytes);
  43. static bool is_likely_compressed(ReadonlyBytes bytes);
  44. private:
  45. class Member {
  46. public:
  47. Member(BlockHeader header, InputStream& stream)
  48. : m_header(header)
  49. , m_stream(stream)
  50. {
  51. }
  52. BlockHeader m_header;
  53. DeflateDecompressor m_stream;
  54. Crypto::Checksum::CRC32 m_checksum;
  55. size_t m_nread { 0 };
  56. };
  57. const Member& current_member() const { return m_current_member.value(); }
  58. Member& current_member() { return m_current_member.value(); }
  59. InputStream& m_input_stream;
  60. u8 m_partial_header[sizeof(BlockHeader)];
  61. size_t m_partial_header_offset { 0 };
  62. Optional<Member> m_current_member;
  63. bool m_eof { false };
  64. };
  65. class GzipCompressor final : public OutputStream {
  66. public:
  67. GzipCompressor(OutputStream&);
  68. ~GzipCompressor();
  69. size_t write(ReadonlyBytes) override;
  70. bool write_or_error(ReadonlyBytes) override;
  71. static Optional<ByteBuffer> compress_all(const ReadonlyBytes& bytes);
  72. private:
  73. OutputStream& m_output_stream;
  74. };
  75. }