155 lines · 3.9 KB · C++
RawDownload
////  Gzip.cpp//  libraries/shared/src////  Created by Seth Alves on 2015-08-03.//  Copyright 2015 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include "Gzip.h" #include <zlib.h> const int GZIP_WINDOWS_BIT = 31;const int GZIP_CHUNK_SIZE = 4096;const int DEFAULT_MEM_LEVEL = 8; bool gunzip(QByteArray source, QByteArray &destination) {    destination.clear();    if (source.length() == 0) {        return true;    }     z_stream strm;    strm.zalloc = Z_NULL;    strm.zfree = Z_NULL;    strm.opaque = Z_NULL;    strm.avail_in = 0;    strm.next_in = Z_NULL;     int status = inflateInit2(&strm, GZIP_WINDOWS_BIT);     if (status != Z_OK) {        return false;    }     char *sourceData = source.data();    int sourceDataLength = source.length();     for (;;) {        int chunkSize = qMin(GZIP_CHUNK_SIZE, sourceDataLength);        if (chunkSize <= 0) {            break;        }         strm.next_in = (unsigned char*)sourceData;        strm.avail_in = chunkSize;        sourceData += chunkSize;        sourceDataLength -= chunkSize;         for (;;) {            char out[GZIP_CHUNK_SIZE];             strm.next_out = (unsigned char*)out;            strm.avail_out = GZIP_CHUNK_SIZE;             status = inflate(&strm, Z_NO_FLUSH);             switch (status) {                case Z_NEED_DICT:                    status = Z_DATA_ERROR;                    // FALLTHRU                case Z_DATA_ERROR:                case Z_MEM_ERROR:                case Z_STREAM_ERROR:                    inflateEnd(&strm);                    return false;            }             int available = (GZIP_CHUNK_SIZE - strm.avail_out);            if (available > 0) {                destination.append((char*)out, available);            }             if (strm.avail_out != 0) {                break;            }        }         if (status == Z_STREAM_END) {            break;        }    }     inflateEnd(&strm);    return status == Z_STREAM_END;} bool gzip(QByteArray source, QByteArray &destination, int compressionLevel) {    destination.clear();    if (source.length() == 0) {        return true;    }     int flushOrFinish = 0;    z_stream strm;    strm.zalloc = Z_NULL;    strm.zfree = Z_NULL;    strm.opaque = Z_NULL;    strm.next_in = Z_NULL;    strm.avail_in = 0;     int status = deflateInit2(&strm,                              qMax(Z_DEFAULT_COMPRESSION, qMin(9, compressionLevel)),                              Z_DEFLATED,                              GZIP_WINDOWS_BIT,                              DEFAULT_MEM_LEVEL,                              Z_DEFAULT_STRATEGY);    if (status != Z_OK) {        return false;    }    char *sourceData = source.data();    int sourceDataLength = source.length();     for (;;) {        int chunkSize = qMin(GZIP_CHUNK_SIZE, sourceDataLength);        strm.next_in = (unsigned char*)sourceData;        strm.avail_in = chunkSize;        sourceData += chunkSize;        sourceDataLength -= chunkSize;         if (sourceDataLength <= 0) {            flushOrFinish = Z_FINISH;        } else {            flushOrFinish = Z_NO_FLUSH;        }         for (;;) {            char out[GZIP_CHUNK_SIZE];            strm.next_out = (unsigned char*)out;            strm.avail_out = GZIP_CHUNK_SIZE;            status = deflate(&strm, flushOrFinish);            if (status == Z_STREAM_ERROR) {                deflateEnd(&strm);                return false;            }            int available = (GZIP_CHUNK_SIZE - strm.avail_out);            if (available > 0) {                destination.append((char*)out, available);            }            if (strm.avail_out != 0) {                break;            }        }         if (flushOrFinish == Z_FINISH) {            break;        }    }     deflateEnd(&strm);    return status == Z_STREAM_END;}