Brotli.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (c) 2022, Michiel Visser <opensource@webmichiel.nl>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/BitStream.h>
  8. #include <AK/CircularQueue.h>
  9. #include <AK/FixedArray.h>
  10. #include <AK/Vector.h>
  11. namespace Compress {
  12. class BrotliDecompressionStream : public Stream {
  13. public:
  14. enum class State {
  15. WindowSize,
  16. Idle,
  17. UncompressedData,
  18. CompressedCommand,
  19. CompressedLiteral,
  20. CompressedDistance,
  21. CompressedCopy,
  22. CompressedDictionary,
  23. };
  24. class CanonicalCode {
  25. friend class BrotliDecompressionStream;
  26. public:
  27. CanonicalCode() = default;
  28. ErrorOr<size_t> read_symbol(LittleEndianInputBitStream&);
  29. void clear()
  30. {
  31. m_symbol_codes.clear();
  32. m_symbol_values.clear();
  33. }
  34. private:
  35. Vector<size_t> m_symbol_codes;
  36. Vector<size_t> m_symbol_values;
  37. };
  38. struct Block {
  39. size_t type;
  40. size_t type_previous;
  41. size_t number_of_types;
  42. size_t length;
  43. CanonicalCode type_code;
  44. CanonicalCode length_code;
  45. };
  46. class LookbackBuffer {
  47. private:
  48. LookbackBuffer(FixedArray<u8>& buffer)
  49. : m_buffer(move(buffer))
  50. {
  51. }
  52. public:
  53. static ErrorOr<LookbackBuffer> try_create(size_t size)
  54. {
  55. auto buffer = TRY(FixedArray<u8>::create(size));
  56. return LookbackBuffer { buffer };
  57. }
  58. void write(u8 value)
  59. {
  60. m_buffer[m_offset] = value;
  61. m_offset = (m_offset + 1) % m_buffer.size();
  62. m_total_written++;
  63. }
  64. u8 lookback(size_t offset) const
  65. {
  66. VERIFY(offset <= m_total_written);
  67. VERIFY(offset <= m_buffer.size());
  68. size_t index = (m_offset + m_buffer.size() - offset) % m_buffer.size();
  69. return m_buffer[index];
  70. }
  71. u8 lookback(size_t offset, u8 fallback) const
  72. {
  73. if (offset > m_total_written || offset > m_buffer.size())
  74. return fallback;
  75. VERIFY(offset <= m_total_written);
  76. VERIFY(offset <= m_buffer.size());
  77. size_t index = (m_offset + m_buffer.size() - offset) % m_buffer.size();
  78. return m_buffer[index];
  79. }
  80. size_t total_written() { return m_total_written; }
  81. private:
  82. FixedArray<u8> m_buffer;
  83. size_t m_offset { 0 };
  84. size_t m_total_written { 0 };
  85. };
  86. public:
  87. BrotliDecompressionStream(Stream&);
  88. ErrorOr<Bytes> read_some(Bytes output_buffer) override;
  89. ErrorOr<size_t> write_some(ReadonlyBytes bytes) override { return m_input_stream.write_some(bytes); }
  90. bool is_eof() const override;
  91. bool is_open() const override { return m_input_stream.is_open(); }
  92. void close() override { m_input_stream.close(); }
  93. private:
  94. ErrorOr<size_t> read_window_length();
  95. ErrorOr<size_t> read_size_number_of_nibbles();
  96. ErrorOr<size_t> read_variable_length();
  97. ErrorOr<size_t> read_complex_prefix_code_length();
  98. ErrorOr<void> read_prefix_code(CanonicalCode&, size_t alphabet_size);
  99. ErrorOr<void> read_simple_prefix_code(CanonicalCode&, size_t alphabet_size);
  100. ErrorOr<void> read_complex_prefix_code(CanonicalCode&, size_t alphabet_size, size_t hskip);
  101. ErrorOr<void> read_context_map(size_t number_of_codes, Vector<u8>& context_map, size_t context_map_size);
  102. ErrorOr<void> read_block_configuration(Block&);
  103. ErrorOr<void> block_update_length(Block&);
  104. ErrorOr<void> block_read_new_state(Block&);
  105. size_t literal_code_index_from_context();
  106. LittleEndianInputBitStream m_input_stream;
  107. State m_current_state { State::WindowSize };
  108. Optional<LookbackBuffer> m_lookback_buffer;
  109. size_t m_window_size { 0 };
  110. bool m_read_final_block { false };
  111. size_t m_postfix_bits { 0 };
  112. size_t m_direct_distances { 0 };
  113. size_t m_distances[4] { 4, 11, 15, 16 };
  114. size_t m_bytes_left { 0 };
  115. size_t m_insert_length { 0 };
  116. size_t m_copy_length { 0 };
  117. bool m_implicit_zero_distance { false };
  118. size_t m_distance { 0 };
  119. ByteBuffer m_dictionary_data;
  120. Block m_literal_block;
  121. Vector<u8> m_literal_context_modes;
  122. Block m_insert_and_copy_block;
  123. Block m_distance_block;
  124. Vector<u8> m_context_mapping_literal;
  125. Vector<u8> m_context_mapping_distance;
  126. Vector<CanonicalCode> m_literal_codes;
  127. Vector<CanonicalCode> m_insert_and_copy_codes;
  128. Vector<CanonicalCode> m_distance_codes;
  129. };
  130. }