mirror of https://github.com/KLayout/klayout.git
561 lines
14 KiB
C++
561 lines
14 KiB
C++
|
|
/*
|
|
|
|
KLayout Layout Viewer
|
|
Copyright (C) 2006-2017 Matthias Koefferlein
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
#include "tlDeflate.h"
|
|
#include "tlException.h"
|
|
#include "tlAssert.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <zlib.h>
|
|
|
|
namespace tl
|
|
{
|
|
|
|
// ------------------------------------------------------------------------
|
|
// The Huffmann decoder core
|
|
|
|
/**
|
|
* @brief The decoder for Huffmann codes
|
|
*
|
|
* The decoder keeps a Huffmann code tree and decodes a value from a bit stream
|
|
* using this tree.
|
|
* As specified by RFC1951, the code tree is constructed from a list of code lengths
|
|
* vs. value alone.
|
|
*/
|
|
class HuffmannDecoder
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Constructor
|
|
*
|
|
* Creates an empty code tree.
|
|
*/
|
|
HuffmannDecoder ()
|
|
{
|
|
mp_codes = 0;
|
|
mp_bitmasks = 0;
|
|
m_max_bits = 0;
|
|
m_num_codes = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Destructor
|
|
*/
|
|
~HuffmannDecoder ()
|
|
{
|
|
if (mp_codes) {
|
|
delete [] mp_codes;
|
|
}
|
|
mp_codes = 0;
|
|
if (mp_bitmasks) {
|
|
delete [] mp_bitmasks;
|
|
}
|
|
mp_bitmasks = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Initialize the code tree with the fixed Huffmann code table for literals/lengths
|
|
*
|
|
* This table is used by compression mode 1.
|
|
* It is specified in RFC1951.
|
|
*/
|
|
void fill_fixed_table_length ()
|
|
{
|
|
reserve (9);
|
|
|
|
unsigned short lengths [288];
|
|
for (unsigned int i = 0; i < 144; ++i) {
|
|
lengths[i] = 8;
|
|
}
|
|
for (unsigned int i = 144; i < 256; ++i) {
|
|
lengths[i] = 9;
|
|
}
|
|
for (unsigned int i = 256; i < 280; ++i) {
|
|
lengths[i] = 7;
|
|
}
|
|
for (unsigned int i = 280; i < 288; ++i) {
|
|
lengths[i] = 8;
|
|
}
|
|
|
|
init_codes (lengths, lengths + sizeof (lengths) / sizeof (lengths [0]));
|
|
}
|
|
|
|
/**
|
|
* @brief Initialize the code tree with the fixed Huffmann code table for distances
|
|
*
|
|
* This table is used by compression mode 1.
|
|
* It is specified in RFC1951.
|
|
*/
|
|
void fill_fixed_table_dist ()
|
|
{
|
|
reserve (5);
|
|
|
|
unsigned short lengths [32];
|
|
for (unsigned int i = 0; i < 32; ++i) {
|
|
lengths[i] = 5;
|
|
}
|
|
init_codes (lengths, lengths + sizeof (lengths) / sizeof (lengths [0]));
|
|
}
|
|
|
|
/**
|
|
* @brief Initialize the code tree from a list of lengths
|
|
*
|
|
* This method initializes the code tree from a list of lengths, given
|
|
* by the sequence [begin_lengths, end_lengths). The codes are assumed to
|
|
* range from 0 to distance(begin_lengths, end_lengths).
|
|
* See RFC1951 for a description about the procedure.
|
|
*/
|
|
template <class Iter>
|
|
void init_codes (Iter begin_lengths, Iter end_lengths)
|
|
{
|
|
const unsigned int MAX_BITS = 16;
|
|
unsigned short bl_count[MAX_BITS + 1];
|
|
unsigned short bitmasks[MAX_BITS + 1];
|
|
unsigned short next_code[MAX_BITS + 1];
|
|
unsigned int max_bits = 0;
|
|
|
|
for (unsigned int bits = 0; bits <= MAX_BITS; bits++) {
|
|
bl_count[bits] = 0;
|
|
}
|
|
|
|
for (Iter l = begin_lengths; l != end_lengths; ++l) {
|
|
tl_assert (*l < MAX_BITS);
|
|
if (*l > 0) {
|
|
++bl_count [*l];
|
|
}
|
|
}
|
|
|
|
unsigned int code = 0;
|
|
for (unsigned int bits = 1; bits <= MAX_BITS; bits++) {
|
|
if (bl_count[bits - 1] > 0) {
|
|
max_bits = bits - 1;
|
|
}
|
|
code = (code + bl_count[bits - 1]) << 1;
|
|
next_code[bits] = code;
|
|
}
|
|
|
|
for (unsigned int bits = 0; bits <= max_bits; bits++) {
|
|
bitmasks [bits] = ((1 << bits) - 1) << (max_bits - bits);
|
|
}
|
|
|
|
reserve (max_bits);
|
|
|
|
unsigned short symbol = 0;
|
|
for (Iter l = begin_lengths; l != end_lengths; ++l, ++symbol) {
|
|
if (*l > 0) {
|
|
unsigned int code = next_code [*l]++;
|
|
code <<= (max_bits - *l);
|
|
mp_codes [code] = symbol;
|
|
mp_bitmasks [code] = bitmasks [*l];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Decode the next value from a bit stream
|
|
*
|
|
* This method takes the next value from the bit stream decoding the bits with
|
|
* the code tree currently loaded.
|
|
*/
|
|
unsigned short decode (BitStream &s) const
|
|
{
|
|
tl_assert (mp_codes != 0);
|
|
|
|
unsigned int m = m_num_codes / 2;
|
|
|
|
unsigned int c = 0;
|
|
do {
|
|
if (s.get_bit ()) {
|
|
c |= m;
|
|
}
|
|
m >>= 1;
|
|
} while ((mp_bitmasks [c] & m) != 0);
|
|
|
|
return mp_codes [c];
|
|
}
|
|
|
|
private:
|
|
unsigned short *mp_codes, *mp_bitmasks;
|
|
unsigned int m_num_codes, m_max_bits;
|
|
|
|
void reserve (unsigned int max_bits)
|
|
{
|
|
m_num_codes = 1 << max_bits;
|
|
if (max_bits > m_max_bits) {
|
|
m_max_bits = max_bits;
|
|
if (mp_codes) {
|
|
delete [] mp_codes;
|
|
}
|
|
mp_codes = new unsigned short [m_num_codes];
|
|
if (mp_bitmasks) {
|
|
delete [] mp_bitmasks;
|
|
}
|
|
mp_bitmasks = new unsigned short [m_num_codes];
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
// InflateFilter implementation
|
|
|
|
InflateFilter::InflateFilter (tl::InputStream &input)
|
|
: m_input (input),
|
|
m_b_insert (0), m_b_read (0), m_at_end (false),
|
|
m_last_block (false),
|
|
m_uncompressed_length (0) // this forces a new block on "process()"
|
|
{
|
|
for (size_t i = 0; i < sizeof (m_buffer) / sizeof (m_buffer [0]); ++i) {
|
|
m_buffer[i] = 0;
|
|
}
|
|
|
|
mp_dist_decoder = new HuffmannDecoder ();
|
|
mp_lit_decoder = new HuffmannDecoder ();
|
|
}
|
|
|
|
InflateFilter::~InflateFilter ()
|
|
{
|
|
delete mp_dist_decoder;
|
|
mp_dist_decoder = 0;
|
|
delete mp_lit_decoder;
|
|
mp_lit_decoder = 0;
|
|
}
|
|
|
|
const char *
|
|
InflateFilter::get (size_t n)
|
|
{
|
|
tl_assert (n < sizeof (m_buffer) / 2);
|
|
|
|
while ((m_b_insert + sizeof (m_buffer) - m_b_read) % sizeof (m_buffer) < n) {
|
|
if (! process ()) {
|
|
throw tl::Exception (tl::to_string (QObject::tr ("Unexpected end of file (DEFLATE implementation)")));
|
|
}
|
|
}
|
|
|
|
tl_assert (m_b_read != m_b_insert);
|
|
|
|
// ensure the block is accessible as a coherent chunk:
|
|
if (m_b_read + n >= sizeof (m_buffer)) {
|
|
std::rotate (m_buffer, m_buffer + m_b_read, m_buffer + sizeof (m_buffer));
|
|
m_b_insert = (m_b_insert - m_b_read + sizeof (m_buffer)) % sizeof (m_buffer);
|
|
m_b_read = 0;
|
|
}
|
|
|
|
const char *r = m_buffer + m_b_read;
|
|
m_b_read = (m_b_read + n) % sizeof (m_buffer);
|
|
return r;
|
|
}
|
|
|
|
void
|
|
InflateFilter::unget (size_t n)
|
|
{
|
|
tl_assert (m_b_read >= n);
|
|
m_b_read -= n;
|
|
}
|
|
|
|
bool
|
|
InflateFilter::at_end ()
|
|
{
|
|
if (! m_at_end && m_b_read == m_b_insert) {
|
|
if (! process ()) {
|
|
m_at_end = true;
|
|
}
|
|
}
|
|
return m_at_end;
|
|
}
|
|
|
|
void
|
|
InflateFilter::put_byte (char b)
|
|
{
|
|
m_buffer [m_b_insert] = b;
|
|
m_b_insert = (m_b_insert + 1) % sizeof (m_buffer);
|
|
}
|
|
|
|
void
|
|
InflateFilter::put_byte_dist (unsigned int d)
|
|
{
|
|
put_byte (m_buffer [(m_b_insert - d) % sizeof (m_buffer)]);
|
|
}
|
|
|
|
bool
|
|
InflateFilter::process ()
|
|
{
|
|
while (true) {
|
|
|
|
bool new_block = false;
|
|
|
|
if (m_uncompressed_length == 0) {
|
|
|
|
m_uncompressed_length = -1;
|
|
new_block = true;
|
|
|
|
} else if (m_uncompressed_length > 0) {
|
|
|
|
put_byte (m_input.get_byte ());
|
|
--m_uncompressed_length;
|
|
|
|
} else {
|
|
|
|
unsigned int l = mp_lit_decoder->decode (m_input);
|
|
if (l < 256) {
|
|
|
|
put_byte (char (l));
|
|
|
|
} else if (l == 256) {
|
|
|
|
new_block = true;
|
|
|
|
} else {
|
|
|
|
unsigned int length = 0;
|
|
if (l < 265) {
|
|
length = l - 254;
|
|
} else if (l < 269) {
|
|
length = (l - 265) * 2 + 11 + m_input.get_bits (1);
|
|
} else if (l < 273) {
|
|
length = (l - 269) * 4 + 19 + m_input.get_bits (2);
|
|
} else if (l < 277) {
|
|
length = (l - 273) * 8 + 35 + m_input.get_bits (3);
|
|
} else if (l < 281) {
|
|
length = (l - 277) * 16 + 67 + m_input.get_bits (4);
|
|
} else if (l < 285) {
|
|
length = (l - 281) * 32 + 131 + m_input.get_bits (5);
|
|
} else {
|
|
length = 258;
|
|
}
|
|
|
|
unsigned int d = mp_dist_decoder->decode (m_input);
|
|
unsigned int dist = 0;
|
|
if (d < 4) {
|
|
dist = d + 1;
|
|
} else if (d < 6) {
|
|
dist = (d - 4) * 2 + 5 + m_input.get_bits (1);
|
|
} else if (d < 8) {
|
|
dist = (d - 6) * 4 + 9 + m_input.get_bits (2);
|
|
} else if (d < 10) {
|
|
dist = (d - 8) * 8 + 17 + m_input.get_bits (3);
|
|
} else if (d < 12) {
|
|
dist = (d - 10) * 16 + 33 + m_input.get_bits (4);
|
|
} else if (d < 14) {
|
|
dist = (d - 12) * 32 + 65 + m_input.get_bits (5);
|
|
} else if (d < 16) {
|
|
dist = (d - 14) * 64 + 129 + m_input.get_bits (6);
|
|
} else if (d < 18) {
|
|
dist = (d - 16) * 128 + 257 + m_input.get_bits (7);
|
|
} else if (d < 20) {
|
|
dist = (d - 18) * 256 + 513 + m_input.get_bits (8);
|
|
} else if (d < 22) {
|
|
dist = (d - 20) * 512 + 1025 + m_input.get_bits (9);
|
|
} else if (d < 24) {
|
|
dist = (d - 22) * 1024 + 2049 + m_input.get_bits (10);
|
|
} else if (d < 26) {
|
|
dist = (d - 24) * 2048 + 4097 + m_input.get_bits (11);
|
|
} else if (d < 28) {
|
|
dist = (d - 26) * 4096 + 8193 + m_input.get_bits (12);
|
|
} else {
|
|
dist = (d - 28) * 8192 + 16385 + m_input.get_bits (13);
|
|
}
|
|
|
|
while (length-- > 0) {
|
|
put_byte_dist (dist);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (new_block) {
|
|
|
|
if (m_last_block) {
|
|
return false;
|
|
}
|
|
|
|
// read new block header
|
|
m_last_block = m_input.get_bit ();
|
|
unsigned int t = m_input.get_bits (2);
|
|
|
|
if (t == 0) {
|
|
|
|
// uncompressed data
|
|
m_input.skip_to_byte ();
|
|
m_uncompressed_length = m_input.get_bits (16);
|
|
m_input.get_bits (16);
|
|
|
|
} else if (t == 1 || t == 2) {
|
|
|
|
if (t == 1) {
|
|
|
|
// KLUDGE: should use a different decoder object, so we save time to do this:
|
|
mp_lit_decoder->fill_fixed_table_length ();
|
|
mp_dist_decoder->fill_fixed_table_dist ();
|
|
|
|
} else {
|
|
|
|
unsigned int hlit = m_input.get_bits (5) + 257;
|
|
unsigned int hdist = m_input.get_bits (5) + 1;
|
|
unsigned int hclen = m_input.get_bits (4) + 4;
|
|
|
|
unsigned int hclengths [19];
|
|
for (unsigned int i = 0; i < sizeof (hclengths) / sizeof (hclengths [0]); ++i) {
|
|
hclengths [i] = 0;
|
|
}
|
|
|
|
static unsigned int hclen_order [] = {
|
|
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2,
|
|
14, 1, 15
|
|
};
|
|
for (unsigned int i = 0; i < hclen; ++i) {
|
|
hclengths [hclen_order [i]] = m_input.get_bits (3);
|
|
}
|
|
|
|
HuffmannDecoder ldecoder;
|
|
ldecoder.init_codes (hclengths, hclengths + sizeof (hclengths) / sizeof (hclengths[0]));
|
|
|
|
unsigned int lengths [286 + 32];
|
|
unsigned int nlengths = hlit + hdist;
|
|
|
|
for (unsigned int i = 0; i < nlengths; ) {
|
|
|
|
unsigned short l = ldecoder.decode (m_input);
|
|
if (l < 16) {
|
|
lengths [i++] = l;
|
|
} else if (l == 16) {
|
|
unsigned int n = m_input.get_bits (2) + 3;
|
|
tl_assert (i > 0);
|
|
l = lengths [i - 1];
|
|
while (n-- > 0) {
|
|
tl_assert (i < nlengths);
|
|
lengths [i++] = l;
|
|
}
|
|
} else if (l == 17) {
|
|
unsigned int n = m_input.get_bits (3) + 3;
|
|
while (n-- > 0) {
|
|
tl_assert (i < nlengths);
|
|
lengths [i++] = 0;
|
|
}
|
|
} else if (l == 18) {
|
|
unsigned int n = m_input.get_bits (7) + 11;
|
|
while (n-- > 0) {
|
|
tl_assert (i < nlengths);
|
|
lengths [i++] = 0;
|
|
}
|
|
} else {
|
|
tl_assert (false);
|
|
}
|
|
|
|
}
|
|
|
|
mp_lit_decoder->init_codes (lengths, lengths + hlit);
|
|
mp_dist_decoder->init_codes (lengths + hlit, lengths + nlengths);
|
|
|
|
}
|
|
|
|
} else {
|
|
throw tl::Exception (tl::to_string (QObject::tr ("Invalid compression type: %d")), t);
|
|
}
|
|
|
|
} else {
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------
|
|
// DeflateFilter implementation
|
|
// This implementation is based on the zlib
|
|
|
|
DeflateFilter::DeflateFilter (tl::OutputStream &output)
|
|
: m_finished (false), mp_output (&output), m_uc (0), m_cc (0)
|
|
{
|
|
mp_stream = new z_stream ();
|
|
mp_stream->zalloc = (alloc_func)0;
|
|
mp_stream->zfree = (free_func)0;
|
|
mp_stream->opaque = (voidpf)0;
|
|
mp_stream->next_in = (Byte *)0;
|
|
mp_stream->avail_in = 0;
|
|
mp_stream->next_out = (Byte *)m_buffer;
|
|
mp_stream->avail_out = sizeof (m_buffer);
|
|
|
|
int err = deflateInit2 (mp_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15 /* == raw deflate data*/, 8 /* == default memory level */, Z_DEFAULT_STRATEGY);
|
|
tl_assert (err == Z_OK);
|
|
}
|
|
|
|
DeflateFilter::~DeflateFilter ()
|
|
{
|
|
delete mp_stream;
|
|
}
|
|
|
|
void
|
|
DeflateFilter::put (const char *b, size_t n)
|
|
{
|
|
m_uc += n;
|
|
|
|
mp_stream->next_in = (Byte *)b;
|
|
mp_stream->avail_in = n;
|
|
|
|
while (mp_stream->avail_in > 0) {
|
|
|
|
int err = deflate (mp_stream, Z_NO_FLUSH);
|
|
tl_assert (err == Z_OK);
|
|
|
|
if (mp_stream->avail_out == 0) {
|
|
m_cc += sizeof (m_buffer);
|
|
mp_output->put (m_buffer, sizeof (m_buffer));
|
|
mp_stream->next_out = (Byte *)m_buffer;
|
|
mp_stream->avail_out = sizeof (m_buffer);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
DeflateFilter::flush ()
|
|
{
|
|
while (true) {
|
|
|
|
int err = deflate (mp_stream, Z_FINISH);
|
|
tl_assert (err == Z_OK || err == Z_STREAM_END);
|
|
|
|
m_cc += sizeof (m_buffer) - mp_stream->avail_out;
|
|
mp_output->put (m_buffer, sizeof (m_buffer) - mp_stream->avail_out);
|
|
mp_stream->next_out = (Byte *)m_buffer;
|
|
mp_stream->avail_out = sizeof (m_buffer);
|
|
|
|
if (err == Z_STREAM_END) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
int err = deflateEnd (mp_stream);
|
|
tl_assert (err == Z_OK);
|
|
|
|
mp_output->flush ();
|
|
m_finished = true;
|
|
}
|
|
|
|
}
|
|
|