about summary refs log tree commit diff stats
path: root/archive/2025/summer/bsc_karidas/src/Compression.cpp
blob: cd25c9310b62d3616f911cf74de90edd22ac8680 (plain) (blame)
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "Compression.hpp"
#include <stdexcept>
#include <cstring>
#include <iostream>

// Helper function to compress raw data using zlib
std::vector<uint8_t> Compression::compress(std::vector<uint8_t> &&data, int level)
{
    if (data.empty())
    {
        return std::vector<uint8_t>();
    }

    z_stream zs;
    std::memset(&zs, 0, sizeof(zs));

    // Use the provided compression level instead of hardcoded Z_BEST_COMPRESSION
    if (deflateInit(&zs, level) != Z_OK)
    {
        throw std::runtime_error("Failed to initialize zlib deflate");
    }

    zs.next_in = const_cast<Bytef *>(data.data());
    zs.avail_in = data.size();

    int ret;
    char outbuffer[32768];
    std::vector<uint8_t> compressedData;

    // Compress data in chunks
    do
    {
        zs.next_out = reinterpret_cast<Bytef *>(outbuffer);
        zs.avail_out = sizeof(outbuffer);

        ret = deflate(&zs, Z_FINISH);

        if (compressedData.size() < zs.total_out)
        {
            compressedData.insert(compressedData.end(),
                                  outbuffer,
                                  outbuffer + (zs.total_out - compressedData.size()));
        }
    } while (ret == Z_OK);

    deflateEnd(&zs);

    if (ret != Z_STREAM_END)
    {
        throw std::runtime_error("Exception during zlib compression");
    }

    return compressedData;
}

// Helper function to decompress raw data using zlib
std::vector<uint8_t> Compression::decompress(std::vector<uint8_t> &&compressedData)
{
    if (compressedData.empty())
    {
        return std::vector<uint8_t>();
    }

    z_stream zs;
    std::memset(&zs, 0, sizeof(zs));

    if (inflateInit(&zs) != Z_OK)
    {
        throw std::runtime_error("Failed to initialize zlib inflate");
    }

    zs.next_in = const_cast<Bytef *>(compressedData.data());
    zs.avail_in = compressedData.size();

    int ret;
    char outbuffer[32768];
    std::vector<uint8_t> decompressedData;

    // Decompress data in chunks
    do
    {
        zs.next_out = reinterpret_cast<Bytef *>(outbuffer);
        zs.avail_out = sizeof(outbuffer);

        ret = inflate(&zs, Z_NO_FLUSH);

        if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
        {
            inflateEnd(&zs);
            throw std::runtime_error("Exception during zlib decompression");
        }

        if (decompressedData.size() < zs.total_out)
        {
            decompressedData.insert(decompressedData.end(),
                                    outbuffer,
                                    outbuffer + (zs.total_out - decompressedData.size()));
        }
    } while (ret == Z_OK);

    inflateEnd(&zs);

    if (ret != Z_STREAM_END)
    {
        throw std::runtime_error("Exception during zlib decompression");
    }

    return decompressedData;
}