MeterLogger
Data Structures | Macros | Enumerations | Functions
heatshrink_decoder.c File Reference
#include <stdlib.h>
#include <string.h>
#include "heatshrink_decoder.h"
Include dependency graph for heatshrink_decoder.c:

Go to the source code of this file.

Data Structures

struct  output_info
 

Macros

#define LOG(...)   /* no-op */
 
#define ASSERT(X)   /* no-op */
 
#define NO_BITS   ((uint32_t)-1)
 
#define BACKREF_COUNT_BITS(HSD)   (HEATSHRINK_DECODER_LOOKAHEAD_BITS(HSD))
 
#define BACKREF_INDEX_BITS(HSD)   (HEATSHRINK_DECODER_WINDOW_BITS(HSD))
 

Enumerations

enum  HSD_state {
  HSDS_EMPTY, HSDS_INPUT_AVAILABLE, HSDS_YIELD_LITERAL, HSDS_BACKREF_INDEX_MSB,
  HSDS_BACKREF_INDEX_LSB, HSDS_BACKREF_COUNT_MSB, HSDS_BACKREF_COUNT_LSB, HSDS_YIELD_BACKREF,
  HSDS_CHECK_FOR_MORE_INPUT
}
 

Functions

static uint32_t get_bits (heatshrink_decoder *hsd, uint8_t count)
 
static void push_byte (heatshrink_decoder *hsd, output_info *oi, uint8_t byte)
 
heatshrink_decoderheatshrink_decoder_alloc (uint16_t input_buffer_size, uint8_t window_sz2, uint8_t lookahead_sz2)
 
void heatshrink_decoder_free (heatshrink_decoder *hsd)
 
void heatshrink_decoder_reset (heatshrink_decoder *hsd)
 
HSD_sink_res heatshrink_decoder_sink (heatshrink_decoder *hsd, uint8_t *in_buf, size_t size, size_t *input_size)
 
static HSD_state st_input_available (heatshrink_decoder *hsd)
 
static HSD_state st_yield_literal (heatshrink_decoder *hsd, output_info *oi)
 
static HSD_state st_backref_index_msb (heatshrink_decoder *hsd)
 
static HSD_state st_backref_index_lsb (heatshrink_decoder *hsd)
 
static HSD_state st_backref_count_msb (heatshrink_decoder *hsd)
 
static HSD_state st_backref_count_lsb (heatshrink_decoder *hsd)
 
static HSD_state st_yield_backref (heatshrink_decoder *hsd, output_info *oi)
 
static HSD_state st_check_for_input (heatshrink_decoder *hsd)
 
HSD_poll_res heatshrink_decoder_poll (heatshrink_decoder *hsd, uint8_t *out_buf, size_t out_buf_size, size_t *output_size)
 
HSD_finish_res heatshrink_decoder_finish (heatshrink_decoder *hsd)
 

Macro Definition Documentation

◆ ASSERT

#define ASSERT (   X)    /* no-op */

◆ BACKREF_COUNT_BITS

#define BACKREF_COUNT_BITS (   HSD)    (HEATSHRINK_DECODER_LOOKAHEAD_BITS(HSD))

◆ BACKREF_INDEX_BITS

#define BACKREF_INDEX_BITS (   HSD)    (HEATSHRINK_DECODER_WINDOW_BITS(HSD))

Definition at line 129 of file heatshrink_decoder.c.

Referenced by st_backref_index_lsb(), and st_backref_index_msb().

◆ LOG

#define LOG (   ...)    /* no-op */

◆ NO_BITS

#define NO_BITS   ((uint32_t)-1)

Enumeration Type Documentation

◆ HSD_state

enum HSD_state
Enumerator
HSDS_EMPTY 
HSDS_INPUT_AVAILABLE 
HSDS_YIELD_LITERAL 
HSDS_BACKREF_INDEX_MSB 
HSDS_BACKREF_INDEX_LSB 
HSDS_BACKREF_COUNT_MSB 
HSDS_BACKREF_COUNT_LSB 
HSDS_YIELD_BACKREF 
HSDS_CHECK_FOR_MORE_INPUT 

Definition at line 6 of file heatshrink_decoder.c.

6  {
7  HSDS_EMPTY, /* no input to process */
8  HSDS_INPUT_AVAILABLE, /* new input, completely unprocessed */
9  HSDS_YIELD_LITERAL, /* ready to yield literal byte */
10  HSDS_BACKREF_INDEX_MSB, /* most significant byte of index */
11  HSDS_BACKREF_INDEX_LSB, /* least significant byte of index */
12  HSDS_BACKREF_COUNT_MSB, /* most significant byte of count */
13  HSDS_BACKREF_COUNT_LSB, /* least significant byte of count */
14  HSDS_YIELD_BACKREF, /* ready to yield back-reference */
15  HSDS_CHECK_FOR_MORE_INPUT, /* check if input is exhausted */
16 } HSD_state;
HSD_state

Function Documentation

◆ get_bits()

static uint32_t get_bits ( heatshrink_decoder hsd,
uint8_t  count 
)
static

Definition at line 305 of file heatshrink_decoder.c.

References heatshrink_decoder::bit_accumulator, heatshrink_decoder::bit_index, heatshrink_decoder::buffers, heatshrink_decoder::current_byte, heatshrink_decoder::input_index, heatshrink_decoder::input_size, LOG, and NO_BITS.

Referenced by st_backref_count_lsb(), st_backref_count_msb(), st_backref_index_lsb(), st_backref_index_msb(), st_input_available(), and st_yield_literal().

305  {
306  int i;
307  if (count > 31) { return NO_BITS; }
308  LOG("-- popping %u bit(s)\n", count);
309 
310  /* If we aren't able to get COUNT bits, suspend immediately, because we
311  * don't track how many bits of COUNT we've accumulated before suspend. */
312  if (hsd->input_size == 0) {
313  if (hsd->bit_index < (1 << (count - 1))) { return NO_BITS; }
314  }
315 
316  for (i = 0; i < count; i++) {
317  if (hsd->bit_index == 0x00) {
318  if (hsd->input_size == 0) {
319  LOG(" -- out of bits, suspending w/ accumulator of %u (0x%02x)\n",
320  hsd->bit_accumulator, hsd->bit_accumulator);
321  return NO_BITS;
322  }
323  hsd->current_byte = hsd->buffers[hsd->input_index++];
324  LOG(" -- pulled byte 0x%02x\n", hsd->current_byte);
325  if (hsd->input_index == hsd->input_size) {
326  hsd->input_index = 0; /* input is exhausted */
327  hsd->input_size = 0;
328  }
329  hsd->bit_index = 0x80;
330  }
331  hsd->bit_accumulator <<= 1;
332  if (hsd->current_byte & hsd->bit_index) {
333  hsd->bit_accumulator |= 0x01;
334  if (0) {
335  LOG(" -- got 1, accumulator 0x%04x, bit_index 0x%02x\n",
336  hsd->bit_accumulator, hsd->bit_index);
337  }
338  } else {
339  if (0) {
340  LOG(" -- got 0, accumulator 0x%04x, bit_index 0x%02x\n",
341  hsd->bit_accumulator, hsd->bit_index);
342  }
343  }
344  hsd->bit_index >>= 1;
345  }
346 
347  uint32_t res = 0;
348  res = hsd->bit_accumulator;
349  hsd->bit_accumulator = 0x00000000;
350  if (count > 1) { LOG(" -- accumulated %08x\n", res); }
351  return res;
352 }
#define NO_BITS
#define LOG(...)
Here is the caller graph for this function:

◆ heatshrink_decoder_alloc()

heatshrink_decoder* heatshrink_decoder_alloc ( uint16_t  input_buffer_size,
uint8_t  window_sz2,
uint8_t  lookahead_sz2 
)

Definition at line 51 of file heatshrink_decoder.c.

References heatshrink_decoder_reset(), HEATSHRINK_MALLOC, HEATSHRINK_MAX_WINDOW_BITS, HEATSHRINK_MIN_LOOKAHEAD_BITS, HEATSHRINK_MIN_WINDOW_BITS, hsd, heatshrink_decoder::input_buffer_size, LOG, heatshrink_decoder::lookahead_sz2, NULL, and heatshrink_decoder::window_sz2.

