summaryrefslogtreecommitdiff
path: root/include/bsdiff/patch_writer.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/bsdiff/patch_writer.h')
-rw-r--r--include/bsdiff/patch_writer.h93
1 files changed, 93 insertions, 0 deletions
diff --git a/include/bsdiff/patch_writer.h b/include/bsdiff/patch_writer.h
new file mode 100644
index 0000000..6d2bcf5
--- /dev/null
+++ b/include/bsdiff/patch_writer.h
@@ -0,0 +1,93 @@
+// 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_PATCH_WRITER_H_
+#define _BSDIFF_PATCH_WRITER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "bsdiff/compressor_interface.h"
+#include "bsdiff/patch_writer_interface.h"
+
+namespace bsdiff {
+
+
+constexpr void EncodeInt64(int64_t x, uint8_t* buf) {
+ uint64_t y = x < 0 ? (1ULL << 63ULL) - x : x;
+ for (int i = 0; i < 8; ++i) {
+ buf[i] = y & 0xff;
+ y /= 256;
+ }
+}
+
+// A PatchWriterInterface class with three compressors and a 32-byte header.
+class BsdiffPatchWriter : public PatchWriterInterface {
+ public:
+ // Create the patch writer using the upstream's "BSDIFF40" format. It uses
+ // bz2 as the compression algorithm and the file |patch_filename| to write
+ // the patch data.
+ explicit BsdiffPatchWriter(const std::string& patch_filename);
+
+ // Create the patch writer using the "BSDF2" format. It uses the compressor
+ // with algorithm |type|; and quality |brotli_quality| if it's brotli. This
+ // writer also writes the patch data to the file |patch_filename|.
+ BsdiffPatchWriter(const std::string& patch_filename,
+ const std::vector<CompressorType>& types,
+ int brotli_quality);
+
+ // PatchWriterInterface overrides.
+ 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 supported compressors to |compressor_list|; return false if we failed
+ // to initialize one of them.
+ bool InitializeCompressorList(
+ std::vector<std::unique_ptr<CompressorInterface>>* compressor_list);
+
+ // Select the compressor in |compressor_list| that produces the smallest
+ // patch, and put the result in |smallest_compressor|.
+ bool SelectSmallestResult(
+ const std::vector<std::unique_ptr<CompressorInterface>>& compressor_list,
+ CompressorInterface** smallest_compressor);
+
+
+ // Write the BSDIFF patch header to the |fp_|.
+ // Arguments:
+ // A three bytes array with the compressor types of ctrl|diff|extra stream
+ // Size of the compressed control block
+ // Size of the compressed diff block.
+ bool WriteHeader(uint8_t types[3], uint64_t ctrl_size, uint64_t diff_size);
+
+ // 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 file we are writing to.
+ FILE* fp_{nullptr};
+ std::string patch_filename_;
+
+ // The format of bsdiff we're using.
+ BsdiffFormat format_;
+
+ // The compressors we're using.
+ std::vector<CompressorType> types_;
+
+ // The compression quality of the brotli compressor.
+ int brotli_quality_;
+
+ // The list of compressors to try for each stream.
+ std::vector<std::unique_ptr<CompressorInterface>> ctrl_stream_list_;
+ std::vector<std::unique_ptr<CompressorInterface>> diff_stream_list_;
+ std::vector<std::unique_ptr<CompressorInterface>> extra_stream_list_;
+};
+
+} // namespace bsdiff
+
+#endif // _BSDIFF_PATCH_WRITER_H_