Reputation: 582
I have compressed data in zlib format that is inside a std::vector
I'm trying to figure out a way to write a function that takes that data and returns another vector with the inflated data. The function does not even need to check if it's valid zlib data etc. just something in these lines:
// infalte compressed zlib data.
std::vector<unsigned char> decompress_zlib(std::vector<unsigned char> data)
{
std::vector<unsigned char> ret;
// magic happens here
return ret;
}
The sample code in pipes.c assumes the data is read from a file. in my case the data is already verified and is stored in the vector.
Thanks
Upvotes: 0
Views: 1216
Reputation: 1646
Something like this should work, though I haven't tested it:
#include <algorithm>
#include <assert.h>
#include <vector>
#include <zlib.h>
#define CHUNK (1024 * 256)
typedef std::vector<unsigned char> vucarr;
void vucarrWrite(vucarr& out, const unsigned char* buf, size_t bufLen)
{
out.insert(out.end(), buf, buf + bufLen);
}
size_t vucarrRead(const vucarr &in, unsigned char *&inBuf, size_t &inPosition)
{
size_t from = inPosition;
inBuf = const_cast<unsigned char*>(in.data()) + inPosition;
inPosition += std::min(CHUNK, in.size() - from);
return inPosition - from;
}
int inf(const vucarr &in, vucarr &out)
{
int ret;
unsigned have;
z_stream strm = {};
unsigned char *inBuf;
unsigned char outBuf[CHUNK];
size_t inPosition = 0; /* position indicator of "in" */
/* allocate inflate state */
ret = inflateInit(&strm);
if (ret != Z_OK)
return ret;
/* decompress until deflate stream ends or end of file */
do {
strm.avail_in = vucarrRead(in, inBuf, inPosition);
if (strm.avail_in == 0)
break;
strm.next_in = inBuf;
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = outBuf;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
vucarrWrite(out, outBuf, have);
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
Upvotes: 1