kopia lustrzana https://github.com/micropython/micropython
lib/uzlib/defl_static: Optimize zlib_start/finish_block.
Collapsing the two adjacent calls to outbits saves 32 bytes. Bringing defl_static.c into lz77.c allows better inlining, saves 24 bytes. Merge the Outbuf/uzlib_lz77_state_t structs, a minor simplification that doesn't change code size. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>pull/11905/head
rodzic
ef5061fefd
commit
7f16bfca9f
|
@ -52,15 +52,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
* having to transmit the trees.
|
* having to transmit the trees.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void outbits(struct Outbuf *out, unsigned long bits, int nbits)
|
static void outbits(uzlib_lz77_state_t *state, unsigned long bits, int nbits)
|
||||||
{
|
{
|
||||||
assert(out->noutbits + nbits <= 32);
|
assert(state->noutbits + nbits <= 32);
|
||||||
out->outbits |= bits << out->noutbits;
|
state->outbits |= bits << state->noutbits;
|
||||||
out->noutbits += nbits;
|
state->noutbits += nbits;
|
||||||
while (out->noutbits >= 8) {
|
while (state->noutbits >= 8) {
|
||||||
out->dest_write_cb(out->dest_write_data, out->outbits & 0xFF);
|
state->dest_write_cb(state->dest_write_data, state->outbits & 0xFF);
|
||||||
out->outbits >>= 8;
|
state->outbits >>= 8;
|
||||||
out->noutbits -= 8;
|
state->noutbits -= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,18 +81,18 @@ static int int_log2(int x) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void zlib_literal(struct Outbuf *out, unsigned char c)
|
static void uzlib_literal(uzlib_lz77_state_t *state, unsigned char c)
|
||||||
{
|
{
|
||||||
if (c <= 143) {
|
if (c <= 143) {
|
||||||
/* 0 through 143 are 8 bits long starting at 00110000. */
|
/* 0 through 143 are 8 bits long starting at 00110000. */
|
||||||
outbits(out, mirrorbyte(0x30 + c), 8);
|
outbits(state, mirrorbyte(0x30 + c), 8);
|
||||||
} else {
|
} else {
|
||||||
/* 144 through 255 are 9 bits long starting at 110010000. */
|
/* 144 through 255 are 9 bits long starting at 110010000. */
|
||||||
outbits(out, 1 + 2 * mirrorbyte(0x90 - 144 + c), 9);
|
outbits(state, 1 + 2 * mirrorbyte(0x90 - 144 + c), 9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void zlib_match(struct Outbuf *out, int distance, int len)
|
static void uzlib_match(uzlib_lz77_state_t *state, int distance, int len)
|
||||||
{
|
{
|
||||||
assert(distance >= 1 && distance <= 32768);
|
assert(distance >= 1 && distance <= 32768);
|
||||||
distance -= 1;
|
distance -= 1;
|
||||||
|
@ -133,9 +133,9 @@ void zlib_match(struct Outbuf *out, int distance, int len)
|
||||||
* 11000000.
|
* 11000000.
|
||||||
*/
|
*/
|
||||||
if (lcode <= 22) {
|
if (lcode <= 22) {
|
||||||
outbits(out, mirrorbyte((lcode + 1) * 2), 7);
|
outbits(state, mirrorbyte((lcode + 1) * 2), 7);
|
||||||
} else {
|
} else {
|
||||||
outbits(out, mirrorbyte(lcode + 169), 8);
|
outbits(state, mirrorbyte(lcode + 169), 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -144,7 +144,7 @@ void zlib_match(struct Outbuf *out, int distance, int len)
|
||||||
if (thislen < 255 && x > 1) {
|
if (thislen < 255 && x > 1) {
|
||||||
int extrabits = x - 1;
|
int extrabits = x - 1;
|
||||||
int lmin = (thislen >> extrabits) << extrabits;
|
int lmin = (thislen >> extrabits) << extrabits;
|
||||||
outbits(out, thislen - lmin, extrabits);
|
outbits(state, thislen - lmin, extrabits);
|
||||||
}
|
}
|
||||||
|
|
||||||
x = int_log2(distance);
|
x = int_log2(distance);
|
||||||
|
@ -153,7 +153,7 @@ void zlib_match(struct Outbuf *out, int distance, int len)
|
||||||
/*
|
/*
|
||||||
* Transmit the distance code. Five bits starting at 00000.
|
* Transmit the distance code. Five bits starting at 00000.
|
||||||
*/
|
*/
|
||||||
outbits(out, mirrorbyte((x * 2 + y) * 8), 5);
|
outbits(state, mirrorbyte((x * 2 + y) * 8), 5);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transmit the extra bits.
|
* Transmit the extra bits.
|
||||||
|
@ -161,20 +161,21 @@ void zlib_match(struct Outbuf *out, int distance, int len)
|
||||||
if (x > 1) {
|
if (x > 1) {
|
||||||
int dextrabits = x - 1;
|
int dextrabits = x - 1;
|
||||||
int dmin = (distance >> dextrabits) << dextrabits;
|
int dmin = (distance >> dextrabits) << dextrabits;
|
||||||
outbits(out, distance - dmin, dextrabits);
|
outbits(state, distance - dmin, dextrabits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void zlib_start_block(struct Outbuf *out)
|
void uzlib_start_block(uzlib_lz77_state_t *state)
|
||||||
{
|
{
|
||||||
// outbits(out, 0x9C78, 16);
|
// Final block (0b1)
|
||||||
outbits(out, 1, 1); /* Final block */
|
// Static huffman block (0b01)
|
||||||
outbits(out, 1, 2); /* Static huffman block */
|
outbits(state, 3, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void zlib_finish_block(struct Outbuf *out)
|
void uzlib_finish_block(uzlib_lz77_state_t *state)
|
||||||
{
|
{
|
||||||
outbits(out, 0, 7); /* close block */
|
// Close block (0b0000000)
|
||||||
outbits(out, 0, 7); /* Make sure all bits are flushed */
|
// Make sure all bits are flushed (0b0000000)
|
||||||
|
outbits(state, 0, 14);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) uzlib authors
|
|
||||||
*
|
|
||||||
* This software is provided 'as-is', without any express
|
|
||||||
* or implied warranty. In no event will the authors 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This files contains type declaration and prototypes for defl_static.c.
|
|
||||||
They may be altered/distinct from the originals used in PuTTY source
|
|
||||||
code. */
|
|
||||||
|
|
||||||
struct Outbuf {
|
|
||||||
void *dest_write_data;
|
|
||||||
void (*dest_write_cb)(void *data, uint8_t byte);
|
|
||||||
unsigned long outbits;
|
|
||||||
int noutbits;
|
|
||||||
};
|
|
||||||
|
|
||||||
void zlib_start_block(struct Outbuf *ctx);
|
|
||||||
void zlib_finish_block(struct Outbuf *ctx);
|
|
||||||
void zlib_literal(struct Outbuf *ectx, unsigned char c);
|
|
||||||
void zlib_match(struct Outbuf *ectx, int distance, int len);
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include "uzlib.h"
|
#include "uzlib.h"
|
||||||
|
|
||||||
|
#include "defl_static.c"
|
||||||
|
|
||||||
#define MATCH_LEN_MIN (3)
|
#define MATCH_LEN_MIN (3)
|
||||||
#define MATCH_LEN_MAX (258)
|
#define MATCH_LEN_MAX (258)
|
||||||
|
|
||||||
|
@ -18,8 +20,8 @@
|
||||||
// hist_max should be greater than 0 a power of 2 (ie 1, 2, 4, 8, ...).
|
// hist_max should be greater than 0 a power of 2 (ie 1, 2, 4, 8, ...).
|
||||||
// It's possible to pass in hist=NULL, and then the history window will be taken from the
|
// It's possible to pass in hist=NULL, and then the history window will be taken from the
|
||||||
// src passed in to uzlib_lz77_compress (this is useful when not doing streaming compression).
|
// src passed in to uzlib_lz77_compress (this is useful when not doing streaming compression).
|
||||||
void uzlib_lz77_init(struct uzlib_lz77_state *state, uint8_t *hist, size_t hist_max) {
|
void uzlib_lz77_init(uzlib_lz77_state_t *state, uint8_t *hist, size_t hist_max) {
|
||||||
memset(&state->outbuf, 0, sizeof(state->outbuf));
|
memset(state, 0, sizeof(uzlib_lz77_state_t));
|
||||||
state->hist_buf = hist;
|
state->hist_buf = hist;
|
||||||
state->hist_max = hist_max;
|
state->hist_max = hist_max;
|
||||||
state->hist_start = 0;
|
state->hist_start = 0;
|
||||||
|
@ -30,7 +32,7 @@ void uzlib_lz77_init(struct uzlib_lz77_state *state, uint8_t *hist, size_t hist_
|
||||||
// Search back in the history for the maximum match of the given src data,
|
// Search back in the history for the maximum match of the given src data,
|
||||||
// with support for searching beyond the end of the history and into the src buffer
|
// with support for searching beyond the end of the history and into the src buffer
|
||||||
// (effectively the history and src buffer are concatenated).
|
// (effectively the history and src buffer are concatenated).
|
||||||
static size_t uzlib_lz77_search_max_match(struct uzlib_lz77_state *state, const uint8_t *src, size_t len, size_t *longest_offset) {
|
static size_t uzlib_lz77_search_max_match(uzlib_lz77_state_t *state, const uint8_t *src, size_t len, size_t *longest_offset) {
|
||||||
size_t longest_len = 0;
|
size_t longest_len = 0;
|
||||||
for (size_t hist_search = 0; hist_search < state->hist_len; ++hist_search) {
|
for (size_t hist_search = 0; hist_search < state->hist_len; ++hist_search) {
|
||||||
size_t match_len;
|
size_t match_len;
|
||||||
|
@ -55,7 +57,7 @@ static size_t uzlib_lz77_search_max_match(struct uzlib_lz77_state *state, const
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress the given chunk of data.
|
// Compress the given chunk of data.
|
||||||
void uzlib_lz77_compress(struct uzlib_lz77_state *state, const uint8_t *src, unsigned len) {
|
void uzlib_lz77_compress(uzlib_lz77_state_t *state, const uint8_t *src, unsigned len) {
|
||||||
const uint8_t *top = src + len;
|
const uint8_t *top = src + len;
|
||||||
while (src < top) {
|
while (src < top) {
|
||||||
// Look for a match in the history window.
|
// Look for a match in the history window.
|
||||||
|
@ -64,10 +66,10 @@ void uzlib_lz77_compress(struct uzlib_lz77_state *state, const uint8_t *src, uns
|
||||||
|
|
||||||
// Encode the literal byte or the match.
|
// Encode the literal byte or the match.
|
||||||
if (match_len == 0) {
|
if (match_len == 0) {
|
||||||
zlib_literal(&state->outbuf, *src);
|
uzlib_literal(state, *src);
|
||||||
match_len = 1;
|
match_len = 1;
|
||||||
} else {
|
} else {
|
||||||
zlib_match(&state->outbuf, match_offset, match_len);
|
uzlib_match(state, match_offset, match_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push the bytes into the history buffer.
|
// Push the bytes into the history buffer.
|
||||||
|
|
|
@ -42,8 +42,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "defl_static.h"
|
|
||||||
|
|
||||||
#include "uzlib_conf.h"
|
#include "uzlib_conf.h"
|
||||||
#if UZLIB_CONF_DEBUG_LOG
|
#if UZLIB_CONF_DEBUG_LOG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -135,16 +133,22 @@ int uzlib_parse_zlib_gzip_header(uzlib_uncomp_t *d, int *wbits);
|
||||||
|
|
||||||
/* Compression API */
|
/* Compression API */
|
||||||
|
|
||||||
struct uzlib_lz77_state {
|
typedef struct {
|
||||||
struct Outbuf outbuf;
|
void *dest_write_data;
|
||||||
|
void (*dest_write_cb)(void *data, uint8_t byte);
|
||||||
|
unsigned long outbits;
|
||||||
|
int noutbits;
|
||||||
uint8_t *hist_buf;
|
uint8_t *hist_buf;
|
||||||
size_t hist_max;
|
size_t hist_max;
|
||||||
size_t hist_start;
|
size_t hist_start;
|
||||||
size_t hist_len;
|
size_t hist_len;
|
||||||
};
|
} uzlib_lz77_state_t;
|
||||||
|
|
||||||
void uzlib_lz77_init(struct uzlib_lz77_state *state, uint8_t *hist, size_t hist_max);
|
void uzlib_lz77_init(uzlib_lz77_state_t *state, uint8_t *hist, size_t hist_max);
|
||||||
void uzlib_lz77_compress(struct uzlib_lz77_state *state, const uint8_t *src, unsigned len);
|
void uzlib_lz77_compress(uzlib_lz77_state_t *state, const uint8_t *src, unsigned len);
|
||||||
|
|
||||||
|
void uzlib_start_block(uzlib_lz77_state_t *state);
|
||||||
|
void uzlib_finish_block(uzlib_lz77_state_t *state);
|
||||||
|
|
||||||
/* Checksum API */
|
/* Checksum API */
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue