cmlenz@541: /* cmlenz@719: * Copyright (C) 2006-2008 Edgewall Software cmlenz@541: * All rights reserved. cmlenz@541: * cmlenz@541: * This software is licensed as described in the file COPYING, which cmlenz@541: * you should have received as part of this distribution. The terms cmlenz@541: * are also available at http://genshi.edgewall.org/wiki/License. cmlenz@541: * cmlenz@541: * This software consists of voluntary contributions made by many cmlenz@541: * individuals. For the exact contribution history, see the revision cmlenz@541: * history and logs, available at http://genshi.edgewall.org/log/. cmlenz@541: */ cmlenz@541: cmlenz@541: #include cmlenz@541: #include cmlenz@541: hodgestar@930: #if PY_MAJOR_VERSION > 2 hodgestar@930: # define IS_PY3K hodgestar@930: #elif PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) hodgestar@930: typedef int Py_ssize_t; hodgestar@930: # define PY_SSIZE_T_MAX INT_MAX hodgestar@930: # define PY_SSIZE_T_MIN INT_MIN hodgestar@930: #endif hodgestar@930: hodgestar@930: /* We only use Unicode Strings in this module */ hodgestar@930: #ifndef IS_PY3K hodgestar@930: # define PyObject_Str PyObject_Unicode jruigrok@723: #endif jruigrok@723: cmlenz@541: static PyObject *amp1, *amp2, *lt1, *lt2, *gt1, *gt2, *qt1, *qt2; cmlenz@541: static PyObject *stripentities, *striptags; cmlenz@541: cmlenz@541: static void cmlenz@541: init_constants(void) cmlenz@541: { cmlenz@541: PyObject *util = PyImport_ImportModule("genshi.util"); cmlenz@541: stripentities = PyObject_GetAttrString(util, "stripentities"); cmlenz@541: striptags = PyObject_GetAttrString(util, "striptags"); cmlenz@541: Py_DECREF(util); cmlenz@541: cmlenz@541: amp1 = PyUnicode_DecodeASCII("&", 1, NULL); cmlenz@541: amp2 = PyUnicode_DecodeASCII("&", 5, NULL); cmlenz@541: lt1 = PyUnicode_DecodeASCII("<", 1, NULL); cmlenz@541: lt2 = PyUnicode_DecodeASCII("<", 4, NULL); cmlenz@541: gt1 = PyUnicode_DecodeASCII(">", 1, NULL); cmlenz@541: gt2 = PyUnicode_DecodeASCII(">", 4, NULL); cmlenz@541: qt1 = PyUnicode_DecodeASCII("\"", 1, NULL); cmlenz@541: qt2 = PyUnicode_DecodeASCII(""", 5, NULL); cmlenz@541: } cmlenz@541: cmlenz@541: /* Markup class */ cmlenz@541: cmlenz@795: PyTypeObject MarkupType; /* declared later */ cmlenz@541: cmlenz@541: PyDoc_STRVAR(Markup__doc__, cmlenz@541: "Marks a string as being safe for inclusion in HTML/XML output without\n\ cmlenz@541: needing to be escaped."); cmlenz@541: cmlenz@541: static PyObject * cmlenz@541: escape(PyObject *text, int quotes) cmlenz@541: { cmlenz@541: PyObject *args, *ret; cmlenz@541: PyUnicodeObject *in, *out; cmlenz@541: Py_UNICODE *inp, *outp; cmlenz@541: int len, inn, outn; cmlenz@541: cmlenz@541: if (PyObject_TypeCheck(text, &MarkupType)) { cmlenz@541: Py_INCREF(text); cmlenz@541: return text; cmlenz@541: } cmlenz@737: if (PyObject_HasAttrString(text, "__html__")) { cmlenz@737: ret = PyObject_CallMethod(text, "__html__", NULL); cmlenz@737: args = PyTuple_New(1); cmlenz@737: if (args == NULL) { cmlenz@737: Py_DECREF(ret); cmlenz@737: return NULL; cmlenz@737: } cmlenz@737: PyTuple_SET_ITEM(args, 0, ret); cmlenz@737: ret = MarkupType.tp_new(&MarkupType, args, NULL); cmlenz@737: Py_DECREF(args); cmlenz@737: return ret; cmlenz@737: } hodgestar@930: in = (PyUnicodeObject *) PyObject_Str(text); cmlenz@541: if (in == NULL) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: /* First we need to figure out how long the escaped string will be */ cmlenz@541: len = inn = 0; cmlenz@541: inp = in->str; cmlenz@541: while (*(inp) || in->length > inp - in->str) { cmlenz@541: switch (*inp++) { cmlenz@541: case '&': len += 5; inn++; break; cmlenz@541: case '"': len += quotes ? 5 : 1; inn += quotes ? 1 : 0; break; cmlenz@541: case '<': cmlenz@541: case '>': len += 4; inn++; break; cmlenz@541: default: len++; cmlenz@541: } cmlenz@541: } cmlenz@541: cmlenz@541: /* Do we need to escape anything at all? */ cmlenz@541: if (!inn) { cmlenz@541: args = PyTuple_New(1); cmlenz@541: if (args == NULL) { cmlenz@541: Py_DECREF((PyObject *) in); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args, 0, (PyObject *) in); cmlenz@541: ret = MarkupType.tp_new(&MarkupType, args, NULL); cmlenz@541: Py_DECREF(args); cmlenz@541: return ret; cmlenz@541: } cmlenz@541: cmlenz@541: out = (PyUnicodeObject*) PyUnicode_FromUnicode(NULL, len); cmlenz@541: if (out == NULL) { cmlenz@665: Py_DECREF((PyObject *) in); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: cmlenz@541: outn = 0; cmlenz@541: inp = in->str; cmlenz@541: outp = out->str; cmlenz@541: while (*(inp) || in->length > inp - in->str) { cmlenz@541: if (outn == inn) { cmlenz@541: /* copy rest of string if we have already replaced everything */ cmlenz@541: Py_UNICODE_COPY(outp, inp, in->length - (inp - in->str)); cmlenz@541: break; cmlenz@541: } cmlenz@541: switch (*inp) { cmlenz@541: case '&': cmlenz@541: Py_UNICODE_COPY(outp, ((PyUnicodeObject *) amp2)->str, 5); cmlenz@541: outp += 5; cmlenz@541: outn++; cmlenz@541: break; cmlenz@541: case '"': cmlenz@541: if (quotes) { cmlenz@541: Py_UNICODE_COPY(outp, ((PyUnicodeObject *) qt2)->str, 5); cmlenz@541: outp += 5; cmlenz@541: outn++; cmlenz@541: } else { cmlenz@541: *outp++ = *inp; cmlenz@541: } cmlenz@541: break; cmlenz@541: case '<': cmlenz@541: Py_UNICODE_COPY(outp, ((PyUnicodeObject *) lt2)->str, 4); cmlenz@541: outp += 4; cmlenz@541: outn++; cmlenz@541: break; cmlenz@541: case '>': cmlenz@541: Py_UNICODE_COPY(outp, ((PyUnicodeObject *) gt2)->str, 4); cmlenz@541: outp += 4; cmlenz@541: outn++; cmlenz@541: break; cmlenz@541: default: cmlenz@541: *outp++ = *inp; cmlenz@541: } cmlenz@541: inp++; cmlenz@541: } cmlenz@541: cmlenz@665: Py_DECREF((PyObject *) in); cmlenz@665: cmlenz@541: args = PyTuple_New(1); cmlenz@541: if (args == NULL) { cmlenz@541: Py_DECREF((PyObject *) out); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args, 0, (PyObject *) out); cmlenz@541: ret = MarkupType.tp_new(&MarkupType, args, NULL); cmlenz@541: Py_DECREF(args); cmlenz@541: return ret; cmlenz@541: } cmlenz@541: cmlenz@541: PyDoc_STRVAR(escape__doc__, cmlenz@541: "Create a Markup instance from a string and escape special characters\n\ cmlenz@541: it may contain (<, >, & and \").\n\ cmlenz@541: \n\ cmlenz@547: >>> escape('\"1 < 2\"')\n\ cmlenz@547: \n\ cmlenz@547: \n\ cmlenz@541: If the `quotes` parameter is set to `False`, the \" character is left\n\ cmlenz@541: as is. Escaping quotes is generally only required for strings that are\n\ cmlenz@547: to be used in attribute values.\n\ cmlenz@547: \n\ cmlenz@547: >>> escape('\"1 < 2\"', quotes=False)\n\ cmlenz@547: \n\ cmlenz@547: \n\ cmlenz@547: :param text: the text to escape\n\ cmlenz@547: :param quotes: if ``True``, double quote characters are escaped in\n\ cmlenz@547: addition to the other special characters\n\ cmlenz@547: :return: the escaped `Markup` string\n\ cmlenz@547: :rtype: `Markup`\n\ cmlenz@547: "); cmlenz@541: cmlenz@541: static PyObject * cmlenz@541: Markup_escape(PyTypeObject* type, PyObject *args, PyObject *kwds) cmlenz@541: { cmlenz@541: static char *kwlist[] = {"text", "quotes", 0}; cmlenz@541: PyObject *text = NULL; cmlenz@541: char quotes = 1; cmlenz@541: cmlenz@541: if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|b", kwlist, &text, "es)) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: if (PyObject_Not(text)) { cmlenz@541: return type->tp_new(type, args, NULL); cmlenz@541: } cmlenz@541: if (PyObject_TypeCheck(text, type)) { cmlenz@541: Py_INCREF(text); cmlenz@541: return text; cmlenz@541: } cmlenz@541: return escape(text, quotes); cmlenz@541: } cmlenz@541: cmlenz@737: static PyObject * cmlenz@737: Markup_html(PyObject *self) cmlenz@737: { cmlenz@737: Py_INCREF(self); cmlenz@737: return self; cmlenz@737: } cmlenz@737: cmlenz@547: PyDoc_STRVAR(join__doc__, cmlenz@547: "Return a `Markup` object which is the concatenation of the strings\n\ cmlenz@547: in the given sequence, where this `Markup` object is the separator\n\ cmlenz@547: between the joined elements.\n\ cmlenz@547: \n\ cmlenz@547: Any element in the sequence that is not a `Markup` instance is\n\ cmlenz@547: automatically escaped.\n\ cmlenz@547: \n\ cmlenz@547: :param seq: the sequence of strings to join\n\ cmlenz@547: :param escape_quotes: whether double quote characters in the elements\n\ cmlenz@547: should be escaped\n\ cmlenz@547: :return: the joined `Markup` object\n\ cmlenz@547: :rtype: `Markup`\n\ cmlenz@547: :see: `escape`\n\ cmlenz@547: "); cmlenz@547: cmlenz@541: static PyObject * cmlenz@541: Markup_join(PyObject *self, PyObject *args, PyObject *kwds) cmlenz@541: { cmlenz@541: static char *kwlist[] = {"seq", "escape_quotes", 0}; cmlenz@665: PyObject *seq = NULL, *seq2, *tmp, *tmp2; cmlenz@541: char quotes = 1; cmlenz@795: Py_ssize_t n; cmlenz@795: int i; cmlenz@541: cmlenz@541: if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|b", kwlist, &seq, "es)) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: if (!PySequence_Check(seq)) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: n = PySequence_Size(seq); cmlenz@541: if (n < 0) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: seq2 = PyTuple_New(n); cmlenz@541: if (seq2 == NULL) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: for (i = 0; i < n; i++) { cmlenz@541: tmp = PySequence_GetItem(seq, i); cmlenz@541: if (tmp == NULL) { cmlenz@541: Py_DECREF(seq2); cmlenz@541: return NULL; cmlenz@541: } cmlenz@665: tmp2 = escape(tmp, quotes); cmlenz@665: if (tmp2 == NULL) { cmlenz@541: Py_DECREF(seq2); cmlenz@541: return NULL; cmlenz@541: } cmlenz@665: PyTuple_SET_ITEM(seq2, i, tmp2); cmlenz@665: Py_DECREF(tmp); cmlenz@541: } cmlenz@541: tmp = PyUnicode_Join(self, seq2); cmlenz@541: Py_DECREF(seq2); cmlenz@541: if (tmp == NULL) cmlenz@541: return NULL; cmlenz@541: args = PyTuple_New(1); cmlenz@541: if (args == NULL) { cmlenz@541: Py_DECREF(tmp); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args, 0, tmp); cmlenz@541: tmp = MarkupType.tp_new(&MarkupType, args, NULL); cmlenz@541: Py_DECREF(args); cmlenz@541: return tmp; cmlenz@541: } cmlenz@541: cmlenz@541: static PyObject * cmlenz@541: Markup_add(PyObject *self, PyObject *other) cmlenz@541: { cmlenz@541: PyObject *tmp, *tmp2, *args, *ret; cmlenz@541: if (PyObject_TypeCheck(self, &MarkupType)) { cmlenz@541: tmp = escape(other, 1); cmlenz@541: if (tmp == NULL) cmlenz@541: return NULL; cmlenz@541: tmp2 = PyUnicode_Concat(self, tmp); cmlenz@541: } else { // __radd__ cmlenz@541: tmp = escape(self, 1); cmlenz@541: if (tmp == NULL) cmlenz@541: return NULL; cmlenz@541: tmp2 = PyUnicode_Concat(tmp, other); cmlenz@541: } cmlenz@665: Py_DECREF(tmp); cmlenz@665: if (tmp2 == NULL) cmlenz@541: return NULL; cmlenz@541: args = PyTuple_New(1); cmlenz@541: if (args == NULL) { cmlenz@541: Py_DECREF(tmp2); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args, 0, tmp2); cmlenz@541: ret = MarkupType.tp_new(&MarkupType, args, NULL); cmlenz@541: Py_DECREF(args); cmlenz@541: return ret; cmlenz@541: } cmlenz@541: cmlenz@541: static PyObject * cmlenz@541: Markup_mod(PyObject *self, PyObject *args) cmlenz@541: { cmlenz@541: PyObject *tmp, *tmp2, *ret, *args2; cmlenz@795: int i; cmlenz@795: Py_ssize_t nargs = 0; cmlenz@713: PyObject *kwds = NULL; cmlenz@541: cmlenz@713: if (PyDict_Check(args)) { cmlenz@713: kwds = args; cmlenz@713: } cmlenz@713: if (kwds && PyDict_Size(kwds)) { cmlenz@713: PyObject *kwcopy, *key, *value; cmlenz@713: Py_ssize_t pos = 0; cmlenz@713: cmlenz@713: kwcopy = PyDict_Copy( kwds ); cmlenz@713: if (kwcopy == NULL) { cmlenz@713: return NULL; cmlenz@713: } cmlenz@713: while (PyDict_Next(kwcopy, &pos, &key, &value)) { cmlenz@713: tmp = escape(value, 1); cmlenz@713: if (tmp == NULL) { cmlenz@713: Py_DECREF(kwcopy); cmlenz@713: return NULL; cmlenz@713: } cmlenz@713: if (PyDict_SetItem(kwcopy, key, tmp) < 0) { cmlenz@713: Py_DECREF(tmp); cmlenz@713: Py_DECREF(kwcopy); cmlenz@713: return NULL; cmlenz@713: } cmlenz@713: } cmlenz@713: tmp = PyUnicode_Format(self, kwcopy); cmlenz@713: Py_DECREF(kwcopy); cmlenz@713: if (tmp == NULL) { cmlenz@713: return NULL; cmlenz@713: } cmlenz@713: } else if (PyTuple_Check(args)) { cmlenz@541: nargs = PyTuple_GET_SIZE(args); cmlenz@541: args2 = PyTuple_New(nargs); cmlenz@541: if (args2 == NULL) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: for (i = 0; i < nargs; i++) { cmlenz@541: tmp = escape(PyTuple_GET_ITEM(args, i), 1); cmlenz@541: if (tmp == NULL) { cmlenz@541: Py_DECREF(args2); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args2, i, tmp); cmlenz@541: } cmlenz@541: tmp = PyUnicode_Format(self, args2); cmlenz@541: Py_DECREF(args2); cmlenz@541: if (tmp == NULL) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: } else { cmlenz@541: tmp2 = escape(args, 1); cmlenz@541: if (tmp2 == NULL) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: tmp = PyUnicode_Format(self, tmp2); cmlenz@541: Py_DECREF(tmp2); cmlenz@541: if (tmp == NULL) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: } cmlenz@541: args = PyTuple_New(1); cmlenz@541: if (args == NULL) { cmlenz@541: Py_DECREF(tmp); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args, 0, tmp); cmlenz@541: ret = PyUnicode_Type.tp_new(&MarkupType, args, NULL); cmlenz@541: Py_DECREF(args); cmlenz@541: return ret; cmlenz@541: } cmlenz@541: cmlenz@541: static PyObject * cmlenz@541: Markup_mul(PyObject *self, PyObject *num) cmlenz@541: { cmlenz@541: PyObject *unicode, *result, *args; cmlenz@541: cmlenz@541: if (PyObject_TypeCheck(self, &MarkupType)) { hodgestar@930: unicode = PyObject_Str(self); cmlenz@541: if (unicode == NULL) return NULL; cmlenz@541: result = PyNumber_Multiply(unicode, num); cmlenz@541: } else { // __rmul__ hodgestar@930: unicode = PyObject_Str(num); cmlenz@541: if (unicode == NULL) return NULL; cmlenz@541: result = PyNumber_Multiply(unicode, self); cmlenz@541: } cmlenz@665: Py_DECREF(unicode); cmlenz@541: cmlenz@541: if (result == NULL) return NULL; cmlenz@541: args = PyTuple_New(1); cmlenz@541: if (args == NULL) { cmlenz@541: Py_DECREF(result); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args, 0, result); cmlenz@541: result = PyUnicode_Type.tp_new(&MarkupType, args, NULL); cmlenz@541: Py_DECREF(args); cmlenz@541: cmlenz@541: return result; cmlenz@541: } cmlenz@541: cmlenz@541: static PyObject * cmlenz@541: Markup_repr(PyObject *self) cmlenz@541: { cmlenz@541: PyObject *format, *result, *args; cmlenz@541: hodgestar@930: #ifdef IS_PY3K hodgestar@930: format = PyUnicode_FromString(""); hodgestar@930: #else cmlenz@541: format = PyString_FromString(""); hodgestar@930: #endif cmlenz@541: if (format == NULL) return NULL; hodgestar@930: result = PyObject_Str(self); cmlenz@665: if (result == NULL) { cmlenz@665: Py_DECREF(format); cmlenz@665: return NULL; cmlenz@665: } cmlenz@541: args = PyTuple_New(1); cmlenz@541: if (args == NULL) { cmlenz@665: Py_DECREF(format); cmlenz@541: Py_DECREF(result); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args, 0, result); hodgestar@930: #ifdef IS_PY3K hodgestar@930: result = PyUnicode_Format(format, args); hodgestar@930: #else cmlenz@541: result = PyString_Format(format, args); hodgestar@930: #endif cmlenz@681: Py_DECREF(format); cmlenz@541: Py_DECREF(args); cmlenz@541: return result; cmlenz@541: } cmlenz@541: cmlenz@541: PyDoc_STRVAR(unescape__doc__, cmlenz@547: "Reverse-escapes &, <, >, and \" and returns a `unicode` object.\n\ cmlenz@547: \n\ cmlenz@547: >>> Markup('1 < 2').unescape()\n\ cmlenz@547: u'1 < 2'\n\ cmlenz@547: \n\ cmlenz@547: :return: the unescaped string\n\ cmlenz@547: :rtype: `unicode`\n\ cmlenz@547: :see: `genshi.core.unescape`\n\ cmlenz@547: "); cmlenz@541: cmlenz@541: static PyObject * cmlenz@541: Markup_unescape(PyObject* self) cmlenz@541: { cmlenz@541: PyObject *tmp, *tmp2; cmlenz@541: cmlenz@541: tmp = PyUnicode_Replace(self, qt2, qt1, -1); cmlenz@541: if (tmp == NULL) return NULL; cmlenz@541: tmp2 = PyUnicode_Replace(tmp, gt2, gt1, -1); cmlenz@541: Py_DECREF(tmp); cmlenz@541: if (tmp2 == NULL) return NULL; cmlenz@541: tmp = PyUnicode_Replace(tmp2, lt2, lt1, -1); cmlenz@541: Py_DECREF(tmp2); cmlenz@541: if (tmp == NULL) return NULL; cmlenz@541: tmp2 = PyUnicode_Replace(tmp, amp2, amp1, -1); cmlenz@541: Py_DECREF(tmp); cmlenz@541: return tmp2; cmlenz@541: } cmlenz@541: cmlenz@541: PyDoc_STRVAR(stripentities__doc__, cmlenz@541: "Return a copy of the text with any character or numeric entities\n\ cmlenz@541: replaced by the equivalent UTF-8 characters.\n\ cmlenz@541: \n\ cmlenz@541: If the `keepxmlentities` parameter is provided and evaluates to `True`,\n\ cmlenz@547: the core XML entities (``&``, ``'``, ``>``, ``<`` and\n\ cmlenz@547: ``"``) are not stripped.\n\ cmlenz@547: \n\ cmlenz@547: :return: a `Markup` instance with entities removed\n\ cmlenz@547: :rtype: `Markup`\n\ cmlenz@547: :see: `genshi.util.stripentities`\n\ cmlenz@547: "); cmlenz@541: cmlenz@541: static PyObject * cmlenz@541: Markup_stripentities(PyObject* self, PyObject *args, PyObject *kwds) cmlenz@541: { cmlenz@541: static char *kwlist[] = {"keepxmlentities", 0}; cmlenz@541: PyObject *result, *args2; cmlenz@541: char keepxml = 0; cmlenz@541: cmlenz@541: if (!PyArg_ParseTupleAndKeywords(args, kwds, "|b", kwlist, &keepxml)) { cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: cmlenz@541: if (stripentities == NULL) return NULL; cmlenz@541: result = PyObject_CallFunction(stripentities, "Ob", self, keepxml); cmlenz@541: if (result == NULL) return NULL; cmlenz@541: args2 = PyTuple_New(1); cmlenz@541: if (args2 == NULL) { cmlenz@541: Py_DECREF(result); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args2, 0, result); cmlenz@541: result = MarkupType.tp_new(&MarkupType, args2, NULL); cmlenz@541: Py_DECREF(args2); cmlenz@541: return result; cmlenz@541: } cmlenz@541: cmlenz@541: PyDoc_STRVAR(striptags__doc__, cmlenz@547: """Return a copy of the text with all XML/HTML tags removed.\n\ cmlenz@547: \n\ cmlenz@547: :return: a `Markup` instance with all tags removed\n\ cmlenz@547: :rtype: `Markup`\n\ cmlenz@547: :see: `genshi.util.striptags`\n\ cmlenz@547: "); cmlenz@541: cmlenz@541: static PyObject * cmlenz@541: Markup_striptags(PyObject* self) cmlenz@541: { cmlenz@541: PyObject *result, *args; cmlenz@541: cmlenz@541: if (striptags == NULL) return NULL; cmlenz@541: result = PyObject_CallFunction(striptags, "O", self); cmlenz@541: if (result == NULL) return NULL; cmlenz@541: args = PyTuple_New(1); cmlenz@541: if (args == NULL) { cmlenz@541: Py_DECREF(result); cmlenz@541: return NULL; cmlenz@541: } cmlenz@541: PyTuple_SET_ITEM(args, 0, result); cmlenz@541: result = MarkupType.tp_new(&MarkupType, args, NULL); cmlenz@541: Py_DECREF(args); cmlenz@541: return result; cmlenz@541: } cmlenz@541: cmlenz@541: typedef struct { cmlenz@541: PyUnicodeObject HEAD; cmlenz@541: } MarkupObject; cmlenz@541: cmlenz@541: static PyMethodDef Markup_methods[] = { cmlenz@737: {"__html__", (PyCFunction) Markup_html, METH_NOARGS, NULL}, cmlenz@541: {"escape", (PyCFunction) Markup_escape, cmlenz@547: METH_VARARGS|METH_CLASS|METH_KEYWORDS, escape__doc__}, cmlenz@547: {"join", (PyCFunction)Markup_join, METH_VARARGS|METH_KEYWORDS, join__doc__}, cmlenz@541: {"unescape", (PyCFunction)Markup_unescape, METH_NOARGS, unescape__doc__}, cmlenz@541: {"stripentities", (PyCFunction) Markup_stripentities, cmlenz@541: METH_VARARGS|METH_KEYWORDS, stripentities__doc__}, cmlenz@541: {"striptags", (PyCFunction) Markup_striptags, METH_NOARGS, cmlenz@541: striptags__doc__}, cmlenz@541: {NULL} /* Sentinel */ cmlenz@541: }; cmlenz@541: cmlenz@541: static PyNumberMethods Markup_as_number = { cmlenz@547: Markup_add, /*nb_add*/ cmlenz@547: 0, /*nb_subtract*/ cmlenz@547: Markup_mul, /*nb_multiply*/ hodgestar@930: #ifndef IS_PY3K cmlenz@547: 0, /*nb_divide*/ hodgestar@930: #endif cmlenz@547: Markup_mod, /*nb_remainder*/ cmlenz@541: }; cmlenz@541: cmlenz@541: PyTypeObject MarkupType = { hodgestar@930: #ifdef IS_PY3K hodgestar@930: PyVarObject_HEAD_INIT(NULL, 0) hodgestar@930: #else cmlenz@541: PyObject_HEAD_INIT(NULL) cmlenz@541: 0, hodgestar@930: #endif cmlenz@541: "genshi._speedups.Markup", cmlenz@541: sizeof(MarkupObject), cmlenz@541: 0, cmlenz@541: 0, /*tp_dealloc*/ jruigrok@722: 0, /*tp_print*/ cmlenz@541: 0, /*tp_getattr*/ cmlenz@541: 0, /*tp_setattr*/ hodgestar@930: #ifdef IS_PY3K hodgestar@930: 0, /*tp_reserved*/ hodgestar@930: #else cmlenz@541: 0, /*tp_compare*/ hodgestar@930: #endif cmlenz@541: Markup_repr, /*tp_repr*/ cmlenz@541: &Markup_as_number, /*tp_as_number*/ cmlenz@541: 0, /*tp_as_sequence*/ cmlenz@541: 0, /*tp_as_mapping*/ cmlenz@541: 0, /*tp_hash */ cmlenz@541: cmlenz@541: 0, /*tp_call*/ cmlenz@541: 0, /*tp_str*/ cmlenz@541: 0, /*tp_getattro*/ cmlenz@541: 0, /*tp_setattro*/ cmlenz@541: 0, /*tp_as_buffer*/ cmlenz@541: hodgestar@930: #ifdef IS_PY3K hodgestar@930: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_UNICODE_SUBCLASS, /*tp_flags*/ hodgestar@930: #elif defined(Py_TPFLAGS_UNICODE_SUBCLASS) hodgestar@930: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_UNICODE_SUBCLASS, /*tp_flags*/ hodgestar@930: #else cmlenz@541: Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ hodgestar@930: #endif hodgestar@930: cmlenz@541: Markup__doc__,/*tp_doc*/ jruigrok@722: cmlenz@541: 0, /*tp_traverse*/ cmlenz@541: 0, /*tp_clear*/ cmlenz@541: cmlenz@541: 0, /*tp_richcompare*/ cmlenz@541: 0, /*tp_weaklistoffset*/ cmlenz@541: cmlenz@541: 0, /*tp_iter*/ cmlenz@541: 0, /*tp_iternext*/ cmlenz@541: cmlenz@541: /* Attribute descriptor and subclassing stuff */ cmlenz@541: cmlenz@541: Markup_methods,/*tp_methods*/ cmlenz@541: 0, /*tp_members*/ cmlenz@541: 0, /*tp_getset*/ cmlenz@541: 0, /*tp_base*/ cmlenz@541: 0, /*tp_dict*/ jruigrok@722: cmlenz@541: 0, /*tp_descr_get*/ cmlenz@541: 0, /*tp_descr_set*/ cmlenz@541: 0, /*tp_dictoffset*/ jruigrok@722: cmlenz@541: 0, /*tp_init*/ cmlenz@541: 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ cmlenz@713: 0, /*tp_new*/ cmlenz@541: 0, /*tp_free Low-level free-memory routine */ cmlenz@541: 0, /*tp_is_gc For PyObject_IS_GC */ cmlenz@541: 0, /*tp_bases*/ cmlenz@541: 0, /*tp_mro method resolution order */ cmlenz@541: 0, /*tp_cache*/ cmlenz@541: 0, /*tp_subclasses*/ cmlenz@541: 0 /*tp_weaklist*/ cmlenz@541: }; cmlenz@541: hodgestar@930: #ifdef IS_PY3K hodgestar@930: struct PyModuleDef module_def = { hodgestar@930: PyModuleDef_HEAD_INIT, /*m_base*/ hodgestar@930: "_speedups", /*m_name*/ hodgestar@930: NULL, /*m_doc*/ hodgestar@930: -1, /*m_size*/ hodgestar@930: NULL, /*m_methods*/ hodgestar@930: NULL, /*m_reload*/ hodgestar@930: NULL, /*m_traverse*/ hodgestar@930: NULL, /*m_clear*/ hodgestar@930: NULL /*m_free*/ hodgestar@930: }; hodgestar@930: hodgestar@930: PyObject * hodgestar@930: PyInit__speedups(void) hodgestar@930: #else cmlenz@541: PyMODINIT_FUNC cmlenz@541: init_speedups(void) hodgestar@930: #endif cmlenz@541: { cmlenz@541: PyObject *module; cmlenz@541: cmlenz@541: /* Workaround for quirk in Visual Studio, see cmlenz@541: */ cmlenz@541: MarkupType.tp_base = &PyUnicode_Type; cmlenz@541: cmlenz@541: if (PyType_Ready(&MarkupType) < 0) hodgestar@930: #ifdef IS_PY3K hodgestar@930: return NULL; hodgestar@930: #else cmlenz@541: return; hodgestar@930: #endif cmlenz@541: cmlenz@541: init_constants(); cmlenz@541: hodgestar@930: #ifdef IS_PY3K hodgestar@930: module = PyModule_Create(&module_def); hodgestar@930: #else cmlenz@541: module = Py_InitModule("_speedups", NULL); hodgestar@930: #endif cmlenz@541: Py_INCREF(&MarkupType); cmlenz@541: PyModule_AddObject(module, "Markup", (PyObject *) &MarkupType); hodgestar@930: hodgestar@930: #ifdef IS_PY3K hodgestar@930: return module; hodgestar@930: #endif cmlenz@541: }