Referenced by compress_and_expand_and_check(), data_with_simple_repetition_should_match_with_absurdly_tiny_buffers(), data_without_duplication_should_match_with_absurdly_tiny_buffers(), decode(), decoder_alloc_should_reject_excessively_small_window(), decoder_alloc_should_reject_zero_byte_input_buffer(), decoder_finish_should_note_when_done(), decoder_finish_should_reject_null_input(), decoder_poll_should_expand_short_literal(), decoder_poll_should_expand_short_literal_and_backref(), decoder_poll_should_expand_short_literal_and_backref_when_fed_input_byte_by_byte(), decoder_poll_should_expand_short_self_overlapping_backref(), decoder_poll_should_reject_null_output_buffer(), decoder_poll_should_reject_null_output_size_pointer(), decoder_poll_should_return_empty_if_empty(), decoder_poll_should_suspend_if_out_of_space_in_output_buffer_during_backref_expansion(), decoder_poll_should_suspend_if_out_of_space_in_output_buffer_during_literal_expansion(), decoder_should_not_get_stuck_with_finish_yielding_MORE_but_0_bytes_output_from_poll(), decoder_sink_should_reject_excessively_large_input(), decoder_sink_should_reject_null_count_pointer(), decoder_sink_should_reject_null_input_pointer(), decoder_sink_should_sink_data_when_preconditions_hold(), and espFsOpen().

53  {
54  if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) ||
55  (window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) ||
56  (input_buffer_size == 0) ||
57  (lookahead_sz2 < HEATSHRINK_MIN_LOOKAHEAD_BITS) ||
58  (lookahead_sz2 > window_sz2)) {
59  return NULL;
60  }
61  size_t buffers_sz = (1 << window_sz2) + input_buffer_size;
62  size_t sz = sizeof(heatshrink_decoder) + buffers_sz;
64  if (hsd == NULL) { return NULL; }
65  hsd->input_buffer_size = input_buffer_size;
66  hsd->window_sz2 = window_sz2;
67  hsd->lookahead_sz2 = lookahead_sz2;
69  LOG("-- allocated decoder with buffer size of %zu (%zu + %u + %u)\n",
70  sz, sizeof(heatshrink_decoder), (1 << window_sz2), input_buffer_size);
71  return hsd;
72 }
#define HEATSHRINK_MAX_WINDOW_BITS
#define NULL
Definition: def.h:47
#define HEATSHRINK_MIN_WINDOW_BITS
#define LOG(...)
static heatshrink_decoder hsd
void heatshrink_decoder_reset(heatshrink_decoder *hsd)
#define HEATSHRINK_MALLOC(SZ)
#define HEATSHRINK_MIN_LOOKAHEAD_BITS
Here is the call graph for this function:
Here is the caller graph for this function:

◆ heatshrink_decoder_finish()

HSD_finish_res heatshrink_decoder_finish ( heatshrink_decoder hsd)

Definition at line 354 of file heatshrink_decoder.c.

References HSDR_FINISH_DONE, HSDR_FINISH_ERROR_NULL, HSDR_FINISH_MORE, HSDS_BACKREF_COUNT_LSB, HSDS_BACKREF_COUNT_MSB, HSDS_BACKREF_INDEX_LSB, HSDS_BACKREF_INDEX_MSB, HSDS_EMPTY, HSDS_YIELD_LITERAL, heatshrink_decoder::input_size, NULL, and heatshrink_decoder::state.

Referenced by compress_and_expand_and_check(), decode(), decoder_finish_should_note_when_done(), decoder_finish_should_reject_null_input(), decoder_poll_should_expand_short_literal_and_backref_when_fed_input_byte_by_byte(), decoder_should_not_get_stuck_with_finish_yielding_MORE_but_0_bytes_output_from_poll(), decoder_sink_read(), and espFsRead().

354  {
355  if (hsd == NULL) { return HSDR_FINISH_ERROR_NULL; }
356  switch (hsd->state) {
357  case HSDS_EMPTY:
358  return HSDR_FINISH_DONE;
359 
360  /* If we want to finish with no input, but are in these states, it's
361  * because the 0-bit padding to the last byte looks like a backref
362  * marker bit followed by all 0s for index and count bits. */
367  return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE;
368 
369  /* If the output stream is padded with 0xFFs (possibly due to being in
370  * flash memory), also explicitly check the input size rather than
371  * uselessly returning MORE but yielding 0 bytes when polling. */
372  case HSDS_YIELD_LITERAL:
373  return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE;
374 
375  default:
376  return HSDR_FINISH_MORE;
377  }
378 }
#define NULL
Definition: def.h:47
Here is the caller graph for this function:

◆ heatshrink_decoder_free()

void heatshrink_decoder_free ( heatshrink_decoder hsd)

