Mercurial > genshi > mirror
annotate genshi/_speedups.c @ 681:3e7cd32c9411 trunk
Fix another memory leak in the C speedups code. Thanks to Erik Bray for finding this one and providing a patch. Closes #166 (again).
author | cmlenz |
---|---|
date | Tue, 05 Feb 2008 17:27:36 +0000 |
parents | 3ee92ec99ad9 |
children | 5420fe9d99a9 |
rev | line source |
---|---|
541 | 1 /* |
2 * Copyright (C) 2006 Edgewall Software | |
3 * All rights reserved. | |
4 * | |
5 * This software is licensed as described in the file COPYING, which | |
6 * you should have received as part of this distribution. The terms | |
7 * are also available at http://genshi.edgewall.org/wiki/License. | |
8 * | |
9 * This software consists of voluntary contributions made by many | |
10 * individuals. For the exact contribution history, see the revision | |
11 * history and logs, available at http://genshi.edgewall.org/log/. | |
12 */ | |
13 | |
14 #include <Python.h> | |
15 #include <structmember.h> | |
16 | |
17 static PyObject *amp1, *amp2, *lt1, *lt2, *gt1, *gt2, *qt1, *qt2; | |
18 static PyObject *stripentities, *striptags; | |
19 | |
20 static void | |
21 init_constants(void) | |
22 { | |
23 PyObject *util = PyImport_ImportModule("genshi.util"); | |
24 stripentities = PyObject_GetAttrString(util, "stripentities"); | |
25 striptags = PyObject_GetAttrString(util, "striptags"); | |
26 Py_DECREF(util); | |
27 | |
28 amp1 = PyUnicode_DecodeASCII("&", 1, NULL); | |
29 amp2 = PyUnicode_DecodeASCII("&", 5, NULL); | |
30 lt1 = PyUnicode_DecodeASCII("<", 1, NULL); | |
31 lt2 = PyUnicode_DecodeASCII("<", 4, NULL); | |
32 gt1 = PyUnicode_DecodeASCII(">", 1, NULL); | |
33 gt2 = PyUnicode_DecodeASCII(">", 4, NULL); | |
34 qt1 = PyUnicode_DecodeASCII("\"", 1, NULL); | |
35 qt2 = PyUnicode_DecodeASCII(""", 5, NULL); | |
36 } | |
37 | |
38 /* Markup class */ | |
39 | |
40 PyAPI_DATA(PyTypeObject) MarkupType; | |
41 | |
42 PyDoc_STRVAR(Markup__doc__, | |
43 "Marks a string as being safe for inclusion in HTML/XML output without\n\ | |
44 needing to be escaped."); | |
45 | |
46 static PyObject * | |
47 escape(PyObject *text, int quotes) | |
48 { | |
49 PyObject *args, *ret; | |
50 PyUnicodeObject *in, *out; | |
51 Py_UNICODE *inp, *outp; | |
52 int len, inn, outn; | |
53 | |
54 if (PyObject_TypeCheck(text, &MarkupType)) { | |
55 Py_INCREF(text); | |
56 return text; | |
57 } | |
58 in = (PyUnicodeObject *) PyObject_Unicode(text); | |
59 if (in == NULL) { | |
60 return NULL; | |
61 } | |
62 /* First we need to figure out how long the escaped string will be */ | |
63 len = inn = 0; | |
64 inp = in->str; | |
65 while (*(inp) || in->length > inp - in->str) { | |
66 switch (*inp++) { | |
67 case '&': len += 5; inn++; break; | |
68 case '"': len += quotes ? 5 : 1; inn += quotes ? 1 : 0; break; | |
69 case '<': | |
70 case '>': len += 4; inn++; break; | |
71 default: len++; | |
72 } | |
73 } | |
74 | |
75 /* Do we need to escape anything at all? */ | |
76 if (!inn) { | |
77 args = PyTuple_New(1); | |
78 if (args == NULL) { | |
79 Py_DECREF((PyObject *) in); | |
80 return NULL; | |
81 } | |
82 PyTuple_SET_ITEM(args, 0, (PyObject *) in); | |
83 ret = MarkupType.tp_new(&MarkupType, args, NULL); | |
84 Py_DECREF(args); | |
85 return ret; | |
86 } | |
87 | |
88 out = (PyUnicodeObject*) PyUnicode_FromUnicode(NULL, len); | |
89 if (out == NULL) { | |
665
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
90 Py_DECREF((PyObject *) in); |
541 | 91 return NULL; |
92 } | |
93 | |
94 outn = 0; | |
95 inp = in->str; | |
96 outp = out->str; | |
97 while (*(inp) || in->length > inp - in->str) { | |
98 if (outn == inn) { | |
99 /* copy rest of string if we have already replaced everything */ | |
100 Py_UNICODE_COPY(outp, inp, in->length - (inp - in->str)); | |
101 break; | |
102 } | |
103 switch (*inp) { | |
104 case '&': | |
105 Py_UNICODE_COPY(outp, ((PyUnicodeObject *) amp2)->str, 5); | |
106 outp += 5; | |
107 outn++; | |
108 break; | |
109 case '"': | |
110 if (quotes) { | |
111 Py_UNICODE_COPY(outp, ((PyUnicodeObject *) qt2)->str, 5); | |
112 outp += 5; | |
113 outn++; | |
114 } else { | |
115 *outp++ = *inp; | |
116 } | |
117 break; | |
118 case '<': | |
119 Py_UNICODE_COPY(outp, ((PyUnicodeObject *) lt2)->str, 4); | |
120 outp += 4; | |
121 outn++; | |
122 break; | |
123 case '>': | |
124 Py_UNICODE_COPY(outp, ((PyUnicodeObject *) gt2)->str, 4); | |
125 outp += 4; | |
126 outn++; | |
127 break; | |
128 default: | |
129 *outp++ = *inp; | |
130 } | |
131 inp++; | |
132 } | |
133 | |
665
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
134 Py_DECREF((PyObject *) in); |
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
135 |
541 | 136 args = PyTuple_New(1); |
137 if (args == NULL) { | |
138 Py_DECREF((PyObject *) out); | |
139 return NULL; | |
140 } | |
141 PyTuple_SET_ITEM(args, 0, (PyObject *) out); | |
142 ret = MarkupType.tp_new(&MarkupType, args, NULL); | |
143 Py_DECREF(args); | |
144 return ret; | |
145 } | |
146 | |
147 static PyObject * | |
148 Markup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | |
149 { | |
150 PyObject *self, *text, *tmp, *args2; | |
151 int nargs, i; | |
152 | |
153 nargs = PyTuple_GET_SIZE(args); | |
154 if (nargs < 2) { | |
155 return PyUnicode_Type.tp_new(type, args, NULL); | |
156 } | |
157 | |
158 text = PyTuple_GET_ITEM(args, 0); | |
159 args2 = PyTuple_New(nargs - 1); | |
160 if (args2 == NULL) { | |
161 return NULL; | |
162 } | |
163 for (i = 1; i < nargs; i++) { | |
164 tmp = escape(PyTuple_GET_ITEM(args, i), 1); | |
165 if (tmp == NULL) { | |
166 Py_DECREF(args2); | |
167 return NULL; | |
168 } | |
169 PyTuple_SET_ITEM(args2, i - 1, tmp); | |
170 } | |
171 tmp = PyUnicode_Format(text, args2); | |
172 Py_DECREF(args2); | |
173 if (tmp == NULL) { | |
174 return NULL; | |
175 } | |
176 args = PyTuple_New(1); | |
177 if (args == NULL) { | |
178 Py_DECREF(tmp); | |
179 return NULL; | |
180 } | |
181 PyTuple_SET_ITEM(args, 0, tmp); | |
182 self = PyUnicode_Type.tp_new(type, args, NULL); | |
183 Py_DECREF(args); | |
184 return self; | |
185 } | |
186 | |
187 PyDoc_STRVAR(escape__doc__, | |
188 "Create a Markup instance from a string and escape special characters\n\ | |
189 it may contain (<, >, & and \").\n\ | |
190 \n\ | |
547 | 191 >>> escape('\"1 < 2\"')\n\ |
192 <Markup u'"1 < 2"'>\n\ | |
193 \n\ | |
541 | 194 If the `quotes` parameter is set to `False`, the \" character is left\n\ |
195 as is. Escaping quotes is generally only required for strings that are\n\ | |
547 | 196 to be used in attribute values.\n\ |
197 \n\ | |
198 >>> escape('\"1 < 2\"', quotes=False)\n\ | |
199 <Markup u'\"1 < 2\"'>\n\ | |
200 \n\ | |
201 :param text: the text to escape\n\ | |
202 :param quotes: if ``True``, double quote characters are escaped in\n\ | |
203 addition to the other special characters\n\ | |
204 :return: the escaped `Markup` string\n\ | |
205 :rtype: `Markup`\n\ | |
206 "); | |
541 | 207 |
208 static PyObject * | |
209 Markup_escape(PyTypeObject* type, PyObject *args, PyObject *kwds) | |
210 { | |
211 static char *kwlist[] = {"text", "quotes", 0}; | |
212 PyObject *text = NULL; | |
213 char quotes = 1; | |
214 | |
215 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|b", kwlist, &text, "es)) { | |
216 return NULL; | |
217 } | |
218 if (PyObject_Not(text)) { | |
219 return type->tp_new(type, args, NULL); | |
220 } | |
221 if (PyObject_TypeCheck(text, type)) { | |
222 Py_INCREF(text); | |
223 return text; | |
224 } | |
225 return escape(text, quotes); | |
226 } | |
227 | |
547 | 228 PyDoc_STRVAR(join__doc__, |
229 "Return a `Markup` object which is the concatenation of the strings\n\ | |
230 in the given sequence, where this `Markup` object is the separator\n\ | |
231 between the joined elements.\n\ | |
232 \n\ | |
233 Any element in the sequence that is not a `Markup` instance is\n\ | |
234 automatically escaped.\n\ | |
235 \n\ | |
236 :param seq: the sequence of strings to join\n\ | |
237 :param escape_quotes: whether double quote characters in the elements\n\ | |
238 should be escaped\n\ | |
239 :return: the joined `Markup` object\n\ | |
240 :rtype: `Markup`\n\ | |
241 :see: `escape`\n\ | |
242 "); | |
243 | |
541 | 244 static PyObject * |
245 Markup_join(PyObject *self, PyObject *args, PyObject *kwds) | |
246 { | |
247 static char *kwlist[] = {"seq", "escape_quotes", 0}; | |
665
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
248 PyObject *seq = NULL, *seq2, *tmp, *tmp2; |
541 | 249 char quotes = 1; |
250 int n, i; | |
251 | |
252 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|b", kwlist, &seq, "es)) { | |
253 return NULL; | |
254 } | |
255 if (!PySequence_Check(seq)) { | |
256 return NULL; | |
257 } | |
258 n = PySequence_Size(seq); | |
259 if (n < 0) { | |
260 return NULL; | |
261 } | |
262 seq2 = PyTuple_New(n); | |
263 if (seq2 == NULL) { | |
264 return NULL; | |
265 } | |
266 for (i = 0; i < n; i++) { | |
267 tmp = PySequence_GetItem(seq, i); | |
268 if (tmp == NULL) { | |
269 Py_DECREF(seq2); | |
270 return NULL; | |
271 } | |
665
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
272 tmp2 = escape(tmp, quotes); |
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
273 if (tmp2 == NULL) { |
541 | 274 Py_DECREF(seq2); |
275 return NULL; | |
276 } | |
665
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
277 PyTuple_SET_ITEM(seq2, i, tmp2); |
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
278 Py_DECREF(tmp); |
541 | 279 } |
280 tmp = PyUnicode_Join(self, seq2); | |
281 Py_DECREF(seq2); | |
282 if (tmp == NULL) | |
283 return NULL; | |
284 args = PyTuple_New(1); | |
285 if (args == NULL) { | |
286 Py_DECREF(tmp); | |
287 return NULL; | |
288 } | |
289 PyTuple_SET_ITEM(args, 0, tmp); | |
290 tmp = MarkupType.tp_new(&MarkupType, args, NULL); | |
291 Py_DECREF(args); | |
292 return tmp; | |
293 } | |
294 | |
295 static PyObject * | |
296 Markup_add(PyObject *self, PyObject *other) | |
297 { | |
298 PyObject *tmp, *tmp2, *args, *ret; | |
299 if (PyObject_TypeCheck(self, &MarkupType)) { | |
300 tmp = escape(other, 1); | |
301 if (tmp == NULL) | |
302 return NULL; | |
303 tmp2 = PyUnicode_Concat(self, tmp); | |
304 } else { // __radd__ | |
305 tmp = escape(self, 1); | |
306 if (tmp == NULL) | |
307 return NULL; | |
308 tmp2 = PyUnicode_Concat(tmp, other); | |
309 } | |
665
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
310 Py_DECREF(tmp); |
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
311 if (tmp2 == NULL) |
541 | 312 return NULL; |
313 args = PyTuple_New(1); | |
314 if (args == NULL) { | |
315 Py_DECREF(tmp2); | |
316 return NULL; | |
317 } | |
318 PyTuple_SET_ITEM(args, 0, tmp2); | |
319 ret = MarkupType.tp_new(&MarkupType, args, NULL); | |
320 Py_DECREF(args); | |
321 return ret; | |
322 } | |
323 | |
324 static PyObject * | |
325 Markup_mod(PyObject *self, PyObject *args) | |
326 { | |
327 PyObject *tmp, *tmp2, *ret, *args2; | |
328 int i, nargs; | |
329 | |
330 if (PyTuple_Check(args)) { | |
331 nargs = PyTuple_GET_SIZE(args); | |
332 args2 = PyTuple_New(nargs); | |
333 if (args2 == NULL) { | |
334 return NULL; | |
335 } | |
336 for (i = 0; i < nargs; i++) { | |
337 tmp = escape(PyTuple_GET_ITEM(args, i), 1); | |
338 if (tmp == NULL) { | |
339 Py_DECREF(args2); | |
340 return NULL; | |
341 } | |
342 PyTuple_SET_ITEM(args2, i, tmp); | |
343 } | |
344 tmp = PyUnicode_Format(self, args2); | |
345 Py_DECREF(args2); | |
346 if (tmp == NULL) { | |
347 return NULL; | |
348 } | |
349 } else { | |
350 tmp2 = escape(args, 1); | |
351 if (tmp2 == NULL) { | |
352 return NULL; | |
353 } | |
354 tmp = PyUnicode_Format(self, tmp2); | |
355 Py_DECREF(tmp2); | |
356 if (tmp == NULL) { | |
357 return NULL; | |
358 } | |
359 } | |
360 args = PyTuple_New(1); | |
361 if (args == NULL) { | |
362 Py_DECREF(tmp); | |
363 return NULL; | |
364 } | |
365 PyTuple_SET_ITEM(args, 0, tmp); | |
366 ret = PyUnicode_Type.tp_new(&MarkupType, args, NULL); | |
367 Py_DECREF(args); | |
368 return ret; | |
369 } | |
370 | |
371 static PyObject * | |
372 Markup_mul(PyObject *self, PyObject *num) | |
373 { | |
374 PyObject *unicode, *result, *args; | |
375 | |
376 if (PyObject_TypeCheck(self, &MarkupType)) { | |
377 unicode = PyObject_Unicode(self); | |
378 if (unicode == NULL) return NULL; | |
379 result = PyNumber_Multiply(unicode, num); | |
380 } else { // __rmul__ | |
381 unicode = PyObject_Unicode(num); | |
382 if (unicode == NULL) return NULL; | |
383 result = PyNumber_Multiply(unicode, self); | |
384 } | |
665
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
385 Py_DECREF(unicode); |
541 | 386 |
387 if (result == NULL) return NULL; | |
388 args = PyTuple_New(1); | |
389 if (args == NULL) { | |
390 Py_DECREF(result); | |
391 return NULL; | |
392 } | |
393 PyTuple_SET_ITEM(args, 0, result); | |
394 result = PyUnicode_Type.tp_new(&MarkupType, args, NULL); | |
395 Py_DECREF(args); | |
396 | |
397 return result; | |
398 } | |
399 | |
400 static PyObject * | |
401 Markup_repr(PyObject *self) | |
402 { | |
403 PyObject *format, *result, *args; | |
404 | |
405 format = PyString_FromString("<Markup %r>"); | |
406 if (format == NULL) return NULL; | |
407 result = PyObject_Unicode(self); | |
665
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
408 if (result == NULL) { |
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
409 Py_DECREF(format); |
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
410 return NULL; |
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
411 } |
541 | 412 args = PyTuple_New(1); |
413 if (args == NULL) { | |
665
3ee92ec99ad9
Applied patch to fix a memory leak in the C implementation of the `Markup.escape()` function. Thanks to Christian Boos for reporting and figuring out the problem. Closes #166.
cmlenz
parents:
547
diff
changeset
|
414 Py_DECREF(format); |
541 | 415 Py_DECREF(result); |
416 return NULL; | |
417 } | |
418 PyTuple_SET_ITEM(args, 0, result); | |
419 result = PyString_Format(format, args); | |
681
3e7cd32c9411
Fix another memory leak in the C speedups code. Thanks to Erik Bray for finding this one and providing a patch. Closes #166 (again).
cmlenz
parents:
665
diff
changeset
|
420 Py_DECREF(format); |
541 | 421 Py_DECREF(args); |
422 return result; | |
423 } | |
424 | |
425 PyDoc_STRVAR(unescape__doc__, | |
547 | 426 "Reverse-escapes &, <, >, and \" and returns a `unicode` object.\n\ |
427 \n\ | |
428 >>> Markup('1 < 2').unescape()\n\ | |
429 u'1 < 2'\n\ | |
430 \n\ | |
431 :return: the unescaped string\n\ | |
432 :rtype: `unicode`\n\ | |
433 :see: `genshi.core.unescape`\n\ | |
434 "); | |
541 | 435 |
436 static PyObject * | |
437 Markup_unescape(PyObject* self) | |
438 { | |
439 PyObject *tmp, *tmp2; | |
440 | |
441 tmp = PyUnicode_Replace(self, qt2, qt1, -1); | |
442 if (tmp == NULL) return NULL; | |
443 tmp2 = PyUnicode_Replace(tmp, gt2, gt1, -1); | |
444 Py_DECREF(tmp); | |
445 if (tmp2 == NULL) return NULL; | |
446 tmp = PyUnicode_Replace(tmp2, lt2, lt1, -1); | |
447 Py_DECREF(tmp2); | |
448 if (tmp == NULL) return NULL; | |
449 tmp2 = PyUnicode_Replace(tmp, amp2, amp1, -1); | |
450 Py_DECREF(tmp); | |
451 return tmp2; | |
452 } | |
453 | |
454 PyDoc_STRVAR(stripentities__doc__, | |
455 "Return a copy of the text with any character or numeric entities\n\ | |
456 replaced by the equivalent UTF-8 characters.\n\ | |
457 \n\ | |
458 If the `keepxmlentities` parameter is provided and evaluates to `True`,\n\ | |
547 | 459 the core XML entities (``&``, ``'``, ``>``, ``<`` and\n\ |
460 ``"``) are not stripped.\n\ | |
461 \n\ | |
462 :return: a `Markup` instance with entities removed\n\ | |
463 :rtype: `Markup`\n\ | |
464 :see: `genshi.util.stripentities`\n\ | |
465 "); | |
541 | 466 |
467 static PyObject * | |
468 Markup_stripentities(PyObject* self, PyObject *args, PyObject *kwds) | |
469 { | |
470 static char *kwlist[] = {"keepxmlentities", 0}; | |
471 PyObject *result, *args2; | |
472 char keepxml = 0; | |
473 | |
474 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|b", kwlist, &keepxml)) { | |
475 return NULL; | |
476 } | |
477 | |
478 if (stripentities == NULL) return NULL; | |
479 result = PyObject_CallFunction(stripentities, "Ob", self, keepxml); | |
480 if (result == NULL) return NULL; | |
481 args2 = PyTuple_New(1); | |
482 if (args2 == NULL) { | |
483 Py_DECREF(result); | |
484 return NULL; | |
485 } | |
486 PyTuple_SET_ITEM(args2, 0, result); | |
487 result = MarkupType.tp_new(&MarkupType, args2, NULL); | |
488 Py_DECREF(args2); | |
489 return result; | |
490 } | |
491 | |
492 PyDoc_STRVAR(striptags__doc__, | |
547 | 493 """Return a copy of the text with all XML/HTML tags removed.\n\ |
494 \n\ | |
495 :return: a `Markup` instance with all tags removed\n\ | |
496 :rtype: `Markup`\n\ | |
497 :see: `genshi.util.striptags`\n\ | |
498 "); | |
541 | 499 |
500 static PyObject * | |
501 Markup_striptags(PyObject* self) | |
502 { | |
503 PyObject *result, *args; | |
504 | |
505 if (striptags == NULL) return NULL; | |
506 result = PyObject_CallFunction(striptags, "O", self); | |
507 if (result == NULL) return NULL; | |
508 args = PyTuple_New(1); | |
509 if (args == NULL) { | |
510 Py_DECREF(result); | |
511 return NULL; | |
512 } | |
513 PyTuple_SET_ITEM(args, 0, result); | |
514 result = MarkupType.tp_new(&MarkupType, args, NULL); | |
515 Py_DECREF(args); | |
516 return result; | |
517 } | |
518 | |
519 typedef struct { | |
520 PyUnicodeObject HEAD; | |
521 } MarkupObject; | |
522 | |
523 static PyMethodDef Markup_methods[] = { | |
524 {"escape", (PyCFunction) Markup_escape, | |
547 | 525 METH_VARARGS|METH_CLASS|METH_KEYWORDS, escape__doc__}, |
526 {"join", (PyCFunction)Markup_join, METH_VARARGS|METH_KEYWORDS, join__doc__}, | |
541 | 527 {"unescape", (PyCFunction)Markup_unescape, METH_NOARGS, unescape__doc__}, |
528 {"stripentities", (PyCFunction) Markup_stripentities, | |
529 METH_VARARGS|METH_KEYWORDS, stripentities__doc__}, | |
530 {"striptags", (PyCFunction) Markup_striptags, METH_NOARGS, | |
531 striptags__doc__}, | |
532 {NULL} /* Sentinel */ | |
533 }; | |
534 | |
535 static PyNumberMethods Markup_as_number = { | |
547 | 536 Markup_add, /*nb_add*/ |
537 0, /*nb_subtract*/ | |
538 Markup_mul, /*nb_multiply*/ | |
539 0, /*nb_divide*/ | |
540 Markup_mod, /*nb_remainder*/ | |
541 | 541 }; |
542 | |
543 PyTypeObject MarkupType = { | |
544 PyObject_HEAD_INIT(NULL) | |
545 0, | |
546 "genshi._speedups.Markup", | |
547 sizeof(MarkupObject), | |
548 0, | |
549 0, /*tp_dealloc*/ | |
550 0, /*tp_print*/ | |
551 0, /*tp_getattr*/ | |
552 0, /*tp_setattr*/ | |
553 0, /*tp_compare*/ | |
554 Markup_repr, /*tp_repr*/ | |
555 &Markup_as_number, /*tp_as_number*/ | |
556 0, /*tp_as_sequence*/ | |
557 0, /*tp_as_mapping*/ | |
558 0, /*tp_hash */ | |
559 | |
560 0, /*tp_call*/ | |
561 0, /*tp_str*/ | |
562 0, /*tp_getattro*/ | |
563 0, /*tp_setattro*/ | |
564 0, /*tp_as_buffer*/ | |
565 | |
566 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ | |
567 Markup__doc__,/*tp_doc*/ | |
568 | |
569 0, /*tp_traverse*/ | |
570 0, /*tp_clear*/ | |
571 | |
572 0, /*tp_richcompare*/ | |
573 0, /*tp_weaklistoffset*/ | |
574 | |
575 0, /*tp_iter*/ | |
576 0, /*tp_iternext*/ | |
577 | |
578 /* Attribute descriptor and subclassing stuff */ | |
579 | |
580 Markup_methods,/*tp_methods*/ | |
581 0, /*tp_members*/ | |
582 0, /*tp_getset*/ | |
583 0, /*tp_base*/ | |
584 0, /*tp_dict*/ | |
585 | |
586 0, /*tp_descr_get*/ | |
587 0, /*tp_descr_set*/ | |
588 0, /*tp_dictoffset*/ | |
589 | |
590 0, /*tp_init*/ | |
591 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ | |
592 Markup_new, /*tp_new*/ | |
593 0, /*tp_free Low-level free-memory routine */ | |
594 0, /*tp_is_gc For PyObject_IS_GC */ | |
595 0, /*tp_bases*/ | |
596 0, /*tp_mro method resolution order */ | |
597 0, /*tp_cache*/ | |
598 0, /*tp_subclasses*/ | |
599 0 /*tp_weaklist*/ | |
600 }; | |
601 | |
602 PyMODINIT_FUNC | |
603 init_speedups(void) | |
604 { | |
605 PyObject *module; | |
606 | |
607 /* Workaround for quirk in Visual Studio, see | |
608 <http://www.python.it/faq/faq-3.html#3.24> */ | |
609 MarkupType.tp_base = &PyUnicode_Type; | |
610 | |
611 if (PyType_Ready(&MarkupType) < 0) | |
612 return; | |
613 | |
614 init_constants(); | |
615 | |
616 module = Py_InitModule("_speedups", NULL); | |
617 Py_INCREF(&MarkupType); | |
618 PyModule_AddObject(module, "Markup", (PyObject *) &MarkupType); | |
619 } |