Merge "Add a brotli decompressor in bsdiff"

am: 2ac5778d43

Change-Id: Id415b001a4b2946015affc4aeece5688227ae7ac
This commit is contained in:
Tianjie Xu authored and android-build-merger committed 2017-11-17 16:13:15 +00:00
commit aeb9e09389
13 files changed
+170 -17

No files matched your search

+2
View File
@@ -35,9 +35,11 @@ cc_library_static {
defaults: ["bsdiff_defaults"],
srcs: [
"brotli_decompressor.cc",
"bspatch.cc",
"bz2_decompressor.cc",
"buffer_file.cc",
"decompressor_interface.cc",
"extents.cc",
"extents_file.cc",
"file.cc",
+2
View File
@@ -47,9 +47,11 @@ bsdiff_src_files := \
# "bspatch" program.
bspatch_src_files := \
brotli_decompressor.cc \
bspatch.cc \
bz2_decompressor.cc \
buffer_file.cc \
decompressor_interface.cc \
extents.cc \
extents_file.cc \
file.cc \
+14 -3
View File
@@ -6,9 +6,11 @@
#include <gtest/gtest.h>
#include "bsdiff/brotli_decompressor.h"
namespace {
const uint8_t kHelloWorld[] = {
constexpr uint8_t kHelloWorld[] = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a,
};
} // namespace
@@ -22,8 +24,17 @@ TEST(BrotliCompressorTest, BrotliCompressorSmoke) {
std::vector<uint8_t> compressed_data = brotli_compressor.GetCompressedData();
EXPECT_GT(compressed_data.size(), static_cast<size_t>(0));
// TODO(xunchang) run brotli decompressor and check we can get back
// kHelloWorld.
// Run decompressor and check we can get the exact same data as kHelloWorld.
std::vector<uint8_t> decompressed_data(sizeof(kHelloWorld));
BrotliDecompressor brotli_decompressor;
EXPECT_TRUE(brotli_decompressor.SetInputData(compressed_data.data(),
compressed_data.size()));
EXPECT_TRUE(
brotli_decompressor.Read(decompressed_data.data(), sizeof(kHelloWorld)));
EXPECT_TRUE(brotli_decompressor.Close());
EXPECT_EQ(
std::vector<uint8_t>(kHelloWorld, kHelloWorld + sizeof(kHelloWorld)),
decompressed_data);
}
} // namespace bsdiff
+61
View File
@@ -0,0 +1,61 @@
// 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/brotli_decompressor.h"
#include "bsdiff/logging.h"
using std::endl;
namespace bsdiff {
bool BrotliDecompressor::SetInputData(const uint8_t* input_data, size_t size) {
brotli_decoder_state_ =
BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
if (brotli_decoder_state_ == nullptr) {
LOG(ERROR) << "Failed to initialize brotli decoder." << endl;
return false;
}
next_in_ = input_data;
available_in_ = size;
return true;
}
bool BrotliDecompressor::Read(uint8_t* output_data, size_t bytes_to_output) {
auto next_out = output_data;
size_t available_out = bytes_to_output;
while (available_out > 0) {
// The brotli decoder will update |available_in_|, |available_in_|,
// |next_out| and |available_out|.
BrotliDecoderResult result = BrotliDecoderDecompressStream(
brotli_decoder_state_, &available_in_, &next_in_, &available_out,
&next_out, nullptr);
if (result == BROTLI_DECODER_RESULT_ERROR) {
LOG(ERROR) << "Decompression failed with "
<< BrotliDecoderErrorString(
BrotliDecoderGetErrorCode(brotli_decoder_state_))
<< endl;
return false;
} else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
LOG(ERROR) << "Decompressor reached EOF while reading from input stream."
<< endl;
return false;
}
}
return true;
}
bool BrotliDecompressor::Close() {
if (!BrotliDecoderIsFinished(brotli_decoder_state_)) {
LOG(ERROR) << "Unfinished brotli decoder." << endl;
return false;
}
BrotliDecoderDestroyInstance(brotli_decoder_state_);
return true;
}
} // namespace bsdiff
+32
View File
@@ -0,0 +1,32 @@
// 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_BROTLI_DECOMPRESSOR_H_
#define _BSDIFF_BROTLI_DECOMPRESSOR_H_
#include <brotli/decode.h>
#include "bsdiff/decompressor_interface.h"
namespace bsdiff {
class BrotliDecompressor : public DecompressorInterface {
public:
BrotliDecompressor()
: brotli_decoder_state_(nullptr), next_in_(nullptr), available_in_(0) {}
// DecompressorInterface overrides.
bool SetInputData(const uint8_t* input_data, size_t size) override;
bool Read(uint8_t* output_data, size_t bytes_to_output) override;
bool Close() override;
private:
BrotliDecoderState* brotli_decoder_state_;
const uint8_t* next_in_;
size_t available_in_;
};
} // namespace bsdiff
#endif // _BSDIFF_BROTLI_DECOMPRESSOR_H_
+2
View File
@@ -93,9 +93,11 @@
},
},
'sources': [
'brotli_decompressor.cc',
'bspatch.cc',
'buffer_file.cc',
'bz2_decompressor.cc',
'decompressor_interface.cc',
'extents.cc',
'extents_file.cc',
'file.cc',
+2 -5
View File
@@ -11,12 +11,9 @@
#include <memory>
#include <vector>
namespace bsdiff {
#include "bsdiff/constants.h"
enum class CompressorType {
kBrotli,
kBZ2,
};
namespace bsdiff {
class CompressorInterface {
public:
+23
View File
@@ -0,0 +1,23 @@
// 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_CONSTANTS_H_
#define _BSDIFF_CONSTANTS_H_
#include <stdint.h>
namespace bsdiff {
enum class CompressorType {
kBrotli,
kBZ2,
};
// The header of the upstream's "BSDIFF40" format using BZ2 as compressor.
constexpr uint8_t kMagicHeader[] = "BSDIFF40";
} // namespace bsdiff
#endif // _BSDIFF_CONSTANTS_H_
+20
View File
@@ -0,0 +1,20 @@
// 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/decompressor_interface.h"
#include "bsdiff/brotli_decompressor.h"
#include "bsdiff/bz2_decompressor.h"
namespace bsdiff {
std::unique_ptr<DecompressorInterface> CreateDecompressor(CompressorType type) {
if (type == CompressorType::kBrotli) {
return std::unique_ptr<DecompressorInterface>(new BrotliDecompressor());
}
// Use BZ2 as a default decompressor.
return std::unique_ptr<DecompressorInterface>(new BZ2Decompressor());
}
} // namespace bsdiff
+6
View File
@@ -8,6 +8,10 @@
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "bsdiff/constants.h"
namespace bsdiff {
class DecompressorInterface {
@@ -28,5 +32,7 @@ class DecompressorInterface {
virtual bool Close() = 0;
};
std::unique_ptr<DecompressorInterface> CreateDecompressor(CompressorType type);
} // namespace bsdiff
#endif // _BSDIFF_DECOMPRESSOR_INTERFACE_H_
+5 -5
View File
@@ -8,8 +8,10 @@
#include <limits>
#include "bsdiff/brotli_decompressor.h"
#include "bsdiff/bspatch.h"
#include "bsdiff/bz2_decompressor.h"
#include "bsdiff/constants.h"
#include "bsdiff/logging.h"
#include "bsdiff/utils.h"
@@ -17,8 +19,6 @@ using std::endl;
namespace bsdiff {
const uint8_t kMagicHeader[] = "BSDIFF40";
bool BsdiffPatchReader::Init(const uint8_t* patch_data, size_t patch_size) {
// File format:
// 0 8 "BSDIFF40"
@@ -54,9 +54,9 @@ bool BsdiffPatchReader::Init(const uint8_t* patch_data, size_t patch_size) {
// TODO(xunchang) set the correct decompressor based on the info in the
// header.
ctrl_stream_.reset(new BZ2Decompressor());
diff_stream_.reset(new BZ2Decompressor());
extra_stream_.reset(new BZ2Decompressor());
ctrl_stream_ = CreateDecompressor(CompressorType::kBZ2);
diff_stream_ = CreateDecompressor(CompressorType::kBZ2);
extra_stream_ = CreateDecompressor(CompressorType::kBZ2);
int64_t offset = 32;
if (!ctrl_stream_->SetInputData(const_cast<uint8_t*>(patch_data) + offset,
-2
View File
@@ -16,8 +16,6 @@
namespace bsdiff {
extern const uint8_t kMagicHeader[];
// A wrapper class to read and parse the data in a bsdiff patch. The reader
// class contains the concatenated streams of control, diff, and extra data.
// After initialization, this class provides the function to read the metadata
+1 -2
View File
@@ -8,6 +8,7 @@
#include "bsdiff/brotli_compressor.h"
#include "bsdiff/bz2_compressor.h"
#include "bsdiff/constants.h"
#include "bsdiff/control_entry.h"
#include "bsdiff/logging.h"
@@ -15,8 +16,6 @@ using std::endl;
namespace {
constexpr uint8_t kMagicHeader[] = "BSDIFF40";
void EncodeInt64(int64_t x, uint8_t* buf) {
uint64_t y = x < 0 ? (1ULL << 63ULL) - x : x;
for (int i = 0; i < 8; ++i) {