Created
July 12, 2016 18:19
-
-
Save chenshuo/23a3c94e2f4b14dd493aee16af7421e4 to your computer and use it in GitHub Desktop.
inplace gunzip
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <zlib.h> | |
#include <boost/noncopyable.hpp> | |
#include <deque> | |
// FIXME: re-implement this with disk buffer. | |
class Buffer : boost::noncopyable | |
{ | |
public: | |
Buffer() : total_(0) {} | |
void append(const char* data, int len) | |
{ | |
total_ += len; | |
buffer_.insert(buffer_.end(), data, data+len); | |
} | |
int take(char* data, int len) | |
{ | |
int x = std::min<int>(len, buffer_.size()); | |
std::copy(buffer_.begin(), buffer_.begin() + x, data); | |
buffer_.erase(buffer_.begin(), buffer_.begin() + x); | |
return x; | |
} | |
private: | |
std::deque<char> buffer_; | |
int64_t total_; | |
}; | |
class InPlaceGunzip : boost::noncopyable | |
{ | |
public: | |
InPlaceGunzip(const char* filename) | |
: file_(::open(filename, O_RDWR)), | |
gzfile_(::gzdopen(file_, "rb")) | |
{ | |
assert(file_ >= 0); | |
assert(gzfile_ != NULL); | |
} | |
~InPlaceGunzip() | |
{ | |
gzclose(gzfile_); | |
} | |
void unzip() | |
{ | |
Buffer queue; | |
char buf[64*1024]; | |
int nr = 0; | |
int64_t last_off = 0; | |
while ( (nr = gzread(gzfile_, buf, sizeof buf)) > 0) { | |
queue.append(buf, nr); | |
// int64_t tell = gztell(gzfile_); | |
int64_t off = gzoffset(gzfile_); | |
int avail = std::min<int>(off - last_off, sizeof buf); | |
int x = queue.take(buf, avail); | |
int nw = pwrite(file_, buf, x, last_off); | |
assert(x == nw); | |
last_off += nw; | |
} | |
while ( (nr = queue.take(buf, sizeof buf)) > 0) { | |
int nw = pwrite(file_, buf, nr, last_off); | |
assert(nr == nw); | |
last_off += nw; | |
} | |
} | |
private: | |
int file_; | |
gzFile gzfile_; | |
}; | |
int main(int argc, char* argv[]) | |
{ | |
if (argc > 1) | |
{ | |
InPlaceGunzip unzip(argv[1]); | |
unzip.unzip(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment