2018-07-31 13:18:18 +02:00
|
|
|
//Based on https://github.com/richgel999/miniz/blob/master/examples/example5.c (Public domain, April 11 2012, Rich Geldreich, richgel99@gmail.com)
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
//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 "inflate.h"
|
|
|
|
|
|
|
|
//The compressed and uncompressed buffer arrays
|
2018-07-31 14:01:33 +02:00
|
|
|
const char* comprBuffer;
|
2018-07-31 13:18:18 +02:00
|
|
|
char* uncomprBuffer;
|
|
|
|
//Position of the inflater in the buffer arrays
|
2018-07-31 14:01:33 +02:00
|
|
|
const char* comprBufferNext;
|
2018-07-31 13:18:18 +02:00
|
|
|
char* uncomprBufferNext;
|
|
|
|
//Buffer lengths
|
|
|
|
unsigned long uncomprBufferSize;
|
|
|
|
unsigned long remainingInput;
|
|
|
|
unsigned long spaceInOutput;
|
|
|
|
//Internal variables used by miniz
|
|
|
|
tinfl_decompressor inflator;
|
|
|
|
tdefl_status status;
|
|
|
|
size_t in_bytes, out_bytes;
|
|
|
|
|
|
|
|
void inflateInit(char* comprBufferIn, char* uncomprBufferIn, unsigned long uncomprBufferSizeIn) {
|
|
|
|
comprBuffer = comprBufferIn;
|
|
|
|
uncomprBuffer = uncomprBufferIn;
|
|
|
|
uncomprBufferSize = uncomprBufferSizeIn;
|
|
|
|
tinfl_init(&inflator);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
remainingInput = numInputBytes;
|
2018-07-31 13:50:30 +02:00
|
|
|
comprBufferNext = (const mz_uint8 *)comprBuffer;
|
2018-07-31 13:18:18 +02:00
|
|
|
}
|
|
|
|
//output buffer has been emptied
|
|
|
|
spaceInOutput = uncomprBufferSize;
|
2018-07-31 13:50:30 +02:00
|
|
|
uncomprBufferNext = (mz_uint8 *)uncomprBuffer;
|
2018-07-31 13:18:18 +02:00
|
|
|
|
|
|
|
struct InflateOutput out;
|
2018-07-31 13:38:21 +02:00
|
|
|
out.hasReachedEnd = false;
|
2018-07-31 13:18:18 +02:00
|
|
|
|
|
|
|
while (remainingInput > 0 && spaceInOutput > 0) {
|
|
|
|
in_bytes = remainingInput;
|
|
|
|
out_bytes = spaceInOutput;
|
|
|
|
|
|
|
|
//Call decompression
|
|
|
|
status = tinfl_decompress(
|
|
|
|
&inflator,
|
|
|
|
(const mz_uint8 *)comprBufferNext,
|
|
|
|
&in_bytes,
|
|
|
|
uncomprBuffer,
|
|
|
|
(mz_uint8 *)uncomprBufferNext,
|
|
|
|
&out_bytes,
|
|
|
|
(hasMoreBytes ? TINFL_FLAG_HAS_MORE_INPUT : 0)
|
|
|
|
);
|
|
|
|
|
|
|
|
//Adjust buffer positions by the amount of bytes processed
|
2018-07-31 13:50:30 +02:00
|
|
|
comprBufferNext = (const mz_uint8 *)comprBufferNext + in_bytes;
|
2018-07-31 13:18:18 +02:00
|
|
|
remainingInput -= in_bytes;
|
2018-07-31 13:50:30 +02:00
|
|
|
uncomprBufferNext = (mz_uint8 *)uncomprBufferNext + out_bytes;
|
2018-07-31 13:18:18 +02:00
|
|
|
spaceInOutput -= out_bytes;
|
|
|
|
|
|
|
|
//Check for errors
|
|
|
|
if (status <= TINFL_STATUS_DONE) {
|
|
|
|
if (status == TINFL_STATUS_DONE) {
|
|
|
|
// Decompression completed successfully.
|
2018-07-31 13:38:21 +02:00
|
|
|
out.hasReachedEnd = true;
|
2018-07-31 13:18:18 +02:00
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
// Decompression failed.
|
|
|
|
fprintf(stderr, "tinfl_decompress() failed with status %i!\n", status);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-31 13:38:21 +02:00
|
|
|
//If output buffer is filled, we need to clear it before decompressing more data
|
2018-07-31 13:18:18 +02:00
|
|
|
if (spaceInOutput == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Return output
|
|
|
|
if (remainingInput == 0) {
|
|
|
|
out.needMoreInput = hasMoreBytes;
|
|
|
|
}
|
|
|
|
out.numBytesWrittenToOutput = uncomprBufferSize - spaceInOutput;
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|