Definition at line 74 of file heatshrink_decoder.c.

References HEATSHRINK_FREE, heatshrink_decoder::input_buffer_size, and heatshrink_decoder::window_sz2.

Referenced by compress_and_expand_and_check(), data_with_simple_repetition_should_match_with_absurdly_tiny_buffers(), data_without_duplication_should_match_with_absurdly_tiny_buffers(), decode(), decoder_finish_should_note_when_done(), decoder_finish_should_reject_null_input(), decoder_poll_should_expand_short_literal(), decoder_poll_should_expand_short_literal_and_backref(), decoder_poll_should_expand_short_literal_and_backref_when_fed_input_byte_by_byte(), decoder_poll_should_expand_short_self_overlapping_backref(), decoder_poll_should_reject_null_output_buffer(), decoder_poll_should_reject_null_output_size_pointer(), decoder_poll_should_return_empty_if_empty(), decoder_poll_should_suspend_if_out_of_space_in_output_buffer_during_backref_expansion(), decoder_poll_should_suspend_if_out_of_space_in_output_buffer_during_literal_expansion(), decoder_should_not_get_stuck_with_finish_yielding_MORE_but_0_bytes_output_from_poll(), decoder_sink_should_reject_excessively_large_input(), decoder_sink_should_reject_null_count_pointer(), decoder_sink_should_reject_null_input_pointer(), decoder_sink_should_sink_data_when_preconditions_hold(), and espFsClose().

74  {
75  size_t buffers_sz = (1 << hsd->window_sz2) + hsd->input_buffer_size;
76  size_t sz = sizeof(heatshrink_decoder) + buffers_sz;
77  HEATSHRINK_FREE(hsd, sz);
78  (void)sz; /* may not be used by free */
79 }
#define HEATSHRINK_FREE(P, SZ)
Here is the caller graph for this function:

◆ heatshrink_decoder_poll()

HSD_poll_res heatshrink_decoder_poll ( heatshrink_decoder hsd,
uint8_t *  out_buf,
size_t  out_buf_size,
size_t output_size 
)

Definition at line 143 of file heatshrink_decoder.c.

References output_info::buf, output_info::buf_size, HSDR_POLL_EMPTY, HSDR_POLL_ERROR_NULL, HSDR_POLL_ERROR_UNKNOWN, HSDR_POLL_MORE, HSDS_BACKREF_COUNT_LSB, HSDS_BACKREF_COUNT_MSB, HSDS_BACKREF_INDEX_LSB, HSDS_BACKREF_INDEX_MSB, HSDS_CHECK_FOR_MORE_INPUT, HSDS_EMPTY, HSDS_INPUT_AVAILABLE, HSDS_YIELD_BACKREF, HSDS_YIELD_LITERAL, heatshrink_decoder::input_size, LOG, NULL, output_info::output_size, st_backref_count_lsb(), st_backref_count_msb(), st_backref_index_lsb(), st_backref_index_msb(), st_check_for_input(), st_input_available(), st_yield_backref(), st_yield_literal(), and heatshrink_decoder::state.

Referenced by compress_and_expand_and_check(), data_with_simple_repetition_should_match_with_absurdly_tiny_buffers(), data_without_duplication_should_match_with_absurdly_tiny_buffers(), decoder_finish_should_note_when_done(), decoder_poll_should_expand_short_literal(), decoder_poll_should_expand_short_literal_and_backref(), decoder_poll_should_expand_short_literal_and_backref_when_fed_input_byte_by_byte(), decoder_poll_should_expand_short_self_overlapping_backref(), decoder_poll_should_reject_null_hsd(), decoder_poll_should_reject_null_output_buffer(), decoder_poll_should_reject_null_output_size_pointer(), decoder_poll_should_return_empty_if_empty(), decoder_poll_should_suspend_if_out_of_space_in_output_buffer_during_backref_expansion(), decoder_poll_should_suspend_if_out_of_space_in_output_buffer_during_literal_expansion(), decoder_should_not_get_stuck_with_finish_yielding_MORE_but_0_bytes_output_from_poll(), decoder_sink_read(), and espFsRead().

