3 static PyObject
* markup
;
10 /* import markup type so that we can mark the return value */
11 module = PyImport_ImportModule("markupsafe");
14 markup
= PyObject_GetAttrString(module, "Markup");
20 #define GET_DELTA(inp, inp_end, delta) \
21 while (inp < inp_end) { \
35 #define DO_ESCAPE(inp, inp_end, outp) \
37 Py_ssize_t ncopy = 0; \
38 while (inp < inp_end) { \
41 memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
42 outp += ncopy; ncopy = 0; \
50 memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
51 outp += ncopy; ncopy = 0; \
59 memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
60 outp += ncopy; ncopy = 0; \
68 memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
69 outp += ncopy; ncopy = 0; \
76 memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
77 outp += ncopy; ncopy = 0; \
88 memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \
92 escape_unicode_kind1(PyUnicodeObject
*in
)
94 Py_UCS1
*inp
= PyUnicode_1BYTE_DATA(in
);
95 Py_UCS1
*inp_end
= inp
+ PyUnicode_GET_LENGTH(in
);
100 GET_DELTA(inp
, inp_end
, delta
);
103 return (PyObject
*)in
;
106 out
= PyUnicode_New(PyUnicode_GET_LENGTH(in
) + delta
,
107 PyUnicode_IS_ASCII(in
) ? 127 : 255);
111 inp
= PyUnicode_1BYTE_DATA(in
);
112 outp
= PyUnicode_1BYTE_DATA(out
);
113 DO_ESCAPE(inp
, inp_end
, outp
);
118 escape_unicode_kind2(PyUnicodeObject
*in
)
120 Py_UCS2
*inp
= PyUnicode_2BYTE_DATA(in
);
121 Py_UCS2
*inp_end
= inp
+ PyUnicode_GET_LENGTH(in
);
124 Py_ssize_t delta
= 0;
126 GET_DELTA(inp
, inp_end
, delta
);
129 return (PyObject
*)in
;
132 out
= PyUnicode_New(PyUnicode_GET_LENGTH(in
) + delta
, 65535);
136 inp
= PyUnicode_2BYTE_DATA(in
);
137 outp
= PyUnicode_2BYTE_DATA(out
);
138 DO_ESCAPE(inp
, inp_end
, outp
);
144 escape_unicode_kind4(PyUnicodeObject
*in
)
146 Py_UCS4
*inp
= PyUnicode_4BYTE_DATA(in
);
147 Py_UCS4
*inp_end
= inp
+ PyUnicode_GET_LENGTH(in
);
150 Py_ssize_t delta
= 0;
152 GET_DELTA(inp
, inp_end
, delta
);
155 return (PyObject
*)in
;
158 out
= PyUnicode_New(PyUnicode_GET_LENGTH(in
) + delta
, 1114111);
162 inp
= PyUnicode_4BYTE_DATA(in
);
163 outp
= PyUnicode_4BYTE_DATA(out
);
164 DO_ESCAPE(inp
, inp_end
, outp
);
169 escape_unicode(PyUnicodeObject
*in
)
171 if (PyUnicode_READY(in
))
174 switch (PyUnicode_KIND(in
)) {
175 case PyUnicode_1BYTE_KIND
:
176 return escape_unicode_kind1(in
);
177 case PyUnicode_2BYTE_KIND
:
178 return escape_unicode_kind2(in
);
179 case PyUnicode_4BYTE_KIND
:
180 return escape_unicode_kind4(in
);
182 assert(0); /* shouldn't happen */
187 escape(PyObject
*self
, PyObject
*text
)
189 static PyObject
*id_html
;
190 PyObject
*s
= NULL
, *rv
= NULL
, *html
;
192 if (id_html
== NULL
) {
193 id_html
= PyUnicode_InternFromString("__html__");
194 if (id_html
== NULL
) {
199 /* we don't have to escape integers, bools or floats */
200 if (PyLong_CheckExact(text
) ||
201 PyFloat_CheckExact(text
) || PyBool_Check(text
) ||
203 return PyObject_CallFunctionObjArgs(markup
, text
, NULL
);
205 /* if the object has an __html__ method that performs the escaping */
206 html
= PyObject_GetAttr(text
,id_html
);
208 s
= PyObject_CallObject(html
, NULL
);
213 /* Convert to Markup object */
214 rv
= PyObject_CallFunctionObjArgs(markup
, (PyObject
*)s
, NULL
);
219 /* otherwise make the object unicode if it isn't, then escape */
221 if (!PyUnicode_Check(text
)) {
222 PyObject
*unicode
= PyObject_Str(text
);
225 s
= escape_unicode((PyUnicodeObject
*)unicode
);
229 s
= escape_unicode((PyUnicodeObject
*)text
);
231 /* convert the unicode string into a markup object. */
232 rv
= PyObject_CallFunctionObjArgs(markup
, (PyObject
*)s
, NULL
);
239 escape_silent(PyObject
*self
, PyObject
*text
)
242 return escape(self
, text
);
243 return PyObject_CallFunctionObjArgs(markup
, NULL
);
248 soft_str(PyObject
*self
, PyObject
*s
)
250 if (!PyUnicode_Check(s
))
251 return PyObject_Str(s
);
257 static PyMethodDef module_methods
[] = {
262 "Replace the characters ``&``, ``<``, ``>``, ``'``, and ``\"`` in"
263 " the string with HTML-safe sequences. Use this if you need to display"
264 " text that might contain such characters in HTML.\n\n"
265 "If the object has an ``__html__`` method, it is called and the"
266 " return value is assumed to already be safe for HTML.\n\n"
267 ":param s: An object to be converted to a string and escaped.\n"
268 ":return: A :class:`Markup` string with the escaped text.\n"
272 (PyCFunction
)escape_silent
,
274 "Like :func:`escape` but treats ``None`` as the empty string."
275 " Useful with optional values, as otherwise you get the string"
276 " ``'None'`` when the value is ``None``.\n\n"
279 ">>> escape_silent(None)\n"
284 (PyCFunction
)soft_str
,
286 "Convert an object to a string if it isn't already. This preserves"
287 " a :class:`Markup` string rather than converting it back to a basic"
288 " string, so it will still be marked as safe and won't be escaped"
290 ">>> value = escape(\"<User 1>\")\n"
292 "Markup('<User 1>')\n"
293 ">>> escape(str(value))\n"
294 "Markup('&lt;User 1&gt;')\n"
295 ">>> escape(soft_str(value))\n"
296 "Markup('<User 1>')\n"
298 {NULL
, NULL
, 0, NULL
} /* Sentinel */
301 static struct PyModuleDef module_definition
= {
302 PyModuleDef_HEAD_INIT
,
303 "markupsafe._speedups",
314 PyInit__speedups(void)
316 if (!init_constants())
319 return PyModule_Create(&module_definition
);