blob: 744ea67066ac2e4b34b13fa6dc22e56133dc4f7b [file] [log] [blame]
// Copyright (c) 2010 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 "update_engine/bzip.h"
#include <stdlib.h>
#include <algorithm>
#include <bzlib.h>
#include "update_engine/utils.h"
using std::max;
using std::string;
using std::vector;
namespace chromeos_update_engine {
namespace {
// BzipData compresses or decompresses the input to the output.
// Returns true on success.
// Use one of BzipBuffToBuff*ompress as the template parameter to BzipData().
int BzipBuffToBuffDecompress(char* out,
uint32_t* out_length,
const char* in,
uint32_t in_length) {
return BZ2_bzBuffToBuffDecompress(out,
out_length,
const_cast<char*>(in),
in_length,
0, // Silent verbosity
0); // Normal algorithm
}
int BzipBuffToBuffCompress(char* out,
uint32_t* out_length,
const char* in,
uint32_t in_length) {
return BZ2_bzBuffToBuffCompress(out,
out_length,
const_cast<char*>(in),
in_length,
9, // Best compression
0, // Silent verbosity
0); // Default work factor
}
template<int F(char* out,
uint32_t* out_length,
const char* in,
uint32_t in_length)>
bool BzipData(const char* const in,
const int32_t in_size,
vector<char>* const out) {
TEST_AND_RETURN_FALSE(out);
out->clear();
if (in_size == 0) {
return true;
}
// Try increasing buffer size until it works
size_t buf_size = in_size;
out->resize(buf_size);
for (;;) {
uint32_t data_size = buf_size;
int rc = F(&(*out)[0], &data_size, in, in_size);
TEST_AND_RETURN_FALSE(rc == BZ_OUTBUFF_FULL || rc == BZ_OK);
if (rc == BZ_OK) {
// we're done!
out->resize(data_size);
return true;
}
// Data didn't fit; double the buffer size.
buf_size *= 2;
out->resize(buf_size);
}
}
} // namespace
bool BzipDecompress(const std::vector<char>& in, std::vector<char>* out) {
return BzipData<BzipBuffToBuffDecompress>(&in[0],
static_cast<int32_t>(in.size()),
out);
}
bool BzipCompress(const std::vector<char>& in, std::vector<char>* out) {
return BzipData<BzipBuffToBuffCompress>(&in[0], in.size(), out);
}
namespace {
template<bool F(const char* const in,
const int32_t in_size,
vector<char>* const out)>
bool BzipString(const std::string& str,
std::vector<char>* out) {
TEST_AND_RETURN_FALSE(out);
vector<char> temp;
TEST_AND_RETURN_FALSE(F(str.data(),
str.size(),
&temp));
out->clear();
out->insert(out->end(), temp.begin(), temp.end());
return true;
}
} // namespace
bool BzipCompressString(const std::string& str,
std::vector<char>* out) {
return BzipString<BzipData<BzipBuffToBuffCompress>>(str, out);
}
bool BzipDecompressString(const std::string& str,
std::vector<char>* out) {
return BzipString<BzipData<BzipBuffToBuffDecompress>>(str, out);
}
} // namespace chromeos_update_engine