144  {
145  if ((hsd == NULL) || (out_buf == NULL) || (output_size == NULL)) {
146  return HSDR_POLL_ERROR_NULL;
147  }
148  *output_size = 0;
149 
150  output_info oi;
151  oi.buf = out_buf;
152  oi.buf_size = out_buf_size;
153  oi.output_size = output_size;
154 
155  while (1) {
156  LOG("-- poll, state is %d (%s), input_size %d\n",
157  hsd->state, state_names[hsd->state], hsd->input_size);
158  uint8_t in_state = hsd->state;
159  switch (in_state) {
160  case HSDS_EMPTY:
161  return HSDR_POLL_EMPTY;
163  hsd->state = st_input_available(hsd);
164  break;
165  case HSDS_YIELD_LITERAL:
166  hsd->state = st_yield_literal(hsd, &oi);
167  break;
169  hsd->state = st_backref_index_msb(hsd);
170  break;
172  hsd->state = st_backref_index_lsb(hsd);
173  break;
175  hsd->state = st_backref_count_msb(hsd);
176  break;
178  hsd->state = st_backref_count_lsb(hsd);
179  break;
180  case HSDS_YIELD_BACKREF:
181  hsd->state = st_yield_backref(hsd, &oi);
182  break;
184  hsd->state = st_check_for_input(hsd);
185  break;
186  default:
188  }
189 
190  /* If the current state cannot advance, check if input or output
191  * buffer are exhausted. */
192  if (hsd->state == in_state) {
193  if (*output_size == out_buf_size) { return HSDR_POLL_MORE; }
194  return HSDR_POLL_EMPTY;
195  }
196  }
197 }
static HSD_state st_yield_literal(heatshrink_decoder *hsd, output_info *oi)
static HSD_state st_yield_backref(heatshrink_decoder *hsd, output_info *oi)
static HSD_state st_backref_count_msb(heatshrink_decoder *hsd)
static HSD_state st_backref_index_lsb(heatshrink_decoder *hsd)
#define NULL
Definition: def.h:47
static HSD_state st_input_available(heatshrink_decoder *hsd)
static HSD_state st_check_for_input(heatshrink_decoder *hsd)
#define LOG(...)
static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd)
static HSD_state st_backref_index_msb(heatshrink_decoder *hsd)
size_t * output_size
Here is the call graph for this function:
Here is the caller graph for this function:

◆ heatshrink_decoder_reset()

void heatshrink_decoder_reset ( heatshrink_decoder hsd)

Definition at line 82 of file heatshrink_decoder.c.

References heatshrink_decoder::bit_accumulator, heatshrink_decoder::bit_index, heatshrink_decoder::buffers, heatshrink_decoder::current_byte, heatshrink_decoder::head_index, HEATSHRINK_DECODER_INPUT_BUFFER_SIZE, HEATSHRINK_DECODER_WINDOW_BITS, HSDS_EMPTY, heatshrink_decoder::input_index, heatshrink_decoder::input_size, memset, heatshrink_decoder::output_count, heatshrink_decoder::output_index, and heatshrink_decoder::state.

Referenced by compress_and_expand_and_check(), decoder_should_not_get_stuck_with_finish_yielding_MORE_but_0_bytes_output_from_poll(), and heatshrink_decoder_alloc().

82  {
83  size_t buf_sz = 1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd);
84  size_t input_sz = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd);
85  memset(hsd->buffers, 0, buf_sz + input_sz);
86  hsd->state = HSDS_EMPTY;
87  hsd->input_size = 0;
88  hsd->input_index = 0;
89  hsd->bit_index = 0x00;
90  hsd->current_byte = 0x00;
91  hsd->output_count = 0;
92  hsd->output_index = 0;
93  hsd->head_index = 0;
94  hsd->bit_accumulator = 0x00000000;
95 }
#define memset(x, a, b)
Definition: platform.h:21
#define HEATSHRINK_DECODER_WINDOW_BITS(BUF)
#define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(BUF)
Here is the caller graph for this function:

◆ heatshrink_decoder_sink()

HSD_sink_res heatshrink_decoder_sink ( heatshrink_decoder hsd,
uint8_t *  in_buf,
size_t  size,
size_t input_size 
)

Definition at line 98 of file heatshrink_decoder.c.

References heatshrink_decoder::buffers, HEATSHRINK_DECODER_INPUT_BUFFER_SIZE, HSDR_SINK_ERROR_NULL, HSDR_SINK_FULL, HSDR_SINK_OK, HSDS_EMPTY, HSDS_INPUT_AVAILABLE, heatshrink_decoder::input_index, heatshrink_decoder::input_size, LOG, memcpy, NULL, and heatshrink_decoder::state.

