6 #include "base/logging.h" 7 #include "util/bzip_source.h" 8 #include "strings/strcat.h" 11 using strings::ByteRange;
16 Rep() { memset(&stream, 0,
sizeof(stream)); }
19 BzipSource::BzipSource(
Source* sub_source)
20 : sub_stream_(sub_source), rep_(new
Rep) {
21 CHECK_EQ(BZ_OK, BZ2_bzDecompressInit(&rep_->stream, 0, 1));
24 BzipSource::~BzipSource() {
25 BZ2_bzDecompressEnd(&rep_->stream);
28 StatusObject<size_t> BzipSource::ReadInternal(
const strings::MutableByteRange& range) {
29 std::array<unsigned char, 1024> buf;
30 char*
const begin = reinterpret_cast<char*>(range.begin());
32 rep_->stream.next_out = begin;
33 rep_->stream.avail_out = range.size();
35 auto res = sub_stream_->Read(strings::MutableByteRange(buf));
42 rep_->stream.next_in = reinterpret_cast<char*>(buf.begin());
43 rep_->stream.avail_in = res.obj;
44 int res_code = BZ2_bzDecompress(&rep_->stream);
45 if (res_code != BZ_OK && res_code != BZ_STREAM_END) {
46 return Status(StatusCode::IO_ERROR, absl::StrCat(
"BZip error ", res_code));
49 if (rep_->stream.avail_in > 0) {
50 CHECK_EQ(0, rep_->stream.avail_out);
52 sub_stream_->Prepend(ByteRange(reinterpret_cast<unsigned char*>(rep_->stream.next_in),
53 rep_->stream.avail_in));
55 }
while (reinterpret_cast<unsigned char*>(rep_->stream.next_out) != range.end());
57 return rep_->stream.next_out - begin;
61 bool BzipSource::IsBzipSource(Source* source) {
62 std::array<unsigned char, 3> buf;
63 auto res = source->Read(strings::MutableByteRange(buf));
67 bool is_bzip = res.obj == 3 && (buf[0] ==
'B') && (buf[1] ==
'Z') && (buf[2] ==
'h');
68 source->Prepend(strings::ByteRange(buf));