static HSD_state st_yield_backref(heatshrink_decoder *hsd, output_info *oi) { size_t count = oi->buf_size - *oi->output_size; if (count > 0) { size_t i = 0; if (hsd->output_count < count) count = hsd->output_count; uint8_t *buf = &hsd->buffers[HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd)]; uint16_t mask = (1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1; uint16_t neg_offset = hsd->output_index; LOG("-- emitting %zu bytes from -%u bytes back\n", count, neg_offset); ASSERT(neg_offset <= mask + 1); ASSERT(count <= (size_t)(1 << BACKREF_COUNT_BITS(hsd))); for (i=0; i<count; i++) { uint8_t c = buf[(hsd->head_index - neg_offset) & mask]; push_byte(hsd, oi, c); buf[hsd->head_index & mask] = c; hsd->head_index++; LOG(" -- ++ 0x%02x\n", c); } hsd->output_count -= count; if (hsd->output_count == 0) { return HSDS_TAG_BIT; } } return HSDS_YIELD_BACKREF; }
static HSD_state st_input_available(heatshrink_decoder *hsd) { uint32_t bits = get_bits(hsd, 1); // get tag bit if (bits) { return HSDS_YIELD_LITERAL; } else if (HEATSHRINK_DECODER_WINDOW_BITS(hsd) > 8) { return HSDS_BACKREF_INDEX_MSB; } else { hsd->output_index = 0; return HSDS_BACKREF_INDEX_LSB; } }
void heatshrink_decoder_reset(heatshrink_decoder *hsd) { size_t buf_sz = 1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd); size_t input_sz = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd); memset(hsd->buffers, 0, buf_sz + input_sz); hsd->state = HSDS_TAG_BIT; hsd->input_size = 0; hsd->input_index = 0; hsd->bit_index = 0x00; hsd->current_byte = 0x00; hsd->output_count = 0; hsd->output_index = 0; hsd->head_index = 0; }
static HSD_state st_yield_literal(heatshrink_decoder *hsd, output_info *oi) { /* Emit a repeated section from the window buffer, and add it (again) * to the window buffer. (Note that the repetition can include * itself.)*/ if (*oi->output_size < oi->buf_size) { uint32_t byte = get_bits(hsd, 8); if (byte == NO_BITS) { return HSDS_YIELD_LITERAL; } /* out of input */ uint8_t *buf = &hsd->buffers[HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd)]; uint16_t mask = (1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1; uint8_t c = byte & 0xFF; LOG("-- emitting literal byte 0x%02x ('%c')\n", c, isprint(c) ? c : '.'); buf[hsd->head_index++ & mask] = c; push_byte(hsd, oi, c); return HSDS_CHECK_FOR_MORE_INPUT; } else { return HSDS_YIELD_LITERAL; } }