Skip to content

Instantly share code, notes, and snippets.

@jgarzik
Created February 28, 2018 06:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jgarzik/1d16c905452ccb83b0b40f0ce4897fd0 to your computer and use it in GitHub Desktop.
Save jgarzik/1d16c905452ccb83b0b40f0ce4897fd0 to your computer and use it in GitHub Desktop.
Decompress gzip files to stdout
#include <stdio.h>
#include <stdexcept>
#include <unistd.h>
#include <fcntl.h>
#include <string>
#include <vector>
#include <string.h>
#include <assert.h>
#include <zlib.h>
using namespace std;
class Gunzipper {
protected:
z_stream strm;
size_t outMax_;
public:
Gunzipper() {
memset(&strm, 0, sizeof(strm));
int rc = inflateInit2(&strm, (15 + 32));
if (rc != Z_OK)
throw std::runtime_error("zlib.inflateInit2 failed");
}
~Gunzipper() {
inflateEnd(&strm);
}
void setInput(const void *buf, size_t buflen) {
strm.next_in = (Bytef *) buf;
strm.avail_in = buflen;
}
void setOutput(void *buf, size_t buflen) {
strm.next_out = (Bytef *) buf;
strm.avail_out = buflen;
outMax_ = buflen;
}
int step(int flush = Z_NO_FLUSH) {
return inflate(&strm, flush);
}
size_t outMax() const { return outMax_; }
size_t outSz() const { return outMax_ - strm.avail_out; }
};
int inflateString(const std::string& dataIn, std::string& dataOut)
{
dataOut.clear();
dataOut.reserve(dataIn.size() * 4);
vector<unsigned char> outBuf(4096);
Gunzipper gunzip;
gunzip.setInput(dataIn.c_str(), dataIn.size());
gunzip.setOutput(&outBuf[0], outBuf.size());
int rc = Z_OK;
while (rc == Z_OK || rc == Z_STREAM_END) {
rc = gunzip.step();
if (rc == Z_OK || rc == Z_STREAM_END) {
size_t outputLen = gunzip.outSz();
dataOut.append((char *) &outBuf[0], outputLen);
if (rc == Z_OK) {
// reset for more reads
gunzip.setOutput(&outBuf[0], outBuf.size());
} else {
return Z_OK;
}
}
}
return rc;
}
int main (int argc, char *argv[])
{
string zdataIn;
char buf[1024];
size_t frc;
while ((frc = fread(buf, 1, sizeof(buf), stdin)) > 0) {
zdataIn.append(&buf[0], frc);
if (frc < sizeof(buf))
break;
}
string dataOut;
int rc = inflateString(zdataIn, dataOut);
assert(rc == Z_OK);
ssize_t wrc = write(STDOUT_FILENO, dataOut.c_str(), dataOut.size());
assert(wrc == (ssize_t) dataOut.size());
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment