5 * This module implements a few functions in C for better performance.
7 * :copyright: 2008 by Armin Ronacher.
14 static const char *samp = "&", *slt = "<", *sgt = ">", *sqt = """;
15 static Py_UNICODE *amp, *lt, *gt, *qt;
16 static PyObject* markup;
22 amp = ((PyUnicodeObject*)PyUnicode_DecodeASCII(samp, 5, NULL))->str;
23 lt = ((PyUnicodeObject*)PyUnicode_DecodeASCII(slt, 4, NULL))->str;
24 gt = ((PyUnicodeObject*)PyUnicode_DecodeASCII(sgt, 4, NULL))->str;
25 qt = ((PyUnicodeObject*)PyUnicode_DecodeASCII(sqt, 6, NULL))->str;
27 PyObject *module = PyImport_ImportModule("jinja2.utils");
30 markup = PyObject_GetAttrString(module, "Markup");
37 escape_unicode(PyUnicodeObject *in)
42 /* First we need to figure out how long the escaped string will be */
43 int len = 0, erepl = 0, repl = 0;
44 Py_UNICODE *inp = in->str;
45 while (*(inp) || in->length > inp - in->str)
64 /* Do we need to escape anything at all? */
70 out = (PyUnicodeObject*)PyUnicode_FromUnicode(NULL, len);
76 while (*(inp) || in->length > inp - in->str) {
77 /* copy rest of string if we have replaced everything */
79 Py_UNICODE_COPY(outp, inp, in->length - (inp - in->str));
82 /* regular replacements */
85 Py_UNICODE_COPY(outp, amp, 5);
90 Py_UNICODE_COPY(outp, qt, 6);
95 Py_UNICODE_COPY(outp, lt, 4);
100 Py_UNICODE_COPY(outp, gt, 4);
110 return (PyObject*)out;
115 soft_unicode(PyObject *self, PyObject *s)
117 if (!PyUnicode_Check(s))
118 return PyObject_Unicode(s);
125 escape(PyObject *self, PyObject *text)
127 PyObject *s = NULL, *rv = NULL;
129 /* we don't have to escape integers, bools or floats */
130 if (PyInt_CheckExact(text) || PyLong_CheckExact(text) ||
131 PyFloat_CheckExact(text) || PyBool_Check(text) ||
133 PyObject *args = PyTuple_New(1);
138 PyTuple_SET_ITEM(args, 0, text);
139 return PyObject_CallObject(markup, args);
142 /* if the object has an __html__ method that performs the escaping */
143 PyObject *html = PyObject_GetAttrString(text, "__html__");
145 rv = PyObject_CallObject(html, NULL);
150 /* otherwise make the object unicode if it isn't, then escape */
152 if (!PyUnicode_Check(text)) {
153 PyObject *unicode = PyObject_Unicode(text);
156 s = escape_unicode((PyUnicodeObject*)unicode);
160 s = escape_unicode((PyUnicodeObject*)text);
162 /* convert the unicode string into a markup object. */
163 return PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL);
168 tb_set_next(PyObject *self, PyObject *args)
170 PyTracebackObject *tb, *old;
173 if (!PyArg_ParseTuple(args, "O!O:tb_set_next", &PyTraceBack_Type, &tb, &next))
177 else if (!PyTraceBack_Check(next)) {
178 PyErr_SetString(PyExc_TypeError,
179 "tb_set_next arg 2 must be traceback or None");
186 tb->tb_next = (PyTracebackObject*)next;
194 static PyMethodDef module_methods[] = {
195 {"escape", (PyCFunction)escape, METH_O,
196 "escape(s) -> string\n\n"
197 "Convert the characters &, <, >, and \" in string s to HTML-safe\n"
198 "sequences. Use this if you need to display text that might contain\n"
199 "such characters in HTML."},
200 {"soft_unicode", (PyCFunction)soft_unicode, METH_O,
201 "soft_unicode(object) -> string\n\n"
202 "Make a string unicode if it isn't already. That way a markup\n"
203 "string is not converted back to unicode."},
204 {"tb_set_next", (PyCFunction)tb_set_next, METH_VARARGS,
205 "Set the tb_next member of a traceback object."},
206 {NULL, NULL, 0, NULL} /* Sentinel */
210 #ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
211 #define PyMODINIT_FUNC void
216 if (!init_constants())
219 Py_InitModule3("jinja2._speedups", module_methods, "");