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_SPLIT_PATCH_WRITER_H_
      6 #define _BSDIFF_SPLIT_PATCH_WRITER_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include <vector>
     11 
     12 #include "bsdiff/patch_writer_interface.h"
     13 
     14 namespace bsdiff {
     15 
     16 // A PatchWriterInterface class that splits the output patch into multiple
     17 // patches of a fixed new-file size. The size of each patch data will depend on
     18 // the contents of the new file data, and won't necessarily be uniform.
     19 class SplitPatchWriter : public PatchWriterInterface {
     20  public:
     21   // Create a PatchWriter that will split the patch in several patches where
     22   // each one will write |new_chunk_size| bytes of new file data. Each patch
     23   // will use the old file as a whole input file.
     24   SplitPatchWriter(uint64_t new_chunk_size,
     25                    const std::vector<PatchWriterInterface*>& patches)
     26       : new_chunk_size_(new_chunk_size), patches_(patches) {
     27     diff_sizes_.resize(patches.size());
     28     extra_sizes_.resize(patches.size());
     29   }
     30 
     31   // PatchWriterInterface overrides.
     32   // Note: Calling WriteDiffStream/WriteExtraStream before calling the
     33   // corresponding AddControlEntry() is not supported and will fail. The reason
     34   // for this is because which underlying patch takes the bytes depends on the
     35   // control entries.
     36   bool Init(size_t new_size) override;
     37   bool WriteDiffStream(const uint8_t* data, size_t size) override;
     38   bool WriteExtraStream(const uint8_t* data, size_t size) override;
     39   bool AddControlEntry(const ControlEntry& entry) override;
     40   bool Close() override;
     41 
     42  private:
     43   // Add a ControlEntry to the |current_patch_| without splitting it. Updates
     44   // the internal structures of used data.
     45   bool AddControlEntryToCurrentPatch(const ControlEntry& entry);
     46 
     47   using WriteStreamMethod = bool (PatchWriterInterface::*)(const uint8_t* data,
     48                                                            size_t size);
     49 
     50   // Write to the diff or extra stream as determined by |method|.
     51   bool WriteToStream(WriteStreamMethod method,
     52                      std::vector<size_t>* sizes_vector,
     53                      const uint8_t* data,
     54                      size_t size);
     55 
     56   // The size of the new file for the patch we are writing.
     57   size_t new_size_{0};
     58 
     59   // The size of each chunk of the new file written to.
     60   uint64_t new_chunk_size_;
     61   std::vector<PatchWriterInterface*> patches_;
     62 
     63   // The size of the diff and extra streams that should go in each patch and has
     64   // been written so far.
     65   std::vector<size_t> diff_sizes_;
     66   std::vector<size_t> extra_sizes_;
     67 
     68   // The current patch number in the |patches_| array we are writing to.
     69   size_t current_patch_{0};
     70 
     71   // The number of patches we already called Close() on. The patches are always
     72   // closed in order.
     73   size_t closed_patches_{0};
     74 
     75   // Bytes of the new files already written. Needed to store the new length in
     76   // the header of the file.
     77   uint64_t written_output_{0};
     78 
     79   // The current pointer into the old stream.
     80   uint64_t old_pos_{0};
     81 };
     82 
     83 }  // namespace bsdiff
     84 
     85 #endif  // _BSDIFF_SPLIT_PATCH_WRITER_H_
     86