Prusa MINI Firmware overview
heatshrink_decoder.cpp File Reference
#include <stdlib.h>
#include <string.h>
#include "heatshrink_decoder.h"

Classes

struct  output_info
 

Macros

#define LOG(...)   /* no-op */
 
#define ASSERT(X)   /* no-op */
 
#define NO_BITS   ((uint16_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_TAG_BIT, HSDS_YIELD_LITERAL, HSDS_BACKREF_INDEX_MSB, HSDS_BACKREF_INDEX_LSB,
  HSDS_BACKREF_COUNT_MSB, HSDS_BACKREF_COUNT_LSB, HSDS_YIELD_BACKREF
}
 

Functions

static uint16_t get_bits (heatshrink_decoder *hsd, uint8_t count)
 
static void push_byte (heatshrink_decoder *hsd, output_info *oi, uint8_t byte)
 
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_tag_bit (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)
 
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

◆ LOG

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

◆ ASSERT

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

◆ NO_BITS

#define NO_BITS   ((uint16_t)-1)

◆ 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))

Enumeration Type Documentation

◆ HSD_state

enum HSD_state

libs/heatshrink/heatshrink_decoder.cpp

Enumerator
HSDS_TAG_BIT 
HSDS_YIELD_LITERAL 
HSDS_BACKREF_INDEX_MSB 
HSDS_BACKREF_INDEX_LSB 
HSDS_BACKREF_COUNT_MSB 
HSDS_BACKREF_COUNT_LSB 
HSDS_YIELD_BACKREF 
11  {
12  HSDS_TAG_BIT, /* tag bit */
13  HSDS_YIELD_LITERAL, /* ready to yield literal byte */
14  HSDS_BACKREF_INDEX_MSB, /* most significant byte of index */
15  HSDS_BACKREF_INDEX_LSB, /* least significant byte of index */
16  HSDS_BACKREF_COUNT_MSB, /* most significant byte of count */
17  HSDS_BACKREF_COUNT_LSB, /* least significant byte of count */
18  HSDS_YIELD_BACKREF /* ready to yield back-reference */
19 } HSD_state;

Function Documentation

◆ get_bits()

static uint16_t get_bits ( heatshrink_decoder hsd,
uint8_t  count 
)
static
283  {
284  uint16_t accumulator = 0;
285  int i = 0;
286  if (count > 15) return NO_BITS;
287  LOG("-- popping %u bit(s)\n", count);
288 
289  /* If we aren't able to get COUNT bits, suspend immediately, because we
290  * don't track how many bits of COUNT we've accumulated before suspend. */
291  if (hsd->input_size == 0 && hsd->bit_index < (1 << (count - 1))) return NO_BITS;
292 
293  for (i = 0; i < count; i++) {
294  if (hsd->bit_index == 0x00) {
295  if (hsd->input_size == 0) {
296  LOG(" -- out of bits, suspending w/ accumulator of %u (0x%02x)\n", accumulator, accumulator);
297  return NO_BITS;
298  }
300  LOG(" -- pulled byte 0x%02x\n", hsd->current_byte);
301  if (hsd->input_index == hsd->input_size) {
302  hsd->input_index = 0; /* input is exhausted */
303  hsd->input_size = 0;
304  }
305  hsd->bit_index = 0x80;
306  }
307  accumulator <<= 1;
308  if (hsd->current_byte & hsd->bit_index) {
309  accumulator |= 0x01;
310  if (0) {
311  LOG(" -- got 1, accumulator 0x%04x, bit_index 0x%02x\n",
312  accumulator, hsd->bit_index);
313  }
314  }
315  else if (0) {
316  LOG(" -- got 0, accumulator 0x%04x, bit_index 0x%02x\n",
317  accumulator, hsd->bit_index);
318  }
319  hsd->bit_index >>= 1;
320  }
321 
322  if (count > 1) LOG(" -- accumulated %08x\n", accumulator);
323  return accumulator;
Here is the caller graph for this function:

◆ push_byte()

static void push_byte ( heatshrink_decoder hsd,
output_info oi,
uint8_t  byte 
)
static
351  {
352  LOG(" -- pushing byte: 0x%02x ('%c')\n", byte, isprint(byte) ? byte : '.');
353  oi->buf[(*oi->output_size)++] = byte;
354  (void)hsd;
Here is the caller graph for this function:

◆ heatshrink_decoder_reset()

void heatshrink_decoder_reset ( heatshrink_decoder hsd)
83  {
84  size_t buf_sz = 1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd);
85  size_t input_sz = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd);
86  memset(hsd->buffers, 0, buf_sz + input_sz);
88  hsd->input_size = 0;
89  hsd->input_index = 0;
90  hsd->bit_index = 0x00;
91  hsd->current_byte = 0x00;
92  hsd->output_count = 0;
93  hsd->output_index = 0;
94  hsd->head_index = 0;
95 }