Referenced by compress_and_expand_and_check(), data_with_simple_repetition_should_match_with_absurdly_tiny_buffers(), data_without_duplication_should_match_with_absurdly_tiny_buffers(), decoder_finish_should_note_when_done(), decoder_poll_should_expand_short_literal(), decoder_poll_should_expand_short_literal_and_backref(), decoder_poll_should_expand_short_literal_and_backref_when_fed_input_byte_by_byte(), decoder_poll_should_expand_short_self_overlapping_backref(), decoder_poll_should_suspend_if_out_of_space_in_output_buffer_during_backref_expansion(), decoder_poll_should_suspend_if_out_of_space_in_output_buffer_during_literal_expansion(), decoder_should_not_get_stuck_with_finish_yielding_MORE_but_0_bytes_output_from_poll(), decoder_sink_read(), decoder_sink_should_reject_excessively_large_input(), decoder_sink_should_reject_null_count_pointer(), decoder_sink_should_reject_null_hsd_pointer(), decoder_sink_should_reject_null_input_pointer(), decoder_sink_should_sink_data_when_preconditions_hold(), and espFsRead().

99  {
100  if ((hsd == NULL) || (in_buf == NULL) || (input_size == NULL)) {
101  return HSDR_SINK_ERROR_NULL;
102  }
103 
104  size_t rem = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd) - hsd->input_size;
105  if (rem == 0) {
106  *input_size = 0;
107  return HSDR_SINK_FULL;
108  }
109 
110  size = rem < size ? rem : size;
111  LOG("-- sinking %zd bytes\n", size);
112  /* copy into input buffer (at head of buffers) */
113  memcpy(&hsd->buffers[hsd->input_size], in_buf, size);
114  hsd->input_size += size;
115  if (hsd->state == HSDS_EMPTY) {
117  hsd->input_index = 0;
118  }
119  *input_size = size;
120  return HSDR_SINK_OK;
121 }
#define NULL
Definition: def.h:47
#define LOG(...)
#define memcpy(x, a, b)
Definition: platform.h:22
#define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(BUF)
Here is the caller graph for this function:

◆ push_byte()

static void push_byte ( heatshrink_decoder hsd,
output_info oi,
uint8_t  byte 
)
static

Definition at line 380 of file heatshrink_decoder.c.

References output_info::buf, isprint, LOG, and output_info::output_size.

Referenced by st_yield_backref(), and st_yield_literal().

380  {
381  LOG(" -- pushing byte: 0x%02x ('%c')\n", byte, isprint(byte) ? byte : '.');
382  oi->buf[(*oi->output_size)++] = byte;
383  (void)hsd;
384 }
#define LOG(...)
#define isprint(c)
Definition: ip_addr.c:115
size_t * output_size
Here is the caller graph for this function:

◆ st_backref_count_lsb()

static HSD_state st_backref_count_lsb ( heatshrink_decoder hsd)
static

Definition at line 263 of file heatshrink_decoder.c.

References BACKREF_COUNT_BITS, get_bits(), HSDS_BACKREF_COUNT_LSB, HSDS_YIELD_BACKREF, LOG, NO_BITS, and heatshrink_decoder::output_count.

Referenced by heatshrink_decoder_poll().

263  {
264  uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
265  uint32_t bits = get_bits(hsd, br_bit_ct < 8 ? br_bit_ct : 8);
266  LOG("-- backref count (lsb), got 0x%04x (+1)\n", bits);
267  if (bits == NO_BITS) { return HSDS_BACKREF_COUNT_LSB; }
268  hsd->output_count |= bits;
269  hsd->output_count++;
270  return HSDS_YIELD_BACKREF;
271 }
#define NO_BITS
#define LOG(...)
#define BACKREF_COUNT_BITS(HSD)
static uint32_t get_bits(heatshrink_decoder *hsd, uint8_t count)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ st_backref_count_msb()

static HSD_state st_backref_count_msb ( heatshrink_decoder hsd)
static

Definition at line 253 of file heatshrink_decoder.c.

References ASSERT, BACKREF_COUNT_BITS, get_bits(), HSDS_BACKREF_COUNT_LSB, HSDS_BACKREF_COUNT_MSB, LOG, NO_BITS, and heatshrink_decoder::output_count.

Referenced by heatshrink_decoder_poll().

