This repository has been archived by the owner on Jun 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathlzf_module.c
135 lines (115 loc) · 3.27 KB
/
lzf_module.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include <errno.h>
#include "lzf.h"
#if PY_MAJOR_VERSION >= 3
#define PYBYTES_FSAS PyBytes_FromStringAndSize
#define PyInt_CheckExact(pyobj) 0
#define PyInt_AsLong(pyobj) 0
#else
#define PYBYTES_FSAS PyString_FromStringAndSize
#endif
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION <= 4
#define Py_ssize_t ssize_t
#endif
static PyObject *
python_compress(PyObject *self, PyObject *args) {
char *input, *output;
Py_ssize_t inlen;
PyObject *pyoutlen = Py_None;
long outlen;
PyObject *result;
if (!PyArg_ParseTuple(args, "s#|O", &input, &inlen, &pyoutlen))
return NULL;
if (pyoutlen == Py_None)
outlen = inlen - 1;
else if (PyInt_CheckExact(pyoutlen))
outlen = PyInt_AsLong(pyoutlen);
else if (PyLong_CheckExact(pyoutlen))
outlen = PyLong_AsLong(pyoutlen);
else {
PyErr_SetString(PyExc_TypeError, "max_len must be an integer");
return NULL;
}
if (inlen == 1) outlen++; /* work around for what looks like a liblzf bug */
if (outlen <= 0) {
PyErr_SetString(PyExc_ValueError, "max_len must be > 0");
return NULL;
}
output = (char *)malloc(outlen + 1);
if (output == NULL) {
PyErr_SetString(PyExc_MemoryError, "out of memory");
return NULL;
}
outlen = lzf_compress(input, inlen, output, outlen + 1);
if (outlen)
result = PYBYTES_FSAS(output, outlen);
else {
Py_XINCREF(Py_None);
result = Py_None;
}
free(output);
return result;
}
static PyObject *
python_decompress(PyObject *self, PyObject *args) {
char *input, *output;
Py_ssize_t inlen;
long outlen;
PyObject *result;
if (!PyArg_ParseTuple(args, "s#l", &input, &inlen, &outlen))
return NULL;
if (outlen < 0) {
PyErr_SetString(PyExc_ValueError, "max_len cannot be less than 0");
return NULL;
}
output = (char *)malloc(outlen);
outlen = lzf_decompress(input, inlen, output, outlen);
if (outlen)
result = PYBYTES_FSAS(output, outlen);
else {
if (errno == EINVAL) {
PyErr_SetString(PyExc_ValueError, "error in compressed data");
free(output);
return NULL;
}
Py_XINCREF(Py_None);
result = Py_None;
}
free(output);
return result;
}
static PyMethodDef methods[] = {
{"compress", python_compress, METH_VARARGS,
"compress(input, max_length=None)\n\
\n\
return the compressed string, or None if it doesn't compress to smaller \n\
than the original\n\
\n\
takes an optional second parameter, for specifying a maximum compressed \n\
length (default is one less than the length of the original)"},
{"decompress", python_decompress, METH_VARARGS,
"decompress(input, max_length)\n\
\n\
return the decompressed string\n\
\n\
will return None if the string doesn't decompress to within max_length bytes"},
{NULL, NULL, 0, NULL}
};
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef lzfmodule = {
PyModuleDef_HEAD_INIT,
"lzf", "", -1, methods,
NULL, NULL, NULL, NULL
};
PyMODINIT_FUNC
PyInit_lzf(void) {
PyObject *module = PyModule_Create(&lzfmodule);
return module;
}
#else
PyMODINIT_FUNC
initlzf(void) {
Py_InitModule("lzf", methods);
}
#endif