Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions heatshrink.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ static void usage(void) {
" -e encode (compress, default)\n"
" -d decode (decompress)\n"
" -v verbose (print input & output sizes, compression ratio, etc.)\n"
" -z avoid references to initial window\n"
"\n"
" -w SIZE Base-2 log of LZSS sliding window size\n"
"\n"
Expand Down Expand Up @@ -102,6 +103,7 @@ typedef struct {
size_t decoder_input_buffer_size;
size_t buffer_size;
uint8_t verbose;
uint8_t no_initial;
Operation cmd;
char *in_fname;
char *out_fname;
Expand Down Expand Up @@ -280,7 +282,7 @@ static int encoder_sink_read(config *cfg, heatshrink_encoder *hse,
static int encode(config *cfg) {
uint8_t window_sz2 = cfg->window_sz2;
size_t window_sz = 1 << window_sz2;
heatshrink_encoder *hse = heatshrink_encoder_alloc(window_sz2, cfg->lookahead_sz2);
heatshrink_encoder *hse = heatshrink_encoder_alloc_z(window_sz2, cfg->lookahead_sz2, cfg->no_initial);
if (hse == NULL) { die("failed to init encoder: bad settings"); }
ssize_t read_sz = 0;
io_handle *in = cfg->in;
Expand Down Expand Up @@ -401,11 +403,12 @@ static void proc_args(config *cfg, int argc, char **argv) {
cfg->decoder_input_buffer_size = DEF_DECODER_INPUT_BUFFER_SIZE;
cfg->cmd = OP_ENC;
cfg->verbose = 0;
cfg->no_initial = 0;
cfg->in_fname = "-";
cfg->out_fname = "-";

int a = 0;
while ((a = getopt(argc, argv, "hedi:w:l:v")) != -1) {
while ((a = getopt(argc, argv, "hedi:w:l:vz")) != -1) {
switch (a) {
case 'h': /* help */
usage();
Expand All @@ -425,6 +428,9 @@ static void proc_args(config *cfg, int argc, char **argv) {
case 'v': /* verbosity++ */
cfg->verbose++;
break;
case 'z': /* verbosity++ */
cfg->no_initial = 1;
break;
case '?': /* unknown argument */
default:
usage();
Expand Down
25 changes: 24 additions & 1 deletion heatshrink_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ static void push_literal_byte(heatshrink_encoder *hse, output_info *oi);
#if HEATSHRINK_DYNAMIC_ALLOC
heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2,
uint8_t lookahead_sz2) {
return heatshrink_encoder_alloc_z(window_sz2, lookahead_sz2, 0);
}

heatshrink_encoder *heatshrink_encoder_alloc_z(uint8_t window_sz2,
uint8_t lookahead_sz2, uint8_t no_initial) {
if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) ||
(window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) ||
(lookahead_sz2 < HEATSHRINK_MIN_LOOKAHEAD_BITS) ||
Expand All @@ -86,6 +91,7 @@ heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2,
if (hse == NULL) { return NULL; }
hse->window_sz2 = window_sz2;
hse->lookahead_sz2 = lookahead_sz2;
hse->no_initial = no_initial;
heatshrink_encoder_reset(hse);

#if HEATSHRINK_USE_INDEX
Expand Down Expand Up @@ -125,6 +131,7 @@ void heatshrink_encoder_reset(heatshrink_encoder *hse) {
hse->bit_index = 0x80;
hse->current_byte = 0x00;
hse->match_length = 0;
hse->processed = 0;

hse->outgoing_bits = 0x0000;
hse->outgoing_bits_count = 0;
Expand Down Expand Up @@ -257,6 +264,15 @@ HSE_finish_res heatshrink_encoder_finish(heatshrink_encoder *hse) {
return hse->state == HSES_DONE ? HSER_FINISH_DONE : HSER_FINISH_MORE;
}

static void add_to_processed(heatshrink_encoder *hse, uint16_t length) {
uint16_t old = hse->processed;
uint16_t new = old + length;
if (new < old) {
new = 0xFFFF; /* saturate */
}
hse->processed = new;
}

static HSE_state st_step_search(heatshrink_encoder *hse) {
uint16_t window_length = get_input_buffer_size(hse);
uint16_t lookahead_sz = get_lookahead_size(hse);
Expand All @@ -274,7 +290,12 @@ static HSE_state st_step_search(heatshrink_encoder *hse) {

uint16_t input_offset = get_input_offset(hse);
uint16_t end = input_offset + msi;
uint16_t start = end - window_length;
uint16_t start;
if (hse->no_initial && hse->processed < window_length) {
start = end - hse->processed;
} else {
start = end - window_length;
}

uint16_t max_possible = lookahead_sz;
if (hse->input_size - msi < lookahead_sz) {
Expand All @@ -289,11 +310,13 @@ static HSE_state st_step_search(heatshrink_encoder *hse) {
LOG("ss Match not found\n");
hse->match_scan_index++;
hse->match_length = 0;
add_to_processed(hse, 1);
return HSES_YIELD_TAG_BIT;
} else {
LOG("ss Found match of %d bytes at %d\n", match_length, match_pos);
hse->match_pos = match_pos;
hse->match_length = match_length;
add_to_processed(hse, match_length);
ASSERT(match_pos <= 1 << HEATSHRINK_ENCODER_WINDOW_BITS(hse) /*window_length*/);

return HSES_YIELD_TAG_BIT;
Expand Down
4 changes: 4 additions & 0 deletions heatshrink_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ typedef struct {
uint16_t match_length;
uint16_t match_pos;
uint16_t outgoing_bits; /* enqueued outgoing bits */
uint16_t processed;
uint8_t outgoing_bits_count;
uint8_t flags;
uint8_t state; /* current state machine node */
uint8_t current_byte; /* current byte of output */
uint8_t bit_index; /* current bit index */
uint8_t no_initial; /* avoid references to initial window */
#if HEATSHRINK_DYNAMIC_ALLOC
uint8_t window_sz2; /* 2^n size of window */
uint8_t lookahead_sz2; /* 2^n size of lookahead */
Expand All @@ -82,6 +84,8 @@ typedef struct {
* Returns NULL on error. */
heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2,
uint8_t lookahead_sz2);
heatshrink_encoder *heatshrink_encoder_alloc_z(uint8_t window_sz2,
uint8_t lookahead_sz2, uint8_t no_initial);

/* Free an encoder. */
void heatshrink_encoder_free(heatshrink_encoder *hse);
Expand Down