253  {
254  uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
255  ASSERT(br_bit_ct > 8);
256  uint32_t bits = get_bits(hsd, br_bit_ct - 8);
257  LOG("-- backref count (msb), got 0x%04x (+1)\n", bits);
258  if (bits == NO_BITS) { return HSDS_BACKREF_COUNT_MSB; }
259  hsd->output_count = bits << 8;
260  return HSDS_BACKREF_COUNT_LSB;
261 }
#define NO_BITS
#define LOG(...)
#define BACKREF_COUNT_BITS(HSD)
static uint32_t get_bits(heatshrink_decoder *hsd, uint8_t count)
#define ASSERT(X)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ st_backref_index_lsb()

static HSD_state st_backref_index_lsb ( heatshrink_decoder hsd)
static

Definition at line 241 of file heatshrink_decoder.c.

References BACKREF_COUNT_BITS, BACKREF_INDEX_BITS, get_bits(), HSDS_BACKREF_COUNT_LSB, HSDS_BACKREF_COUNT_MSB, HSDS_BACKREF_INDEX_LSB, LOG, NO_BITS, heatshrink_decoder::output_count, and heatshrink_decoder::output_index.

Referenced by heatshrink_decoder_poll().

241  {
242  uint8_t bit_ct = BACKREF_INDEX_BITS(hsd);
243  uint32_t bits = get_bits(hsd, bit_ct < 8 ? bit_ct : 8);
244  LOG("-- backref index (lsb), got 0x%04x (+1)\n", bits);
245  if (bits == NO_BITS) { return HSDS_BACKREF_INDEX_LSB; }
246  hsd->output_index |= bits;
247  hsd->output_index++;
248  uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
249  hsd->output_count = 0;
250  return (br_bit_ct > 8) ? HSDS_BACKREF_COUNT_MSB : HSDS_BACKREF_COUNT_LSB;
251 }
#define NO_BITS
#define LOG(...)
#define BACKREF_COUNT_BITS(HSD)
static uint32_t get_bits(heatshrink_decoder *hsd, uint8_t count)
#define BACKREF_INDEX_BITS(HSD)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ st_backref_index_msb()

static HSD_state st_backref_index_msb ( heatshrink_decoder hsd)
static

Definition at line 231 of file heatshrink_decoder.c.

References ASSERT, BACKREF_INDEX_BITS, get_bits(), HSDS_BACKREF_INDEX_LSB, HSDS_BACKREF_INDEX_MSB, LOG, NO_BITS, and heatshrink_decoder::output_index.

Referenced by heatshrink_decoder_poll().

231  {
232  uint8_t bit_ct = BACKREF_INDEX_BITS(hsd);
233  ASSERT(bit_ct > 8);
234  uint32_t bits = get_bits(hsd, bit_ct - 8);
235  LOG("-- backref index (msb), got 0x%04x (+1)\n", bits);
236  if (bits == NO_BITS) { return HSDS_BACKREF_INDEX_MSB; }
237  hsd->output_index = bits << 8;
238  return HSDS_BACKREF_INDEX_LSB;
239 }
#define NO_BITS
#define LOG(...)
static uint32_t get_bits(heatshrink_decoder *hsd, uint8_t count)
#define BACKREF_INDEX_BITS(HSD)
#define ASSERT(X)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ st_check_for_input()

static HSD_state st_check_for_input ( heatshrink_decoder hsd)
static

Definition at line 299 of file heatshrink_decoder.c.

References HSDS_EMPTY, HSDS_INPUT_AVAILABLE, and heatshrink_decoder::input_size.

Referenced by heatshrink_decoder_poll().

Here is the caller graph for this function:

◆ st_input_available()

static HSD_state st_input_available ( heatshrink_decoder hsd)
static

Definition at line 199 of file heatshrink_decoder.c.

References get_bits(), HEATSHRINK_DECODER_WINDOW_BITS, HSDS_BACKREF_INDEX_LSB, HSDS_BACKREF_INDEX_MSB, HSDS_YIELD_LITERAL, and heatshrink_decoder::output_index.

Referenced by heatshrink_decoder_poll().

199  {
200  uint32_t bits = get_bits(hsd, 1); // get tag bit
201  if (bits) {
202  return HSDS_YIELD_LITERAL;
203  } else if (HEATSHRINK_DECODER_WINDOW_BITS(hsd) > 8) {
204  return HSDS_BACKREF_INDEX_MSB;
205  } else {
206  hsd->output_index = 0;
207  return HSDS_BACKREF_INDEX_LSB;
208  }
209 }
#define HEATSHRINK_DECODER_WINDOW_BITS(BUF)
static uint32_t get_bits(heatshrink_decoder *hsd, uint8_t count)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ st_yield_backref()

