Mercurial > genshi > mirror
annotate genshi/_speedups.c @ 745:74b5c5476ddb trunk
Preparing for [milestone:0.5] release.
author | cmlenz |
---|---|
date | Mon, 09 Jun 2008 09:50:03 +0000 |
parents | ca72e3dc443d |
children | f5076e2a9786 |
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 | |
46 PyAPI_DATA(PyTypeObject) MarkupType; | |
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
ca72e3dc443d
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__")) { |
ca72e3dc443d
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); |
ca72e3dc443d
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); |
ca72e3dc443d
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) { |
ca72e3dc443d
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); |
ca72e3dc443d
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; |
ca72e3dc443d
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 } |
ca72e3dc443d
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); |
ca72e3dc443d
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); |
ca72e3dc443d
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); |
ca72e3dc443d
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; |
ca72e3dc443d
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
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
|
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
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
|
152 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
|
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
ca72e3dc443d
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 * |
ca72e3dc443d
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) |
ca72e3dc443d
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 { |
ca72e3dc443d
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); |
ca72e3dc443d
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; |
ca72e3dc443d
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 } |
ca72e3dc443d
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
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
|
233 PyObject *seq = NULL, *seq2, *tmp, *tmp2; |
541 | 234 char quotes = 1; |
235 int n, i; | |
236 | |
237 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|b", kwlist, &seq, "es)) { | |
238 return NULL; | |
239 } | |
240 if (!PySequence_Check(seq)) { | |
241 return NULL; | |
242 } | |
243 n = PySequence_Size(seq); | |
244 if (n < 0) { | |
245 return NULL; | |
246 } | |
247 seq2 = PyTuple_New(n); | |
248 if (seq2 == NULL) { | |
249 return NULL; | |
250 } | |
251 for (i = 0; i < n; i++) { | |
252 tmp = PySequence_GetItem(seq, i); | |
253 if (tmp == NULL) { | |
254 Py_DECREF(seq2); | |
255 return NULL; | |
256 } | |
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
|
257 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
|
258 if (tmp2 == NULL) { |
541 | 259 Py_DECREF(seq2); |
260 return NULL; | |
261 } | |
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
|
262 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
|
263 Py_DECREF(tmp); |
541 | 264 } |
265 tmp = PyUnicode_Join(self, seq2); | |
266 Py_DECREF(seq2); | |
267 if (tmp == NULL) | |
268 return NULL; | |
269 args = PyTuple_New(1); | |
270 if (args == NULL) { | |
271 Py_DECREF(tmp); | |
272 return NULL; | |
273 } | |
274 PyTuple_SET_ITEM(args, 0, tmp); | |
275 tmp = MarkupType.tp_new(&MarkupType, args, NULL); | |
276 Py_DECREF(args); | |
277 return tmp; | |
278 } | |
279 | |
280 static PyObject * | |
281 Markup_add(PyObject *self, PyObject *other) | |
282 { | |
283 PyObject *tmp, *tmp2, *args, *ret; | |
284 if (PyObject_TypeCheck(self, &MarkupType)) { | |
285 tmp = escape(other, 1); | |
286 if (tmp == NULL) | |
287 return NULL; | |
288 tmp2 = PyUnicode_Concat(self, tmp); | |
289 } else { // __radd__ | |
290 tmp = escape(self, 1); | |
291 if (tmp == NULL) | |
292 return NULL; | |
293 tmp2 = PyUnicode_Concat(tmp, other); | |
294 } | |
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
|
295 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
|
296 if (tmp2 == NULL) |
541 | 297 return NULL; |
298 args = PyTuple_New(1); | |
299 if (args == NULL) { | |
300 Py_DECREF(tmp2); | |
301 return NULL; | |
302 } | |
303 PyTuple_SET_ITEM(args, 0, tmp2); | |
304 ret = MarkupType.tp_new(&MarkupType, args, NULL); | |
305 Py_DECREF(args); | |
306 return ret; | |
307 } | |
308 | |
309 static PyObject * | |
310 Markup_mod(PyObject *self, PyObject *args) | |
311 { | |
312 PyObject *tmp, *tmp2, *ret, *args2; | |
713
5420fe9d99a9
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
|
313 int i, nargs = 0; |
5420fe9d99a9
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
|
314 PyObject *kwds = NULL; |
541 | 315 |
713
5420fe9d99a9
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 if (PyDict_Check(args)) { |
5420fe9d99a9
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
|
317 kwds = args; |
5420fe9d99a9
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 } |
5420fe9d99a9
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 if (kwds && PyDict_Size(kwds)) { |
5420fe9d99a9
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 PyObject *kwcopy, *key, *value; |
5420fe9d99a9
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 Py_ssize_t pos = 0; |
5420fe9d99a9
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 |
5420fe9d99a9
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 kwcopy = PyDict_Copy( kwds ); |
5420fe9d99a9
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 if (kwcopy == NULL) { |
5420fe9d99a9
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 return NULL; |
5420fe9d99a9
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 } |
5420fe9d99a9
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 while (PyDict_Next(kwcopy, &pos, &key, &value)) { |
5420fe9d99a9
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 tmp = escape(value, 1); |
5420fe9d99a9
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 if (tmp == NULL) { |
5420fe9d99a9
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 Py_DECREF(kwcopy); |
5420fe9d99a9
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 return NULL; |
5420fe9d99a9
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 } |
5420fe9d99a9
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 if (PyDict_SetItem(kwcopy, key, tmp) < 0) { |
5420fe9d99a9
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 Py_DECREF(tmp); |
5420fe9d99a9
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 Py_DECREF(kwcopy); |
5420fe9d99a9
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 return NULL; |
5420fe9d99a9
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 } |
5420fe9d99a9
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 } |
5420fe9d99a9
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 tmp = PyUnicode_Format(self, kwcopy); |
5420fe9d99a9
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 Py_DECREF(kwcopy); |
5420fe9d99a9
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 if (tmp == NULL) { |
5420fe9d99a9
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 return NULL; |
5420fe9d99a9
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 } |
5420fe9d99a9
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 } else if (PyTuple_Check(args)) { |
541 | 345 nargs = PyTuple_GET_SIZE(args); |
346 args2 = PyTuple_New(nargs); | |
347 if (args2 == NULL) { | |
348 return NULL; | |
349 } | |
350 for (i = 0; i < nargs; i++) { | |
351 tmp = escape(PyTuple_GET_ITEM(args, i), 1); | |
352 if (tmp == NULL) { | |
353 Py_DECREF(args2); | |
354 return NULL; | |
355 } | |
356 PyTuple_SET_ITEM(args2, i, tmp); | |
357 } | |
358 tmp = PyUnicode_Format(self, args2); | |
359 Py_DECREF(args2); | |
360 if (tmp == NULL) { | |
361 return NULL; | |
362 } | |
363 } else { | |
364 tmp2 = escape(args, 1); | |
365 if (tmp2 == NULL) { | |
366 return NULL; | |
367 } | |
368 tmp = PyUnicode_Format(self, tmp2); | |
369 Py_DECREF(tmp2); | |
370 if (tmp == NULL) { | |
371 return NULL; | |
372 } | |
373 } | |
374 args = PyTuple_New(1); | |
375 if (args == NULL) { | |
376 Py_DECREF(tmp); | |
377 return NULL; | |
378 } | |
379 PyTuple_SET_ITEM(args, 0, tmp); | |
380 ret = PyUnicode_Type.tp_new(&MarkupType, args, NULL); | |
381 Py_DECREF(args); | |
382 return ret; | |
383 } | |
384 | |
385 static PyObject * | |
386 Markup_mul(PyObject *self, PyObject *num) | |
387 { | |
388 PyObject *unicode, *result, *args; | |
389 | |
390 if (PyObject_TypeCheck(self, &MarkupType)) { | |
391 unicode = PyObject_Unicode(self); | |
392 if (unicode == NULL) return NULL; | |
393 result = PyNumber_Multiply(unicode, num); | |
394 } else { // __rmul__ | |
395 unicode = PyObject_Unicode(num); | |
396 if (unicode == NULL) return NULL; | |
397 result = PyNumber_Multiply(unicode, self); | |
398 } | |
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
|
399 Py_DECREF(unicode); |
541 | 400 |
401 if (result == NULL) return NULL; | |
402 args = PyTuple_New(1); | |
403 if (args == NULL) { | |
404 Py_DECREF(result); | |
405 return NULL; | |
406 } | |
407 PyTuple_SET_ITEM(args, 0, result); | |
408 result = PyUnicode_Type.tp_new(&MarkupType, args, NULL); | |
409 Py_DECREF(args); | |
410 | |
411 return result; | |
412 } | |
413 | |
414 static PyObject * | |
415 Markup_repr(PyObject *self) | |
416 { | |
417 PyObject *format, *result, *args; | |
418 | |
419 format = PyString_FromString("<Markup %r>"); | |
420 if (format == NULL) return NULL; | |
421 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
|
422 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
|
423 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
|
424 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
|
425 } |
541 | 426 args = PyTuple_New(1); |
427 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
|
428 Py_DECREF(format); |
541 | 429 Py_DECREF(result); |
430 return NULL; | |
431 } | |
432 PyTuple_SET_ITEM(args, 0, result); | |
433 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
|
434 Py_DECREF(format); |
541 | 435 Py_DECREF(args); |
436 return result; | |
437 } | |
438 | |
439 PyDoc_STRVAR(unescape__doc__, | |
547 | 440 "Reverse-escapes &, <, >, and \" and returns a `unicode` object.\n\ |
441 \n\ | |
442 >>> Markup('1 < 2').unescape()\n\ | |
443 u'1 < 2'\n\ | |
444 \n\ | |
445 :return: the unescaped string\n\ | |
446 :rtype: `unicode`\n\ | |
447 :see: `genshi.core.unescape`\n\ | |
448 "); | |
541 | 449 |
450 static PyObject * | |
451 Markup_unescape(PyObject* self) | |
452 { | |
453 PyObject *tmp, *tmp2; | |
454 | |
455 tmp = PyUnicode_Replace(self, qt2, qt1, -1); | |
456 if (tmp == NULL) return NULL; | |
457 tmp2 = PyUnicode_Replace(tmp, gt2, gt1, -1); | |
458 Py_DECREF(tmp); | |
459 if (tmp2 == NULL) return NULL; | |
460 tmp = PyUnicode_Replace(tmp2, lt2, lt1, -1); | |
461 Py_DECREF(tmp2); | |
462 if (tmp == NULL) return NULL; | |
463 tmp2 = PyUnicode_Replace(tmp, amp2, amp1, -1); | |
464 Py_DECREF(tmp); | |
465 return tmp2; | |
466 } | |
467 | |
468 PyDoc_STRVAR(stripentities__doc__, | |
469 "Return a copy of the text with any character or numeric entities\n\ | |
470 replaced by the equivalent UTF-8 characters.\n\ | |
471 \n\ | |
472 If the `keepxmlentities` parameter is provided and evaluates to `True`,\n\ | |
547 | 473 the core XML entities (``&``, ``'``, ``>``, ``<`` and\n\ |
474 ``"``) are not stripped.\n\ | |
475 \n\ | |
476 :return: a `Markup` instance with entities removed\n\ | |
477 :rtype: `Markup`\n\ | |
478 :see: `genshi.util.stripentities`\n\ | |
479 "); | |
541 | 480 |
481 static PyObject * | |
482 Markup_stripentities(PyObject* self, PyObject *args, PyObject *kwds) | |
483 { | |
484 static char *kwlist[] = {"keepxmlentities", 0}; | |
485 PyObject *result, *args2; | |
486 char keepxml = 0; | |
487 | |
488 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|b", kwlist, &keepxml)) { | |
489 return NULL; | |
490 } | |
491 | |
492 if (stripentities == NULL) return NULL; | |
493 result = PyObject_CallFunction(stripentities, "Ob", self, keepxml); | |
494 if (result == NULL) return NULL; | |
495 args2 = PyTuple_New(1); | |
496 if (args2 == NULL) { | |
497 Py_DECREF(result); | |
498 return NULL; | |
499 } | |
500 PyTuple_SET_ITEM(args2, 0, result); | |
501 result = MarkupType.tp_new(&MarkupType, args2, NULL); | |
502 Py_DECREF(args2); | |
503 return result; | |
504 } | |
505 | |
506 PyDoc_STRVAR(striptags__doc__, | |
547 | 507 """Return a copy of the text with all XML/HTML tags removed.\n\ |
508 \n\ | |
509 :return: a `Markup` instance with all tags removed\n\ | |
510 :rtype: `Markup`\n\ | |
511 :see: `genshi.util.striptags`\n\ | |
512 "); | |
541 | 513 |
514 static PyObject * | |
515 Markup_striptags(PyObject* self) | |
516 { | |
517 PyObject *result, *args; | |
518 | |
519 if (striptags == NULL) return NULL; | |
520 result = PyObject_CallFunction(striptags, "O", self); | |
521 if (result == NULL) return NULL; | |
522 args = PyTuple_New(1); | |
523 if (args == NULL) { | |
524 Py_DECREF(result); | |
525 return NULL; | |
526 } | |
527 PyTuple_SET_ITEM(args, 0, result); | |
528 result = MarkupType.tp_new(&MarkupType, args, NULL); | |
529 Py_DECREF(args); | |
530 return result; | |
531 } | |
532 | |
533 typedef struct { | |
534 PyUnicodeObject HEAD; | |
535 } MarkupObject; | |
536 | |
537 static PyMethodDef Markup_methods[] = { | |
737
ca72e3dc443d
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
|
538 {"__html__", (PyCFunction) Markup_html, METH_NOARGS, NULL}, |
541 | 539 {"escape", (PyCFunction) Markup_escape, |
547 | 540 METH_VARARGS|METH_CLASS|METH_KEYWORDS, escape__doc__}, |
541 {"join", (PyCFunction)Markup_join, METH_VARARGS|METH_KEYWORDS, join__doc__}, | |
541 | 542 {"unescape", (PyCFunction)Markup_unescape, METH_NOARGS, unescape__doc__}, |
543 {"stripentities", (PyCFunction) Markup_stripentities, | |
544 METH_VARARGS|METH_KEYWORDS, stripentities__doc__}, | |
545 {"striptags", (PyCFunction) Markup_striptags, METH_NOARGS, | |
546 striptags__doc__}, | |
547 {NULL} /* Sentinel */ | |
548 }; | |
549 | |
550 static PyNumberMethods Markup_as_number = { | |
547 | 551 Markup_add, /*nb_add*/ |
552 0, /*nb_subtract*/ | |
553 Markup_mul, /*nb_multiply*/ | |
554 0, /*nb_divide*/ | |
555 Markup_mod, /*nb_remainder*/ | |
541 | 556 }; |
557 | |
558 PyTypeObject MarkupType = { | |
559 PyObject_HEAD_INIT(NULL) | |
560 0, | |
561 "genshi._speedups.Markup", | |
562 sizeof(MarkupObject), | |
563 0, | |
564 0, /*tp_dealloc*/ | |
722 | 565 0, /*tp_print*/ |
541 | 566 0, /*tp_getattr*/ |
567 0, /*tp_setattr*/ | |
568 0, /*tp_compare*/ | |
569 Markup_repr, /*tp_repr*/ | |
570 &Markup_as_number, /*tp_as_number*/ | |
571 0, /*tp_as_sequence*/ | |
572 0, /*tp_as_mapping*/ | |
573 0, /*tp_hash */ | |
574 | |
575 0, /*tp_call*/ | |
576 0, /*tp_str*/ | |
577 0, /*tp_getattro*/ | |
578 0, /*tp_setattro*/ | |
579 0, /*tp_as_buffer*/ | |
580 | |
581 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ | |
582 Markup__doc__,/*tp_doc*/ | |
722 | 583 |
541 | 584 0, /*tp_traverse*/ |
585 0, /*tp_clear*/ | |
586 | |
587 0, /*tp_richcompare*/ | |
588 0, /*tp_weaklistoffset*/ | |
589 | |
590 0, /*tp_iter*/ | |
591 0, /*tp_iternext*/ | |
592 | |
593 /* Attribute descriptor and subclassing stuff */ | |
594 | |
595 Markup_methods,/*tp_methods*/ | |
596 0, /*tp_members*/ | |
597 0, /*tp_getset*/ | |
598 0, /*tp_base*/ | |
599 0, /*tp_dict*/ | |
722 | 600 |
541 | 601 0, /*tp_descr_get*/ |
602 0, /*tp_descr_set*/ | |
603 0, /*tp_dictoffset*/ | |
722 | 604 |
541 | 605 0, /*tp_init*/ |
606 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ | |
713
5420fe9d99a9
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
|
607 0, /*tp_new*/ |
541 | 608 0, /*tp_free Low-level free-memory routine */ |
609 0, /*tp_is_gc For PyObject_IS_GC */ | |
610 0, /*tp_bases*/ | |
611 0, /*tp_mro method resolution order */ | |
612 0, /*tp_cache*/ | |
613 0, /*tp_subclasses*/ | |
614 0 /*tp_weaklist*/ | |
615 }; | |
616 | |
617 PyMODINIT_FUNC | |
618 init_speedups(void) | |
619 { | |
620 PyObject *module; | |
621 | |
622 /* Workaround for quirk in Visual Studio, see | |
623 <http://www.python.it/faq/faq-3.html#3.24> */ | |
624 MarkupType.tp_base = &PyUnicode_Type; | |
625 | |
626 if (PyType_Ready(&MarkupType) < 0) | |
627 return; | |
628 | |
629 init_constants(); | |
630 | |
631 module = Py_InitModule("_speedups", NULL); | |
632 Py_INCREF(&MarkupType); | |
633 PyModule_AddObject(module, "Markup", (PyObject *) &MarkupType); | |
634 } |