From 7a375134b7efc4ea502af075044270ceffc3a6a1 Mon Sep 17 00:00:00 2001 From: Kelvin Zhang Date: Thu, 15 Jul 2021 16:42:15 -0400 Subject: Expose PatchWriter for consumption Test: th Change-Id: I1d0657bc886967e73b926fae13300bd401696d6a --- compressor_interface.h | 40 --------------- include/bsdiff/compressor_interface.h | 40 +++++++++++++++ include/bsdiff/control_entry.h | 15 +++--- include/bsdiff/patch_writer.h | 93 +++++++++++++++++++++++++++++++++++ patch_writer.cc | 7 --- patch_writer.h | 84 ------------------------------- 6 files changed, 141 insertions(+), 138 deletions(-) delete mode 100644 compressor_interface.h create mode 100644 include/bsdiff/compressor_interface.h create mode 100644 include/bsdiff/patch_writer.h delete mode 100644 patch_writer.h diff --git a/compressor_interface.h b/compressor_interface.h deleted file mode 100644 index c0ff18d..0000000 --- a/compressor_interface.h +++ /dev/null @@ -1,40 +0,0 @@ -// 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_COMPRESSOR_INTERFACE_H_ -#define _BSDIFF_COMPRESSOR_INTERFACE_H_ - -#include -#include - -#include -#include - -#include "bsdiff/constants.h" - -namespace bsdiff { - -class CompressorInterface { - public: - virtual ~CompressorInterface() = default; - - // Compress and write |size| bytes of input data starting from |buf|. - virtual bool Write(const uint8_t* buf, size_t size) = 0; - - // Finish the compression step. - virtual bool Finish() = 0; - - // Return the compressed data. This method must be only called after Finish(). - virtual const std::vector& GetCompressedData() = 0; - - // Return the type of the current compressor. - virtual CompressorType Type() const = 0; - - protected: - CompressorInterface() = default; -}; - -} // namespace bsdiff - -#endif // _BSDIFF_COMPRESSOR_INTERFACE_H_ diff --git a/include/bsdiff/compressor_interface.h b/include/bsdiff/compressor_interface.h new file mode 100644 index 0000000..c0ff18d --- /dev/null +++ b/include/bsdiff/compressor_interface.h @@ -0,0 +1,40 @@ +// 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_COMPRESSOR_INTERFACE_H_ +#define _BSDIFF_COMPRESSOR_INTERFACE_H_ + +#include +#include + +#include +#include + +#include "bsdiff/constants.h" + +namespace bsdiff { + +class CompressorInterface { + public: + virtual ~CompressorInterface() = default; + + // Compress and write |size| bytes of input data starting from |buf|. + virtual bool Write(const uint8_t* buf, size_t size) = 0; + + // Finish the compression step. + virtual bool Finish() = 0; + + // Return the compressed data. This method must be only called after Finish(). + virtual const std::vector& GetCompressedData() = 0; + + // Return the type of the current compressor. + virtual CompressorType Type() const = 0; + + protected: + CompressorInterface() = default; +}; + +} // namespace bsdiff + +#endif // _BSDIFF_COMPRESSOR_INTERFACE_H_ diff --git a/include/bsdiff/control_entry.h b/include/bsdiff/control_entry.h index 2c849f6..3d2d96c 100644 --- a/include/bsdiff/control_entry.h +++ b/include/bsdiff/control_entry.h @@ -8,23 +8,24 @@ #include struct ControlEntry { - ControlEntry(uint64_t diff_size, - uint64_t extra_size, - int64_t offset_increment) + constexpr ControlEntry(uint64_t diff_size, + uint64_t extra_size, + int64_t offset_increment) : diff_size(diff_size), extra_size(extra_size), offset_increment(offset_increment) {} + constexpr ControlEntry() = default; // The number of bytes to copy from the source and diff stream. - uint64_t diff_size; + uint64_t diff_size{0}; // The number of bytes to copy from the extra stream. - uint64_t extra_size; + uint64_t extra_size{0}; // The value to add to the source pointer after patching from the diff stream. - int64_t offset_increment; + int64_t offset_increment{0}; - bool operator==(const ControlEntry& o) const { + [[nodiscard]] bool operator==(const ControlEntry& o) const { return diff_size == o.diff_size && extra_size == o.extra_size && offset_increment == o.offset_increment; } 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 +#include +#include + +#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& 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>* 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>& 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 types_; + + // The compression quality of the brotli compressor. + int brotli_quality_; + + // The list of compressors to try for each stream. + std::vector> ctrl_stream_list_; + std::vector> diff_stream_list_; + std::vector> extra_stream_list_; +}; + +} // namespace bsdiff + +#endif // _BSDIFF_PATCH_WRITER_H_ diff --git a/patch_writer.cc b/patch_writer.cc index 52982e0..b7d9b08 100644 --- a/patch_writer.cc +++ b/patch_writer.cc @@ -15,13 +15,6 @@ namespace { -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; - } -} } // namespace diff --git a/patch_writer.h b/patch_writer.h deleted file mode 100644 index 8ad4cde..0000000 --- a/patch_writer.h +++ /dev/null @@ -1,84 +0,0 @@ -// 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 -#include -#include - -#include "bsdiff/compressor_interface.h" -#include "bsdiff/patch_writer_interface.h" - -namespace bsdiff { - -// 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& 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>* 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>& 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 types_; - - // The compression quality of the brotli compressor. - int brotli_quality_; - - // The list of compressors to try for each stream. - std::vector> ctrl_stream_list_; - std::vector> diff_stream_list_; - std::vector> extra_stream_list_; -}; - -} // namespace bsdiff - -#endif // _BSDIFF_PATCH_WRITER_H_ -- cgit v1.2.3