| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- /* Copyright 2018 Google Inc. All Rights Reserved.
- Distributed under MIT license.
- See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <brotli/decode.h>
- #if !defined(_WIN32)
- #include <unistd.h>
- #else
- #include <io.h>
- #define fdopen _fdopen
- #if !defined(__MINGW32__)
- #define STDIN_FILENO _fileno(stdin)
- #define STDOUT_FILENO _fileno(stdout)
- #endif
- #endif
- #define BUFFER_SIZE (1u << 20)
- typedef struct Context {
- FILE* fin;
- FILE* fout;
- uint8_t* input_buffer;
- uint8_t* output_buffer;
- BrotliDecoderState* decoder;
- } Context;
- void init(Context* ctx) {
- ctx->fin = 0;
- ctx->fout = 0;
- ctx->input_buffer = 0;
- ctx->output_buffer = 0;
- ctx->decoder = 0;
- }
- void cleanup(Context* ctx) {
- if (ctx->decoder) BrotliDecoderDestroyInstance(ctx->decoder);
- if (ctx->output_buffer) free(ctx->output_buffer);
- if (ctx->input_buffer) free(ctx->input_buffer);
- if (ctx->fout) fclose(ctx->fout);
- if (ctx->fin) fclose(ctx->fin);
- }
- void fail(Context* ctx, const char* message) {
- fprintf(stderr, "%s\n", message);
- cleanup(ctx);
- exit(1);
- }
- int main(int argc, char** argv) {
- Context ctx;
- BrotliDecoderResult result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
- size_t available_in;
- const uint8_t* next_in;
- size_t available_out = BUFFER_SIZE;
- uint8_t* next_out;
- init(&ctx);
- ctx.fin = fdopen(STDIN_FILENO, "rb");
- if (!ctx.fin) fail(&ctx, "can't open input file");
- ctx.fout = fdopen(STDOUT_FILENO, "wb");
- if (!ctx.fout) fail(&ctx, "can't open output file");
- ctx.input_buffer = (uint8_t*)malloc(BUFFER_SIZE);
- if (!ctx.input_buffer) fail(&ctx, "out of memory / input buffer");
- ctx.output_buffer = (uint8_t*)malloc(BUFFER_SIZE);
- if (!ctx.output_buffer) fail(&ctx, "out of memory / output buffer");
- ctx.decoder = BrotliDecoderCreateInstance(0, 0, 0);
- if (!ctx.decoder) fail(&ctx, "out of memory / decoder");
- BrotliDecoderSetParameter(ctx.decoder, BROTLI_DECODER_PARAM_LARGE_WINDOW, 1);
- next_out = ctx.output_buffer;
- while (1) {
- if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
- if (feof(ctx.fin)) break;
- available_in = fread(ctx.input_buffer, 1, BUFFER_SIZE, ctx.fin);
- next_in = ctx.input_buffer;
- if (ferror(ctx.fin)) break;
- } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
- fwrite(ctx.output_buffer, 1, BUFFER_SIZE, ctx.fout);
- if (ferror(ctx.fout)) break;
- available_out = BUFFER_SIZE;
- next_out = ctx.output_buffer;
- } else {
- break;
- }
- result = BrotliDecoderDecompressStream(
- ctx.decoder, &available_in, &next_in, &available_out, &next_out, 0);
- }
- if (next_out != ctx.output_buffer) {
- fwrite(ctx.output_buffer, 1, next_out - ctx.output_buffer, ctx.fout);
- }
- if ((result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) || ferror(ctx.fout)) {
- fail(&ctx, "failed to write output");
- } else if (result != BROTLI_DECODER_RESULT_SUCCESS) {
- fail(&ctx, "corrupt input");
- }
- cleanup(&ctx);
- return 0;
- }
|