static HSD_state st_yield_backref ( heatshrink_decoder hsd,
output_info oi 
)
static

Definition at line 273 of file heatshrink_decoder.c.

References ASSERT, BACKREF_COUNT_BITS, output_info::buf_size, heatshrink_decoder::buffers, heatshrink_decoder::head_index, HEATSHRINK_DECODER_INPUT_BUFFER_SIZE, HEATSHRINK_DECODER_WINDOW_BITS, HSDS_CHECK_FOR_MORE_INPUT, HSDS_YIELD_BACKREF, LOG, heatshrink_decoder::output_count, heatshrink_decoder::output_index, output_info::output_size, and push_byte().

Referenced by heatshrink_decoder_poll().

274  {
275  size_t count = oi->buf_size - *oi->output_size;
276  size_t i;
277  if (count > 0) {
278  if (hsd->output_count < count) count = hsd->output_count;
279  uint8_t *buf = &hsd->buffers[HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd)];
280  uint16_t mask = (1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1;
281  uint16_t neg_offset = hsd->output_index;
282  LOG("-- emitting %zu bytes from -%u bytes back\n", count, neg_offset);
283  ASSERT(neg_offset < mask + 1);
284  ASSERT(count <= 1 << BACKREF_COUNT_BITS(hsd));
285 
286  for (i=0; i<count; i++) {
287  uint8_t c = buf[(hsd->head_index - neg_offset) & mask];
288  push_byte(hsd, oi, c);
289  buf[hsd->head_index & mask] = c;
290  hsd->head_index++;
291  LOG(" -- ++ 0x%02x\n", c);
292  }
293  hsd->output_count -= count;
294  if (hsd->output_count == 0) { return HSDS_CHECK_FOR_MORE_INPUT; }
295  }
296  return HSDS_YIELD_BACKREF;
297 }
static void push_byte(heatshrink_decoder *hsd, output_info *oi, uint8_t byte)
#define HEATSHRINK_DECODER_WINDOW_BITS(BUF)
#define LOG(...)
#define BACKREF_COUNT_BITS(HSD)
#define ASSERT(X)
size_t * output_size
#define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(BUF)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ st_yield_literal()

static HSD_state st_yield_literal ( heatshrink_decoder hsd,
output_info oi 
)
static

Definition at line 211 of file heatshrink_decoder.c.

References output_info::buf_size, heatshrink_decoder::buffers, get_bits(), heatshrink_decoder::head_index, HEATSHRINK_DECODER_INPUT_BUFFER_SIZE, HEATSHRINK_DECODER_WINDOW_BITS, HSDS_CHECK_FOR_MORE_INPUT, HSDS_YIELD_LITERAL, isprint, LOG, NO_BITS, output_info::output_size, and push_byte().

Referenced by heatshrink_decoder_poll().

212  {
213  /* Emit a repeated section from the window buffer, and add it (again)
214  * to the window buffer. (Note that the repetition can include
215  * itself.)*/
216  if (*oi->output_size < oi->buf_size) {
217  uint32_t byte = get_bits(hsd, 8);
218  if (byte == NO_BITS) { return HSDS_YIELD_LITERAL; } /* out of input */
219  uint8_t *buf = &hsd->buffers[HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd)];
220  uint16_t mask = (1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1;
221  uint8_t c = byte & 0xFF;
222  LOG("-- emitting literal byte 0x%02x ('%c')\n", c, isprint(c) ? c : '.');
223  buf[hsd->head_index++ & mask] = c;
224  push_byte(hsd, oi, c);
226  } else {
227  return HSDS_YIELD_LITERAL;
228  }
229 }
static void push_byte(heatshrink_decoder *hsd, output_info *oi, uint8_t byte)
#define HEATSHRINK_DECODER_WINDOW_BITS(BUF)
#define NO_BITS
#define LOG(...)
#define isprint(c)
Definition: ip_addr.c:115
static uint32_t get_bits(heatshrink_decoder *hsd, uint8_t count)
size_t * output_size
#define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(BUF)
Here is the call graph for this function:
Here is the caller graph for this function: