static BROTLI_BOOL DecompressFile(Context* context, BrotliDecoderState* s) { BrotliDecoderResult result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT; InitializeBuffers(context); for (;;) { if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) { if (!HasMoreInput(context)) { fprintf(stderr, "corrupt input [%s]\n", PrintablePath(context->current_input_path)); return BROTLI_FALSE; } if (!ProvideInput(context)) return BROTLI_FALSE; } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { if (!ProvideOutput(context)) return BROTLI_FALSE; } else if (result == BROTLI_DECODER_RESULT_SUCCESS) { if (!FlushOutput(context)) return BROTLI_FALSE; if (context->available_in != 0 || HasMoreInput(context)) { fprintf(stderr, "corrupt input [%s]\n", PrintablePath(context->current_input_path)); return BROTLI_FALSE; } return BROTLI_TRUE; } else { fprintf(stderr, "corrupt input [%s]\n", PrintablePath(context->current_input_path)); return BROTLI_FALSE; } result = BrotliDecoderDecompressStream(s, &context->available_in, &context->next_in, &context->available_out, &context->next_out, 0); } }
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; }
static CURLcode brotli_unencode_write(struct connectdata *conn, contenc_writer *writer, const char *buf, size_t nbytes) { brotli_params *bp = (brotli_params *) &writer->params; const uint8_t *src = (const uint8_t *) buf; char *decomp; uint8_t *dst; size_t dstleft; CURLcode result = CURLE_OK; BrotliDecoderResult r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT; if(!bp->br) return CURLE_WRITE_ERROR; /* Stream already ended. */ decomp = malloc(DSIZ); if(!decomp) return CURLE_OUT_OF_MEMORY; while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) && result == CURLE_OK) { dst = (uint8_t *) decomp; dstleft = DSIZ; r = BrotliDecoderDecompressStream(bp->br, &nbytes, &src, &dstleft, &dst, NULL); result = Curl_unencode_write(conn, writer->downstream, decomp, DSIZ - dstleft); if(result) break; switch(r) { case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: break; case BROTLI_DECODER_RESULT_SUCCESS: BrotliDecoderDestroyInstance(bp->br); bp->br = NULL; if(nbytes) result = CURLE_WRITE_ERROR; break; default: result = brotli_map_error(BrotliDecoderGetErrorCode(bp->br)); break; } } free(decomp); return result; }
BrotliDecoderResult decompress(const unsigned char *data, size_t len, struct VecU8 *ret_buffer) { unsigned char buf[BUF_SIZE]; size_t total_out = 0; BrotliDecoderState *state = BrotliDecoderCreateInstance(custom_malloc, custom_free, custom_alloc_opaque); BrotliDecoderResult res; do { size_t read_offset = 0; uint8_t *next_out = &buf[0]; size_t avail_out = BUF_SIZE; res = BrotliDecoderDecompressStream(state, &len, &data, &avail_out, &next_out, &total_out); if (res == BROTLI_DECODER_RESULT_ERROR || (res == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT && len == 0)) { BrotliDecoderDestroyInstance(state); return res; } push_vec_u8(ret_buffer, buf, next_out - buf); } while (res != BROTLI_DECODER_RESULT_SUCCESS); BrotliDecoderDestroyInstance(state); return BROTLI_DECODER_RESULT_SUCCESS; }