Browse Source

AK+LibCompress: Remove the Deflate back-reference intermediate buffer

Instead of reading bytes from the output stream into a buffer, just to
immediately write them back out, we can skip the middle-man and copy the
bytes directly into the output buffer.
Timothy Flynn 2 years ago
parent
commit
8b56d82865
3 changed files with 19 additions and 3 deletions
  1. 16 0
      AK/CircularBuffer.cpp
  2. 2 0
      AK/CircularBuffer.h
  3. 1 3
      Userland/Libraries/LibCompress/Deflate.cpp

+ 16 - 0
AK/CircularBuffer.cpp

@@ -206,4 +206,20 @@ ErrorOr<size_t> CircularBuffer::fill_from_stream(Stream& stream)
     return bytes.size();
 }
 
+ErrorOr<void> CircularBuffer::copy_from_seekback(size_t distance, size_t length)
+{
+    if (distance > m_seekback_limit)
+        return Error::from_string_literal("Tried a seekback copy beyond the seekback limit");
+
+    while (length > 0) {
+        auto next_span = next_read_span_with_seekback(distance);
+        if (next_span.size() == 0)
+            break;
+
+        length -= write(next_span.trim(length));
+    }
+
+    return {};
+}
+
 }

+ 2 - 0
AK/CircularBuffer.h

@@ -33,6 +33,8 @@ public:
     /// before the current write pointer and allows for reading already-read data.
     ErrorOr<Bytes> read_with_seekback(Bytes bytes, size_t distance);
 
+    ErrorOr<void> copy_from_seekback(size_t distance, size_t length);
+
     [[nodiscard]] size_t empty_space() const;
     [[nodiscard]] size_t used_space() const;
     [[nodiscard]] size_t capacity() const;

+ 1 - 3
Userland/Libraries/LibCompress/Deflate.cpp

@@ -207,9 +207,7 @@ ErrorOr<bool> DeflateDecompressor::CompressedBlock::try_read_more()
                 m_decompressor.m_output_buffer.write({ &byte, sizeof(byte) });
             }
         } else {
-            Array<u8, DeflateDecompressor::max_back_reference_length> buffer;
-            auto bytes = TRY(m_decompressor.m_output_buffer.read_with_seekback({ buffer.data(), length }, distance));
-            m_decompressor.m_output_buffer.write(bytes);
+            TRY(m_decompressor.m_output_buffer.copy_from_seekback(distance, length));
         }
 
         return true;