简体   繁体   中英

C++ inflate zlib from std::vector

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

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM