static BROTLI_BOOL DecompressFiles(Context* context) { while (NextFile(context)) { BROTLI_BOOL is_ok = BROTLI_TRUE; BrotliDecoderState* s = BrotliDecoderCreateInstance(BrotliAllocFunc, BrotliFreeFunc, &scratch_buffer_size); if (!s) { fprintf(stderr, "out of memory\n"); return BROTLI_FALSE; } /* This allows decoding "large-window" streams. Though it creates fragmentation (new builds decode streams that old builds don't), it is better from used experience perspective. */ BrotliDecoderSetParameter(s, BROTLI_DECODER_PARAM_LARGE_WINDOW, 1u); is_ok = OpenFiles(context); if (is_ok && !context->current_input_path && !context->force_overwrite && isatty(STDIN_FILENO)) { fprintf(stderr, "Use -h help. Use -f to force input from a terminal.\n"); is_ok = BROTLI_FALSE; } if (is_ok) is_ok = DecompressFile(context, s); BrotliDecoderDestroyInstance(s); if (!CloseFiles(context, is_ok)) is_ok = BROTLI_FALSE; if (!is_ok) return BROTLI_FALSE; } return BROTLI_TRUE; }
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); }
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; }
static void brotli_close_writer(struct connectdata *conn, contenc_writer *writer) { brotli_params *bp = (brotli_params *) &writer->params; (void) conn; if(bp->br) { BrotliDecoderDestroyInstance(bp->br); bp->br = NULL; } }
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; }