static unsigned char * brotli_decode_buffer(struct stream_encoded *st, unsigned char *data, int len, int *new_len) { struct br_enc_data *enc_data = (struct br_enc_data *)st->data; BrotliInput inp; BrotliOutput outp; BrotliState *stream = &enc_data->br_stream; int error; int finish = (len == 0); *new_len = 0; /* default, left there if an error occurs */ enc_data->input = data; enc_data->input_length = len; enc_data->input_pos = 0; enc_data->output = NULL; enc_data->output_length = 0; enc_data->output_pos = 0; inp.data_ = enc_data; outp.data_ = enc_data; inp.cb_ = brotli_read_function; outp.cb_ = brotli_write_function; error = BrotliDecompressStreaming(inp, outp, finish, stream); switch (error) { case BROTLI_RESULT_ERROR: return NULL; case BROTLI_RESULT_SUCCESS: enc_data->after_end = 1; case BROTLI_RESULT_NEEDS_MORE_INPUT: default: *new_len = enc_data->output_length; return enc_data->output; } }
static int brotli_read(struct stream_encoded *stream, unsigned char *buf, int len) { struct br_enc_data *enc_data = (struct br_enc_data *) stream->data; BrotliState *s; BrotliInput inp; BrotliOutput outp; size_t l; int error; if (!enc_data) return -1; s = &enc_data->br_stream; assert(len > 0); if (enc_data->after_end) { l = MIN(len, enc_data->output_length - enc_data->output_pos); memcpy(buf, enc_data->output + enc_data->output_pos, l); enc_data->output_pos += l; return l; } enc_data->input = NULL; enc_data->input_length = 0; enc_data->output = NULL; enc_data->output_length = 0; enc_data->output_pos = 0; inp.data_ = enc_data; outp.data_ = enc_data; inp.cb_ = brotli_read_function_fd; outp.cb_ = brotli_write_function; error = BrotliDecompressStreaming(inp, outp, 1, s); switch (error) { case BROTLI_RESULT_ERROR: return -1; case BROTLI_RESULT_SUCCESS: enc_data->after_end = 1; case BROTLI_RESULT_NEEDS_MORE_INPUT: default: enc_data->need_free = 1; l = MIN(len, enc_data->output_length - enc_data->output_pos); memcpy(buf, enc_data->output + enc_data->output_pos, l); enc_data->output_pos += l; return l; } }
void QBrotliDecoder::decode() { if (m_pInputDevice == nullptr || m_pOutputDevice == nullptr) { emit onError("IO devices not set."); return; } if (!m_pInputDevice->isReadable()) { emit onError("Input not readable."); return; } if (!m_pOutputDevice->isWritable()) { emit onError("Output not writeable."); return; } BrotliState state; qint64 totalsize=-1; if (!m_pInputDevice->isSequential()) totalsize = m_pInputDevice->size(); BrotliStateInit(&state); int finish = 0; BrotliResult r; BrotliInput input = initInput(m_pInputDevice); BrotliOutput output = initOutput(m_pOutputDevice); for (;;) { r = BrotliDecompressStreaming(input,output,finish,&state); if (r==0) { //error emit onError("Decoding error."); break; } else if (r==1) { //done break; } if (totalsize!=-1) emit onProgress((double)m_pInputDevice->pos()/(double)totalsize); if (m_pInputDevice->atEnd()) finish=1; } emit onProgress(1.0); emit onDone(); BrotliStateCleanup(&state); }