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