// Copyright 2017 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef _BSDIFF_SPLIT_PATCH_WRITER_H_ #define _BSDIFF_SPLIT_PATCH_WRITER_H_ #include <stdint.h> #include <vector> #include "bsdiff/patch_writer_interface.h" namespace bsdiff { // A PatchWriterInterface class that splits the output patch into multiple // patches of a fixed new-file size. The size of each patch data will depend on // the contents of the new file data, and won't necessarily be uniform. class SplitPatchWriter : public PatchWriterInterface { public: // Create a PatchWriter that will split the patch in several patches where // each one will write |new_chunk_size| bytes of new file data. Each patch // will use the old file as a whole input file. SplitPatchWriter(uint64_t new_chunk_size, const std::vector<PatchWriterInterface*>& patches) : new_chunk_size_(new_chunk_size), patches_(patches) { diff_sizes_.resize(patches.size()); extra_sizes_.resize(patches.size()); } // PatchWriterInterface overrides. // Note: Calling WriteDiffStream/WriteExtraStream before calling the // corresponding AddControlEntry() is not supported and will fail. The reason // for this is because which underlying patch takes the bytes depends on the // control entries. bool Init(size_t new_size) override; bool WriteDiffStream(const uint8_t* data, size_t size) override; bool WriteExtraStream(const uint8_t* data, size_t size) override; bool AddControlEntry(const ControlEntry& entry) override; bool Close() override; private: // Add a ControlEntry to the |current_patch_| without splitting it. Updates // the internal structures of used data. bool AddControlEntryToCurrentPatch(const ControlEntry& entry); using WriteStreamMethod = bool (PatchWriterInterface::*)(const uint8_t* data, size_t size); // Write to the diff or extra stream as determined by |method|. bool WriteToStream(WriteStreamMethod method, std::vector<size_t>* sizes_vector, const uint8_t* data, size_t size); // The size of the new file for the patch we are writing. size_t new_size_{0}; // The size of each chunk of the new file written to. uint64_t new_chunk_size_; std::vector<PatchWriterInterface*> patches_; // The size of the diff and extra streams that should go in each patch and has // been written so far. std::vector<size_t> diff_sizes_; std::vector<size_t> extra_sizes_; // The current patch number in the |patches_| array we are writing to. size_t current_patch_{0}; // The number of patches we already called Close() on. The patches are always // closed in order. size_t closed_patches_{0}; // Bytes of the new files already written. Needed to store the new length in // the header of the file. uint64_t written_output_{0}; // The current pointer into the old stream. uint64_t old_pos_{0}; }; } // namespace bsdiff #endif // _BSDIFF_SPLIT_PATCH_WRITER_H_