summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xMeta/check-newlines-at-eof.py2
-rwxr-xr-xMeta/check-style.sh2
-rwxr-xr-xMeta/lint-clang-format.sh2
-rw-r--r--Userland/Libraries/LibCompress/Gzip.cpp17
-rw-r--r--Userland/Libraries/LibCompress/Gzip.h4
-rw-r--r--Userland/Libraries/LibCore/CMakeLists.txt2
-rw-r--r--Userland/Libraries/LibCore/Gzip.cpp160
-rw-r--r--Userland/Libraries/LibCore/Gzip.h41
-rw-r--r--Userland/Libraries/LibCore/puff.cpp832
-rw-r--r--Userland/Libraries/LibCore/puff.h44
-rw-r--r--Userland/Libraries/LibGfx/CMakeLists.txt2
-rw-r--r--Userland/Libraries/LibGfx/PNGLoader.cpp33
-rw-r--r--Userland/Libraries/LibHTTP/CMakeLists.txt2
-rw-r--r--Userland/Libraries/LibHTTP/HttpJob.cpp1
-rw-r--r--Userland/Libraries/LibHTTP/HttpsJob.cpp1
-rw-r--r--Userland/Libraries/LibHTTP/Job.cpp7
16 files changed, 31 insertions, 1121 deletions
diff --git a/Meta/check-newlines-at-eof.py b/Meta/check-newlines-at-eof.py
index 052813b657..57ff5f9517 100755
--- a/Meta/check-newlines-at-eof.py
+++ b/Meta/check-newlines-at-eof.py
@@ -22,8 +22,6 @@ files = subprocess.run(
":!:Base",
":!:Kernel/FileSystem/ext2_fs.h",
":!:Userland/Libraries/LibC/getopt.cpp",
- ":!:Userland/Libraries/LibCore/puff.h",
- ":!:Userland/Libraries/LibCore/puff.cpp",
":!:Userland/Libraries/LibELF/exec_elf.h"
],
capture_output=True
diff --git a/Meta/check-style.sh b/Meta/check-style.sh
index b0d1310aeb..c127385493 100755
--- a/Meta/check-style.sh
+++ b/Meta/check-style.sh
@@ -42,8 +42,6 @@ done < <(git ls-files -- \
':!:Base' \
':!:Kernel/FileSystem/ext2_fs.h' \
':!:Userland/Libraries/LibC/getopt.cpp' \
- ':!:Userland/Libraries/LibCore/puff.h' \
- ':!:Userland/Libraries/LibCore/puff.cpp' \
':!:Userland/Libraries/LibELF/exec_elf.h' \
)
diff --git a/Meta/lint-clang-format.sh b/Meta/lint-clang-format.sh
index 0aa4c90d6e..42e5a4d0be 100755
--- a/Meta/lint-clang-format.sh
+++ b/Meta/lint-clang-format.sh
@@ -14,8 +14,6 @@ if [ "$#" -eq "1" ]; then
':!:Kernel/FileSystem/ext2_fs.h' \
':!:Userland/Libraries/LibC/getopt.cpp' \
':!:Userland/Libraries/LibC/syslog.h' \
- ':!:Userland/Libraries/LibCore/puff.h' \
- ':!:Userland/Libraries/LibCore/puff.cpp' \
':!:Userland/Libraries/LibELF/exec_elf.h'
)
else
diff --git a/Userland/Libraries/LibCompress/Gzip.cpp b/Userland/Libraries/LibCompress/Gzip.cpp
index cbedc5843b..edebdcb0d4 100644
--- a/Userland/Libraries/LibCompress/Gzip.cpp
+++ b/Userland/Libraries/LibCompress/Gzip.cpp
@@ -31,9 +31,14 @@
namespace Compress {
+bool GzipDecompressor::is_likely_compressed(ReadonlyBytes bytes)
+{
+ return bytes.size() >= 2 && bytes[0] == gzip_magic_1 && bytes[1] == gzip_magic_2;
+}
+
bool GzipDecompressor::BlockHeader::valid_magic_number() const
{
- return identification_1 == 0x1f && identification_2 == 0x8b;
+ return identification_1 == gzip_magic_1 && identification_2 == gzip_magic_2;
}
bool GzipDecompressor::BlockHeader::supported_by_implementation() const
@@ -48,10 +53,6 @@ bool GzipDecompressor::BlockHeader::supported_by_implementation() const
return false;
}
- if (flags & Flags::FHCRC) {
- TODO();
- }
-
return true;
}
@@ -128,6 +129,12 @@ size_t GzipDecompressor::read(Bytes bytes)
m_input_stream >> comment;
}
+ if (header.flags & Flags::FHCRC) {
+ LittleEndian<u16> crc16;
+ m_input_stream >> crc16;
+ // FIXME: we should probably verify this instead of just assuming it matches
+ }
+
m_current_member.emplace(header, m_input_stream);
return read(bytes);
}
diff --git a/Userland/Libraries/LibCompress/Gzip.h b/Userland/Libraries/LibCompress/Gzip.h
index fc8b92f38f..191cd6f905 100644
--- a/Userland/Libraries/LibCompress/Gzip.h
+++ b/Userland/Libraries/LibCompress/Gzip.h
@@ -31,6 +31,9 @@
namespace Compress {
+constexpr u8 gzip_magic_1 = 0x1f;
+constexpr u8 gzip_magic_2 = 0x8b;
+
class GzipDecompressor final : public InputStream {
public:
GzipDecompressor(InputStream&);
@@ -43,6 +46,7 @@ public:
bool unreliable_eof() const override;
static Optional<ByteBuffer> decompress_all(ReadonlyBytes);
+ static bool is_likely_compressed(ReadonlyBytes bytes);
private:
struct [[gnu::packed]] BlockHeader {
diff --git a/Userland/Libraries/LibCore/CMakeLists.txt b/Userland/Libraries/LibCore/CMakeLists.txt
index 2705753b34..63593e1352 100644
--- a/Userland/Libraries/LibCore/CMakeLists.txt
+++ b/Userland/Libraries/LibCore/CMakeLists.txt
@@ -12,7 +12,6 @@ set(SOURCES
FileWatcher.cpp
File.cpp
GetPassword.cpp
- Gzip.cpp
IODevice.cpp
LocalServer.cpp
LocalSocket.cpp
@@ -23,7 +22,6 @@ set(SOURCES
Object.cpp
ProcessStatisticsReader.cpp
Property.cpp
- puff.cpp
SocketAddress.cpp
Socket.cpp
StandardPaths.cpp
diff --git a/Userland/Libraries/LibCore/Gzip.cpp b/Userland/Libraries/LibCore/Gzip.cpp
deleted file mode 100644
index 4dcdbe39f1..0000000000
--- a/Userland/Libraries/LibCore/Gzip.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <AK/ByteBuffer.h>
-#include <AK/Debug.h>
-#include <AK/Optional.h>
-#include <LibCore/Gzip.h>
-#include <LibCore/puff.h>
-#include <limits.h>
-#include <stddef.h>
-
-namespace Core {
-
-bool Gzip::is_compressed(const ByteBuffer& data)
-{
- return data.size() > 2 && data[0] == 0x1F && data[1] == 0x8b;
-}
-
-// skips the gzip header
-// see: https://tools.ietf.org/html/rfc1952#page-5
-static Optional<ByteBuffer> get_gzip_payload(const ByteBuffer& data)
-{
- size_t current = 0;
- auto read_byte = [&]() {
- if (current >= data.size()) {
- VERIFY_NOT_REACHED();
- return (u8)0;
- }
- return data[current++];
- };
-
-#if GZIP_DEBUG
- dbgln("get_gzip_payload: Skipping over gzip header.");
-#endif
-
- // Magic Header
- if (read_byte() != 0x1F || read_byte() != 0x8B) {
- dbgln("get_gzip_payload: Wrong magic number.");
- return Optional<ByteBuffer>();
- }
-
- // Compression method
- auto method = read_byte();
- if (method != 8) {
- dbgln("get_gzip_payload: Wrong compression method={}", method);
- return Optional<ByteBuffer>();
- }
-
- u8 flags = read_byte();
-
- // Timestamp, Extra flags, OS
- current += 6;
-
- // FEXTRA
- if (flags & 4) {
- u16 length = read_byte() & read_byte() << 8;
- dbgln("get_gzip_payload: Header has FEXTRA flag set. length={}", length);
- current += length;
- }
-
- // FNAME
- if (flags & 8) {
- dbgln("get_gzip_payload: Header has FNAME flag set.");
- while (read_byte() != '\0')
- ;
- }
-
- // FCOMMENT
- if (flags & 16) {
- dbgln("get_gzip_payload: Header has FCOMMENT flag set.");
- while (read_byte() != '\0')
- ;
- }
-
- // FHCRC
- if (flags & 2) {
- dbgln("get_gzip_payload: Header has FHCRC flag set.");
- current += 2;
- }
-
- auto new_size = data.size() - current;
- dbgln_if(GZIP_DEBUG, "get_gzip_payload: Returning slice from {} with size {}", current, new_size);
- return data.slice(current, new_size);
-}
-
-Optional<ByteBuffer> Gzip::decompress(const ByteBuffer& data)
-{
- VERIFY(is_compressed(data));
-
- dbgln_if(GZIP_DEBUG, "Gzip::decompress: Decompressing gzip compressed data. size={}", data.size());
- auto optional_payload = get_gzip_payload(data);
- if (!optional_payload.has_value()) {
- return Optional<ByteBuffer>();
- }
-
- auto source = optional_payload.value();
- unsigned long source_len = source.size();
- auto destination = ByteBuffer::create_uninitialized(1024);
- while (true) {
- unsigned long destination_len = destination.size();
-
- if constexpr (GZIP_DEBUG) {
- dbgln("Gzip::decompress: Calling puff()");
- dbgln(" destination_data = {}", destination.data());
- dbgln(" destination_len = {}", destination_len);
- dbgln(" source_data = {}", source.data());
- dbgln(" source_len = {}", source_len);
- }
-
- auto puff_ret = puff(
- destination.data(), &destination_len,
- source.data(), &source_len);
-
- if (puff_ret == 0) {
-#if GZIP_DEBUG
- dbgln("Gzip::decompress: Decompression success.");
-#endif
- destination.trim(destination_len);
- break;
- }
-
- if (puff_ret == 1) {
- // FIXME: Find a better way of decompressing without needing to try over and over again.
-#if GZIP_DEBUG
- dbgln("Gzip::decompress: Output buffer exhausted. Growing.");
-#endif
- destination.grow(destination.size() * 2);
- } else {
- dbgln("Gzip::decompress: Error. puff() returned: {}", puff_ret);
- VERIFY_NOT_REACHED();
- }
- }
-
- return destination;
-}
-
-}
diff --git a/Userland/Libraries/LibCore/Gzip.h b/Userland/Libraries/LibCore/Gzip.h
deleted file mode 100644
index a96af59536..0000000000
--- a/Userland/Libraries/LibCore/Gzip.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <AK/ByteBuffer.h>
-#include <AK/Optional.h>
-#include <AK/String.h>
-
-namespace Core {
-
-class Gzip {
-public:
- static bool is_compressed(const ByteBuffer& data);
- static Optional<ByteBuffer> decompress(const ByteBuffer& data);
-};
-
-}
diff --git a/Userland/Libraries/LibCore/puff.cpp b/Userland/Libraries/LibCore/puff.cpp
deleted file mode 100644
index b17f26a00e..0000000000
--- a/Userland/Libraries/LibCore/puff.cpp
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- * puff.c
- * Copyright (C) 2002-2013 Mark Adler
- * For conditions of distribution and use, see copyright notice in puff.h
- * version 2.3, 21 Jan 2013
- *
- * puff.c is a simple inflate written to be an unambiguous way to specify the
- * deflate format. It is not written for speed but rather simplicity. As a
- * side benefit, this code might actually be useful when small code is more
- * important than speed, such as bootstrap applications. For typical deflate
- * data, zlib's inflate() is about four times as fast as puff(). zlib's
- * inflate compiles to around 20K on my machine, whereas puff.c compiles to
- * around 4K on my machine (a PowerPC using GNU cc). If the faster decode()
- * function here is used, then puff() is only twice as slow as zlib's
- * inflate().
- *
- * All dynamically allocated memory comes from the stack. The stack required
- * is less than 2K bytes. This code is compatible with 16-bit int's and
- * assumes that long's are at least 32 bits. puff.c uses the short data type,
- * assumed to be 16 bits, for arrays in order to conserve memory. The code
- * works whether integers are stored big endian or little endian.
- *
- * In the comments below are "Format notes" that describe the inflate process
- * and document some of the less obvious aspects of the format. This source
- * code is meant to supplement RFC 1951, which formally describes the deflate
- * format:
- *
- * http://www.zlib.org/rfc-deflate.html
- */
-
-/*
- * Change history:
- *
- * 1.0 10 Feb 2002 - First version
- * 1.1 17 Feb 2002 - Clarifications of some comments and notes
- * - Update puff() dest and source pointers on negative
- * errors to facilitate debugging deflators
- * - Remove longest from struct huffman -- not needed
- * - Simplify offs[] index in construct()
- * - Add input size and checking, using longjmp() to
- * maintain easy readability
- * - Use short data type for large arrays
- * - Use pointers instead of long to specify source and
- * destination sizes to avoid arbitrary 4 GB limits
- * 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!),
- * but leave simple version for readabilty
- * - Make sure invalid distances detected if pointers
- * are 16 bits
- * - Fix fixed codes table error
- * - Provide a scanning mode for determining size of
- * uncompressed data
- * 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Gailly]
- * - Add a puff.h file for the interface
- * - Add braces in puff() for else do [Gailly]
- * - Use indexes instead of pointers for readability
- * 1.4 31 Mar 2002 - Simplify construct() code set check
- * - Fix some comments
- * - Add FIXLCODES #define
- * 1.5 6 Apr 2002 - Minor comment fixes
- * 1.6 7 Aug 2002 - Minor format changes
- * 1.7 3 Mar 2003 - Added test code for distribution
- * - Added zlib-like license
- * 1.8 9 Jan 2004 - Added some comments on no distance codes case
- * 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland]
- * - Catch missing end-of-block symbol error
- * 2.0 25 Jul 2008 - Add #define to permit distance too far back
- * - Add option in TEST code for puff to write the data
- * - Add option in TEST code to skip input bytes
- * - Allow TEST code to read from piped stdin
- * 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers
- * - Avoid unsigned comparisons for even happier compilers
- * 2.2 25 Apr 2010 - Fix bug in variable initializations [Oberhumer]
- * - Add const where appropriate [Oberhumer]
- * - Split if's and ?'s for coverage testing
- * - Break out test code to separate file
- * - Move NIL to puff.h
- * - Allow incomplete code only if single code length is 1
- * - Add full code coverage test to Makefile
- * 2.3 21 Jan 2013 - Check for invalid code length codes in dynamic blocks
- */
-
-#include "puff.h" /* prototype for puff() */
-#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */
-
-#define local static /* for local function definitions */
-
-/*
- * Maximums for allocations and loops. It is not useful to change these --
- * they are fixed by the deflate format.
- */
-#define MAXBITS 15 /* maximum bits in a code */
-#define MAXLCODES 286 /* maximum number of literal/length codes */
-#define MAXDCODES 30 /* maximum number of distance codes */
-#define MAXCODES (MAXLCODES + MAXDCODES) /* maximum codes lengths to read */
-#define FIXLCODES 288 /* number of fixed literal/length codes */
-
-/* input and output state */
-struct state {
- /* output state */
- unsigned char* out; /* output buffer */
- unsigned long outlen; /* available space at out */
- unsigned long outcnt; /* bytes written to out so far */
-
- /* input state */
- const unsigned char* in; /* input buffer */
- unsigned long inlen; /* available input at in */
- unsigned long incnt; /* bytes read so far */
- int bitbuf; /* bit buffer */
- int bitcnt; /* number of bits in bit buffer */
-
- /* input limit error return state for bits() and decode() */
- jmp_buf env;
-};
-
-/*
- * Return need bits from the input stream. This always leaves less than
- * eight bits in the buffer. bits() works properly for need == 0.
- *
- * Format notes:
- *
- * - Bits are stored in bytes from the least significant bit to the most
- * significant bit. Therefore bits are dropped from the bottom of the bit
- * buffer, using shift right, and new bytes are appended to the top of the
- * bit buffer, using shift left.
- */
-local int bits(struct state* s, int need)
-{
- long val; /* bit accumulator (can use up to 20 bits) */
-
- /* load at least need bits into val */
- val = s->bitbuf;
- while (s->bitcnt < need) {
- if (s->incnt == s->inlen)
- longjmp(s->env, 1); /* out of input */
- val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */
- s->bitcnt += 8;
- }
-
- /* drop need bits and update buffer, always zero to seven bits left */
- s->bitbuf = (int)(val >> need);
- s->bitcnt -= need;
-
- /* return need bits, zeroing the bits above that */
- return (int)(val & ((1L << need) - 1));
-}
-
-/*
- * Process a stored block.
- *
- * Format notes:
- *
- * - After the two-bit stored block type (00), the stored block length and
- * stored bytes are byte-aligned for fast copying. Therefore any leftover
- * bits in the byte that has the last bit of the type, as many as seven, are
- * discarded. The value of the discarded bits are not defined and should not
- * be checked against any expectation.
- *
- * - The second inverted copy of the stored block length does not have to be
- * checked, but it's probably a good idea to do so anyway.
- *
- * - A stored block can have zero length. This is sometimes used to byte-align
- * subsets of the compressed data for random access or partial recovery.
- */
-local int stored(struct state* s)
-{
- unsigned len; /* length of stored block */
-
- /* discard leftover bits from current byte (assumes s->bitcnt < 8) */
- s->bitbuf = 0;
- s->bitcnt = 0;
-
- /* get length and check against its one's complement */
- if (s->incnt + 4 > s->inlen)
- return 2; /* not enough input */
- len = s->in[s->incnt++];
- len |= s->in[s->incnt++] << 8;
- if (s->in[s->incnt++] != (~len & 0xff) || s->in[s->incnt++] != ((~len >> 8) & 0xff))
- return -2; /* didn't match complement! */
-
- /* copy len bytes from in to out */
- if (s->incnt + len > s->inlen)
- return 2; /* not enough input */
- if (s->out != NIL) {
- if (s->outcnt + len > s->outlen)
- return 1; /* not enough output space */
- while (len--)
- s->out[s->outcnt++] = s->in[s->incnt++];
- } else { /* just scanning */
- s->outcnt += len;
- s->incnt += len;
- }
-
- /* done with a valid stored block */
- return 0;
-}
-
-/*
- * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of
- * each length, which for a canonical code are stepped through in order.
- * symbol[] are the symbol values in canonical order, where the number of
- * entries is the sum of the counts in count[]. The decoding process can be
- * seen in the function decode() below.
- */
-struct huffman {
- short* count; /* number of symbols of each length */
- short* symbol; /* canonically ordered symbols */
-};
-
-/*
- * Decode a code from the stream s using huffman table h. Return the symbol or
- * a negative value if there is an error. If all of the lengths are zero, i.e.
- * an empty code, or if the code is incomplete and an invalid code is received,
- * then -10 is returned after reading MAXBITS bits.
- *
- * Format notes:
- *
- * - The codes as stored in the compressed data are bit-reversed relative to
- * a simple integer ordering of codes of the same lengths. Hence below the
- * bits are pulled from the compressed data one at a time and used to
- * build the code value reversed from what is in the stream in order to
- * permit simple integer comparisons for decoding. A table-based decoding
- * scheme (as used in zlib) does not need to do this reversal.
- *
- * - The first code for the shortest length is all zeros. Subsequent codes of
- * the same length are simply integer increments of the previous code. When
- * moving up a length, a zero bit is appended to the code. For a complete
- * code, the last code of the longest length will be all ones.
- *
- * - Incomplete codes are handled by this decoder, since they are permitted
- * in the deflate format. See the format notes for fixed() and dynamic().
- */
-#ifdef SLOW
-local int decode(struct state* s, const struct huffman* h)
-{
- int len; /* current number of bits in code */
- int code; /* len bits being decoded */
- int first; /* first code of length len */
- int count; /* number of codes of length len */
- int index; /* index of first code of length len in symbol table */
-
- code = first = index = 0;
- for (len = 1; len <= MAXBITS; len++) {
- code |= bits(s, 1); /* get next bit */
- count = h->count[len];
- if (code - count < first) /* if length len, return symbol */
- return h->symbol[index + (code - first)];
- index += count; /* else update for next length */
- first += count;
- first <<= 1;
- code <<= 1;
- }
- return -10; /* ran out of codes */
-}
-
-/*
- * A faster version of decode() for real applications of this code. It's not
- * as readable, but it makes puff() twice as fast. And it only makes the code
- * a few percent larger.
- */
-#else /* !SLOW */
-local int decode(struct state* s, const struct huffman* h)
-{
- int len; /* current number of bits in code */
- int code; /* len bits being decoded */
- int first; /* first code of length len */
- int count; /* number of codes of length len */
- int index; /* index of first code of length len in symbol table */
- int bitbuf; /* bits from stream */
- int left; /* bits left in next or left to process */
- short* next; /* next number of codes */
-
- bitbuf = s->bitbuf;
- left = s->bitcnt;
- code = first = index = 0;
- len = 1;
- next = h->count + 1;
- while (1) {
- while (left--) {
- code |= bitbuf & 1;
- bitbuf >>= 1;
- count = *next++;
- if (code - count < first) { /* if length len, return symbol */
- s->bitbuf = bitbuf;
- s->bitcnt = (s->bitcnt - len) & 7;
- return h->symbol[index + (code - first)];
- }
- index += count; /* else update for next length */
- first += count;
- first <<= 1;
- code <<= 1;
- len++;
- }
- left = (MAXBITS + 1) - len;
- if (left == 0)
- break;
- if (s->incnt == s->inlen)
- longjmp(s->env, 1); /* out of input */
- bitbuf = s->in[s->incnt++];
- if (left > 8)
- left = 8;
- }
- return -10; /* ran out of codes */
-}
-#endif /* SLOW */
-
-/*
- * Given the list of code lengths length[0..n-1] representing a canonical
- * Huffman code for n symbols, construct the tables required to decode those
- * codes. Those tables are the number of codes of each length, and the symbols
- * sorted by length, retaining their original order within each length. The
- * return value is zero for a complete code set, negative for an over-
- * subscribed code set, and positive for an incomplete code set. The tables
- * can be used if the return value is zero or positive, but they cannot be used
- * if the return value is negative. If the return value is zero, it is not
- * possible for decode() using that table to return an error--any stream of
- * enough bits will resolve to a symbol. If the return value is positive, then
- * it is possible for decode() using that table to return an error for received
- * codes past the end of the incomplete lengths.
- *
- * Not used by decode(), but used for error checking, h->count[0] is the number
- * of the n symbols not in the code. So n - h->count[0] is the number of
- * codes. This is useful for checking for incomplete codes that have more than
- * one symbol, which is an error in a dynamic block.
- *
- * Assumption: for all i in 0..n-1, 0 <= length[i] <= MAXBITS
- * This is assured by the construction of the length arrays in dynamic() and
- * fixed() and is not verified by construct().
- *
- * Format notes:
- *
- * - Permitted and expected examples of incomplete codes are one of the fixed
- * codes and any code with a single symbol which in deflate is coded as one
- * bit instead of zero bits. See the format notes for fixed() and dynamic().
- *
- * - Within a given code length, the symbols are kept in ascending order for
- * the code bits definition.
- */
-local int construct(struct huffman* h, const short* length, int n)
-{
- int symbol; /* current symbol when stepping through length[] */
- int len; /* current length when stepping through h->count[] */
- int left; /* number of possible codes left of current length */
- short offs[MAXBITS + 1]; /* offsets in symbol table for each length */
-
- /* count number of codes of each length */
- for (len = 0; len <= MAXBITS; len++)
- h->count[len] = 0;
- for (symbol = 0; symbol < n; symbol++)
- (h->count[length[symbol]])++; /* assumes lengths are within bounds */
- if (h->count[0] == n) /* no codes! */
- return 0; /* complete, but decode() will fail */
-
- /* check for an over-subscribed or incomplete set of lengths */
- left = 1; /* one possible code of zero length */
- for (len = 1; len <= MAXBITS; len++) {
- left <<= 1; /* one more bit, double codes left */
- left -= h->count[len]; /* deduct count from possible codes */
- if (left < 0)
- return left; /* over-subscribed--return negative */
- } /* left > 0 means incomplete */
-
- /* generate offsets into symbol table for each length for sorting */
- offs[1] = 0;
- for (len = 1; len < MAXBITS; len++)
- offs[len + 1] = offs[len] + h->count[len];
-
- /*
- * put symbols in table sorted by length, by symbol order within each
- * length
- */
- for (symbol = 0; symbol < n; symbol++)
- if (length[symbol] != 0)
- h->symbol[offs[length[symbol]]++] = symbol;
-
- /* return zero for complete set, positive for incomplete set */
- return left;
-}
-
-/*
- * Decode literal/length and distance codes until an end-of-block code.
- *
- * Format notes:
- *
- * - Compressed data that is after the block type if fixed or after the code
- * description if dynamic is a combination of literals and length/distance
- * pairs terminated by and end-of-block code. Literals are simply Huffman
- * coded bytes. A length/distance pair is a coded length followed by a
- * coded distance to represent a string that occurs earlier in the
- * uncompressed data that occurs again at the current location.
- *
- * - Literals, lengths, and the end-of-block code are combined into a single
- * code of up to 286 symbols. They are 256 literals (0..255), 29 length
- * symbols (257..285), and the end-of-block symbol (256).
- *
- * - There are 256 possible lengths (3..258), and so 29 symbols are not enough
- * to represent all of those. Lengths 3..10 and 258 are in fact represented
- * by just a length symbol. Lengths 11..257 are represented as a symbol and
- * some number of extra bits that are added as an integer to the base length
- * of the length symbol. The number of extra bits is determined by the base
- * length symbol. These are in the static arrays below, lens[] for the base
- * lengths and lext[] for the corresponding number of extra bits.
- *
- * - The reason that 258 gets its own symbol is that the longest length is used
- * often in highly redundant files. Note that 258 can also be coded as the
- * base value 227 plus the maximum extra value of 31. While a good deflate
- * should never do this, it is not an error, and should be decoded properly.
- *
- * - If a length is decoded, including its extra bits if any, then it is
- * followed a distance code. There are up to 30 distance symbols. Again
- * there are many more possible distances (1..32768), so extra bits are added
- * to a base value represented by the symbol. The distances 1..4 get their
- * own symbol, but the rest require extra bits. The base distances and
- * corresponding number of extra bits are below in the static arrays dist[]
- * and dext[].
- *
- * - Literal bytes are simply written to the output. A length/distance pair is
- * an instruction to copy previously uncompressed bytes to the output. The
- * copy is from distance bytes back in the output stream, copying for length
- * bytes.
- *
- * - Distances pointing before the beginning of the output data are not
- * permitted.
- *
- * - Overlapped copies, where the length is greater than the distance, are
- * allowed and common. For example, a distance of one and a length of 258
- * simply copies the last byte 258 times. A distance of four and a length of
- * twelve copies the last four bytes three times. A simple forward copy
- * ignoring whether the length is greater than the distance or not implements
- * this correctly. You should not use memcpy() since its behavior is not
- * defined for overlapped arrays. You should not use memmove() or bcopy()
- * since though their behavior -is- defined for overlapping arrays, it is
- * defined to do the wrong thing in this case.
- */
-local int codes(struct state* s,
- const struct huffman* lencode,
- const struct huffman* distcode)
-{
- int symbol; /* decoded symbol */
- int len; /* length for copy */
- unsigned dist; /* distance for copy */
- static const short lens[29] = { /* Size base for length codes 257..285 */
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
- };
- static const short lext[29] = { /* Extra bits for length codes 257..285 */
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
- };
- static const short dists[30] = { /* Offset base for distance codes 0..29 */
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
- 8193, 12289, 16385, 24577
- };
- static const short dext[30] = { /* Extra bits for distance codes 0..29 */
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
- 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
- 12, 12, 13, 13
- };
-
- /* decode literals and length/distance pairs */
- do {
- symbol = decode(s, lencode);
- if (symbol < 0)
- return symbol; /* invalid symbol */
- if (symbol < 256) { /* literal: symbol is the byte */
- /* write out the literal */
- if (s->out != NIL) {
- if (s->outcnt == s->outlen)
- return 1;
- s->out[s->outcnt] = symbol;
- }
- s->outcnt++;
- } else if (symbol > 256) { /* length */
- /* get and compute length */
- symbol -= 257;
- if (symbol >= 29)
- return -10; /* invalid fixed code */
- len = lens[symbol] + bits(s, lext[symbol]);
-
- /* get and check distance */
- symbol = decode(s, distcode);
- if (symbol < 0)
- return symbol; /* invalid symbol */
- dist = dists[symbol] + bits(s, dext[symbol]);
-#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
- if (dist > s->outcnt)
- return -11; /* distance too far back */
-#endif
-
- /* copy length bytes from distance bytes back */
- if (s->out != NIL) {
- if (s->outcnt + len > s->outlen)
- return 1;
- while (len--) {
- s->out[s->outcnt] =
-#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
- dist > s->outcnt ? 0 :
-#endif
- s->out[s->outcnt - dist];
- s->outcnt++;
- }
- } else
- s->outcnt += len;
- }
- } while (symbol != 256); /* end of block symbol */
-
- /* done with a valid fixed or dynamic block */
- return 0;
-}
-
-/*
- * Process a fixed codes block.
- *
- * Format notes:
- *
- * - This block type can be useful for compressing small amounts of data for
- * which the size of the code descriptions in a dynamic block exceeds the
- * benefit of custom codes for that block. For fixed codes, no bits are
- * spent on code descriptions. Instead the code lengths for literal/length
- * codes and distance codes are fixed. The specific lengths for each symbol
- * can be seen in the "for" loops below.
- *
- * - The literal/length code is complete, but has two symbols that are invalid
- * and should result in an error if received. This cannot be implemented
- * simply as an incomplete code since those two symbols are in the "middle"
- * of the code. They are eight bits long and the longest literal/length\
- * code is nine bits. Therefore the code must be constructed with those
- * symbols, and the invalid symbols must be detected after decoding.
- *
- * - The fixed distance codes also have two invalid symbols that should result
- * in an error if received. Since all of the distance codes are the same
- * length, this can be implemented as an incomplete code. Then the invalid
- * codes are detected while decoding.
- */
-local int fixed(struct state* s)
-{
- static int virgin = 1;
- static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
- static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
- static struct huffman lencode, distcode;
-
- /* build fixed huffman tables if first call (may not be thread safe) */
- if (virgin) {
- int symbol;
- short lengths[FIXLCODES];
-
- /* construct lencode and distcode */
- lencode.count = lencnt;
- lencode.symbol = lensym;
- distcode.count = distcnt;
- distcode.symbol = distsym;
-
- /* literal/length table */
- for (symbol = 0; symbol < 144; symbol++)
- lengths[symbol] = 8;
- for (; symbol < 256; symbol++)
- lengths[symbol] = 9;
- for (; symbol < 280; symbol++)
- lengths[symbol] = 7;
- for (; symbol < FIXLCODES; symbol++)
- lengths[symbol] = 8;
- construct(&lencode, lengths, FIXLCODES);
-
- /* distance table */
- for (symbol = 0; symbol < MAXDCODES; symbol++)
- lengths[symbol] = 5;
- construct(&distcode, lengths, MAXDCODES);
-
- /* do this just once */
- virgin = 0;
- }
-
- /* decode data until end-of-block code */
- return codes(s, &lencode, &distcode);
-}
-
-/*
- * Process a dynamic codes block.
- *
- * Format notes:
- *
- * - A dynamic block starts with a description of the literal/length and
- * distance codes for that block. New dynamic blocks allow the compressor to
- * rapidly adapt to changing data with new codes optimized for that data.
- *
- * - The codes used by the deflate format are "canonical", which means that
- * the actual bits of the codes are generated in an unambiguous way simply
- * from the number of bits in each code. Therefore the code descriptions
- * are simply a list of code lengths for each symbol.
- *
- * - The code lengths are stored in order for the symbols, so lengths are
- * provided for each of the literal/length symbols, and for each of the
- * distance symbols.
- *
- * - If a symbol is not used in the block, this is represented by a zero as
- * as the code length. This does not mean a zero-length code, but rather
- * that no code should be created for this symbol. There is no way in the
- * deflate format to represent a zero-length code.
- *
- * - The maximum number of bits in a code is 15, so the possible lengths for
- * any code are 1..15.
- *
- * - The fact that a length of zero is not permitted for a code has an
- * interesting consequence. Normally if only one symbol is used for a given
- * code, then in fact that code could be represented with zero bits. However
- * in deflate, that code has to be at least one bit. So for example, if
- * only a single distance base symbol appears in a block, then it will be
- * represented by a single code of length one, in particular one 0 bit. This
- * is an incomplete code, since if a 1 bit is received, it has no meaning,
- * and should result in an error. So incomplete distance codes of one symbol
- * should be permitted, and the receipt of invalid codes should be handled.
- *
- * - It is also possible to have a single literal/length code, but that code
- * must be the end-of-block code, since every dynamic block has one. This
- * is not the most efficient way to create an empty block (an empty fixed
- * block is fewer bits), but it is allowed by the format. So incomplete
- * literal/length codes of one symbol should also be permitted.
- *
- * - If there are only literal codes and no lengths, then there are no distance
- * codes. This is represented by one distance code with zero bits.
- *
- * - The list of up to 286 length/literal lengths and up to 30 distance lengths
- * are themselves compressed using Huffman codes and run-length encoding. In
- * the list of code lengths, a 0 symbol means no code, a 1..15 symbol means
- * that length, and the symbols 16, 17, and 18 are run-length instructions.
- * Each of 16, 17, and 18 are follwed by extra bits to define the length of
- * the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10
- * zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols
- * are common, hence the special coding for zero lengths.
- *
- * - The symbols for 0..18 are Huffman coded, and so that code must be
- * described first. This is simply a sequence of up to 19 three-bit values
- * representing no code (0) or the code length for that symbol (1..7).
- *
- * - A dynamic block starts with three fixed-size counts from which is computed
- * the number of literal/length code lengths, the number of distance code
- * lengths, and the number of code length code lengths (ok, you come up with
- * a better name!) in the code descriptions. For the literal/length and
- * distance codes, lengths after those provided are considered zero, i.e. no
- * code. The code length code lengths are received in a permuted order (see
- * the order[] array below) to make a short code length code length list more
- * likely. As it turns out, very short and very long codes are less likely
- * to be seen in a dynamic code description, hence what may appear initially
- * to be a peculiar ordering.
- *
- * - Given the number of literal/length code lengths (nlen) and distance code
- * lengths (ndist), then they are treated as one long list of nlen + ndist
- * code lengths. Therefore run-length coding can and often does cross the
- * boundary between the two sets of lengths.
- *
- * - So to summarize, the code description at the start of a dynamic block is
- * three counts for the number of code lengths for the literal/length codes,
- * the distance codes, and the code length codes. This is followed by the
- * code length code lengths, three bits each. This is used to construct the
- * code length code which is used to read the remainder of the lengths. Then
- * the literal/length code lengths and distance lengths are read as a single
- * set of lengths using the code length codes. Codes are constructed from
- * the resulting two sets of lengths, and then finally you can start
- * decoding actual compressed data in the block.
- *
- * - For reference, a "typical" size for the code description in a dynamic
- * block is around 80 bytes.
- */
-local int dynamic(struct state* s)
-{
- int nlen, ndist, ncode; /* number of lengths in descriptor */
- int index; /* index of lengths[] */
- int err; /* construct() return value */
- short lengths[MAXCODES]; /* descriptor code lengths */
- short lencnt[MAXBITS + 1], lensym[MAXLCODES]; /* lencode memory */
- short distcnt[MAXBITS + 1], distsym[MAXDCODES]; /* distcode memory */
- struct huffman lencode, distcode; /* length and distance codes */
- static const short order[19] = /* permutation of code length codes */
- { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
-
- /* construct lencode and distcode */
- lencode.count = lencnt;
- lencode.symbol = lensym;
- distcode.count = distcnt;
- distcode.symbol = distsym;
-
- /* get number of lengths in each table, check lengths */
- nlen = bits(s, 5) + 257;
- ndist = bits(s, 5) + 1;
- ncode = bits(s, 4) + 4;
- if (nlen > MAXLCODES || ndist > MAXDCODES)
- return -3; /* bad counts */
-
- /* read code length code lengths (really), missing lengths are zero */
- for (index = 0; index < ncode; index++)
- lengths[order[index]] = bits(s, 3);
- for (; index < 19; index++)
- lengths[order[index]] = 0;
-
- /* build huffman table for code lengths codes (use lencode temporarily) */
- err = construct(&lencode, lengths, 19);
- if (err != 0) /* require complete code set here */
- return -4;
-
- /* read length/literal and distance code length tables */
- index = 0;
- while (index < nlen + ndist) {
- int symbol; /* decoded value */
- int len; /* last length to repeat */
-
- symbol = decode(s, &lencode);
- if (symbol < 0)
- return symbol; /* invalid symbol */
- if (symbol < 16) /* length in 0..15 */
- lengths[index++] = symbol;
- else { /* repeat instruction */
- len = 0; /* assume repeating zeros */
- if (symbol == 16) { /* repeat last length 3..6 times */
- if (index == 0)
- return -5; /* no last length! */
- len = lengths[index - 1]; /* last length */
- symbol = 3 + bits(s, 2);
- } else if (symbol == 17) /* repeat zero 3..10 times */
- symbol = 3 + bits(s, 3);
- else /* == 18, repeat zero 11..138 times */
- symbol = 11 + bits(s, 7);
- if (index + symbol > nlen + ndist)
- return -6; /* too many lengths! */
- while (symbol--) /* repeat last or zero symbol times */
- lengths[index++] = len;
- }
- }
-
- /* check for end-of-block code -- there better be one! */
- if (lengths[256] == 0)
- return -9;
-
- /* build huffman table for literal/length codes */
- err = construct(&lencode, lengths, nlen);
- if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
- return -7; /* incomplete code ok only for single length 1 code */
-
- /* build huffman table for distance codes */
- err = construct(&distcode, lengths + nlen, ndist);
- if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
- return -8; /* incomplete code ok only for single length 1 code */
-
- /* decode data until end-of-block code */
- return codes(s, &lencode, &distcode);
-}
-
-/*
- * Inflate source to dest. On return, destlen and sourcelen are updated to the
- * size of the uncompressed data and the size of the deflate data respectively.
- * On success, the return value of puff() is zero. If there is an error in the
- * source data, i.e. it is not in the deflate format, then a negative value is
- * returned. If there is not enough input available or there is not enough
- * output space, then a positive error is returned. In that case, destlen and
- * sourcelen are not updated to facilitate retrying from the beginning with the
- * provision of more input data or more output space. In the case of invalid
- * inflate data (a negative error), the dest and source pointers are updated to
- * facilitate the debugging of deflators.
- *
- * puff() also has a mode to determine the size of the uncompressed output with
- * no output written. For this dest must be (unsigned char *)0. In this case,
- * the input value of *destlen is ignored, and on return *destlen is set to the
- * size of the uncompressed output.
- *
- * The return codes are:
- *
- * 2: available inflate data did not terminate
- * 1: output space exhausted before completing inflate
- * 0: successful inflate
- * -1: invalid block type (type == 3)
- * -2: stored block length did not match one's complement
- * -3: dynamic block code description: too many length or distance codes
- * -4: dynamic block code description: code lengths codes incomplete
- * -5: dynamic block code description: repeat lengths with no first length
- * -6: dynamic block code description: repeat more than specified lengths
- * -7: dynamic block code description: invalid literal/length code lengths
- * -8: dynamic block code description: invalid distance code lengths
- * -9: dynamic block code description: missing end-of-block code
- * -10: invalid literal/length or distance code in fixed or dynamic block
- * -11: distance is too far back in fixed or dynamic block
- *
- * Format notes:
- *
- * - Three bits are read for each block to determine the kind of block and
- * whether or not it is the last block. Then the block is decoded and the
- * process repeated if it was not the last block.
- *
- * - The leftover bits in the last byte of the deflate data after the last
- * block (if it was a fixed or dynamic block) are undefined and have no
- * expected values to check.
- */
-int puff(unsigned char* dest, /* pointer to destination pointer */
- unsigned long* destlen, /* amount of output space */
- const unsigned char* source, /* pointer to source data pointer */
- unsigned long* sourcelen) /* amount of input available */
-{
- struct state s; /* input/output state */
- int last, type; /* block information */
- int err; /* return value */
-
- /* initialize output state */
- s.out = dest;
- s.outlen = *destlen; /* ignored if dest is NIL */
- s.outcnt = 0;
-
- /* initialize input state */
- s.in = source;
- s.inlen = *sourcelen;
- s.incnt = 0;
- s.bitbuf = 0;
- s.bitcnt = 0;
-
- /* return if bits() or decode() tries to read past available input */
- if (setjmp(s.env) != 0) /* if came back here via longjmp() */
- err = 2; /* then skip do-loop, return error */
- else {
- /* process blocks until last block or error */
- do {
- last = bits(&s, 1); /* one if last block */
- type = bits(&s, 2); /* block type 0..3 */
- err = type == 0 ? stored(&s) : (type == 1 ? fixed(&s) : (type == 2 ? dynamic(&s) : -1)); /* type == 3, invalid */
- if (err != 0)
- break; /* return with error */
- } while (!last);
- }
-
- /* update the lengths and return */
- if (err <= 0) {
- *destlen = s.outcnt;
- *sourcelen = s.incnt;
- }
- return err;
-}
diff --git a/Userland/Libraries/LibCore/puff.h b/Userland/Libraries/LibCore/puff.h
deleted file mode 100644
index 5943910403..0000000000
--- a/Userland/Libraries/LibCore/puff.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#pragma once
-
-/* puff.h
- Copyright (C) 2002-2013 Mark Adler, all rights reserved
- version 2.3, 21 Jan 2013
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the author be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- Mark Adler madler@alumni.caltech.edu
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * See puff.c for purpose and usage.
- */
-#ifndef NIL
-# define NIL ((unsigned char*)0) /* for no output option */
-#endif
-
-int puff(unsigned char* dest, /* pointer to destination pointer */
- unsigned long* destlen, /* amount of output space */
- const unsigned char* source, /* pointer to source data pointer */
- unsigned long* sourcelen); /* amount of input available */
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt
index 52287a1dd0..02e224d787 100644
--- a/Userland/Libraries/LibGfx/CMakeLists.txt
+++ b/Userland/Libraries/LibGfx/CMakeLists.txt
@@ -35,4 +35,4 @@ set(SOURCES
)
serenity_lib(LibGfx gfx)
-target_link_libraries(LibGfx LibM LibCore LibTTF)
+target_link_libraries(LibGfx LibM LibCompress LibCore LibTTF)
diff --git a/Userland/Libraries/LibGfx/PNGLoader.cpp b/Userland/Libraries/LibGfx/PNGLoader.cpp
index fbb4a4d8b9..6dc47cc4f6 100644
--- a/Userland/Libraries/LibGfx/PNGLoader.cpp
+++ b/Userland/Libraries/LibGfx/PNGLoader.cpp
@@ -28,7 +28,7 @@
#include <AK/Endian.h>
#include <AK/LexicalPath.h>
#include <AK/MappedFile.h>
-#include <LibCore/puff.h>
+#include <LibCompress/Gzip.h>
#include <LibGfx/PNGLoader.h>
#include <fcntl.h>
#include <math.h>
@@ -39,6 +39,7 @@
#include <unistd.h>
#ifdef __serenity__
+# include <LibCompress/Deflate.h>
# include <serenity.h>
#endif
@@ -120,8 +121,7 @@ struct PNGLoadingContext {
bool has_alpha() const { return color_type & 4 || palette_transparency_data.size() > 0; }
Vector<Scanline> scanlines;
RefPtr<Gfx::Bitmap> bitmap;
- u8* decompression_buffer { nullptr };
- size_t decompression_buffer_size { 0 };
+ ByteBuffer decompression_buffer;
Vector<u8> compressed_data;
Vector<PaletteEntry> palette_data;
Vector<u8> palette_transparency_data;
@@ -603,7 +603,7 @@ static bool decode_png_chunks(PNGLoadingContext& context)
static bool decode_png_bitmap_simple(PNGLoadingContext& context)
{
- Streamer streamer(context.decompression_buffer, context.decompression_buffer_size);
+ Streamer streamer(context.decompression_buffer.data(), context.decompression_buffer.size());
for (int y = 0; y < context.height; ++y) {
u8 filter;
@@ -749,7 +749,7 @@ static bool decode_adam7_pass(PNGLoadingContext& context, Streamer& streamer, in
static bool decode_png_adam7(PNGLoadingContext& context)
{
- Streamer streamer(context.decompression_buffer, context.decompression_buffer_size);
+ Streamer streamer(context.decompression_buffer.data(), context.decompression_buffer.size());
context.bitmap = Bitmap::create_purgeable(context.has_alpha() ? BitmapFormat::RGBA32 : BitmapFormat::RGB32, { context.width, context.height });
if (!context.bitmap)
return false;
@@ -777,25 +777,12 @@ static bool decode_png_bitmap(PNGLoadingContext& context)
if (context.color_type == 3 && context.palette_data.is_empty())
return false; // Didn't see a PLTE chunk for a palettized image, or it was empty.
- unsigned long srclen = context.compressed_data.size() - 6;
- unsigned long destlen = 0;
- int ret = puff(nullptr, &destlen, context.compressed_data.data() + 2, &srclen);
- if (ret != 0) {
- context.state = PNGLoadingContext::State::Error;
- return false;
- }
- context.decompression_buffer_size = destlen;
-#ifdef __serenity__
- context.decompression_buffer = (u8*)mmap_with_name(nullptr, context.decompression_buffer_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0, "PNG decompression buffer");
-#else
- context.decompression_buffer = (u8*)mmap(nullptr, context.decompression_buffer_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
-#endif
-
- ret = puff(context.decompression_buffer, &destlen, context.compressed_data.data() + 2, &srclen);
- if (ret != 0) {
+ auto result = Compress::DeflateDecompressor::decompress_all(context.compressed_data.span().slice(2));
+ if (!result.has_value()) {
context.state = PNGLoadingContext::State::Error;
return false;
}
+ context.decompression_buffer = result.value();
context.compressed_data.clear();
context.scanlines.ensure_capacity(context.height);
@@ -812,9 +799,7 @@ static bool decode_png_bitmap(PNGLoadingContext& context)
VERIFY_NOT_REACHED();
}
- munmap(context.decompression_buffer, context.decompression_buffer_size);
- context.decompression_buffer = nullptr;
- context.decompression_buffer_size = 0;
+ context.decompression_buffer.clear();
context.state = PNGLoadingContext::State::BitmapDecoded;
return true;
diff --git a/Userland/Libraries/LibHTTP/CMakeLists.txt b/Userland/Libraries/LibHTTP/CMakeLists.txt
index 57c79b55e2..42cd10fac3 100644
--- a/Userland/Libraries/LibHTTP/CMakeLists.txt
+++ b/Userland/Libraries/LibHTTP/CMakeLists.txt
@@ -7,4 +7,4 @@ set(SOURCES
)
serenity_lib(LibHTTP http)
-target_link_libraries(LibHTTP LibCore LibTLS)
+target_link_libraries(LibHTTP LibCompress LibCore LibTLS)
diff --git a/Userland/Libraries/LibHTTP/HttpJob.cpp b/Userland/Libraries/LibHTTP/HttpJob.cpp
index c2b73aa12a..34bc0a2596 100644
--- a/Userland/Libraries/LibHTTP/HttpJob.cpp
+++ b/Userland/Libraries/LibHTTP/HttpJob.cpp
@@ -25,7 +25,6 @@
*/
#include <AK/Debug.h>
-#include <LibCore/Gzip.h>
#include <LibCore/TCPSocket.h>
#include <LibHTTP/HttpJob.h>
#include <LibHTTP/HttpResponse.h>
diff --git a/Userland/Libraries/LibHTTP/HttpsJob.cpp b/Userland/Libraries/LibHTTP/HttpsJob.cpp
index 3f89c4b971..5cafeb8198 100644
--- a/Userland/Libraries/LibHTTP/HttpsJob.cpp
+++ b/Userland/Libraries/LibHTTP/HttpsJob.cpp
@@ -26,7 +26,6 @@
#include <AK/Debug.h>
#include <LibCore/EventLoop.h>
-#include <LibCore/Gzip.h>
#include <LibHTTP/HttpResponse.h>
#include <LibHTTP/HttpsJob.h>
#include <LibTLS/TLSv12.h>
diff --git a/Userland/Libraries/LibHTTP/Job.cpp b/Userland/Libraries/LibHTTP/Job.cpp
index 7da8eee947..062397071f 100644
--- a/Userland/Libraries/LibHTTP/Job.cpp
+++ b/Userland/Libraries/LibHTTP/Job.cpp
@@ -25,7 +25,7 @@
*/
#include <AK/Debug.h>
-#include <LibCore/Gzip.h>
+#include <LibCompress/Gzip.h>
#include <LibCore/TCPSocket.h>
#include <LibHTTP/HttpResponse.h>
#include <LibHTTP/Job.h>
@@ -39,13 +39,13 @@ static ByteBuffer handle_content_encoding(const ByteBuffer& buf, const String& c
dbgln_if(JOB_DEBUG, "Job::handle_content_encoding: buf has content_encoding={}", content_encoding);
if (content_encoding == "gzip") {
- if (!Core::Gzip::is_compressed(buf)) {
+ if (!Compress::GzipDecompressor::is_likely_compressed(buf)) {
dbgln("Job::handle_content_encoding: buf is not gzip compressed!");
}
dbgln_if(JOB_DEBUG, "Job::handle_content_encoding: buf is gzip compressed!");
- auto uncompressed = Core::Gzip::decompress(buf);
+ auto uncompressed = Compress::GzipDecompressor::decompress_all(buf);
if (!uncompressed.has_value()) {
dbgln("Job::handle_content_encoding: Gzip::decompress() failed. Returning original buffer.");
return buf;
@@ -352,6 +352,7 @@ void Job::finish_up()
m_received_buffers.clear();
// For the time being, we cannot stream stuff with content-encoding set to _anything_.
+ // FIXME: LibCompress exposes a streaming interface, so this can be resolved
auto content_encoding = m_headers.get("Content-Encoding");
if (content_encoding.has_value()) {
flattened_buffer = handle_content_encoding(flattened_buffer, content_encoding.value());