ssn-installer/src/inflate.c

99 lines
2.6 KiB
C
Raw Normal View History

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
char* comprBuffer;
char* uncomprBuffer;
//Position of the inflater in the buffer arrays
char* comprBufferNext;
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;
comprBufferNext = comprBuffer;
}
//output buffer has been emptied
spaceInOutput = uncomprBufferSize;
uncomprBufferNext = uncomprBuffer;
struct InflateOutput out;
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
comprBufferNext += in_bytes;
remainingInput -= in_bytes;
uncomprBufferNext += out_bytes;
spaceInOutput -= out_bytes;
//Check for errors
if (status <= TINFL_STATUS_DONE) {
if (status == TINFL_STATUS_DONE) {
// Decompression completed successfully.
break;
} else {
// Decompression failed.
fprintf(stderr, "tinfl_decompress() failed with status %i!\n", status);
exit(1);
}
}
//If output buffer is filled
if (spaceInOutput == 0) {
break;
}
}
//Return output
if (remainingInput == 0) {
out.needMoreInput = hasMoreBytes;
}
out.numBytesWrittenToOutput = uncomprBufferSize - spaceInOutput;
return out;
}