CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/Data/Encoding/Compression.cpp
Views: 1401
1
// Little utility functions for data compression.
2
// Taken from http://panthema.net/2007/0328-ZLibString.html
3
4
5
#include <string>
6
#include <stdexcept>
7
#include <iostream>
8
#include <iomanip>
9
#include <sstream>
10
#include <cstring>
11
12
#include <zlib.h>
13
14
#include "Common/Log.h"
15
16
/** Compress a STL string using zlib with given compression level and return
17
* the binary data. */
18
bool compress_string(const std::string& str, std::string *dest, int compressionlevel) {
19
z_stream zs; // z_stream is zlib's control structure
20
memset(&zs, 0, sizeof(zs));
21
22
if (deflateInit(&zs, compressionlevel) != Z_OK) {
23
ERROR_LOG(Log::IO, "deflateInit failed while compressing.");
24
return false;
25
}
26
27
zs.next_in = (Bytef*)str.data();
28
zs.avail_in = (uInt)str.size(); // set the z_stream's input
29
30
int ret;
31
char outbuffer[32768];
32
std::string outstring;
33
34
// retrieve the compressed bytes blockwise
35
do {
36
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
37
zs.avail_out = sizeof(outbuffer);
38
39
ret = deflate(&zs, Z_FINISH);
40
41
if (outstring.size() < zs.total_out) {
42
// append the block to the output string
43
outstring.append(outbuffer,
44
zs.total_out - outstring.size());
45
}
46
} while (ret == Z_OK);
47
48
deflateEnd(&zs);
49
50
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
51
std::ostringstream oss;
52
oss << "Exception during zlib compression: (" << ret << ") " << zs.msg;
53
return false;
54
}
55
56
*dest = outstring;
57
return true;
58
}
59
60
/** Decompress an STL string using zlib and return the original data. */
61
bool decompress_string(const std::string& str, std::string *dest) {
62
if (!str.size())
63
return false;
64
65
z_stream zs; // z_stream is zlib's control structure
66
memset(&zs, 0, sizeof(zs));
67
68
// modification by hrydgard: inflateInit2, 16+MAXWBITS makes it read gzip data too
69
if (inflateInit2(&zs, 32+MAX_WBITS) != Z_OK) {
70
ERROR_LOG(Log::IO, "inflateInit failed while decompressing.");
71
return false;
72
}
73
74
zs.next_in = (Bytef*)str.data();
75
zs.avail_in = (uInt)str.size();
76
77
int ret;
78
char outbuffer[32768];
79
std::string outstring;
80
81
// get the decompressed bytes blockwise using repeated calls to inflate
82
do {
83
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
84
zs.avail_out = sizeof(outbuffer);
85
86
ret = inflate(&zs, 0);
87
88
if (outstring.size() < zs.total_out) {
89
outstring.append(outbuffer,
90
zs.total_out - outstring.size());
91
}
92
93
} while (ret == Z_OK);
94
95
inflateEnd(&zs);
96
97
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
98
ERROR_LOG(Log::IO, "Exception during zlib decompression: (%i) %s", ret, zs.msg);
99
return false;
100
}
101
102
*dest = outstring;
103
return true;
104
}
105
106