forked from cyxx/linyaga
-
Notifications
You must be signed in to change notification settings - Fork 0
/
zlib.c
100 lines (89 loc) · 2.51 KB
/
zlib.c
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
#include <Python.h>
#include <zlib.h>
#include "intern.h"
static PyObject *_zlibException;
static void ZlibFormatException(z_stream *z_str, const char *str, int code) {
if (z_str->msg) {
PyErr_Format(_zlibException, "Error %d %s: %.200s", code, str, z_str->msg);
} else {
PyErr_Format(_zlibException, "Error %d %s", code, str);
}
}
static PyObject *ZlibDecompress(PyObject *self, PyObject *args) {
uint32_t len, wbits, bufsize;
char *buf;
wbits = MAX_WBITS;
bufsize = 16 * 1024;
if (!PyArg_ParseTuple(args, "s#", &buf, &len)) {
return 0;
}
PyObject *py_string = PyString_FromStringAndSize(0, bufsize);
if (!py_string) {
return 0;
}
z_stream z_str;
z_str.avail_in = len;
z_str.avail_out = bufsize;
z_str.zalloc = 0;
z_str.zfree = 0;
z_str.next_in = (Bytef *)buf;
z_str.next_out = (Bytef *)&((PyStringObject *)py_string)->ob_sval[0];
int ret = inflateInit2(&z_str, wbits);
if (ret == Z_MEM_ERROR) {
PyErr_SetString(PyExc_MemoryError, "Out of memory while decompressing data");
} else if (ret != Z_OK) {
inflateEnd(&z_str);
ZlibFormatException(&z_str, "while preparing to decompress data", ret);
} else {
do {
PyThreadState *state = PyEval_SaveThread();
ret = inflate(&z_str, Z_FINISH);
PyEval_RestoreThread(state);
switch (ret) {
case Z_STREAM_END:
break;
case Z_BUF_ERROR:
if (z_str.avail_out > 0) {
inflateEnd(&z_str);
PyErr_Format(_zlibException, "Error %i while decompressing data", Z_BUF_ERROR);
goto ret_decref;
}
case Z_OK:
if (_PyString_Resize(&py_string, bufsize * 2) == -1) {
inflateEnd(&z_str);
goto ret_decref;
}
z_str.next_out = (Bytef *)&((PyStringObject *)py_string)->ob_sval[bufsize];
z_str.avail_out = bufsize;
bufsize *= 2;
break;
default:
inflateEnd(&z_str);
ZlibFormatException(&z_str, "while decompressing data", ret);
goto ret_decref;
}
} while (ret != Z_STREAM_END);
ret = inflateEnd(&z_str);
if (ret == Z_OK) {
_PyString_Resize(&py_string, z_str.total_out);
return py_string;
}
ZlibFormatException(&z_str, "while finishing data decompression", ret);
}
ret_decref:
assert(0);
Py_DECREF(py_string);
return 0;
}
static PyMethodDef ZlibMethods[] = {
{ "decompress", ZlibDecompress, METH_VARARGS, "" },
{ 0, 0, 0, 0 }
};
void initzlib() {
PyObject *module = Py_InitModule("zlib", ZlibMethods);
PyObject *dict = PyModule_GetDict(module);
_zlibException = PyErr_NewException("zlib.error", 0, 0);
if (_zlibException) {
PyDict_SetItemString(dict, "error", _zlibException);
}
}