◆ heatshrink_decoder_sink()

HSD_sink_res heatshrink_decoder_sink ( heatshrink_decoder hsd,
uint8_t in_buf,
size_t  size,
size_t *  input_size 
)
99  {
100  if (hsd == nullptr || in_buf == nullptr || input_size == nullptr)
101  return HSDR_SINK_ERROR_NULL;
102 
104  if (rem == 0) {
105  *input_size = 0;
106  return HSDR_SINK_FULL;
107  }
108 
109  size = rem < size ? rem : size;
110  LOG("-- sinking %zd bytes\n", size);
111  /* copy into input buffer (at head of buffers) */
112  memcpy(&hsd->buffers[hsd->input_size], in_buf, size);
113  hsd->input_size += size;
114  *input_size = size;
115  return HSDR_SINK_OK;
116 }

◆ st_tag_bit()

static HSD_state st_tag_bit ( heatshrink_decoder hsd)
static
182  {
183  uint32_t bits = get_bits(hsd, 1); // get tag bit
184  if (bits == NO_BITS)
185  return HSDS_TAG_BIT;
186  else if (bits)
187  return HSDS_YIELD_LITERAL;
188  else if (HEATSHRINK_DECODER_WINDOW_BITS(hsd) > 8)
189  return HSDS_BACKREF_INDEX_MSB;
190  else {
191  hsd->output_index = 0;
192  return HSDS_BACKREF_INDEX_LSB;
193  }
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
196  {
197  /* Emit a repeated section from the window buffer, and add it (again)
198  * to the window buffer. (Note that the repetition can include
199  * itself.)*/
200  if (*oi->output_size < oi->buf_size) {
201  uint16_t byte = get_bits(hsd, 8);
202  if (byte == NO_BITS) { return HSDS_YIELD_LITERAL; } /* out of input */
204  uint16_t mask = (1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1;
205  uint8_t c = byte & 0xFF;
206  LOG("-- emitting literal byte 0x%02x ('%c')\n", c, isprint(c) ? c : '.');
207  buf[hsd->head_index++ & mask] = c;
208  push_byte(hsd, oi, c);
209  return HSDS_TAG_BIT;
210  }
211  return HSDS_YIELD_LITERAL;
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
214  {
215  uint8_t bit_ct = BACKREF_INDEX_BITS(hsd);
216  ASSERT(bit_ct > 8);
217  uint16_t bits = get_bits(hsd, bit_ct - 8);
218  LOG("-- backref index (msb), got 0x%04x (+1)\n", bits);
219  if (bits == NO_BITS) { return HSDS_BACKREF_INDEX_MSB; }
220  hsd->output_index = bits << 8;
221  return HSDS_BACKREF_INDEX_LSB;
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
224  {
225  uint8_t bit_ct = BACKREF_INDEX_BITS(hsd);
226  uint16_t bits = get_bits(hsd, bit_ct < 8 ? bit_ct : 8);
227  LOG("-- backref index (lsb), got 0x%04x (+1)\n", bits);
228  if (bits == NO_BITS) { return HSDS_BACKREF_INDEX_LSB; }
229  hsd->output_index |= bits;
230  hsd->output_index++;
231  uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
232  hsd->output_count = 0;
233  return (br_bit_ct > 8) ? HSDS_BACKREF_COUNT_MSB : HSDS_BACKREF_COUNT_LSB;
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
236  {
237  uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
238  ASSERT(br_bit_ct > 8);
239  uint16_t bits = get_bits(hsd, br_bit_ct - 8);
240  LOG("-- backref count (msb), got 0x%04x (+1)\n", bits);
241  if (bits == NO_BITS) { return HSDS_BACKREF_COUNT_MSB; }
242  hsd->output_count = bits << 8;
243  return HSDS_BACKREF_COUNT_LSB;
Here is the call graph for this function:
Here is the caller graph for this function:

◆ st_backref_count_lsb()

static HSD_state st_backref_count_lsb ( heatshrink_decoder hsd)
static
246  {
247  uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd);
248  uint16_t bits = get_bits(hsd, br_bit_ct < 8 ? br_bit_ct : 8);
249  LOG("-- backref count (lsb), got 0x%04x (+1)\n", bits);
250  if (bits == NO_BITS) { return HSDS_BACKREF_COUNT_LSB; }
251  hsd->output_count |= bits;
252  hsd->output_count++;
253  return HSDS_YIELD_BACKREF;
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
256  {
257  size_t count = oi->buf_size - *oi->output_size;
258  if (count > 0) {
259  size_t i = 0;
260  if (hsd->output_count < count) count = hsd->output_count;
262  uint16_t mask = (1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1;
263  uint16_t neg_offset = hsd->output_index;
264  LOG("-- emitting %zu bytes from -%u bytes back\n", count, neg_offset);
265  ASSERT(neg_offset <= mask + 1);
266  ASSERT(count <= (size_t)(1 << BACKREF_COUNT_BITS(hsd)));
267 
268  for (i = 0; i < count; i++) {
269  uint8_t c = buf[(hsd->head_index - neg_offset) & mask];
270  push_byte(hsd, oi, c);
271  buf[hsd->head_index & mask] = c;
272  hsd->head_index++;
273  LOG(" -- ++ 0x%02x\n", c);
274  }
275  hsd->output_count -= count;
276  if (hsd->output_count == 0) { return HSDS_TAG_BIT; }
277  }
278  return HSDS_YIELD_BACKREF;
Here is the call graph for this function:
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 
)
135  {
136  if (hsd == nullptr || out_buf == nullptr || output_size == nullptr)
137  return HSDR_POLL_ERROR_NULL;
138 
139  *output_size = 0;
140 
141  output_info oi;
142  oi.buf = out_buf;
143  oi.buf_size = out_buf_size;
144  oi.output_size = output_size;
145 
146  while (1) {
147  LOG("-- poll, state is %d (%s), input_size %d\n", hsd->state, state_names[hsd->state], hsd->input_size);
148  uint8_t in_state = hsd->state;
149  switch (in_state) {
150  case HSDS_TAG_BIT:
151  hsd->state = st_tag_bit(hsd);
152  break;
153  case HSDS_YIELD_LITERAL:
154  hsd->state = st_yield_literal(hsd, &oi);
155  break;
158  break;
161  break;
164  break;
167  break;
168  case HSDS_YIELD_BACKREF:
169  hsd->state = st_yield_backref(hsd, &oi);
170  break;
171  default:
173  }
174 
175  // If the current state cannot advance, check if input or output
176  // buffer are exhausted.
177  if (hsd->state == in_state)
178  return (*output_size == out_buf_size) ? HSDR_POLL_MORE : HSDR_POLL_EMPTY;
179  }
Here is the call graph for this function:

◆ heatshrink_decoder_finish()

HSD_finish_res heatshrink_decoder_finish ( heatshrink_decoder hsd)
326  {
327  if (hsd == nullptr) { return HSDR_FINISH_ERROR_NULL; }
328  switch (hsd->state) {
329  case HSDS_TAG_BIT:
331 
332  /* If we want to finish with no input, but are in these states, it's
333  * because the 0-bit padding to the last byte looks like a backref
334  * marker bit followed by all 0s for index and count bits. */
340 
341  /* If the output stream is padded with 0xFFs (possibly due to being in
342  * flash memory), also explicitly check the input size rather than
343  * uselessly returning MORE but yielding 0 bytes when polling. */
344  case HSDS_YIELD_LITERAL:
346 
347  default: return HSDR_FINISH_MORE;
348  }
HEATSHRINK_DECODER_INPUT_BUFFER_SIZE
#define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(_)
Definition: heatshrink_decoder.h:38
output_info::buf_size
size_t buf_size
Definition: heatshrink_decoder.cpp:43
HSDR_FINISH_MORE
Definition: heatshrink_decoder.h:26
HSDR_POLL_ERROR_UNKNOWN
Definition: heatshrink_decoder.h:21
HSDR_SINK_OK
Definition: heatshrink_decoder.h:12
BACKREF_COUNT_BITS
#define BACKREF_COUNT_BITS(HSD)
Definition: heatshrink_decoder.cpp:122
heatshrink_decoder::output_index
uint16_t output_index
Definition: heatshrink_decoder.h:50
HSDR_POLL_EMPTY
Definition: heatshrink_decoder.h:18
st_backref_index_msb
static HSD_state st_backref_index_msb(heatshrink_decoder *hsd)
Definition: heatshrink_decoder.cpp:213
LOG
#define LOG(...)
Definition: heatshrink_decoder.cpp:37
HSDR_SINK_FULL
Definition: heatshrink_decoder.h:13
i
uint8_t i
Definition: screen_test_graph.c:72
heatshrink_decoder::buffers
uint8_t buffers[(1<< HEATSHRINK_DECODER_WINDOW_BITS(_))+HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(_)]
Definition: heatshrink_decoder.h:66
BACKREF_INDEX_BITS
#define BACKREF_INDEX_BITS(HSD)
Definition: heatshrink_decoder.cpp:123
heatshrink_decoder::state
uint8_t state
Definition: heatshrink_decoder.h:52
HSDR_POLL_MORE
Definition: heatshrink_decoder.h:19
HSDR_FINISH_ERROR_NULL
Definition: heatshrink_decoder.h:27
get_bits
static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count)
Definition: heatshrink_decoder.cpp:282
st_tag_bit
static HSD_state st_tag_bit(heatshrink_decoder *hsd)
Definition: heatshrink_decoder.cpp:181
HSD_state
HSD_state
Definition: heatshrink_decoder.cpp:11
st_yield_literal
static HSD_state st_yield_literal(heatshrink_decoder *hsd, output_info *oi)
Definition: heatshrink_decoder.cpp:195
HSDR_FINISH_DONE
Definition: heatshrink_decoder.h:25
st_backref_index_lsb
static HSD_state st_backref_index_lsb(heatshrink_decoder *hsd)
Definition: heatshrink_decoder.cpp:223
push_byte
static void push_byte(heatshrink_decoder *hsd, output_info *oi, uint8_t byte)
Definition: heatshrink_decoder.cpp:350
heatshrink_decoder::bit_index
uint8_t bit_index
Definition: heatshrink_decoder.h:54
HSDS_BACKREF_COUNT_MSB
Definition: heatshrink_decoder.cpp:16
HSDS_YIELD_BACKREF
Definition: heatshrink_decoder.cpp:18
void
void
Definition: png.h:1083
output_info::output_size
size_t * output_size
Definition: heatshrink_decoder.cpp:44
HSDS_BACKREF_INDEX_LSB
Definition: heatshrink_decoder.cpp:15
st_yield_backref
static HSD_state st_yield_backref(heatshrink_decoder *hsd, output_info *oi)
Definition: heatshrink_decoder.cpp:255
heatshrink_decoder::head_index
uint16_t head_index
Definition: heatshrink_decoder.h:51
heatshrink_decoder::input_size
uint16_t input_size
Definition: heatshrink_decoder.h:47
heatshrink_decoder::output_count
uint16_t output_count
Definition: heatshrink_decoder.h:49
uint8_t
const uint8_t[]
Definition: 404_html.c:3
HSDS_BACKREF_INDEX_MSB
Definition: heatshrink_decoder.cpp:14
heatshrink_decoder::current_byte
uint8_t current_byte
Definition: heatshrink_decoder.h:53
HEATSHRINK_DECODER_WINDOW_BITS
#define HEATSHRINK_DECODER_WINDOW_BITS(_)
Definition: heatshrink_decoder.h:40
output_info
Definition: heatshrink_decoder.cpp:41
hsd
static heatshrink_decoder hsd
Definition: binary_protocol.h:53
ASSERT
#define ASSERT(X)
Definition: heatshrink_decoder.cpp:38
heatshrink_decoder::input_index
uint16_t input_index
Definition: heatshrink_decoder.h:48
st_backref_count_msb
static HSD_state st_backref_count_msb(heatshrink_decoder *hsd)
Definition: heatshrink_decoder.cpp:235
HSDS_TAG_BIT
Definition: heatshrink_decoder.cpp:12
output_info::buf
uint8_t * buf
Definition: heatshrink_decoder.cpp:42
st_backref_count_lsb
static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd)
Definition: heatshrink_decoder.cpp:245
HSDS_BACKREF_COUNT_LSB
Definition: heatshrink_decoder.cpp:17
NO_BITS
#define NO_BITS
Definition: heatshrink_decoder.cpp:47
HSDR_POLL_ERROR_NULL
Definition: heatshrink_decoder.h:20
HSDS_YIELD_LITERAL
Definition: heatshrink_decoder.cpp:13
HSDR_SINK_ERROR_NULL
Definition: heatshrink_decoder.h:14
size
static png_bytep size_t size
Definition: pngwrite.c:2170