-
Notifications
You must be signed in to change notification settings - Fork 8
/
pyspamsum.c
159 lines (129 loc) · 3.22 KB
/
pyspamsum.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* PySpamsum v1.0.0
*
* A Python wrapper around the spamsum library written by
* Andrew Tridgell.
*
* Copyright 2009 Russell Keith-Magee <[email protected]>
*/
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
int edit_distn(char *from, int from_len, char *to, int to_len);
char *spamsum(const unsigned char *in, unsigned int length, unsigned int flags, unsigned int bsize);
unsigned int spamsum_match(const char *str1, const char *str2);
struct module_state {
PyObject *error;
};
#if PY_MAJOR_VERSION >= 3
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
#else
#define GETSTATE(m) (&_state)
static struct module_state _state;
#endif
PyObject *py_edit_distance(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
int distance;
char *from, *to;
Py_ssize_t from_len, to_len;
if (!PyArg_ParseTuple(args, "s#s#", &from, &from_len, &to, &to_len))
{
return NULL;
}
distance = edit_distn(from, from_len, to, to_len);
result = Py_BuildValue("i", distance);
return result;
}
PyObject *py_spamsum(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
char *sum;
unsigned char *in;
Py_ssize_t length;
unsigned int flags, bsize;
flags = 0;
bsize = 0;
if (!PyArg_ParseTuple(args, "s#|ii", &in, &length, &flags, &bsize))
{
return NULL;
}
sum = spamsum(in, length, flags, bsize);
result = Py_BuildValue("s", sum);
free(sum);
return result;
}
PyObject *py_match(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
unsigned int match;
char *str1, *str2;
if (!PyArg_ParseTuple(args, "ss", &str1, &str2))
{
return NULL;
}
match = spamsum_match(str1, str2);
result = Py_BuildValue("i", match);
return result;
}
static PyMethodDef methods[] = {
{"edit_distance", py_edit_distance, METH_VARARGS,
"Calculate the edit distance between two strings."
},
{"spamsum", py_spamsum, METH_VARARGS,
"Calculate the spamsum of a string."
},
{"match", py_match, METH_VARARGS,
"Given two spamsum strings return a value indicating the degree to which they match."
},
{NULL, NULL, 0, NULL}
};
#if PY_MAJOR_VERSION >= 3
static int spamsum_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
static int spamsum_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef ss =
{
PyModuleDef_HEAD_INIT,
"spamsum",
"",
sizeof(struct module_state),
methods,
NULL,
spamsum_traverse,
spamsum_clear,
NULL
};
#define INITERROR return NULL
PyMODINIT_FUNC
PyInit_spamsum(void)
#else
#define INITERROR return
void
initspamsum(void)
#endif
{
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&ss);
#else
PyObject *module = Py_InitModule("spamsum", methods);
#endif
if (module == NULL)
INITERROR;
struct module_state *st = GETSTATE(module);
st->error = PyErr_NewException("spamsum.Error", NULL, NULL);
if (st->error == NULL) {
Py_DECREF(module);
INITERROR;
}
#if PY_MAJOR_VERSION >= 3
return module;
#endif
}