You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.8 KiB
102 lines
2.8 KiB
// 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/bz2_compressor.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "bsdiff/logging.h"
|
|
|
|
namespace {
|
|
|
|
// The BZ2 compression level used. Smaller compression levels are nowadays
|
|
// pointless.
|
|
const int kCompressionLevel = 9;
|
|
|
|
} // namespace
|
|
|
|
namespace bsdiff {
|
|
|
|
BZ2Compressor::BZ2Compressor() : comp_buffer_(1024 * 1024) {
|
|
memset(&bz_strm_, 0, sizeof(bz_strm_));
|
|
int bz_err = BZ2_bzCompressInit(&bz_strm_, kCompressionLevel,
|
|
0 /* verbosity */, 0 /* workFactor */);
|
|
if (bz_err != BZ_OK) {
|
|
LOG(ERROR) << "Initializing bz_strm, bz_error=" << bz_err;
|
|
} else {
|
|
bz_strm_initialized_ = true;
|
|
}
|
|
}
|
|
|
|
BZ2Compressor::~BZ2Compressor() {
|
|
if (!bz_strm_initialized_)
|
|
return;
|
|
int bz_err = BZ2_bzCompressEnd(&bz_strm_);
|
|
if (bz_err != BZ_OK) {
|
|
LOG(ERROR) << "Deleting the compressor stream, bz_error=" << bz_err;
|
|
}
|
|
}
|
|
|
|
bool BZ2Compressor::Write(const uint8_t* buf, size_t size) {
|
|
if (!bz_strm_initialized_)
|
|
return false;
|
|
|
|
// The bz_stream struct defines the next_in as a non-const data pointer,
|
|
// although the documentation says it won't modify it.
|
|
bz_strm_.next_in = reinterpret_cast<char*>(const_cast<uint8_t*>(buf));
|
|
bz_strm_.avail_in = size;
|
|
|
|
while (bz_strm_.avail_in) {
|
|
bz_strm_.next_out = reinterpret_cast<char*>(comp_buffer_.buffer_data());
|
|
bz_strm_.avail_out = comp_buffer_.buffer_size();
|
|
int bz_err = BZ2_bzCompress(&bz_strm_, BZ_RUN);
|
|
if (bz_err != BZ_RUN_OK) {
|
|
LOG(ERROR) << "Compressing data, bz_error=" << bz_err;
|
|
return false;
|
|
}
|
|
|
|
uint64_t output_bytes = comp_buffer_.buffer_size() - bz_strm_.avail_out;
|
|
if (output_bytes) {
|
|
comp_buffer_.AddDataToChunks(output_bytes);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool BZ2Compressor::Finish() {
|
|
if (!bz_strm_initialized_)
|
|
return false;
|
|
bz_strm_.next_in = nullptr;
|
|
bz_strm_.avail_in = 0;
|
|
|
|
int bz_err = BZ_FINISH_OK;
|
|
while (bz_err == BZ_FINISH_OK) {
|
|
bz_strm_.next_out = reinterpret_cast<char*>(comp_buffer_.buffer_data());
|
|
bz_strm_.avail_out = comp_buffer_.buffer_size();
|
|
bz_err = BZ2_bzCompress(&bz_strm_, BZ_FINISH);
|
|
|
|
uint64_t output_bytes = comp_buffer_.buffer_size() - bz_strm_.avail_out;
|
|
if (output_bytes) {
|
|
comp_buffer_.AddDataToChunks(output_bytes);
|
|
}
|
|
}
|
|
if (bz_err != BZ_STREAM_END) {
|
|
LOG(ERROR) << "Finishing compressing data, bz_error=" << bz_err;
|
|
return false;
|
|
}
|
|
bz_err = BZ2_bzCompressEnd(&bz_strm_);
|
|
bz_strm_initialized_ = false;
|
|
if (bz_err != BZ_OK) {
|
|
LOG(ERROR) << "Deleting the compressor stream, bz_error=" << bz_err;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const std::vector<uint8_t>& BZ2Compressor::GetCompressedData() {
|
|
return comp_buffer_.GetCompressedData();
|
|
}
|
|
|
|
} // namespace bsdiff
|