Home | History | Annotate | Download | only in bsdiff
      1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "bsdiff/brotli_decompressor.h"
      6 
      7 #include "bsdiff/logging.h"
      8 
      9 namespace bsdiff {
     10 
     11 bool BrotliDecompressor::SetInputData(const uint8_t* input_data, size_t size) {
     12   brotli_decoder_state_ =
     13       BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
     14   if (brotli_decoder_state_ == nullptr) {
     15     LOG(ERROR) << "Failed to initialize brotli decoder.";
     16     return false;
     17   }
     18   next_in_ = input_data;
     19   available_in_ = size;
     20   return true;
     21 }
     22 
     23 bool BrotliDecompressor::Read(uint8_t* output_data, size_t bytes_to_output) {
     24   auto next_out = output_data;
     25   size_t available_out = bytes_to_output;
     26 
     27   while (available_out > 0) {
     28     // The brotli decoder will update |available_in_|, |available_in_|,
     29     // |next_out| and |available_out|.
     30     BrotliDecoderResult result = BrotliDecoderDecompressStream(
     31         brotli_decoder_state_, &available_in_, &next_in_, &available_out,
     32         &next_out, nullptr);
     33 
     34     if (result == BROTLI_DECODER_RESULT_ERROR) {
     35       LOG(ERROR) << "Decompression failed with "
     36                  << BrotliDecoderErrorString(
     37                         BrotliDecoderGetErrorCode(brotli_decoder_state_));
     38       return false;
     39     } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
     40       LOG(ERROR) << "Decompressor reached EOF while reading from input stream.";
     41       return false;
     42     }
     43   }
     44   return true;
     45 }
     46 
     47 bool BrotliDecompressor::Close() {
     48   // In some cases, the brotli compressed stream could be empty. As a result,
     49   // the function BrotliDecoderIsFinished() will return false because we never
     50   // start the decompression. When that happens, we just destroy the decoder
     51   // and return true.
     52   if (BrotliDecoderIsUsed(brotli_decoder_state_) &&
     53       !BrotliDecoderIsFinished(brotli_decoder_state_)) {
     54     LOG(ERROR) << "Unfinished brotli decoder.";
     55     return false;
     56   }
     57 
     58   BrotliDecoderDestroyInstance(brotli_decoder_state_);
     59   return true;
     60 }
     61 
     62 }  // namespace bsdiff
     63