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