summaryrefslogtreecommitdiffstats
path: root/src/musicbrainz/gzip.cpp
blob: d0a88e3c48fb18c7d76700ca198042ea138fb02b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "musicbrainz/crc.h"
#include "musicbrainz/gzip.h"

inline QByteArray render32BitInt(unsigned long value)
{
    unsigned char data[4];
    data[0] = (value      ) & 255;
    data[1] = (value >>  8) & 255;
    data[2] = (value >> 16) & 255;
    data[3] = (value >> 24) & 255;
    return QByteArray((char *)data, 4);
}

inline unsigned long calculateCrc32(const QByteArray &data)
{
    crc_t crc;
    crc = crc_init();
    crc = crc_update(crc, (unsigned char *)data.data(), data.size());
    crc = crc_finalize(crc);
    return crc;
}

QByteArray gzipCompress(const QByteArray &data)
{
    const unsigned char header[10] = {
        0x1f, 0x8b, // ID1 + ID2
        8,          // Compression Method
        0,          // Flags
        0, 0, 0, 0, // Modification Time
        2,          // Extra Flags
        255,        // Operating System
    };

    QByteArray compressedData = qCompress(data);
    compressedData.remove(0, 6); // Qt size + zlib header
    compressedData.remove(compressedData.size() - 4, 4); // zlib footer

    QByteArray result;
    result.append(reinterpret_cast<const char*>(header), 10);
    result.append(compressedData);
    result.append(render32BitInt(calculateCrc32(data)));
    result.append(render32BitInt(data.size()));
    return result;
}