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 #ifndef _BSDIFF_PATCH_WRITER_H_
      6 #define _BSDIFF_PATCH_WRITER_H_
      7 
      8 #include <memory>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "bsdiff/compressor_interface.h"
     13 #include "bsdiff/patch_writer_interface.h"
     14 
     15 namespace bsdiff {
     16 
     17 // A PatchWriterInterface class with three compressors and a 32-byte header.
     18 class BsdiffPatchWriter : public PatchWriterInterface {
     19  public:
     20   // Create the patch writer using the upstream's "BSDIFF40" format. It uses
     21   // bz2 as the compression algorithm and the file |patch_filename| to write
     22   // the patch data.
     23   explicit BsdiffPatchWriter(const std::string& patch_filename);
     24 
     25   // Create the patch writer using the "BSDF2" format. It uses the compressor
     26   // with algorithm |type|; and quality |brotli_quality| if it's brotli. This
     27   // writer also writes the patch data to the file |patch_filename|.
     28   BsdiffPatchWriter(const std::string& patch_filename,
     29                     const std::vector<CompressorType>& types,
     30                     int brotli_quality);
     31 
     32   // PatchWriterInterface overrides.
     33   bool Init(size_t new_size) override;
     34   bool WriteDiffStream(const uint8_t* data, size_t size) override;
     35   bool WriteExtraStream(const uint8_t* data, size_t size) override;
     36   bool AddControlEntry(const ControlEntry& entry) override;
     37   bool Close() override;
     38 
     39  private:
     40   // Add supported compressors to |compressor_list|; return false if we failed
     41   // to initialize one of them.
     42   bool InitializeCompressorList(
     43       std::vector<std::unique_ptr<CompressorInterface>>* compressor_list);
     44 
     45   // Select the compressor in |compressor_list| that produces the smallest
     46   // patch, and put the result in |smallest_compressor|.
     47   bool SelectSmallestResult(
     48       const std::vector<std::unique_ptr<CompressorInterface>>& compressor_list,
     49       CompressorInterface** smallest_compressor);
     50 
     51 
     52   // Write the BSDIFF patch header to the |fp_|.
     53   // Arguments:
     54   //   A three bytes array with the compressor types of ctrl|diff|extra stream
     55   //   Size of the compressed control block
     56   //   Size of the compressed diff block.
     57   bool WriteHeader(uint8_t types[3], uint64_t ctrl_size, uint64_t diff_size);
     58 
     59   // Bytes of the new files already written. Needed to store the new length in
     60   // the header of the file.
     61   uint64_t written_output_{0};
     62 
     63   // The current file we are writing to.
     64   FILE* fp_{nullptr};
     65   std::string patch_filename_;
     66 
     67   // The format of bsdiff we're using.
     68   BsdiffFormat format_;
     69 
     70   // The compressors we're using.
     71   std::vector<CompressorType> types_;
     72 
     73   // The compression quality of the brotli compressor.
     74   int brotli_quality_;
     75 
     76   // The list of compressors to try for each stream.
     77   std::vector<std::unique_ptr<CompressorInterface>> ctrl_stream_list_;
     78   std::vector<std::unique_ptr<CompressorInterface>> diff_stream_list_;
     79   std::vector<std::unique_ptr<CompressorInterface>> extra_stream_list_;
     80 };
     81 
     82 }  // namespace bsdiff
     83 
     84 #endif  // _BSDIFF_PATCH_WRITER_H_
     85