void decompress(uint8_t *input, uint32_t compressed_size) { printf("Decompressing data...\n"); heatshrink_decoder_reset(&hsd); size_t decomp_sz = 2048; /* Maximum buffer size before compression */ uint8_t *decomp = malloc(decomp_sz); memset(decomp, 0, decomp_sz); size_t count; uint32_t sunk = 0; uint32_t polled = 0; while (sunk < compressed_size) { heatshrink_decoder_sink(&hsd, &input[sunk], compressed_size - sunk, &count); sunk += count; if (sunk == compressed_size) { heatshrink_decoder_finish(&hsd); } HSD_poll_res pres; do { pres = heatshrink_decoder_poll(&hsd, &decomp[polled], decomp_sz - polled, &count); polled += count; } while (pres == HSDR_POLL_MORE); if (sunk == compressed_size) { heatshrink_decoder_finish(&hsd); } } printf("Size after decompression: %d\n", polled); csv = fopen("data.csv", "a"); for (int i = 0; i < polled; ++i) { fprintf(csv, "%hhu\n", decomp[i]); } fclose(csv); free(decomp); }
/** gets data from callback, writes it into array if nonzero. Returns total length */ uint32_t heatshrink_decode(int (*callback)(uint32_t *cbdata), uint32_t *cbdata, unsigned char *data) { heatshrink_decoder hsd; uint8_t inBuf[BUFFERSIZE]; uint8_t outBuf[BUFFERSIZE]; heatshrink_decoder_reset(&hsd); size_t count = 0; size_t sunk = 0; size_t polled = 0; int lastByte = 0; size_t inBufCount = 0; while (lastByte >= 0 || inBufCount>0) { // Read data from flash while (inBufCount<BUFFERSIZE && lastByte>=0) { lastByte = callback(cbdata); if (lastByte >= 0) inBuf[inBufCount++] = (uint8_t)lastByte; } // decode bool ok = heatshrink_decoder_sink(&hsd, inBuf, inBufCount, &count) >= 0; // if not all the data was read, shift what's left to the start of our buffer if (count < inBufCount) { size_t i; for (i=count;i<inBufCount;i++) inBuf[i-count] = inBuf[i]; } inBufCount -= count; assert(ok);NOT_USED(ok); sunk += count; if (lastByte < 0) { heatshrink_decoder_finish(&hsd); } HSE_poll_res pres; do { pres = heatshrink_decoder_poll(&hsd, outBuf, sizeof(outBuf), &count); assert(pres >= 0); if (data) memcpy(&data[polled], outBuf, count); polled += count; } while (pres == HSER_POLL_MORE); assert(pres == HSER_POLL_EMPTY); if (lastByte < 0) { heatshrink_decoder_finish(&hsd); } } return (uint32_t)polled; }
static int compress_and_expand_and_check(uint8_t *input, uint32_t input_size) { // clear encoder&decoder state machines heatshrink_encoder_reset(&hse); heatshrink_decoder_reset(&hsd); // allocate memory for before and after size_t comp_sz = input_size + (input_size/2) + 4; uint8_t *comp = malloc(comp_sz); if (comp == NULL) printf("malloc fail\r\n"); memset(comp, 0, comp_sz); size_t count = 0; uint32_t sunk = 0; uint32_t polled = 0; while (sunk < input_size) { ASSERT(heatshrink_encoder_sink(&hse, &input[sunk], input_size - sunk, &count) >= 0); sunk += count; if (sunk == input_size) { ASSERT_EQ(HSER_FINISH_MORE, heatshrink_encoder_finish(&hse)); } HSE_poll_res pres; do { /* "turn the crank" */ pres = heatshrink_encoder_poll(&hse, &comp[polled], comp_sz - polled, &count); ASSERT(pres >= 0); polled += count; } while (pres == HSER_POLL_MORE); ASSERT_EQ(HSER_POLL_EMPTY, pres); if (polled >= comp_sz) { printf("compression should never expand that muchr\r\n"); show_error(); return-1;} if (sunk == input_size) { ASSERT_EQ(HSER_FINISH_DONE, heatshrink_encoder_finish(&hse)); } } for (int i = 0; i < polled; i++) { while(app_uart_put(comp[i]) != NRF_SUCCESS); // for(int time_ctr = 0; time_ctr <100000; time_ctr ++); } // while(app_uart_put(13) != NRF_SUCCESS); // printf("%d", polled); free(comp); }
heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size, uint8_t window_sz2, uint8_t lookahead_sz2) { if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) || (window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) || (input_buffer_size == 0) || (lookahead_sz2 < HEATSHRINK_MIN_LOOKAHEAD_BITS) || (lookahead_sz2 > window_sz2)) { return NULL; } size_t buffers_sz = (1 << window_sz2) + input_buffer_size; size_t sz = sizeof(heatshrink_decoder) + buffers_sz; heatshrink_decoder *hsd = HEATSHRINK_MALLOC(sz); if (hsd == NULL) { return NULL; } hsd->input_buffer_size = input_buffer_size; hsd->window_sz2 = window_sz2; hsd->lookahead_sz2 = lookahead_sz2; heatshrink_decoder_reset(hsd); LOG("-- allocated decoder with buffer size of %zu (%zu + %u + %u)\n", sz, sizeof(heatshrink_decoder), (1 << window_sz2), input_buffer_size); return hsd; }
TEST decoder_should_not_get_stuck_with_finish_yielding_MORE_but_0_bytes_output_from_poll(void) { uint8_t input[512]; memset(input, 0xff, 256); uint8_t output[1024]; heatshrink_decoder *hsd = heatshrink_decoder_alloc(256, 8, 4); ASSERT(hsd); /* Confirm that no byte of trailing context can lead to * heatshrink_decoder_finish erroneously returning HSDR_FINISH_MORE * when heatshrink_decoder_poll will yield 0 bytes. * * Before 0.3.1, a final byte of 0xFF could potentially cause * this to happen, if at exactly the byte boundary. */ for (uint16_t byte = 0; byte < 256; byte++) { for (int i = 1; i < 512; i++) { input[i] = byte; heatshrink_decoder_reset(hsd); memset(output, 0, sizeof(*output)); size_t count = 0; HSD_sink_res sres = heatshrink_decoder_sink(hsd, input, i, &count); ASSERT_EQ(HSDR_SINK_OK, sres); size_t out_sz = 0; HSD_poll_res pres = heatshrink_decoder_poll(hsd, output, sizeof(output), &out_sz); ASSERT_EQ(HSDR_POLL_EMPTY, pres); HSD_finish_res fres = heatshrink_decoder_finish(hsd); ASSERT_EQ(HSDR_FINISH_DONE, fres); input[i] = 0xff; } } heatshrink_decoder_free(hsd); PASS(); }
static int compress_and_expand_and_check(uint8_t *input, uint32_t input_size, int log_lvl) { heatshrink_encoder_reset(&hse); heatshrink_decoder_reset(&hsd); size_t comp_sz = input_size + (input_size/2) + 4; size_t decomp_sz = input_size + (input_size/2) + 4; uint8_t *comp = malloc(comp_sz); uint8_t *decomp = malloc(decomp_sz); if (comp == NULL) FAILm("malloc fail"); if (decomp == NULL) FAILm("malloc fail"); memset(comp, 0, comp_sz); memset(decomp, 0, decomp_sz); size_t count = 0; if (log_lvl > 1) { printf("\n^^ COMPRESSING\n"); dump_buf("input", input, input_size); } uint32_t sunk = 0; uint32_t polled = 0; while (sunk < input_size) { ASSERT(heatshrink_encoder_sink(&hse, &input[sunk], input_size - sunk, &count) >= 0); sunk += count; if (log_lvl > 1) printf("^^ sunk %zd\n", count); if (sunk == input_size) { ASSERT_EQ(HSER_FINISH_MORE, heatshrink_encoder_finish(&hse)); } HSE_poll_res pres; do { /* "turn the crank" */ pres = heatshrink_encoder_poll(&hse, &comp[polled], comp_sz - polled, &count); ASSERT(pres >= 0); polled += count; if (log_lvl > 1) printf("^^ polled %zd\n", count); } while (pres == HSER_POLL_MORE); ASSERT_EQ(HSER_POLL_EMPTY, pres); if (polled >= comp_sz) FAILm("compression should never expand that much"); if (sunk == input_size) { ASSERT_EQ(HSER_FINISH_DONE, heatshrink_encoder_finish(&hse)); } } if (log_lvl > 0) printf("in: %u compressed: %u ", input_size, polled); uint32_t compressed_size = polled; sunk = 0; polled = 0; if (log_lvl > 1) { printf("\n^^ DECOMPRESSING\n"); dump_buf("comp", comp, compressed_size); } while (sunk < compressed_size) { ASSERT(heatshrink_decoder_sink(&hsd, &comp[sunk], compressed_size - sunk, &count) >= 0); sunk += count; if (log_lvl > 1) printf("^^ sunk %zd\n", count); if (sunk == compressed_size) { ASSERT_EQ(HSDR_FINISH_MORE, heatshrink_decoder_finish(&hsd)); } HSD_poll_res pres; do { pres = heatshrink_decoder_poll(&hsd, &decomp[polled], decomp_sz - polled, &count); ASSERT(pres >= 0); polled += count; if (log_lvl > 1) printf("^^ polled %zd\n", count); } while (pres == HSDR_POLL_MORE); ASSERT_EQ(HSDR_POLL_EMPTY, pres); if (sunk == compressed_size) { HSD_finish_res fres = heatshrink_decoder_finish(&hsd); ASSERT_EQ(HSDR_FINISH_DONE, fres); } if (polled > input_size) { FAILm("Decompressed data is larger than original input"); } } if (log_lvl > 0) printf("decompressed: %u\n", polled); if (polled != input_size) { FAILm("Decompressed length does not match original input length"); } if (log_lvl > 1) dump_buf("decomp", decomp, polled); for (size_t i=0; i<input_size; i++) { if (input[i] != decomp[i]) { printf("*** mismatch at %zd\n", i); if (0) { for (size_t j=0; j<=/*i*/ input_size; j++) { printf("in[%zd] == 0x%02x ('%c') => out[%zd] == 0x%02x ('%c')\n", j, input[j], isprint(input[j]) ? input[j] : '.', j, decomp[j], isprint(decomp[j]) ? decomp[j] : '.'); } } } ASSERT_EQ(input[i], decomp[i]); } free(comp); free(decomp); PASS(); }