//Based on https://github.com/richgel999/miniz/blob/master/examples/example5.c (Public domain, April 11 2012, Rich Geldreich, richgel99@gmail.com) #include #include //Include miniz, disabling what we don't need #define MINIZ_NO_STDIO #define MINIZ_NO_ARCHIVE_APIS #define MINIZ_NO_TIME #define MINIZ_NO_ZLIB_APIS #define MINIZ_NO_MALLOC #include "../lib/miniz/miniz.h" #include "errorAndExit.h" #include "inflate.h" //The compressed and uncompressed buffer arrays static const uint8_t* comprBuffer; static uint8_t* uncomprBuffer; //Position of the inflater in the buffer arrays static const uint8_t* comprBufferNext; static uint8_t* uncomprBufferNext; //Buffer lengths static unsigned long uncomprBufferSize; static size_t remainingInput; static size_t spaceInOutput; //Internal variables used by miniz static tinfl_decompressor decompressor; static tinfl_status status; static size_t in_bytes, out_bytes; void inflateInit(uint8_t* comprBufferIn, uint8_t* uncomprBufferIn, unsigned long uncomprBufferSizeIn) { comprBuffer = comprBufferIn; uncomprBuffer = uncomprBufferIn; uncomprBufferSize = uncomprBufferSizeIn; tinfl_init(&decompressor); } struct InflateOutput inflateInflate(unsigned long numInputBytes, bool hasMoreBytes) { if (numInputBytes == 0) { //continue in input buffer where we were before } else { //go back to beginning of input buffer comprBufferNext = comprBuffer; remainingInput = numInputBytes; } //output buffer was previously fully filled and all output was processed. New uncompressed data can be written starting at offset 0 if (spaceInOutput == 0) { uncomprBufferNext = (mz_uint8 *)uncomprBuffer; spaceInOutput = uncomprBufferSize; } struct InflateOutput out; out.hasReachedEnd = false; out.numBytesWrittenToOutput = 0UL; while (remainingInput > 0 && spaceInOutput > 0) { in_bytes = remainingInput; out_bytes = spaceInOutput; //Call decompression status = tinfl_decompress( &decompressor, (const mz_uint8 *)comprBufferNext, &in_bytes, (mz_uint8 *)uncomprBuffer, (mz_uint8 *)uncomprBufferNext, &out_bytes, (hasMoreBytes ? TINFL_FLAG_HAS_MORE_INPUT : 0) ); //Adjust buffer positions by the amount of bytes processed comprBufferNext = (const uint8_t *)(comprBufferNext + in_bytes); remainingInput -= in_bytes; uncomprBufferNext = (uint8_t *)(uncomprBufferNext + out_bytes); spaceInOutput -= out_bytes; out.numBytesWrittenToOutput += out_bytes; //Check for errors if (status <= TINFL_STATUS_DONE) { if (status == TINFL_STATUS_DONE) { // Decompression completed successfully. out.hasReachedEnd = true; break; } else { // Decompression failed. fprintf(stderr, "tinfl_decompress() failed with status %i!\n", status); errorAndExit(); } } if (status == TINFL_STATUS_NEEDS_MORE_INPUT && remainingInput != 0) { fprintf(stderr, "Received status NEEDS_MORE_INPUT, with remaining input %lu and space in output %lu.\n", remainingInput, spaceInOutput); } if (status == TINFL_STATUS_HAS_MORE_OUTPUT && spaceInOutput != 0) { fprintf(stderr, "Received status HAS_MORE_OUTPUT, with remaining input %lu and space in output %lu.\n", remainingInput, spaceInOutput); } } //Return output if (remainingInput == 0) { out.needMoreInput = hasMoreBytes; } else { out.needMoreInput = false; } return out; }