mirror of
https://github.com/expo/bsdiff.git
synced 2026-11-14 17:49:03 -10:00
Merge changes I2bd068c6,If46080a8 am: f6f8ae0cba
am: 328224ec87
Change-Id: I076ac664f54941b8f61ff77722be837d3917ffa0
This commit is contained in:
commit
c3de65b894
7 files changed
+113
-14
No files matched your search
@@ -1,3 +1,7 @@
|
||||
// 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.
|
||||
|
||||
#include "bsdiff/bsdiff_arguments.h"
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
+38
-7
@@ -8,6 +8,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "bsdiff/brotli_compressor.h"
|
||||
#include "bsdiff/bz2_compressor.h"
|
||||
#include "bsdiff/logging.h"
|
||||
|
||||
namespace {
|
||||
@@ -30,12 +32,30 @@ constexpr size_t kMinimumFlushSize = 1024 * 1024; // 1 MiB
|
||||
namespace bsdiff {
|
||||
|
||||
bool EndsleyPatchWriter::Init(size_t new_size) {
|
||||
// The patch is uncompressed and it will need exactly:
|
||||
// new_size + 24 * len(control_entries) + sizeof(header)
|
||||
// We don't know the length of the control entries yet, but we can reserve
|
||||
// enough space to hold at least |new_size|.
|
||||
patch_->clear();
|
||||
patch_->reserve(new_size);
|
||||
switch (compressor_type_) {
|
||||
case CompressorType::kNoCompression:
|
||||
// The patch is uncompressed and it will need exactly:
|
||||
// new_size + 24 * len(control_entries) + sizeof(header)
|
||||
// We don't know the length of the control entries yet, but we can reserve
|
||||
// enough space to hold at least |new_size|.
|
||||
patch_->clear();
|
||||
patch_->reserve(new_size);
|
||||
break;
|
||||
case CompressorType::kBrotli:
|
||||
compressor_.reset(new BrotliCompressor(quality_));
|
||||
if (!compressor_) {
|
||||
LOG(ERROR) << "Error creating brotli compressor.";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case CompressorType::kBZ2:
|
||||
compressor_.reset(new BZ2Compressor());
|
||||
if (!compressor_) {
|
||||
LOG(ERROR) << "Error creating BZ2 compressor.";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Header is the magic followed by the new length.
|
||||
uint8_t header[24];
|
||||
@@ -116,6 +136,13 @@ bool EndsleyPatchWriter::Close() {
|
||||
LOG(ERROR) << "Pending data to diff/extra not flushed out on Close()";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (compressor_) {
|
||||
if (!compressor_->Finish())
|
||||
return false;
|
||||
*patch_ = compressor_->GetCompressedData();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -129,7 +156,11 @@ void EndsleyPatchWriter::EmitControlEntry(const ControlEntry& entry) {
|
||||
}
|
||||
|
||||
void EndsleyPatchWriter::EmitBuffer(const uint8_t* data, size_t size) {
|
||||
patch_->insert(patch_->end(), data, data + size);
|
||||
if (compressor_) {
|
||||
compressor_->Write(data, size);
|
||||
} else {
|
||||
patch_->insert(patch_->end(), data, data + size);
|
||||
}
|
||||
}
|
||||
|
||||
void EndsleyPatchWriter::Flush() {
|
||||
|
||||
+15
-2
@@ -5,9 +5,12 @@
|
||||
#ifndef _BSDIFF_ENDSLEY_PATCH_WRITER_H_
|
||||
#define _BSDIFF_ENDSLEY_PATCH_WRITER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "bsdiff/compressor_interface.h"
|
||||
#include "bsdiff/constants.h"
|
||||
#include "bsdiff/patch_writer_interface.h"
|
||||
|
||||
namespace bsdiff {
|
||||
@@ -35,8 +38,12 @@ class EndsleyPatchWriter : public PatchWriterInterface {
|
||||
public:
|
||||
// Create the patch writer that will write the data to the passed vector
|
||||
// |patch|, resizing it as needed. The |patch| vector must be valid until
|
||||
// Close() is called or this patch is destroyed.
|
||||
explicit EndsleyPatchWriter(std::vector<uint8_t>* patch) : patch_(patch) {}
|
||||
// Close() is called or this patch is destroyed. The data in |patch| will be
|
||||
// compressed using the compressor type |type|.
|
||||
EndsleyPatchWriter(std::vector<uint8_t>* patch,
|
||||
CompressorType type,
|
||||
int quality)
|
||||
: patch_(patch), compressor_type_(type), quality_(quality) {}
|
||||
|
||||
// PatchWriterInterface overrides.
|
||||
bool Init(size_t new_size) override;
|
||||
@@ -58,6 +65,12 @@ class EndsleyPatchWriter : public PatchWriterInterface {
|
||||
// The vector we are writing to, owned by the caller.
|
||||
std::vector<uint8_t>* patch_;
|
||||
|
||||
// The compressor type to use and its quality (if any).
|
||||
CompressorType compressor_type_;
|
||||
int quality_;
|
||||
|
||||
std::unique_ptr<CompressorInterface> compressor_;
|
||||
|
||||
// The pending diff and extra data to be encoded in the file. These vectors
|
||||
// would not be used whenever is possible to the data directly to the patch_
|
||||
// vector; namely when the control, diff and extra stream data are provided in
|
||||
|
||||
@@ -31,7 +31,7 @@ class EndsleyPatchWriterTest : public testing::Test {
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_;
|
||||
EndsleyPatchWriter patch_writer_{&data_};
|
||||
EndsleyPatchWriter patch_writer_{&data_, CompressorType::kNoCompression, 0};
|
||||
};
|
||||
|
||||
// Smoke check that a patch includes the new_size and magic header.
|
||||
@@ -51,6 +51,34 @@ TEST_F(EndsleyPatchWriterTest, CreateEmptyPatchTest) {
|
||||
EXPECT_EQ(empty_patch, data_);
|
||||
}
|
||||
|
||||
TEST_F(EndsleyPatchWriterTest, CreateCompressedPatchTest) {
|
||||
EndsleyPatchWriter compressed_writer(&data_, CompressorType::kBZ2, 9);
|
||||
|
||||
auto text = VectorFromString("HelloWorld");
|
||||
EXPECT_TRUE(compressed_writer.Init(text.size()));
|
||||
|
||||
EXPECT_TRUE(compressed_writer.AddControlEntry(ControlEntry(5, 5, -2)));
|
||||
EXPECT_TRUE(compressed_writer.WriteDiffStream(text.data(), 5));
|
||||
EXPECT_TRUE(compressed_writer.WriteExtraStream(text.data() + 5, 5));
|
||||
|
||||
// Check that the output patch had no data written to it before Close() is
|
||||
// called, since we are still compressing it.
|
||||
EXPECT_TRUE(data_.empty());
|
||||
|
||||
EXPECT_TRUE(compressed_writer.Close());
|
||||
|
||||
// Check that the whole file is compressed with BZ2 by looking at the header.
|
||||
const auto bz2_header = VectorFromString("BZh9");
|
||||
data_.resize(4);
|
||||
EXPECT_EQ(bz2_header, data_);
|
||||
}
|
||||
|
||||
TEST_F(EndsleyPatchWriterTest, CreateEmptyBrotliPatchTest) {
|
||||
EndsleyPatchWriter compressed_writer(&data_, CompressorType::kBrotli, 9);
|
||||
EXPECT_TRUE(compressed_writer.Init(0));
|
||||
EXPECT_TRUE(compressed_writer.Close());
|
||||
}
|
||||
|
||||
// Test we generate the right patch when the control, diff and extra stream come
|
||||
// in the right order.
|
||||
TEST_F(EndsleyPatchWriterTest, DataInNiceOrderTest) {
|
||||
|
||||
@@ -29,13 +29,23 @@ std::unique_ptr<PatchWriterInterface> CreateBSDF2PatchWriter(
|
||||
CompressorType type,
|
||||
int quality);
|
||||
|
||||
// Create a patch writer compatible with Android Play Store bsdiff patches,
|
||||
// uncompressed. The data will be written to the passed |patch| vector, which
|
||||
// must be valid until Close() is called or this patch is destroyed.
|
||||
// Create a patch writer compatible with Android Play Store bsdiff patches.
|
||||
// The data will be written to the passed |patch| vector, which must be valid
|
||||
// until Close() is called or this patch is destroyed. The data will be
|
||||
// compressed using the compressor type |type|. To get an uncompressed patch,
|
||||
// pass CompressortType::kNoCompression.
|
||||
BSDIFF_EXPORT
|
||||
std::unique_ptr<PatchWriterInterface> CreateEndsleyPatchWriter(
|
||||
std::vector<uint8_t>* patch,
|
||||
CompressorType type,
|
||||
int quality);
|
||||
|
||||
// Helper function to create an Endsley patch writer with no compression.
|
||||
BSDIFF_EXPORT
|
||||
std::unique_ptr<PatchWriterInterface> CreateEndsleyPatchWriter(
|
||||
std::vector<uint8_t>* patch);
|
||||
|
||||
|
||||
} // namespace bsdiff
|
||||
|
||||
#endif // _BSDIFF_PATCH_WRITER_FACTORY_H_
|
||||
+10
-1
@@ -23,9 +23,18 @@ std::unique_ptr<PatchWriterInterface> CreateBSDF2PatchWriter(
|
||||
new BsdiffPatchWriter(patch_filename, type, quality));
|
||||
}
|
||||
|
||||
std::unique_ptr<PatchWriterInterface> CreateEndsleyPatchWriter(
|
||||
std::vector<uint8_t>* patch,
|
||||
CompressorType type,
|
||||
int quality) {
|
||||
return std::unique_ptr<PatchWriterInterface>(
|
||||
new EndsleyPatchWriter(patch, type, quality));
|
||||
}
|
||||
|
||||
std::unique_ptr<PatchWriterInterface> CreateEndsleyPatchWriter(
|
||||
std::vector<uint8_t>* patch) {
|
||||
return std::unique_ptr<PatchWriterInterface>(new EndsleyPatchWriter(patch));
|
||||
return std::unique_ptr<PatchWriterInterface>(
|
||||
new EndsleyPatchWriter(patch, CompressorType::kNoCompression, 0));
|
||||
}
|
||||
|
||||
} // namespace bsdiff
|
||||
Reference in new issue
Block a user